Merge remote-tracking branch 'Kernel/master'

This commit is contained in:
EnderIce2
2024-11-20 05:00:33 +02:00
468 changed files with 112800 additions and 1 deletions

93
Kernel/include/abi.h Normal file
View File

@ -0,0 +1,93 @@
/*
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_ABI_H__
#define __FENNIX_KERNEL_ABI_H__
#include <types.h>
#define AT_NULL 0
#define AT_IGNORE 1
#define AT_EXECFD 2
#define AT_PHDR 3
#define AT_PHENT 4
#define AT_PHNUM 5
#define AT_PAGESZ 6
#define AT_BASE 7
#define AT_FLAGS 8
#define AT_ENTRY 9
#define AT_NOTELF 10
#define AT_UID 11
#define AT_EUID 12
#define AT_GID 13
#define AT_EGID 14
#define AT_PLATFORM 15
#define AT_HWCAP 16
#define AT_CLKTCK 17
#define AT_SECURE 23
#define AT_BASE_PLATFORM 24
#define AT_RANDOM 25
#define AT_HWCAP2 26
#define AT_EXECFN 31
#define AT_SYSINFO 32
#define AT_SYSINFO_EHDR 33
#define AT_L1I_CACHESHAPE 34
#define AT_L1D_CACHESHAPE 35
#define AT_L2_CACHESHAPE 36
#define AT_L3_CACHESHAPE 37
#define AT_L1I_CACHESIZE 40
#define AT_L1I_CACHEGEOMETRY 41
#define AT_L1D_CACHESIZE 42
#define AT_L1D_CACHEGEOMETRY 43
#define AT_L2_CACHESIZE 44
#define AT_L2_CACHEGEOMETRY 45
#define AT_L3_CACHESIZE 46
#define AT_L3_CACHEGEOMETRY 47
#define AT_MINSIGSTKSZ 51
typedef struct
{
uint32_t a_type;
union
{
uint32_t a_val;
} a_un;
} Elf32_auxv_t;
typedef struct
{
uint64_t a_type;
union
{
uint64_t a_val;
} a_un;
} Elf64_auxv_t;
#if defined(a64)
typedef Elf64_auxv_t Elf_auxv_t;
#elif defined(a32)
typedef Elf64_auxv_t Elf_auxv_t;
#elif defined(aa64)
typedef Elf64_auxv_t Elf_auxv_t;
#endif
typedef struct
{
Elf_auxv_t archaux;
} AuxiliaryVector;
#endif // !__FENNIX_KERNEL_ABI_H__

386
Kernel/include/acpi.hpp Normal file
View File

@ -0,0 +1,386 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef __FENNIX_KERNEL_ACPI_H__
#define __FENNIX_KERNEL_ACPI_H__
#include <types.h>
#include <unordered_map>
#include <boot/binfo.h>
#include <ints.hpp>
#include <cpu.hpp>
#include <vector>
namespace ACPI
{
class ACPI
{
public:
struct ACPIHeader
{
unsigned char Signature[4];
uint32_t Length;
uint8_t Revision;
uint8_t Checksum;
uint8_t OEMID[6];
uint8_t OEMTableID[8];
uint32_t OEMRevision;
uint32_t CreatorID;
uint32_t CreatorRevision;
} __packed;
struct GenericAddressStructure
{
uint8_t AddressSpace;
uint8_t BitWidth;
uint8_t BitOffset;
uint8_t AccessSize;
uint64_t Address;
} __packed;
enum DBG2PortType
{
TYPE_SERIAL = 0x8000,
TYPE_1394 = 0x8001,
TYPE_USB = 0x8002,
TYPE_NET = 0x8003
};
enum DBG2PortSubtype
{
SUBTYPE_SERIAL_16550_COMPATIBLE = 0x0000,
SUBTYPE_SERIAL_16550_SUBSET = 0x0001,
SUBTYPE_SERIAL_MAX311xE_SPI_UART = 0x0002,
SUBTYPE_SERIAL_Arm_PL011_UART = 0x0003,
SUBTYPE_SERIAL_MSM8x60 = 0x0004,
SUBTYPE_SERIAL_Nvidia_16550 = 0x0005,
SUBTYPE_SERIAL_TI_OMAP = 0x0006,
SUBTYPE_SERIAL_APM88xxxx = 0x0008,
SUBTYPE_SERIAL_MSM8974 = 0x0009,
SUBTYPE_SERIAL_SAM5250 = 0x000A,
SUBTYPE_SERIAL_Intel_USIF = 0x000B,
SUBTYPE_SERIAL_iMX6 = 0x000C,
SUBTYPE_SERIAL_Arm_SBSA_UART = 0x000D,
SUBTYPE_SERIAL_Arm_SBSA_Generic_UART = 0x000E,
SUBTYPE_SERIAL_Arm_DCC = 0x000F,
SUBTYPE_SERIAL_BCM2835 = 0x0010,
SUBTYPE_SERIAL_SDM845_At_1_8432MHz = 0x0011,
SUBTYPE_SERIAL_16550_With_Generic_Address_Structure = 0x0012,
SUBTYPE_SERIAL_SDM845_At_7_372MHz = 0x0013,
SUBTYPE_SERIAL_Intel_LPSS = 0x0014,
SUBTYPE_SERIAL_RISC_V_SBI_Console = 0x0015,
SUBTYPE_1394_IEEE1394_HCI = 0x0000,
SUBTYPE_USB_XHCI = 0x0000,
SUBTYPE_USB_EHCI = 0x0001,
SUBTYPE_NET_NNNN = 0x0000,
};
struct DBG2Device
{
uint8_t Revision;
uint16_t Length;
uint8_t NumberofGenericAddressRegisters;
uint16_t NamespaceStringLength;
uint16_t NamespaceStringOffset;
uint16_t OemDataLength;
uint16_t OemDataOffset;
uint16_t PortType;
uint16_t PortSubtype;
uint16_t Reserved;
uint16_t BaseAddressRegisterOffset;
uint16_t AddressSizeOffset;
/* BaseAddressRegister[NumberofGenericAddressRegisters * 12] at offset BaseAddressRegisterOffset */
/* AddressSize[NumberofGenericAddressRegisters * 4] at offset AddressSizeOffset */
/* NamespaceString[NamespaceStringLength] at offset NamespaceStringOffset */
/* OemData[OemDataLength] at offset OemDataOffset */
} __packed;
struct MCFGHeader
{
struct ACPIHeader Header;
uint64_t Reserved;
} __packed;
struct HPETHeader
{
ACPIHeader Header;
uint8_t HardwareRevID;
uint8_t ComparatorCount : 5;
uint8_t CounterSize : 1;
uint8_t Reserved : 1;
uint8_t LegacyReplacement : 1;
uint16_t PCIVendorID;
struct GenericAddressStructure Address;
uint8_t HPETNumber;
uint16_t MinimumTick;
uint8_t PageProtection;
} __packed;
struct FADTHeader
{
ACPIHeader Header;
uint32_t FirmwareCtrl;
uint32_t Dsdt;
uint8_t Reserved;
uint8_t PreferredPowerManagementProfile;
uint16_t SCI_Interrupt;
uint32_t SMI_CommandPort;
uint8_t AcpiEnable;
uint8_t AcpiDisable;
uint8_t S4BIOS_REQ;
uint8_t PSTATE_Control;
uint32_t PM1aEventBlock;
uint32_t PM1bEventBlock;
uint32_t PM1aControlBlock;
uint32_t PM1bControlBlock;
uint32_t PM2ControlBlock;
uint32_t PMTimerBlock;
uint32_t GPE0Block;
uint32_t GPE1Block;
uint8_t PM1EventLength;
uint8_t PM1ControlLength;
uint8_t PM2ControlLength;
uint8_t PMTimerLength;
uint8_t GPE0Length;
uint8_t GPE1Length;
uint8_t GPE1Base;
uint8_t CStateControl;
uint16_t WorstC2Latency;
uint16_t WorstC3Latency;
uint16_t FlushSize;
uint16_t FlushStride;
uint8_t DutyOffset;
uint8_t DutyWidth;
uint8_t DayAlarm;
uint8_t MonthAlarm;
uint8_t Century;
uint16_t BootArchitectureFlags;
uint8_t Reserved2;
uint32_t Flags;
struct GenericAddressStructure ResetReg;
uint8_t ResetValue;
uint8_t Reserved3[3];
uint64_t X_FirmwareControl;
uint64_t X_Dsdt;
struct GenericAddressStructure X_PM1aEventBlock;
struct GenericAddressStructure X_PM1bEventBlock;
struct GenericAddressStructure X_PM1aControlBlock;
struct GenericAddressStructure X_PM1bControlBlock;
struct GenericAddressStructure X_PM2ControlBlock;
struct GenericAddressStructure X_PMTimerBlock;
struct GenericAddressStructure X_GPE0Block;
struct GenericAddressStructure X_GPE1Block;
} __packed;
struct BGRTHeader
{
ACPIHeader Header;
uint16_t Version;
uint8_t Status;
uint8_t ImageType;
uint64_t ImageAddress;
uint32_t ImageOffsetX;
uint32_t ImageOffsetY;
} __packed;
struct SRATHeader
{
ACPIHeader Header;
uint32_t TableRevision; // Must be value 1
uint64_t Reserved; // Reserved, must be zero
} __packed;
struct TPM2Header
{
ACPIHeader Header;
uint32_t Flags;
uint64_t ControlAddress;
uint32_t StartMethod;
} __packed;
struct TCPAHeader
{
ACPIHeader Header;
uint16_t Reserved;
uint32_t MaxLogLength;
uint64_t LogAddress;
} __packed;
struct WAETHeader
{
ACPIHeader Header;
uint32_t Flags;
} __packed;
struct HESTHeader
{
ACPIHeader Header;
uint32_t ErrorSourceCount;
} __packed;
struct MADTHeader
{
ACPIHeader Header;
uint32_t LocalControllerAddress;
uint32_t Flags;
char Entries[];
} __packed;
struct SSDTHeader
{
ACPIHeader Header;
char DefinitionBlock[];
} __packed;
struct DBGPHeader
{
ACPIHeader Header;
/**
* 0 - 16550 compatible
* 1 - Subset of 16550
*/
uint8_t InterfaceType;
uint8_t Reserved[3];
GenericAddressStructure BaseAddress;
} __packed;
struct DBG2Header
{
ACPIHeader Header;
uint32_t OffsetDbgDeviceInfo;
uint32_t NumberDbgDeviceInfo;
/* DBG2Device[NumberDbgDeviceInfo] at offset OffsetDbgDeviceInfo */
} __packed;
ACPIHeader *XSDT = nullptr;
MCFGHeader *MCFG = nullptr;
HPETHeader *HPET = nullptr;
FADTHeader *FADT = nullptr;
BGRTHeader *BGRT = nullptr;
SRATHeader *SRAT = nullptr;
TPM2Header *TPM2 = nullptr;
TCPAHeader *TCPA = nullptr;
WAETHeader *WAET = nullptr;
MADTHeader *MADT = nullptr;
HESTHeader *HEST = nullptr;
SSDTHeader *SSDT = nullptr;
DBGPHeader *DBGP = nullptr;
DBG2Header *DBG2 = nullptr;
bool XSDTSupported = false;
std::unordered_map<const char *, ACPIHeader *> Tables;
void *FindTable(ACPIHeader *ACPIHeader, char *Signature);
void SearchTables(ACPIHeader *Header);
ACPI();
~ACPI();
};
class MADT
{
public:
struct APICHeader
{
uint8_t Type;
uint8_t Length;
} __packed;
struct MADTIOApic
{
struct APICHeader Header;
uint8_t APICID;
uint8_t reserved;
uint32_t Address;
uint32_t GSIBase;
} __packed;
struct MADTIso
{
struct APICHeader Header;
uint8_t BuSSource;
uint8_t IRQSource;
uint32_t GSI;
uint16_t Flags;
} __packed;
struct MADTNmi
{
struct APICHeader Header;
uint8_t processor;
uint16_t flags;
uint8_t lint;
} __packed;
struct LocalAPIC
{
struct APICHeader Header;
uint8_t ACPIProcessorId;
uint8_t APICId;
uint32_t Flags;
} __packed;
struct LAPIC
{
uint8_t id;
uintptr_t PhysicalAddress;
void *VirtualAddress;
};
std::vector<MADTIOApic *> ioapic;
std::vector<MADTIso *> iso;
std::vector<MADTNmi *> nmi;
std::vector<LocalAPIC *> lapic;
struct LAPIC *LAPICAddress;
uint16_t CPUCores;
MADT(ACPI::MADTHeader *madt);
~MADT();
};
class DSDT : public Interrupts::Handler
{
private:
uint32_t SMI_CMD = 0;
uint8_t ACPI_ENABLE = 0;
uint8_t ACPI_DISABLE = 0;
uint32_t PM1a_CNT = 0;
uint32_t PM1b_CNT = 0;
uint16_t SLP_TYPa = 0;
uint16_t SLP_TYPb = 0;
uint16_t SLP_EN = 0;
uint16_t SCI_EN = 0;
uint8_t PM1_CNT_LEN = 0;
ACPI *acpi;
void OnInterruptReceived(CPU::TrapFrame *Frame);
public:
bool ACPIShutdownSupported = false;
void Reboot();
void Shutdown();
DSDT(ACPI *acpi);
~DSDT();
};
}
#endif // !__FENNIX_KERNEL_ACPI_H__

34
Kernel/include/bitmap.hpp Normal file
View File

@ -0,0 +1,34 @@
/*
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_BITMAP_H__
#define __FENNIX_KERNEL_BITMAP_H__
#include <types.h>
class Bitmap
{
public:
size_t Size;
uint8_t *Buffer;
bool Set(uint64_t index, bool value);
bool Get(uint64_t index);
bool operator[](uint64_t index);
};
#endif // !__FENNIX_KERNEL_BITMAP_H__

155
Kernel/include/boot/binfo.h Normal file
View File

@ -0,0 +1,155 @@
/*
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_BOOT_INFO_H__
#define __FENNIX_KERNEL_BOOT_INFO_H__
enum MemoryType
{
Unknown_Memory_Type,
Usable,
Reserved,
ACPIReclaimable,
ACPINVS,
BadMemory,
BootloaderReclaimable,
KernelAndModules,
Framebuffer,
Unknown
};
enum FramebufferType
{
Unknown_Framebuffer_Type,
Indexed,
RGB,
EGA
};
#define MAX_FRAMEBUFFERS 16
#define MAX_MEMORY_ENTRIES 256
#define MAX_MODULES 4
struct BootInfo
{
struct FramebufferInfo
{
enum FramebufferType Type;
void *BaseAddress;
__UINT32_TYPE__ Width;
__UINT32_TYPE__ Height;
__SIZE_TYPE__ Pitch;
__UINT16_TYPE__ BitsPerPixel;
__UINT8_TYPE__ RedMaskSize;
__UINT8_TYPE__ RedMaskShift;
__UINT8_TYPE__ GreenMaskSize;
__UINT8_TYPE__ GreenMaskShift;
__UINT8_TYPE__ BlueMaskSize;
__UINT8_TYPE__ BlueMaskShift;
void *ExtendedDisplayIdentificationData;
__SIZE_TYPE__ EDIDSize;
} Framebuffer[MAX_FRAMEBUFFERS];
struct MemoryInfo
{
struct MemoryEntryInfo
{
void *BaseAddress;
__SIZE_TYPE__ Length;
enum MemoryType Type;
} Entry[MAX_MEMORY_ENTRIES];
__SIZE_TYPE__ Entries;
__SIZE_TYPE__ Size;
} Memory;
struct ModuleInfo
{
void *Address;
char Path[256];
char CommandLine[256];
__SIZE_TYPE__ Size;
} Modules[MAX_MODULES];
struct RSDPInfo
{
/**
* @brief Signature
*/
__UINT8_TYPE__ Signature[8];
/**
* @brief Checksum
*/
__UINT8_TYPE__ Checksum;
/**
* @brief OEM ID
*/
__UINT8_TYPE__ OEMID[6];
/**
* @brief Revision
*/
__UINT8_TYPE__ Revision;
/**
* @brief Address of the Root System Description Table
*/
__UINT32_TYPE__ RSDTAddress;
/* END OF RSDP 1.0 */
/**
* @brief Length
*/
__UINT32_TYPE__ Length;
/**
* @brief Extended System Descriptor Table
*/
__UINT64_TYPE__ XSDTAddress;
/**
* @brief Extended checksum
*/
__UINT8_TYPE__ ExtendedChecksum;
/**
* @brief Reserved
*/
__UINT8_TYPE__ Reserved[3];
} __attribute__((packed)) * RSDP;
struct KernelInfo
{
void *PhysicalBase;
void *VirtualBase;
void *FileBase;
char CommandLine[256];
__SIZE_TYPE__ Size;
struct KernelSymbolInfo
{
__UINT32_TYPE__ Num;
__UINT32_TYPE__ EntSize;
__UINT32_TYPE__ Shndx;
__UINTPTR_TYPE__ Sections;
} Symbols;
} Kernel;
struct BootloaderInfo
{
char Name[256];
char Version[64];
} Bootloader;
void *SMBIOSPtr;
};
#endif // !__FENNIX_KERNEL_BOOT_INFO_H__

View File

@ -0,0 +1,274 @@
/* multiboot.h - Multiboot header file. */
/* Copyright (C) 1999,2003,2007,2008,2009,2010 Free Software Foundation, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
* deal in the Software without restriction, including without limitation the
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
* sell copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL ANY
* DEVELOPER OR DISTRIBUTOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
* IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef MULTIBOOT_HEADER
#define MULTIBOOT_HEADER 1
/* How many bytes from the start of the file we search for the header. */
#define MULTIBOOT_SEARCH 8192
#define MULTIBOOT_HEADER_ALIGN 4
/* The magic field should contain this. */
#define MULTIBOOT_HEADER_MAGIC 0x1BADB002
/* This should be in %eax. */
#define MULTIBOOT_BOOTLOADER_MAGIC 0x2BADB002
/* Alignment of multiboot modules. */
#define MULTIBOOT_MOD_ALIGN 0x00001000
/* Alignment of the multiboot info structure. */
#define MULTIBOOT_INFO_ALIGN 0x00000004
/* Flags set in the 'flags' member of the multiboot header. */
/* Align all boot modules on i386 page (4KB) boundaries. */
#define MULTIBOOT_PAGE_ALIGN 0x00000001
/* Must pass memory information to OS. */
#define MULTIBOOT_MEMORY_INFO 0x00000002
/* Must pass video information to OS. */
#define MULTIBOOT_VIDEO_MODE 0x00000004
/* This flag indicates the use of the address fields in the header. */
#define MULTIBOOT_AOUT_KLUDGE 0x00010000
/* Flags to be set in the 'flags' member of the multiboot info structure. */
/* is there basic lower/upper memory information? */
#define MULTIBOOT_INFO_MEMORY 0x00000001
/* is there a boot device set? */
#define MULTIBOOT_INFO_BOOTDEV 0x00000002
/* is the command-line defined? */
#define MULTIBOOT_INFO_CMDLINE 0x00000004
/* are there modules to do something with? */
#define MULTIBOOT_INFO_MODS 0x00000008
/* These next two are mutually exclusive */
/* is there a symbol table loaded? */
#define MULTIBOOT_INFO_AOUT_SYMS 0x00000010
/* is there an ELF section header table? */
#define MULTIBOOT_INFO_ELF_SHDR 0X00000020
/* is there a full memory map? */
#define MULTIBOOT_INFO_MEM_MAP 0x00000040
/* Is there drive info? */
#define MULTIBOOT_INFO_DRIVE_INFO 0x00000080
/* Is there a config table? */
#define MULTIBOOT_INFO_CONFIG_TABLE 0x00000100
/* Is there a boot loader name? */
#define MULTIBOOT_INFO_BOOT_LOADER_NAME 0x00000200
/* Is there a APM table? */
#define MULTIBOOT_INFO_APM_TABLE 0x00000400
/* Is there video information? */
#define MULTIBOOT_INFO_VBE_INFO 0x00000800
#define MULTIBOOT_INFO_FRAMEBUFFER_INFO 0x00001000
#ifndef ASM_FILE
typedef unsigned char multiboot_uint8_t;
typedef unsigned short multiboot_uint16_t;
typedef unsigned int multiboot_uint32_t;
typedef unsigned long long multiboot_uint64_t;
struct multiboot_header
{
/* Must be MULTIBOOT_MAGIC - see above. */
multiboot_uint32_t magic;
/* Feature flags. */
multiboot_uint32_t flags;
/* The above fields plus this one must equal 0 mod 2^32. */
multiboot_uint32_t checksum;
/* These are only valid if MULTIBOOT_AOUT_KLUDGE is set. */
multiboot_uint32_t header_addr;
multiboot_uint32_t load_addr;
multiboot_uint32_t load_end_addr;
multiboot_uint32_t bss_end_addr;
multiboot_uint32_t entry_addr;
/* These are only valid if MULTIBOOT_VIDEO_MODE is set. */
multiboot_uint32_t mode_type;
multiboot_uint32_t width;
multiboot_uint32_t height;
multiboot_uint32_t depth;
};
/* The symbol table for a.out. */
struct multiboot_aout_symbol_table
{
multiboot_uint32_t tabsize;
multiboot_uint32_t strsize;
multiboot_uint32_t addr;
multiboot_uint32_t reserved;
};
typedef struct multiboot_aout_symbol_table multiboot_aout_symbol_table_t;
/* The section header table for ELF. */
struct multiboot_elf_section_header_table
{
multiboot_uint32_t num;
multiboot_uint32_t size;
multiboot_uint32_t addr;
multiboot_uint32_t shndx;
};
typedef struct multiboot_elf_section_header_table multiboot_elf_section_header_table_t;
struct multiboot_info
{
/* Multiboot info version number */
multiboot_uint32_t flags;
/* Available memory from BIOS */
multiboot_uint32_t mem_lower;
multiboot_uint32_t mem_upper;
/* "root" partition */
multiboot_uint32_t boot_device;
/* Kernel command line */
multiboot_uint32_t cmdline;
/* Boot-Module list */
multiboot_uint32_t mods_count;
multiboot_uint32_t mods_addr;
union
{
multiboot_aout_symbol_table_t aout_sym;
multiboot_elf_section_header_table_t elf_sec;
} u;
/* Memory Mapping buffer */
multiboot_uint32_t mmap_length;
multiboot_uint32_t mmap_addr;
/* Drive Info buffer */
multiboot_uint32_t drives_length;
multiboot_uint32_t drives_addr;
/* ROM configuration table */
multiboot_uint32_t config_table;
/* Boot Loader Name */
multiboot_uint32_t boot_loader_name;
/* APM table */
multiboot_uint32_t apm_table;
/* Video */
multiboot_uint32_t vbe_control_info;
multiboot_uint32_t vbe_mode_info;
multiboot_uint16_t vbe_mode;
multiboot_uint16_t vbe_interface_seg;
multiboot_uint16_t vbe_interface_off;
multiboot_uint16_t vbe_interface_len;
multiboot_uint64_t framebuffer_addr;
multiboot_uint32_t framebuffer_pitch;
multiboot_uint32_t framebuffer_width;
multiboot_uint32_t framebuffer_height;
multiboot_uint8_t framebuffer_bpp;
#define MULTIBOOT_FRAMEBUFFER_TYPE_INDEXED 0
#define MULTIBOOT_FRAMEBUFFER_TYPE_RGB 1
#define MULTIBOOT_FRAMEBUFFER_TYPE_EGA_TEXT 2
multiboot_uint8_t framebuffer_type;
union
{
struct
{
multiboot_uint32_t framebuffer_palette_addr;
multiboot_uint16_t framebuffer_palette_num_colors;
};
struct
{
multiboot_uint8_t framebuffer_red_field_position;
multiboot_uint8_t framebuffer_red_mask_size;
multiboot_uint8_t framebuffer_green_field_position;
multiboot_uint8_t framebuffer_green_mask_size;
multiboot_uint8_t framebuffer_blue_field_position;
multiboot_uint8_t framebuffer_blue_mask_size;
};
};
};
typedef struct multiboot_info multiboot_info_t;
struct multiboot_color
{
multiboot_uint8_t red;
multiboot_uint8_t green;
multiboot_uint8_t blue;
};
struct multiboot_mmap_entry
{
multiboot_uint32_t size;
multiboot_uint64_t addr;
multiboot_uint64_t len;
#define MULTIBOOT_MEMORY_AVAILABLE 1
#define MULTIBOOT_MEMORY_RESERVED 2
#define MULTIBOOT_MEMORY_ACPI_RECLAIMABLE 3
#define MULTIBOOT_MEMORY_NVS 4
#define MULTIBOOT_MEMORY_BADRAM 5
multiboot_uint32_t type;
} __attribute__((packed));
typedef struct multiboot_mmap_entry multiboot_memory_map_t;
struct multiboot_mod_list
{
/* the memory used goes from bytes 'mod_start' to 'mod_end-1' inclusive */
multiboot_uint32_t mod_start;
multiboot_uint32_t mod_end;
/* Module command line */
multiboot_uint32_t cmdline;
/* padding to take it to 16 bytes (must be zero) */
multiboot_uint32_t pad;
};
typedef struct multiboot_mod_list multiboot_module_t;
/* APM BIOS info. */
struct multiboot_apm_info
{
multiboot_uint16_t version;
multiboot_uint16_t cseg;
multiboot_uint32_t offset;
multiboot_uint16_t cseg_16;
multiboot_uint16_t dseg;
multiboot_uint16_t flags;
multiboot_uint16_t cseg_len;
multiboot_uint16_t cseg_16_len;
multiboot_uint16_t dseg_len;
};
#endif /* ! ASM_FILE */
#endif /* ! MULTIBOOT_HEADER */

View File

@ -0,0 +1,417 @@
/* multiboot2.h - Multiboot 2 header file. */
/* Copyright (C) 1999,2003,2007,2008,2009,2010 Free Software Foundation, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
* deal in the Software without restriction, including without limitation the
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
* sell copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL ANY
* DEVELOPER OR DISTRIBUTOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
* IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef MULTIBOOT_HEADER
#define MULTIBOOT_HEADER 1
/* How many bytes from the start of the file we search for the header. */
#define MULTIBOOT_SEARCH 32768
#define MULTIBOOT_HEADER_ALIGN 8
/* The magic field should contain this. */
#define MULTIBOOT2_HEADER_MAGIC 0xe85250d6
/* This should be in %eax. */
#define MULTIBOOT2_BOOTLOADER_MAGIC 0x36d76289
/* Alignment of multiboot modules. */
#define MULTIBOOT_MOD_ALIGN 0x00001000
/* Alignment of the multiboot info structure. */
#define MULTIBOOT_INFO_ALIGN 0x00000008
/* Flags set in the 'flags' member of the multiboot header. */
#define MULTIBOOT_TAG_ALIGN 8
#define MULTIBOOT_TAG_TYPE_END 0
#define MULTIBOOT_TAG_TYPE_CMDLINE 1
#define MULTIBOOT_TAG_TYPE_BOOT_LOADER_NAME 2
#define MULTIBOOT_TAG_TYPE_MODULE 3
#define MULTIBOOT_TAG_TYPE_BASIC_MEMINFO 4
#define MULTIBOOT_TAG_TYPE_BOOTDEV 5
#define MULTIBOOT_TAG_TYPE_MMAP 6
#define MULTIBOOT_TAG_TYPE_VBE 7
#define MULTIBOOT_TAG_TYPE_FRAMEBUFFER 8
#define MULTIBOOT_TAG_TYPE_ELF_SECTIONS 9
#define MULTIBOOT_TAG_TYPE_APM 10
#define MULTIBOOT_TAG_TYPE_EFI32 11
#define MULTIBOOT_TAG_TYPE_EFI64 12
#define MULTIBOOT_TAG_TYPE_SMBIOS 13
#define MULTIBOOT_TAG_TYPE_ACPI_OLD 14
#define MULTIBOOT_TAG_TYPE_ACPI_NEW 15
#define MULTIBOOT_TAG_TYPE_NETWORK 16
#define MULTIBOOT_TAG_TYPE_EFI_MMAP 17
#define MULTIBOOT_TAG_TYPE_EFI_BS 18
#define MULTIBOOT_TAG_TYPE_EFI32_IH 19
#define MULTIBOOT_TAG_TYPE_EFI64_IH 20
#define MULTIBOOT_TAG_TYPE_LOAD_BASE_ADDR 21
#define MULTIBOOT_HEADER_TAG_END 0
#define MULTIBOOT_HEADER_TAG_INFORMATION_REQUEST 1
#define MULTIBOOT_HEADER_TAG_ADDRESS 2
#define MULTIBOOT_HEADER_TAG_ENTRY_ADDRESS 3
#define MULTIBOOT_HEADER_TAG_CONSOLE_FLAGS 4
#define MULTIBOOT_HEADER_TAG_FRAMEBUFFER 5
#define MULTIBOOT_HEADER_TAG_MODULE_ALIGN 6
#define MULTIBOOT_HEADER_TAG_EFI_BS 7
#define MULTIBOOT_HEADER_TAG_ENTRY_ADDRESS_EFI32 8
#define MULTIBOOT_HEADER_TAG_ENTRY_ADDRESS_EFI64 9
#define MULTIBOOT_HEADER_TAG_RELOCATABLE 10
#define MULTIBOOT_ARCHITECTURE_I386 0
#define MULTIBOOT_ARCHITECTURE_MIPS32 4
#define MULTIBOOT_HEADER_TAG_OPTIONAL 1
#define MULTIBOOT_LOAD_PREFERENCE_NONE 0
#define MULTIBOOT_LOAD_PREFERENCE_LOW 1
#define MULTIBOOT_LOAD_PREFERENCE_HIGH 2
#define MULTIBOOT_CONSOLE_FLAGS_CONSOLE_REQUIRED 1
#define MULTIBOOT_CONSOLE_FLAGS_EGA_TEXT_SUPPORTED 2
#ifndef ASM_FILE
typedef unsigned char multiboot_uint8_t;
typedef unsigned short multiboot_uint16_t;
typedef unsigned int multiboot_uint32_t;
typedef unsigned long long multiboot_uint64_t;
struct multiboot_header
{
/* Must be MULTIBOOT_MAGIC - see above. */
multiboot_uint32_t magic;
/* ISA */
multiboot_uint32_t architecture;
/* Total header length. */
multiboot_uint32_t header_length;
/* The above fields plus this one must equal 0 mod 2^32. */
multiboot_uint32_t checksum;
};
struct multiboot_header_tag
{
multiboot_uint16_t type;
multiboot_uint16_t flags;
multiboot_uint32_t size;
};
struct multiboot_header_tag_information_request
{
multiboot_uint16_t type;
multiboot_uint16_t flags;
multiboot_uint32_t size;
multiboot_uint32_t requests[0];
};
struct multiboot_header_tag_address
{
multiboot_uint16_t type;
multiboot_uint16_t flags;
multiboot_uint32_t size;
multiboot_uint32_t header_addr;
multiboot_uint32_t load_addr;
multiboot_uint32_t load_end_addr;
multiboot_uint32_t bss_end_addr;
};
struct multiboot_header_tag_entry_address
{
multiboot_uint16_t type;
multiboot_uint16_t flags;
multiboot_uint32_t size;
multiboot_uint32_t entry_addr;
};
struct multiboot_header_tag_console_flags
{
multiboot_uint16_t type;
multiboot_uint16_t flags;
multiboot_uint32_t size;
multiboot_uint32_t console_flags;
};
struct multiboot_header_tag_framebuffer
{
multiboot_uint16_t type;
multiboot_uint16_t flags;
multiboot_uint32_t size;
multiboot_uint32_t width;
multiboot_uint32_t height;
multiboot_uint32_t depth;
};
struct multiboot_header_tag_module_align
{
multiboot_uint16_t type;
multiboot_uint16_t flags;
multiboot_uint32_t size;
};
struct multiboot_header_tag_relocatable
{
multiboot_uint16_t type;
multiboot_uint16_t flags;
multiboot_uint32_t size;
multiboot_uint32_t min_addr;
multiboot_uint32_t max_addr;
multiboot_uint32_t align;
multiboot_uint32_t preference;
};
struct multiboot_color
{
multiboot_uint8_t red;
multiboot_uint8_t green;
multiboot_uint8_t blue;
};
struct multiboot_mmap_entry
{
multiboot_uint64_t addr;
multiboot_uint64_t len;
#define MULTIBOOT_MEMORY_AVAILABLE 1
#define MULTIBOOT_MEMORY_RESERVED 2
#define MULTIBOOT_MEMORY_ACPI_RECLAIMABLE 3
#define MULTIBOOT_MEMORY_NVS 4
#define MULTIBOOT_MEMORY_BADRAM 5
multiboot_uint32_t type;
multiboot_uint32_t zero;
};
typedef struct multiboot_mmap_entry multiboot_memory_map_t;
struct multiboot_tag
{
multiboot_uint32_t type;
multiboot_uint32_t size;
};
struct multiboot_tag_string
{
multiboot_uint32_t type;
multiboot_uint32_t size;
char string[0];
};
struct multiboot_tag_module
{
multiboot_uint32_t type;
multiboot_uint32_t size;
multiboot_uint32_t mod_start;
multiboot_uint32_t mod_end;
char cmdline[0];
};
struct multiboot_tag_basic_meminfo
{
multiboot_uint32_t type;
multiboot_uint32_t size;
multiboot_uint32_t mem_lower;
multiboot_uint32_t mem_upper;
};
struct multiboot_tag_bootdev
{
multiboot_uint32_t type;
multiboot_uint32_t size;
multiboot_uint32_t biosdev;
multiboot_uint32_t slice;
multiboot_uint32_t part;
};
struct multiboot_tag_mmap
{
multiboot_uint32_t type;
multiboot_uint32_t size;
multiboot_uint32_t entry_size;
multiboot_uint32_t entry_version;
struct multiboot_mmap_entry entries[0];
};
struct multiboot_vbe_info_block
{
multiboot_uint8_t external_specification[512];
};
struct multiboot_vbe_mode_info_block
{
multiboot_uint8_t external_specification[256];
};
struct multiboot_tag_vbe
{
multiboot_uint32_t type;
multiboot_uint32_t size;
multiboot_uint16_t vbe_mode;
multiboot_uint16_t vbe_interface_seg;
multiboot_uint16_t vbe_interface_off;
multiboot_uint16_t vbe_interface_len;
struct multiboot_vbe_info_block vbe_control_info;
struct multiboot_vbe_mode_info_block vbe_mode_info;
};
struct multiboot_tag_framebuffer_common
{
multiboot_uint32_t type;
multiboot_uint32_t size;
multiboot_uint64_t framebuffer_addr;
multiboot_uint32_t framebuffer_pitch;
multiboot_uint32_t framebuffer_width;
multiboot_uint32_t framebuffer_height;
multiboot_uint8_t framebuffer_bpp;
#define MULTIBOOT_FRAMEBUFFER_TYPE_INDEXED 0
#define MULTIBOOT_FRAMEBUFFER_TYPE_RGB 1
#define MULTIBOOT_FRAMEBUFFER_TYPE_EGA_TEXT 2
multiboot_uint8_t framebuffer_type;
multiboot_uint16_t reserved;
};
struct multiboot_tag_framebuffer
{
struct multiboot_tag_framebuffer_common common;
union
{
struct
{
multiboot_uint16_t framebuffer_palette_num_colors;
struct multiboot_color framebuffer_palette[0];
};
struct
{
multiboot_uint8_t framebuffer_red_field_position;
multiboot_uint8_t framebuffer_red_mask_size;
multiboot_uint8_t framebuffer_green_field_position;
multiboot_uint8_t framebuffer_green_mask_size;
multiboot_uint8_t framebuffer_blue_field_position;
multiboot_uint8_t framebuffer_blue_mask_size;
};
};
};
struct multiboot_tag_elf_sections
{
multiboot_uint32_t type;
multiboot_uint32_t size;
multiboot_uint32_t num;
multiboot_uint32_t entsize;
multiboot_uint32_t shndx;
char sections[0];
};
struct multiboot_tag_apm
{
multiboot_uint32_t type;
multiboot_uint32_t size;
multiboot_uint16_t version;
multiboot_uint16_t cseg;
multiboot_uint32_t offset;
multiboot_uint16_t cseg_16;
multiboot_uint16_t dseg;
multiboot_uint16_t flags;
multiboot_uint16_t cseg_len;
multiboot_uint16_t cseg_16_len;
multiboot_uint16_t dseg_len;
};
struct multiboot_tag_efi32
{
multiboot_uint32_t type;
multiboot_uint32_t size;
multiboot_uint32_t pointer;
};
struct multiboot_tag_efi64
{
multiboot_uint32_t type;
multiboot_uint32_t size;
multiboot_uint64_t pointer;
};
struct multiboot_tag_smbios
{
multiboot_uint32_t type;
multiboot_uint32_t size;
multiboot_uint8_t major;
multiboot_uint8_t minor;
multiboot_uint8_t reserved[6];
multiboot_uint8_t tables[0];
};
struct multiboot_tag_old_acpi
{
multiboot_uint32_t type;
multiboot_uint32_t size;
multiboot_uint8_t rsdp[0];
};
struct multiboot_tag_new_acpi
{
multiboot_uint32_t type;
multiboot_uint32_t size;
multiboot_uint8_t rsdp[0];
};
struct multiboot_tag_network
{
multiboot_uint32_t type;
multiboot_uint32_t size;
multiboot_uint8_t dhcpack[0];
};
struct multiboot_tag_efi_mmap
{
multiboot_uint32_t type;
multiboot_uint32_t size;
multiboot_uint32_t descr_size;
multiboot_uint32_t descr_vers;
multiboot_uint8_t efi_mmap[0];
};
struct multiboot_tag_efi32_ih
{
multiboot_uint32_t type;
multiboot_uint32_t size;
multiboot_uint32_t pointer;
};
struct multiboot_tag_efi64_ih
{
multiboot_uint32_t type;
multiboot_uint32_t size;
multiboot_uint64_t pointer;
};
struct multiboot_tag_load_base_addr
{
multiboot_uint32_t type;
multiboot_uint32_t size;
multiboot_uint32_t load_base_addr;
};
#endif /* ! ASM_FILE */
#endif /* ! MULTIBOOT_HEADER */

187
Kernel/include/cargs.h Normal file
View File

@ -0,0 +1,187 @@
/*
MIT License
Copyright (c) 2022 Leonard Iklé
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#pragma once
/**
* This is a simple alternative cross-platform implementation of getopt, which
* is used to parse argument strings submitted to the executable (argc and argv
* which are received in the main function).
*/
#ifndef CAG_LIBRARY_H
#define CAG_LIBRARY_H
#include <types.h>
typedef unsigned int FILE; // TODO: Implement FILE
#if defined(_WIN32) || defined(__CYGWIN__)
#define CAG_EXPORT __declspec(dllexport)
#define CAG_IMPORT __declspec(dllimport)
#elif __GNUC__ >= 4
#define CAG_EXPORT __attribute__((visibility("default")))
#define CAG_IMPORT __attribute__((visibility("default")))
#else
#define CAG_EXPORT
#define CAG_IMPORT
#endif
#if defined(CAG_SHARED)
#if defined(CAG_EXPORTS)
#define CAG_PUBLIC CAG_EXPORT
#else
#define CAG_PUBLIC CAG_IMPORT
#endif
#else
#define CAG_PUBLIC
#endif
#ifdef __cplusplus
extern "C"
{
#endif
/**
* An option is used to describe a flag/argument option submitted when the
* program is run.
*/
typedef struct cag_option
{
const char identifier;
const char *access_letters;
const char *access_name;
const char *value_name;
const char *description;
} cag_option;
/**
* A context is used to iterate over all options provided. It stores the parsing
* state.
*/
typedef struct cag_option_context
{
const struct cag_option *options;
size_t option_count;
int argc;
char **argv;
int index;
int inner_index;
bool forced_end;
char identifier;
char *value;
} cag_option_context;
/**
* This is just a small macro which calculates the size of an array.
*/
#define CAG_ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
/**
* @brief Prints all options to the terminal.
*
* This function prints all options to the terminal. This can be used to
* generate the output for a "--help" option.
*
* @param options The options which will be printed.
* @param option_count The option count which will be printed.
* @param destination The destination where the output will be printed.
*/
CAG_PUBLIC void cag_option_print(const cag_option *options, size_t option_count,
FILE *destination);
/**
* @brief Prepare argument options context for parsing.
*
* This function prepares the context for iteration and initializes the context
* with the supplied options and arguments. After the context has been prepared,
* it can be used to fetch arguments from it.
*
* @param context The context which will be initialized.
* @param options The registered options which are available for the program.
* @param option_count The amount of options which are available for the
* program.
* @param argc The amount of arguments the user supplied in the main function.
* @param argv A pointer to the arguments of the main function.
*/
CAG_PUBLIC void cag_option_prepare(cag_option_context *context,
const cag_option *options, size_t option_count, int argc, char **argv);
/**
* @brief Fetches an option from the argument list.
*
* This function fetches a single option from the argument list. The context
* will be moved to that item. Information can be extracted from the context
* after the item has been fetched.
* The arguments will be re-ordered, which means that non-option arguments will
* be moved to the end of the argument list. After all options have been
* fetched, all non-option arguments will be positioned after the index of
* the context.
*
* @param context The context from which we will fetch the option.
* @return Returns true if there was another option or false if the end is
* reached.
*/
CAG_PUBLIC bool cag_option_fetch(cag_option_context *context);
/**
* @brief Gets the identifier of the option.
*
* This function gets the identifier of the option, which should be unique to
* this option and can be used to determine what kind of option this is.
*
* @param context The context from which the option was fetched.
* @return Returns the identifier of the option.
*/
CAG_PUBLIC char cag_option_get(const cag_option_context *context);
/**
* @brief Gets the value from the option.
*
* This function gets the value from the option, if any. If the option does not
* contain a value, this function will return NULL.
*
* @param context The context from which the option was fetched.
* @return Returns a pointer to the value or NULL if there is no value.
*/
CAG_PUBLIC const char *cag_option_get_value(const cag_option_context *context);
/**
* @brief Gets the current index of the context.
*
* This function gets the index within the argv arguments of the context. The
* context always points to the next item which it will inspect. This is
* particularly useful to inspect the original argument array, or to get
* non-option arguments after option fetching has finished.
*
* @param context The context from which the option was fetched.
* @return Returns the current index of the context.
*/
CAG_PUBLIC int cag_option_get_index(const cag_option_context *context);
#ifdef __cplusplus
} // extern "C"
#endif
#endif

139
Kernel/include/convert.h Normal file
View File

@ -0,0 +1,139 @@
/*
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/>.
*/
#pragma once
#include <types.h>
#include <ctype.h>
#ifdef __cplusplus
extern "C"
{
#endif
typedef struct mbstate_t
{
int count;
unsigned int value;
} mbstate_t;
#define NAN (__builtin_nanf(""))
int isempty(char *str);
unsigned int isdelim(char c, const char *delim);
long abs(long i);
void swap(char *x, char *y);
char *reverse(char *Buffer, int i, int j);
float sqrtf(float x);
double clamp(double x, double low, double high);
float lerp(float a, float b, float t);
float smoothstep(float a, float b, float t);
float cubicInterpolate(float a, float b, float t);
void backspace(char s[]);
void append(char s[], char n);
int atoi(const char *String);
double atof(const char *String);
char *itoa(int Value, char *Buffer, int Base);
char *ltoa(long Value, char *Buffer, int Base);
char *ultoa(unsigned long Value, char *Buffer, int Base);
unsigned long int strtoul(const char *str, char **endptr, int base);
void *memcpy_unsafe(void *dest, const void *src, size_t n);
void *memset_unsafe(void *dest, int c, size_t n);
void *memmove_unsafe(void *dest, const void *src, size_t n);
int memcmp(const void *vl, const void *vr, size_t n);
void *memcpy_sse(void *dest, const void *src, size_t n);
void *memcpy_sse2(void *dest, const void *src, size_t n);
void *memcpy_sse3(void *dest, const void *src, size_t n);
void *memcpy_ssse3(void *dest, const void *src, size_t n);
void *memcpy_sse4_1(void *dest, const void *src, size_t n);
void *memcpy_sse4_2(void *dest, const void *src, size_t n);
void *memset_sse(void *dest, int c, size_t n);
void *memset_sse2(void *dest, int c, size_t n);
void *memset_sse3(void *dest, int c, size_t n);
void *memset_ssse3(void *dest, int c, size_t n);
void *memset_sse4_1(void *dest, int c, size_t n);
void *memset_sse4_2(void *dest, int c, size_t n);
void *memmove_sse(void *dest, const void *src, size_t n);
void *memmove_sse2(void *dest, const void *src, size_t n);
void *memmove_sse3(void *dest, const void *src, size_t n);
void *memmove_ssse3(void *dest, const void *src, size_t n);
void *memmove_sse4_1(void *dest, const void *src, size_t n);
void *memmove_sse4_2(void *dest, const void *src, size_t n);
long unsigned __strlen(const char s[]);
long unsigned strlen_sse(const char s[]);
long unsigned strlen_sse2(const char s[]);
long unsigned strlen_sse3(const char s[]);
long unsigned strlen_ssse3(const char s[]);
long unsigned strlen_sse4_1(const char s[]);
long unsigned strlen_sse4_2(const char s[]);
long unsigned strlen(const char s[]);
int strncmp(const char *s1, const char *s2, unsigned long n);
char *strcat_unsafe(char *destination, const char *source);
char *strcpy_unsafe(char *destination, const char *source);
char *strncpy(char *destination, const char *source, unsigned long num);
int strcmp(const char *l, const char *r);
char *strstr(const char *haystack, const char *needle);
char *strdup(const char *String);
char *strchr(const char *String, int Char);
char *strrchr(const char *String, int Char);
int strncasecmp(const char *string1, const char *string2, size_t count);
int strcasecmp(const char *s1, const char *s2);
char *strtok(char *src, const char *delim);
long int strtol(const char *str, char **endptr, int base);
size_t wcslen(const wchar_t *s);
size_t wcsrtombs(char *dst, const wchar_t **src, size_t len, mbstate_t *ps);
int log2(unsigned int n);
void *__memcpy_chk(void *dest, const void *src, size_t len, size_t slen);
void *__memset_chk(void *dest, int val, size_t len, size_t slen);
void *__memmove_chk(void *dest, const void *src, size_t len, size_t slen);
char *__strcat_chk(char *dest, const char *src, size_t slen);
char *__strcpy_chk(char *dest, const char *src, size_t slen);
#ifdef __cplusplus
}
#endif
#undef memcpy
#define memcpy(dest, src, n) \
__memcpy_chk(dest, src, n, __builtin_object_size(dest, 0))
#undef memset
#define memset(dest, c, n) \
__memset_chk(dest, c, n, __builtin_object_size(dest, 0))
#undef memmove
#define memmove(dest, src, n) \
__memmove_chk(dest, src, n, __builtin_object_size(dest, 0))
#undef strcat
#define strcat(dest, src) \
__strcat_chk(dest, src, __builtin_object_size(dest, 0))
#undef strcpy
#define strcpy(dest, src) \
__strcpy_chk(dest, src, __builtin_object_size(dest, 0))

1084
Kernel/include/cpu.hpp Normal file

File diff suppressed because it is too large Load Diff

View File

View File

@ -0,0 +1,73 @@
/*
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_CPU_MEMBAR_H__
#define __FENNIX_KERNEL_CPU_MEMBAR_H__
#include <types.h>
namespace CPU
{
namespace MemBar
{
nsa static inline void Barrier()
{
#if defined(a86)
asmv("" ::
: "memory");
#elif defined(aa64)
asmv("dmb ish" ::
: "memory");
#endif
}
nsa static inline void Fence()
{
#if defined(a86)
asmv("mfence" ::
: "memory");
#elif defined(aa64)
asmv("dmb ish" ::
: "memory");
#endif
}
nsa static inline void StoreFence()
{
#if defined(a86)
asmv("sfence" ::
: "memory");
#elif defined(aa64)
asmv("dmb ishst" ::
: "memory");
#endif
}
nsa static inline void LoadFence()
{
#if defined(a86)
asmv("lfence" ::
: "memory");
#elif defined(aa64)
asmv("dmb ishld" ::
: "memory");
#endif
}
}
}
#endif // !__FENNIX_KERNEL_CPU_MEMBAR_H__

View File

@ -0,0 +1,108 @@
/*
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_CPU_SIGNATURES_H__
#define __FENNIX_KERNEL_CPU_SIGNATURES_H__
#include <types.h>
#define x86_CPUID_VENDOR_OLDAMD "AMDisbetter!" /* Early engineering samples of AMD K5 processor */
#define x86_CPUID_VENDOR_AMD "AuthenticAMD"
#define x86_CPUID_VENDOR_INTEL "GenuineIntel"
#define x86_CPUID_VENDOR_VIA "CentaurHauls"
#define x86_CPUID_VENDOR_OLDTRANSMETA "TransmetaCPU"
#define x86_CPUID_VENDOR_TRANSMETA "GenuineTMx86"
#define x86_CPUID_VENDOR_CYRIX "CyrixInstead"
#define x86_CPUID_VENDOR_CENTAUR "CentaurHauls"
#define x86_CPUID_VENDOR_NEXGEN "NexGenDriven"
#define x86_CPUID_VENDOR_UMC "UMC UMC UMC "
#define x86_CPUID_VENDOR_SIS "SiS SiS SiS "
#define x86_CPUID_VENDOR_NSC "Geode by NSC"
#define x86_CPUID_VENDOR_RISE "RiseRiseRise"
#define x86_CPUID_VENDOR_VORTEX "Vortex86 SoC"
#define x86_CPUID_VENDOR_VIA2 "VIA VIA VIA "
#define x86_CPUID_VENDOR_HYGON "HygonGenuine"
#define x86_CPUID_VENDOR_E2K "E2K MACHINE"
#define x86_CPUID_VENDOR_MISTER "MiSTer AO486"
/* Vendor-strings from Virtual Machines. */
#define x86_CPUID_VENDOR_VMWARE "VMwareVMware"
#define x86_CPUID_VENDOR_XENHVM "XenVMMXenVMM"
#define x86_CPUID_VENDOR_MICROSOFT_HV "Microsoft Hv"
#define x86_CPUID_VENDOR_MICROSOFT_XTA "MicrosoftXTA"
#define x86_CPUID_VENDOR_PARALLELS " lrpepyh vr"
#define x86_CPUID_VENDOR_KVM "KVMKVMKVM"
#define x86_CPUID_VENDOR_VIRTUALBOX "VBoxVBoxVBox"
#define x86_CPUID_VENDOR_TCG "TCGTCGTCGTCG"
#define x86_CPUID_VENDOR_BHYVE "bhyve bhyve "
#define x86_CPUID_VENDOR_ACRN "ACRNACRNACRN"
#define x86_CPUID_VENDOR_QNX "QNXQVMBSQG"
#define x86_CPUID_VENDOR_APPLE "VirtualApple"
#define x86_CPUID_SIGNATURE_INTEL_b 0x756e6547
#define x86_CPUID_SIGNATURE_INTEL_c 0x6c65746e
#define x86_CPUID_SIGNATURE_INTEL_d 0x49656e69
#define x86_CPUID_SIGNATURE_AMD_b 0x68747541
#define x86_CPUID_SIGNATURE_AMD_c 0x444d4163
#define x86_CPUID_SIGNATURE_AMD_d 0x69746e65
#define x86_CPUID_SIGNATURE_CENTAUR_b 0x746e6543
#define x86_CPUID_SIGNATURE_CENTAUR_c 0x736c7561
#define x86_CPUID_SIGNATURE_CENTAUR_d 0x48727561
#define x86_CPUID_SIGNATURE_CYRIX_b 0x69727943
#define x86_CPUID_SIGNATURE_CYRIX_c 0x64616574
#define x86_CPUID_SIGNATURE_CYRIX_d 0x736e4978
#define x86_CPUID_SIGNATURE_TM1_b 0x6e617254
#define x86_CPUID_SIGNATURE_TM1_c 0x55504361
#define x86_CPUID_SIGNATURE_TM1_d 0x74656d73
#define x86_CPUID_SIGNATURE_TM2_b 0x756e6547
#define x86_CPUID_SIGNATURE_TM2_c 0x3638784d
#define x86_CPUID_SIGNATURE_TM2_d 0x54656e69
#define x86_CPUID_SIGNATURE_NSC_b 0x646f6547
#define x86_CPUID_SIGNATURE_NSC_c 0x43534e20
#define x86_CPUID_SIGNATURE_NSC_d 0x79622065
#define x86_CPUID_SIGNATURE_NEXGEN_b 0x4778654e
#define x86_CPUID_SIGNATURE_NEXGEN_c 0x6e657669
#define x86_CPUID_SIGNATURE_NEXGEN_d 0x72446e65
#define x86_CPUID_SIGNATURE_RISE_b 0x65736952
#define x86_CPUID_SIGNATURE_RISE_c 0x65736952
#define x86_CPUID_SIGNATURE_RISE_d 0x65736952
#define x86_CPUID_SIGNATURE_SIS_b 0x20536953
#define x86_CPUID_SIGNATURE_SIS_c 0x20536953
#define x86_CPUID_SIGNATURE_SIS_d 0x20536953
#define x86_CPUID_SIGNATURE_UMC_b 0x20434d55
#define x86_CPUID_SIGNATURE_UMC_c 0x20434d55
#define x86_CPUID_SIGNATURE_UMC_d 0x20434d55
#define x86_CPUID_SIGNATURE_VIA_b 0x20414956
#define x86_CPUID_SIGNATURE_VIA_c 0x20414956
#define x86_CPUID_SIGNATURE_VIA_d 0x20414956
#define x86_CPUID_SIGNATURE_VORTEX_b 0x74726f56
#define x86_CPUID_SIGNATURE_VORTEX_c 0x436f5320
#define x86_CPUID_SIGNATURE_VORTEX_d 0x36387865
#endif // !__FENNIX_KERNEL_CPU_SIGNATURES_H__

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,54 @@
/*
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_CPU_x86_EXCEPTIONS_H__
#define __FENNIX_KERNEL_CPU_x86_EXCEPTIONS_H__
#include <types.h>
namespace CPU
{
namespace x86
{
enum ISRExceptions
{
DivideByZero = 0x0,
Debug = 0x1,
NonMaskableInterrupt = 0x2,
Breakpoint = 0x3,
Overflow = 0x4,
BoundRange = 0x5,
InvalidOpcode = 0x6,
DeviceNotAvailable = 0x7,
DoubleFault = 0x8,
CoprocessorSegmentOverrun = 0x9,
InvalidTSS = 0xa,
SegmentNotPresent = 0xb,
StackSegmentFault = 0xc,
GeneralProtectionFault = 0xd,
PageFault = 0xe,
x87FloatingPoint = 0x10,
AlignmentCheck = 0x11,
MachineCheck = 0x12,
SIMDFloatingPoint = 0x13,
Virtualization = 0x14,
Security = 0x1e
};
}
}
#endif // !__FENNIX_KERNEL_CPU_x86_EXCEPTIONS_H__

View File

@ -0,0 +1,80 @@
/*
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_CPU_x86_CPUID_HYPERVISOR_H__
#define __FENNIX_KERNEL_CPU_x86_CPUID_HYPERVISOR_H__
#include <types.h>
namespace CPU
{
namespace x86
{
/** @brief EXPERIMENTAL IMPLEMENTATION */
namespace Hypervisor
{
/** @brief Get CPU hypervisor information */
struct CPUID0x40000000
{
union
{
struct
{
/**
* @brief Maximum input value for hypervisor CPUID information.
* @note Can be from 0x40000001 to 0x400000FF
*/
uint64_t MaximumInputValue : 32;
};
uint64_t raw;
} EAX;
union
{
struct
{
/** @brief Hypervisor vendor signature */
char Hypervisor[4];
};
uint64_t raw;
} EBX;
union
{
struct
{
/** @brief Hypervisor vendor signature */
char Hypervisor[4];
};
uint64_t raw;
} ECX;
union
{
struct
{
/** @brief Hypervisor vendor signature */
char Hypervisor[4];
};
uint64_t raw;
} EDX;
};
}
}
}
#endif // !__FENNIX_KERNEL_CPU_x86_CPUID_HYPERVISOR_H__

View File

@ -0,0 +1,300 @@
/*
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_CPU_x86_INTERRUPTS_H__
#define __FENNIX_KERNEL_CPU_x86_INTERRUPTS_H__
#include <types.h>
namespace CPU
{
namespace x86
{
enum CPUInterrupts
{
/* ISR */
ISR0 = 0x0, /* Divide-by-zero Error */
ISR1 = 0x1, /* Debug */
ISR2 = 0x2, /* Non-maskable Interrupt */
ISR3 = 0x3, /* Breakpoint */
ISR4 = 0x4, /* Overflow */
ISR5 = 0x5, /* Bound Range Exceeded */
ISR6 = 0x6, /* Invalid Opcode */
ISR7 = 0x7, /* Device Not Available */
ISR8 = 0x8, /* Double Fault */
ISR9 = 0x9, /* Coprocessor Segment Overrun */
ISR10 = 0xa, /* Invalid TSS */
ISR11 = 0xb, /* Segment Not P */
ISR12 = 0xc, /* Stack-Segment Fault */
ISR13 = 0xd, /* General Protection Fault */
ISR14 = 0xe, /* Page Fault */
ISR15 = 0xf, /* Reserved */
ISR16 = 0x10, /* x87 Floating-Point Exception */
ISR17 = 0x11, /* Alignment Check */
ISR18 = 0x12, /* Machine Check */
ISR19 = 0x13, /* SIMD Floating-Point Exception */
ISR20 = 0x14, /* Virtualization Exception */
ISR21 = 0x15, /* Reserved */
ISR22 = 0x16, /* Reserved */
ISR23 = 0x17, /* Reserved */
ISR24 = 0x18, /* Reserved */
ISR25 = 0x19, /* Reserved */
ISR26 = 0x1a, /* Reserved */
ISR27 = 0x1b, /* Reserved */
ISR28 = 0x1c, /* Reserved */
ISR29 = 0x1d, /* Reserved */
ISR30 = 0x1e, /* Security Exception */
ISR31 = 0x1f, /* Reserved */
/* IRQ */
IRQ0 = 0x20, /* Programmable Interrupt Timer Interrupt */
IRQ1 = 0x21, /* Keyboard Interrupt */
IRQ2 = 0x22, /* Cascade (used internally by the two PICs. never raised) */
IRQ3 = 0x23, /* COM2/COM4 (if enabled) */
IRQ4 = 0x24, /* COM1/COM3 (if enabled) */
IRQ5 = 0x25, /* LPT2 (if enabled) */
IRQ6 = 0x26, /* Floppy Disk */
IRQ7 = 0x27, /* LPT1 / Unreliable "spurious" interrupt (usually) */
IRQ8 = 0x28, /* CMOS real-time clock (if enabled) */
IRQ9 = 0x29, /* Free for peripherals / legacy SCSI / NIC */
IRQ10 = 0x2a, /* Free for peripherals / SCSI / NIC */
IRQ11 = 0x2b, /* Free for peripherals / SCSI / NIC */
IRQ12 = 0x2c, /* PS2 Mouse */
IRQ13 = 0x2d, /* FPU / Coprocessor / Inter-processor */
IRQ14 = 0x2e, /* Primary ATA Hard Disk */
IRQ15 = 0x2f, /* Secondary ATA Hard Disk */
/* Reserved by OS */
IRQ16 = 0x30, /* Reserved for multitasking */
IRQ17 = 0x31,
IRQ18 = 0x32,
IRQ19 = 0x33,
IRQ20 = 0x34,
IRQ21 = 0x35,
IRQ22 = 0x36,
IRQ23 = 0x37,
IRQ24 = 0x38,
IRQ25 = 0x39,
IRQ26 = 0x3a,
IRQ27 = 0x3b,
IRQ28 = 0x3c,
IRQ29 = 0x3d,
IRQ30 = 0x3e,
IRQ31 = 0x3f, /* Halt core interrupt */
/* Free */
IRQ32 = 0x40,
IRQ33 = 0x41,
IRQ34 = 0x42,
IRQ35 = 0x43,
IRQ36 = 0x44,
IRQ37 = 0x45,
IRQ38 = 0x46,
IRQ39 = 0x47,
IRQ40 = 0x48,
IRQ41 = 0x49,
IRQ42 = 0x4a,
IRQ43 = 0x4b,
IRQ44 = 0x4c,
IRQ45 = 0x4d,
IRQ46 = 0x4e,
IRQ47 = 0x4f,
IRQ48 = 0x50,
IRQ49 = 0x51,
IRQ50 = 0x52,
IRQ51 = 0x53,
IRQ52 = 0x54,
IRQ53 = 0x55,
IRQ54 = 0x56,
IRQ55 = 0x57,
IRQ56 = 0x58,
IRQ57 = 0x59,
IRQ58 = 0x5a,
IRQ59 = 0x5b,
IRQ60 = 0x5c,
IRQ61 = 0x5d,
IRQ62 = 0x5e,
IRQ63 = 0x5f,
IRQ64 = 0x60,
IRQ65 = 0x61,
IRQ66 = 0x62,
IRQ67 = 0x63,
IRQ68 = 0x64,
IRQ69 = 0x65,
IRQ70 = 0x66,
IRQ71 = 0x67,
IRQ72 = 0x68,
IRQ73 = 0x69,
IRQ74 = 0x6a,
IRQ75 = 0x6b,
IRQ76 = 0x6c,
IRQ77 = 0x6d,
IRQ78 = 0x6e,
IRQ79 = 0x6f,
IRQ80 = 0x70,
IRQ81 = 0x71,
IRQ82 = 0x72,
IRQ83 = 0x73,
IRQ84 = 0x74,
IRQ85 = 0x75,
IRQ86 = 0x76,
IRQ87 = 0x77,
IRQ88 = 0x78,
IRQ89 = 0x79,
IRQ90 = 0x7a,
IRQ91 = 0x7b,
IRQ92 = 0x7c,
IRQ93 = 0x7d,
IRQ94 = 0x7e,
IRQ95 = 0x7f,
IRQ96 = 0x80,
IRQ97 = 0x81,
IRQ98 = 0x82,
IRQ99 = 0x83,
IRQ100 = 0x84,
IRQ101 = 0x85,
IRQ102 = 0x86,
IRQ103 = 0x87,
IRQ104 = 0x88,
IRQ105 = 0x89,
IRQ106 = 0x8a,
IRQ107 = 0x8b,
IRQ108 = 0x8c,
IRQ109 = 0x8d,
IRQ110 = 0x8e,
IRQ111 = 0x8f,
IRQ112 = 0x90,
IRQ113 = 0x91,
IRQ114 = 0x92,
IRQ115 = 0x93,
IRQ116 = 0x94,
IRQ117 = 0x95,
IRQ118 = 0x96,
IRQ119 = 0x97,
IRQ120 = 0x98,
IRQ121 = 0x99,
IRQ122 = 0x9a,
IRQ123 = 0x9b,
IRQ124 = 0x9c,
IRQ125 = 0x9d,
IRQ126 = 0x9e,
IRQ127 = 0x9f,
IRQ128 = 0xa0,
IRQ129 = 0xa1,
IRQ130 = 0xa2,
IRQ131 = 0xa3,
IRQ132 = 0xa4,
IRQ133 = 0xa5,
IRQ134 = 0xa6,
IRQ135 = 0xa7,
IRQ136 = 0xa8,
IRQ137 = 0xa9,
IRQ138 = 0xaa,
IRQ139 = 0xab,
IRQ140 = 0xac,
IRQ141 = 0xad,
IRQ142 = 0xae,
IRQ143 = 0xaf,
IRQ144 = 0xb0,
IRQ145 = 0xb1,
IRQ146 = 0xb2,
IRQ147 = 0xb3,
IRQ148 = 0xb4,
IRQ149 = 0xb5,
IRQ150 = 0xb6,
IRQ151 = 0xb7,
IRQ152 = 0xb8,
IRQ153 = 0xb9,
IRQ154 = 0xba,
IRQ155 = 0xbb,
IRQ156 = 0xbc,
IRQ157 = 0xbd,
IRQ158 = 0xbe,
IRQ159 = 0xbf,
IRQ160 = 0xc0,
IRQ161 = 0xc1,
IRQ162 = 0xc2,
IRQ163 = 0xc3,
IRQ164 = 0xc4,
IRQ165 = 0xc5,
IRQ166 = 0xc6,
IRQ167 = 0xc7,
IRQ168 = 0xc8,
IRQ169 = 0xc9,
IRQ170 = 0xca,
IRQ171 = 0xcb,
IRQ172 = 0xcc,
IRQ173 = 0xcd,
IRQ174 = 0xce,
IRQ175 = 0xcf,
IRQ176 = 0xd0,
IRQ177 = 0xd1,
IRQ178 = 0xd2,
IRQ179 = 0xd3,
IRQ180 = 0xd4,
IRQ181 = 0xd5,
IRQ182 = 0xd6,
IRQ183 = 0xd7,
IRQ184 = 0xd8,
IRQ185 = 0xd9,
IRQ186 = 0xda,
IRQ187 = 0xdb,
IRQ188 = 0xdc,
IRQ189 = 0xdd,
IRQ190 = 0xde,
IRQ191 = 0xdf,
IRQ192 = 0xe0,
IRQ193 = 0xe1,
IRQ194 = 0xe2,
IRQ195 = 0xe3,
IRQ196 = 0xe4,
IRQ197 = 0xe5,
IRQ198 = 0xe6,
IRQ199 = 0xe7,
IRQ200 = 0xe8,
IRQ201 = 0xe9,
IRQ202 = 0xea,
IRQ203 = 0xeb,
IRQ204 = 0xec,
IRQ205 = 0xed,
IRQ206 = 0xee,
IRQ207 = 0xef,
IRQ208 = 0xf0,
IRQ209 = 0xf1,
IRQ210 = 0xf2,
IRQ211 = 0xf3,
IRQ212 = 0xf4,
IRQ213 = 0xf5,
IRQ214 = 0xf6,
IRQ215 = 0xf7,
IRQ216 = 0xf8,
IRQ217 = 0xf9,
IRQ218 = 0xfa,
IRQ219 = 0xfb,
IRQ220 = 0xfc,
IRQ221 = 0xfd,
IRQ222 = 0xfe,
IRQ223 = 0xff,
};
}
}
#endif // !__FENNIX_KERNEL_CPU_x86_INTERRUPTS_H__

View File

@ -0,0 +1,228 @@
/*
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_CPU_x32_CR_H__
#define __FENNIX_KERNEL_CPU_x32_CR_H__
#include <types.h>
namespace CPU
{
namespace x32
{
typedef union CR0
{
struct
{
/** Protection Enable */
uint32_t PE : 1;
/** Monitor Coprocessor */
uint32_t MP : 1;
/** Emulation */
uint32_t EM : 1;
/** Task Switched */
uint32_t TS : 1;
/** Extension Type */
uint32_t ET : 1;
/** Numeric Error */
uint32_t NE : 1;
/** Reserved */
uint32_t Reserved0 : 10;
/** Write Protect */
uint32_t WP : 1;
/** Reserved */
uint32_t Reserved1 : 1;
/** Alignment Mask */
uint32_t AM : 1;
/** Reserved */
uint32_t Reserved2 : 10;
/** Not Write-through */
uint32_t NW : 1;
/** Cache Disable */
uint32_t CD : 1;
/** Paging */
uint32_t PG : 1;
};
uint32_t raw;
} CR0;
typedef union CR2
{
struct
{
/** Page Fault Linear Address */
uint32_t PFLA;
};
uint32_t raw;
} CR2;
typedef union CR3
{
struct
{
/** Not used if bit 17 of CR4 is 1 */
uint32_t PWT : 1;
/** Not used if bit 17 of CR4 is 1 */
uint32_t PCD : 1;
/** Base of PML4T/PML5T */
uint32_t PDBR;
};
uint32_t raw;
} CR3;
typedef union CR4
{
struct
{
/** Virtual-8086 Mode Extensions */
uint32_t VME : 1;
/** Protected-Mode Virtual Interrupts */
uint32_t PVI : 1;
/** Time Stamp Disable */
uint32_t TSD : 1;
/** Debugging Extensions */
uint32_t DE : 1;
/** Page Size Extensions */
uint32_t PSE : 1;
/** Physical Address Extension */
uint32_t PAE : 1;
/** Machine Check Enable */
uint32_t MCE : 1;
/** Page Global Enable */
uint32_t PGE : 1;
/** Performance Monitoring Counter */
uint32_t PCE : 1;
/** Operating System Support */
uint32_t OSFXSR : 1;
/** Operating System Support */
uint32_t OSXMMEXCPT : 1;
/** User-Mode Instruction Prevention */
uint32_t UMIP : 1;
/** Linear Address 57bit */
uint32_t LA57 : 1;
/** VMX Enable */
uint32_t VMXE : 1;
/** SMX Enable */
uint32_t SMXE : 1;
/** Reserved */
uint32_t Reserved0 : 1;
/** FSGSBASE Enable */
uint32_t FSGSBASE : 1;
/** PCID Enable */
uint32_t PCIDE : 1;
/** XSAVE and Processor Extended States Enable */
uint32_t OSXSAVE : 1;
/** Reserved */
uint32_t Reserved1 : 1;
/** SMEP Enable */
uint32_t SMEP : 1;
/** SMAP Enable */
uint32_t SMAP : 1;
/** Protection-Key Enable */
uint32_t PKE : 1;
/** Control-flow Enforcement Technology*/
uint32_t CET : 1;
/* Enable Protection Keys for Supervisor Mode Pages */
uint32_t PKS : 1;
};
uint32_t raw;
} CR4;
#if defined(a32)
nsa static inline CR0 readcr0()
{
uint32_t Result = 0;
asmv("mov %%cr0, %[Result]"
: [Result] "=q"(Result));
return (CR0){.raw = Result};
}
nsa static inline CR2 readcr2()
{
uint32_t Result = 0;
asmv("mov %%cr2, %[Result]"
: [Result] "=q"(Result));
return (CR2){.raw = Result};
}
nsa static inline CR3 readcr3()
{
uint32_t Result = 0;
asmv("mov %%cr3, %[Result]"
: [Result] "=q"(Result));
return (CR3){.raw = Result};
}
nsa static inline CR4 readcr4()
{
uint32_t Result = 0;
asmv("mov %%cr4, %[Result]"
: [Result] "=q"(Result));
return (CR4){.raw = Result};
}
nsa static inline CR8 readcr8()
{
uint32_t Result = 0;
asmv("mov %%cr8, %[Result]"
: [Result] "=q"(Result));
return (CR8){.raw = Result};
}
nsa static inline void writecr0(CR0 ControlRegister)
{
asmv("mov %[ControlRegister], %%cr0"
:
: [ControlRegister] "q"(ControlRegister.raw)
: "memory");
}
nsa static inline void writecr2(CR2 ControlRegister)
{
asmv("mov %[ControlRegister], %%cr2"
:
: [ControlRegister] "q"(ControlRegister.raw)
: "memory");
}
nsa static inline void writecr3(CR3 ControlRegister)
{
asmv("mov %[ControlRegister], %%cr3"
:
: [ControlRegister] "q"(ControlRegister.raw)
: "memory");
}
nsa static inline void writecr4(CR4 ControlRegister)
{
asmv("mov %[ControlRegister], %%cr4"
:
: [ControlRegister] "q"(ControlRegister.raw)
: "memory");
}
nsa static inline void writecr8(CR8 ControlRegister)
{
asmv("mov %[ControlRegister], %%cr8"
:
: [ControlRegister] "q"(ControlRegister.raw)
: "memory");
}
#endif
}
}
#endif // !__FENNIX_KERNEL_CPU_x32_CR_H__

View File

@ -0,0 +1,426 @@
/*
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_CPU_x32_MSR_H__
#define __FENNIX_KERNEL_CPU_x32_MSR_H__
#include <types.h>
namespace CPU
{
namespace x32
{
enum MSRID
{
MSR_MONITOR_FILTER_SIZE = 0x6,
MSR_TIME_STAMP_COUNTER = 0x10,
MSR_PLATFORM_ID = 0x17,
MSR_APIC_BASE = 0x1B,
MSR_FEATURE_CONTROL = 0x3A,
MSR_TSC_ADJUST = 0x3B,
MSR_SPEC_CTRL = 0x48,
MSR_PRED_CMD = 0x49,
MSR_BIOS_UPDT_TRIG = 0x79,
MSR_BIOS_SIGN_ID = 0x8B,
MSR_SGXLEPUBKEYHASH0 = 0x8C,
MSR_SGXLEPUBKEYHASH1 = 0x8D,
MSR_SGXLEPUBKEYHASH2 = 0x8E,
MSR_SGXLEPUBKEYHASH3 = 0x8F,
MSR_SMM_MONITOR_CTL = 0x9B,
MSR_SMBASE = 0x9E,
MSR_PMC0 = 0xC1,
MSR_PMC1 = 0xC2,
MSR_PMC2 = 0xC3,
MSR_PMC3 = 0xC4,
MSR_PMC4 = 0xC5,
MSR_PMC5 = 0xC6,
MSR_PMC6 = 0xC7,
MSR_PMC7 = 0xC8,
MSR_UMWAIT_CONTROL = 0xE1,
MSR_MPERF = 0xE7,
MSR_APERF = 0xE8,
MSR_MTRRCAP = 0xFE,
MSR_ARCH_CAPABILITIES = 0x10A,
MSR_FLUSH_CMD = 0x10B,
MSR_SYSENTER_CS = 0x17A,
MSR_SYSENTER_ESP = 0x175,
MSR_SYSENTER_EIP = 0x176,
MSR_MCG_CAP = 0x179,
MSR_MCG_STATUS = 0x17A,
MSR_MCG_CTL = 0x17B,
MSR_PERFEVTSEL0 = 0x186,
MSR_PERFEVTSEL1 = 0x187,
MSR_PERFEVTSEL2 = 0x188,
MSR_PERFEVTSEL3 = 0x189,
MSR_PERF_STATUS = 0x198,
MSR_PERF_CTL = 0x199,
MSR_CLOCK_MODULATION = 0x19A,
MSR_THERM_INTERRUPT = 0x19B,
MSR_THERM_STATUS = 0x19C,
MSR_MISC_ENABLE = 0x1A0,
MSR_ENERGY_PERF_BIAS = 0x1B0,
MSR_PACKAGE_THERM_STATUS = 0x1B1,
MSR_PACKAGE_THERM_INTERRUPT = 0x1B2,
MSR_DEBUGCTL = 0x1D9,
MSR_SMRR_PHYSBASE = 0x1F2,
MSR_SMRR_PHYSMASK = 0x1F3,
MSR_PLATFORM_DCA_CAP = 0x1F8,
MSR_CPU_DCA_CAP = 0x1F9,
MSR_DCA_0_CAP = 0x1FA,
MSR_MTRR_PHYSBASE0 = 0x200,
MSR_MTRR_PHYSMASK0 = 0x201,
MSR_MTRR_PHYSBASE1 = 0x202,
MSR_MTRR_PHYSMASK1 = 0x203,
MSR_MTRR_PHYSBASE2 = 0x204,
MSR_MTRR_PHYSMASK2 = 0x205,
MSR_MTRR_PHYSBASE3 = 0x206,
MSR_MTRR_PHYSMASK3 = 0x207,
MSR_MTRR_PHYSBASE4 = 0x208,
MSR_MTRR_PHYSMASK4 = 0x209,
MSR_MTRR_PHYSBASE5 = 0x20A,
MSR_MTRR_PHYSMASK5 = 0x20B,
MSR_MTRR_PHYSBASE6 = 0x20C,
MSR_MTRR_PHYSMASK6 = 0x20D,
MSR_MTRR_PHYSBASE7 = 0x20E,
MSR_MTRR_PHYSMASK7 = 0x20F,
MSR_MTRR_PHYSBASE8 = 0x210,
MSR_MTRR_PHYSMASK8 = 0x211,
MSR_MTRR_PHYSBASE9 = 0x212,
MSR_MTRR_PHYSMASK9 = 0x213,
MSR_MTRR_FIX64K_00000 = 0x250,
MSR_MTRR_FIX16K_80000 = 0x258,
MSR_MTRR_FIX16K_A0000 = 0x259,
MSR_MTRR_FIX4K_C0000 = 0x268,
MSR_MTRR_FIX4K_C8000 = 0x269,
MSR_MTRR_FIX4K_D0000 = 0x26A,
MSR_MTRR_FIX4K_D8000 = 0x26B,
MSR_MTRR_FIX4K_E0000 = 0x26C,
MSR_MTRR_FIX4K_E8000 = 0x26D,
MSR_MTRR_FIX4K_F0000 = 0x26E,
MSR_MTRR_FIX4K_F8000 = 0x26F,
MSR_PAT = 0x277,
MSR_MC0_CTL2 = 0x280,
MSR_MC1_CTL2 = 0x281,
MSR_MC2_CTL2 = 0x282,
MSR_MC3_CTL2 = 0x283,
MSR_MC4_CTL2 = 0x284,
MSR_MC5_CTL2 = 0x285,
MSR_MC6_CTL2 = 0x286,
MSR_MC7_CTL2 = 0x287,
MSR_MC8_CTL2 = 0x288,
MSR_MC9_CTL2 = 0x289,
MSR_MC10_CTL2 = 0x28A,
MSR_MC11_CTL2 = 0x28B,
MSR_MC12_CTL2 = 0x28C,
MSR_MC13_CTL2 = 0x28D,
MSR_MC14_CTL2 = 0x28E,
MSR_MC15_CTL2 = 0x28F,
MSR_MC16_CTL2 = 0x290,
MSR_MC17_CTL2 = 0x291,
MSR_MC18_CTL2 = 0x292,
MSR_MC19_CTL2 = 0x293,
MSR_MC20_CTL2 = 0x294,
MSR_MC21_CTL2 = 0x295,
MSR_MC22_CTL2 = 0x296,
MSR_MC23_CTL2 = 0x297,
MSR_MC24_CTL2 = 0x298,
MSR_MC25_CTL2 = 0x299,
MSR_MC26_CTL2 = 0x29A,
MSR_MC27_CTL2 = 0x29B,
MSR_MC28_CTL2 = 0x29C,
MSR_MC29_CTL2 = 0x29D,
MSR_MC30_CTL2 = 0x29E,
MSR_MC31_CTL2 = 0x29F,
MSR_MTRR_DEF_TYPE = 0x2FF,
MSR_FIXED_CTR0 = 0x309,
MSR_FIXED_CTR1 = 0x30A,
MSR_FIXED_CTR2 = 0x30B,
MSR_PERF_CAPABILITIES = 0x345,
MSR_FIXED_CTR_CTRL = 0x38D,
MSR_PERF_GLOBAL_STATUS = 0x38E,
MSR_PERF_GLOBAL_CTRL = 0x38F,
MSR_PERF_GLOBAL_STATUS_RESET = 0x390,
MSR_PERF_GLOBAL_STATUS_SET = 0x391,
MSR_PERF_GLOBAL_INUSE = 0x392,
MSR_PEBS_ENABLE = 0x3F1,
MSR_MC0_CTL = 0x400,
MSR_MC0_STATUS = 0x401,
MSR_MC0_ADDR = 0x402,
MSR_MC0_MISC = 0x403,
MSR_MC1_CTL = 0x404,
MSR_MC1_STATUS = 0x405,
MSR_MC1_ADDR = 0x406,
MSR_MC1_MISC = 0x407,
MSR_MC2_CTL = 0x408,
MSR_MC2_STATUS = 0x409,
MSR_MC2_ADDR = 0x40A,
MSR_MC2_MISC = 0x40B,
MSR_MC3_CTL = 0x40C,
MSR_MC3_STATUS = 0x40D,
MSR_MC3_ADDR = 0x40E,
MSR_MC3_MISC = 0x40F,
MSR_MC4_CTL = 0x410,
MSR_MC4_STATUS = 0x411,
MSR_MC4_ADDR = 0x412,
MSR_MC4_MISC = 0x413,
MSR_MC5_CTL = 0x414,
MSR_MC5_STATUS = 0x415,
MSR_MC5_ADDR = 0x416,
MSR_MC5_MISC = 0x417,
MSR_MC6_CTL = 0x418,
MSR_MC6_STATUS = 0x419,
MSR_MC6_ADDR = 0x41A,
MSR_MC6_MISC = 0x41B,
MSR_MC7_CTL = 0x41C,
MSR_MC7_STATUS = 0x41D,
MSR_MC7_ADDR = 0x41E,
MSR_MC7_MISC = 0x41F,
MSR_MC8_CTL = 0x420,
MSR_MC8_STATUS = 0x421,
MSR_MC8_ADDR = 0x422,
MSR_MC8_MISC = 0x423,
MSR_MC9_CTL = 0x424,
MSR_MC9_STATUS = 0x425,
MSR_MC9_ADDR = 0x426,
MSR_MC9_MISC = 0x427,
MSR_MC10_CTL = 0x428,
MSR_MC10_STATUS = 0x429,
MSR_MC10_ADDR = 0x42A,
MSR_MC10_MISC = 0x42B,
MSR_MC11_CTL = 0x42C,
MSR_MC11_STATUS = 0x42D,
MSR_MC11_ADDR = 0x42E,
MSR_MC11_MISC = 0x42F,
MSR_MC12_CTL = 0x430,
MSR_MC12_STATUS = 0x431,
MSR_MC12_ADDR = 0x432,
MSR_MC12_MISC = 0x433,
MSR_MC13_CTL = 0x434,
MSR_MC13_STATUS = 0x435,
MSR_MC13_ADDR = 0x436,
MSR_MC13_MISC = 0x437,
MSR_MC14_CTL = 0x438,
MSR_MC14_STATUS = 0x439,
MSR_MC14_ADDR = 0x43A,
MSR_MC14_MISC = 0x43B,
MSR_MC15_CTL = 0x43C,
MSR_MC15_STATUS = 0x43D,
MSR_MC15_ADDR = 0x43E,
MSR_MC15_MISC = 0x43F,
MSR_MC16_CTL = 0x440,
MSR_MC16_STATUS = 0x441,
MSR_MC16_ADDR = 0x442,
MSR_MC16_MISC = 0x443,
MSR_MC17_CTL = 0x444,
MSR_MC17_STATUS = 0x445,
MSR_MC17_ADDR = 0x446,
MSR_MC17_MISC = 0x447,
MSR_MC18_CTL = 0x448,
MSR_MC18_STATUS = 0x449,
MSR_MC18_ADDR = 0x44A,
MSR_MC18_MISC = 0x44B,
MSR_MC19_CTL = 0x44C,
MSR_MC19_STATUS = 0x44D,
MSR_MC19_ADDR = 0x44E,
MSR_MC19_MISC = 0x44F,
MSR_MC20_CTL = 0x450,
MSR_MC20_STATUS = 0x451,
MSR_MC20_ADDR = 0x452,
MSR_MC20_MISC = 0x453,
MSR_MC21_CTL = 0x454,
MSR_MC21_STATUS = 0x455,
MSR_MC21_ADDR = 0x456,
MSR_MC21_MISC = 0x457,
MSR_MC22_CTL = 0x458,
MSR_MC22_STATUS = 0x459,
MSR_MC22_ADDR = 0x45A,
MSR_MC22_MISC = 0x45B,
MSR_MC23_CTL = 0x45C,
MSR_MC23_STATUS = 0x45D,
MSR_MC23_ADDR = 0x45E,
MSR_MC23_MISC = 0x45F,
MSR_MC24_CTL = 0x460,
MSR_MC24_STATUS = 0x461,
MSR_MC24_ADDR = 0x462,
MSR_MC24_MISC = 0x463,
MSR_MC25_CTL = 0x464,
MSR_MC25_STATUS = 0x465,
MSR_MC25_ADDR = 0x466,
MSR_MC25_MISC = 0x467,
MSR_MC26_CTL = 0x468,
MSR_MC26_STATUS = 0x469,
MSR_MC26_ADDR = 0x46A,
MSR_MC26_MISC = 0x46B,
MSR_MC27_CTL = 0x46C,
MSR_MC27_STATUS = 0x46D,
MSR_MC27_ADDR = 0x46E,
MSR_MC27_MISC = 0x46F,
MSR_MC28_CTL = 0x470,
MSR_MC28_STATUS = 0x471,
MSR_MC28_ADDR = 0x472,
MSR_MC28_MISC = 0x473,
MSR_VMX_BASIC = 0x480,
MSR_VMX_PINBASED_CTLS = 0x481,
MSR_VMX_PROCBASED_CTLS = 0x482,
MSR_VMX_EXIT_CTLS = 0x483,
MSR_VMX_ENTRY_CTLS = 0x484,
MSR_VMX_MISC = 0x485,
MSR_VMX_CR0_FIXED0 = 0x486,
MSR_VMX_CR0_FIXED1 = 0x487,
MSR_VMX_CR4_FIXED0 = 0x488,
MSR_VMX_CR4_FIXED1 = 0x489,
MSR_VMX_VMCS_ENUM = 0x48A,
MSR_VMX_PROCBASED_CTLS2 = 0x48B,
MSR_VMX_EPT_VPID_CAP = 0x48C,
MSR_VMX_TRUE_PINBASED_CTLS = 0x48D,
MSR_VMX_TRUE_PROCBASED_CTLS = 0x48E,
MSR_VMX_TRUE_EXIT_CTLS = 0x48F,
MSR_VMX_TRUE_ENTRY_CTLS = 0x490,
MSR_VMX_VMFUNC = 0x491,
MSR_A_PMC0 = 0x4C1,
MSR_A_PMC1 = 0x4C2,
MSR_A_PMC2 = 0x4C3,
MSR_A_PMC3 = 0x4C4,
MSR_A_PMC4 = 0x4C5,
MSR_A_PMC5 = 0x4C6,
MSR_A_PMC6 = 0x4C7,
MSR_A_PMC7 = 0x4C8,
MSR_MCG_EXT_CTL = 0x4D0,
MSR_SGX_SVN_STATUS = 0x500,
MSR_RTIT_OUTPUT_BASE = 0x560,
MSR_RTIT_OUTPUT_MASK_PTRS = 0x561,
MSR_RTIT_CTL = 0x570,
MSR_RTIT_STATUS = 0x571,
MSR_RTIT_CR3_MATCH = 0x572,
MSR_RTIT_ADDR0_A = 0x580,
MSR_RTIT_ADDR0_B = 0x581,
MSR_RTIT_ADDR1_A = 0x582,
MSR_RTIT_ADDR1_B = 0x583,
MSR_RTIT_ADDR2_A = 0x584,
MSR_RTIT_ADDR2_B = 0x585,
MSR_RTIT_ADDR3_A = 0x586,
MSR_RTIT_ADDR3_B = 0x587,
MSR_DS_AREA = 0x600,
MSR_TSC_DEADLINE = 0x6E0,
MSR_PM_ENABLE = 0x770,
MSR_HWP_CAPABILITIES = 0x771,
MSR_HWP_REQUEST_PKG = 0x772,
MSR_HWP_INTERRUPT = 0x773,
MSR_HWP_REQUEST = 0x774,
MSR_HWP_STATUS = 0x777,
MSR_X2APIC_APICID = 0x802,
MSR_X2APIC_VERSION = 0x803,
MSR_X2APIC_TPR = 0x808,
MSR_X2APIC_PPR = 0x80A,
MSR_X2APIC_EOI = 0x80B,
MSR_X2APIC_LDR = 0x80D,
MSR_X2APIC_SIVR = 0x80F,
MSR_X2APIC_ISR0 = 0x810,
MSR_X2APIC_ISR1 = 0x811,
MSR_X2APIC_ISR2 = 0x812,
MSR_X2APIC_ISR3 = 0x813,
MSR_X2APIC_ISR4 = 0x814,
MSR_X2APIC_ISR5 = 0x815,
MSR_X2APIC_ISR6 = 0x816,
MSR_X2APIC_ISR7 = 0x817,
MSR_X2APIC_TMR0 = 0x818,
MSR_X2APIC_TMR1 = 0x819,
MSR_X2APIC_TMR2 = 0x81A,
MSR_X2APIC_TMR3 = 0x81B,
MSR_X2APIC_TMR4 = 0x81C,
MSR_X2APIC_TMR5 = 0x81D,
MSR_X2APIC_TMR6 = 0x81E,
MSR_X2APIC_TMR7 = 0x81F,
MSR_X2APIC_IRR0 = 0x820,
MSR_X2APIC_IRR1 = 0x821,
MSR_X2APIC_IRR2 = 0x822,
MSR_X2APIC_IRR3 = 0x823,
MSR_X2APIC_IRR4 = 0x824,
MSR_X2APIC_IRR5 = 0x825,
MSR_X2APIC_IRR6 = 0x826,
MSR_X2APIC_IRR7 = 0x827,
MSR_X2APIC_ESR = 0x828,
MSR_X2APIC_LVT_CMCI = 0x82F,
MSR_X2APIC_ICR = 0x830,
MSR_X2APIC_LVT_TIMER = 0x832,
MSR_X2APIC_LVT_THERMAL = 0x833,
MSR_X2APIC_LVT_PMI = 0x834,
MSR_X2APIC_LVT_LINT0 = 0x835,
MSR_X2APIC_LVT_LINT1 = 0x836,
MSR_X2APIC_LVT_ERROR = 0x837,
MSR_X2APIC_INIT_COUNT = 0x838,
MSR_X2APIC_CUR_COUNT = 0x839,
MSR_X2APIC_DIV_CONF = 0x83E,
MSR_X2APIC_SELF_IPI = 0x83F,
MSR_DEBUG_INTERFACE = 0xC80,
MSR_L3_QOS_CFG = 0xC81,
MSR_L2_QOS_CFG = 0xC82,
MSR_QM_EVTSEL = 0xC8D,
MSR_QM_CTR = 0xC8E,
MSR_PQR_ASSOC = 0xC8F,
MSR_L3_MASK_0 = 0xC90,
MSR_L2_MASK_0 = 0xD10,
MSR_BNDCFGS = 0xD90,
MSR_XSS = 0xDA0,
MSR_PKG_HDC_CTL = 0xDB0,
MSR_PM_CTL1 = 0xDB1,
MSR_THREAD_STALL = 0xDB2,
/** @brief Extended Feature Enable Register (0xc0000080) */
MSR_EFER = 0xC0000080,
/** @brief legacy SYSCALL (0xC0000081) */
MSR_STAR = 0xC0000081,
/** @brief 64bit SYSCALL (0xC0000082) */
MSR_LSTAR = 0xC0000082,
/** @brief compatibility mode SYSCALL (0xC0000083) */
MSR_CSTAR = 0xC0000083,
/** @brief EFLAGS mask for syscall (0xC0000084) */
MSR_SYSCALL_MASK = 0xC0000084,
/** @brief 64bit FS base (0xC0000100) */
MSR_FS_BASE = 0xC0000100,
/** @brief 64bit GS base (0xC0000101) */
MSR_GS_BASE = 0xC0000101,
/** @brief SwapGS GS shadow (0xC0000102) */
MSR_SHADOW_GS_BASE = 0xC0000102,
/** @brief Auxiliary TSC (0xC0000103) */
MSR_TSC_AUX = 0xC0000103,
MSR_CR_PAT = 0x00000277,
};
#if defined(a32)
nsa static inline uint64_t rdmsr(uint32_t msr)
{
uint32_t Low, High;
asmv("rdmsr"
: "=a"(Low), "=d"(High)
: "c"(msr)
: "memory");
return ((uint64_t)Low) | (((uint64_t)High) << 32);
}
nsa static inline void wrmsr(uint32_t msr, uint64_t Value)
{
uint32_t Low = (uint32_t)Value, High = (uint32_t)(Value >> 32);
asmv("wrmsr"
:
: "c"(msr), "a"(Low), "d"(High)
: "memory");
}
#endif
}
}
#endif // !__FENNIX_KERNEL_CPU_x32_MSR_H__

View File

@ -0,0 +1,168 @@
/*
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_SEGMENT_DESCRIPTORS_H__
#define __FENNIX_KERNEL_SEGMENT_DESCRIPTORS_H__
#include <types.h>
/**
* Manual: AMD Architecture Programmer's Manual Volume 2: System Programming
* Subsection: 4.8.3 System Descriptors
* Table: 4-6
*
* @note Reserved values are not listed in the table.
*/
enum GateType
{
LDT_64BIT = 0b0010,
AVAILABLE_64BIT_TSS = 0b1001,
BUSY_64BIT_TSS = 0b1011,
CALL_GATE_64BIT = 0b1100,
INTERRUPT_GATE_64BIT = 0b1110,
TRAP_GATE_64BIT = 0b1111,
};
enum PrivilegeLevelType
{
RING0 = 0b0,
RING1 = 0b1,
RING2 = 0b10,
RING3 = 0b11,
};
enum InterruptStackTableType
{
IST0 = 0b0,
IST1 = 0b1,
IST2 = 0b10,
IST3 = 0b11,
IST4 = 0b100,
IST5 = 0b101,
IST6 = 0b110,
};
struct InterruptGate
{
/* +0 */
uint64_t TargetOffsetLow : 16;
uint64_t TargetSelector : 16;
/* +4 */
uint64_t InterruptStackTable : 3;
uint64_t Reserved0 : 5;
uint64_t Type : 4;
uint64_t Zero : 1;
uint64_t DescriptorPrivilegeLevel : 2;
uint64_t Present : 1;
uint64_t TargetOffsetMiddle : 16;
/* +8 */
uint64_t TargetOffsetHigh : 32;
/* +12 */
uint64_t Reserved1 : 32;
} __packed;
typedef InterruptGate TrapGate;
struct CallGate
{
/* +0 */
uint64_t TargetOffsetLow : 16;
uint64_t TargetSelector : 16;
/* +4 */
uint64_t Reserved0 : 8;
uint64_t Type : 4;
uint64_t Zero0 : 1;
uint64_t DescriptorPrivilegeLevel : 2;
uint64_t Present : 1;
uint64_t TargetOffsetMiddle : 16;
/* +8 */
uint64_t TargetOffsetHigh : 32;
/* +12 */
uint64_t Reserved1 : 8;
uint64_t Zero1 : 5;
uint64_t Reserved2 : 19;
} __packed;
struct SystemSegmentDescriptor
{
/* +0 */
uint64_t SegmentLimitLow : 16;
uint64_t BaseAddressLow : 16;
/* +4 */
uint64_t BaseAddressMiddle : 8;
uint64_t Type : 4;
uint64_t Zero0 : 1;
uint64_t DescriptorPrivilegeLevel : 2;
uint64_t Present : 1;
uint64_t SegmentLimitMiddle : 4;
uint64_t Available : 1;
uint64_t Reserved0 : 2;
uint64_t Granularity : 1;
uint64_t BaseAddressHigh : 8;
/* +8 */
uint64_t BaseAddressHigher : 32;
/* +12 */
uint64_t Reserved1 : 8;
uint64_t Zero1 : 5;
uint64_t Reserved2 : 19;
} __packed;
struct CodeSegmentDescriptor
{
/* +0 */
uint64_t SegmentLimitLow : 16;
uint64_t BaseAddressLow : 16;
/* +4 */
uint64_t BaseAddressHigh : 8;
uint64_t Accessed : 1;
uint64_t Readable : 1;
uint64_t Conforming : 1;
uint64_t Executable : 1;
uint64_t Type : 1;
uint64_t DescriptorPrivilegeLevel : 2;
uint64_t Present : 1;
uint64_t SegmentLimitHigh : 4;
uint64_t Available : 1;
uint64_t Long : 1;
uint64_t Default : 1;
uint64_t Granularity : 1;
uint64_t BaseAddressHigher : 8;
} __packed;
struct DataSegmentDescriptor
{
/* +0 */
uint64_t SegmentLimitLow : 16;
uint64_t BaseAddressLow : 16;
/* +4 */
uint64_t BaseAddressHigh : 8;
uint64_t Accessed : 1;
uint64_t Writable : 1;
uint64_t ExpandDown : 1;
uint64_t Executable : 1;
uint64_t Type : 1;
uint64_t DescriptorPrivilegeLevel : 2;
uint64_t Present : 1;
uint64_t SegmentLimitHigh : 4;
uint64_t Available : 1;
uint64_t Reserved : 1;
uint64_t Default : 1;
uint64_t Granularity : 1;
uint64_t BaseAddressHigher : 8;
} __packed;
#endif // !__FENNIX_KERNEL_SEGMENT_DESCRIPTORS_H__

View File

@ -0,0 +1,296 @@
/*
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_CPU_x64_CR_H__
#define __FENNIX_KERNEL_CPU_x64_CR_H__
#include <types.h>
namespace CPU
{
namespace x64
{
typedef union CR0
{
struct
{
/** Protection Enable */
uint64_t PE : 1;
/** Monitor Coprocessor */
uint64_t MP : 1;
/** Emulation */
uint64_t EM : 1;
/** Task Switched */
uint64_t TS : 1;
/** Extension Type */
uint64_t ET : 1;
/** Numeric Error */
uint64_t NE : 1;
/** Reserved */
uint64_t Reserved0 : 10;
/** Write Protect */
uint64_t WP : 1;
/** Reserved */
uint64_t Reserved1 : 1;
/** Alignment Mask */
uint64_t AM : 1;
/** Reserved */
uint64_t Reserved2 : 10;
/** Not Write-through */
uint64_t NW : 1;
/** Cache Disable */
uint64_t CD : 1;
/** Paging */
uint64_t PG : 1;
};
uint64_t raw;
} CR0;
typedef union CR2
{
struct
{
/** Page Fault Linear Address */
uint64_t PFLA;
};
uint64_t raw;
} CR2;
typedef union CR3
{
struct
{
/** Not used if bit 17 of CR4 is 1 */
uint64_t PWT : 1;
/** Not used if bit 17 of CR4 is 1 */
uint64_t PCD : 1;
/** Base of PML4T/PML5T */
uint64_t PDBR;
};
uint64_t raw;
} CR3;
typedef union CR4
{
struct
{
/** Virtual-8086 Mode Extensions */
uint64_t VME : 1;
/** Protected-Mode Virtual Interrupts */
uint64_t PVI : 1;
/** Time Stamp Disable */
uint64_t TSD : 1;
/** Debugging Extensions */
uint64_t DE : 1;
/** Page Size Extensions */
uint64_t PSE : 1;
/** Physical Address Extension */
uint64_t PAE : 1;
/** Machine Check Enable */
uint64_t MCE : 1;
/** Page Global Enable */
uint64_t PGE : 1;
/** Performance Monitoring Counter */
uint64_t PCE : 1;
/** FXSAVE/FXRSTOR Support */
uint64_t OSFXSR : 1;
/** Unmasked Exception Support */
uint64_t OSXMMEXCPT : 1;
/** User-Mode Instruction Prevention */
uint64_t UMIP : 1;
/** Linear Address 57bit */
uint64_t LA57 : 1;
/** VMX Enable */
uint64_t VMXE : 1;
/** SMX Enable */
uint64_t SMXE : 1;
/** Reserved */
uint64_t Reserved0 : 1;
/** FSGSBASE Enable */
uint64_t FSGSBASE : 1;
/** PCID Enable */
uint64_t PCIDE : 1;
/** XSAVE and Processor Extended States Enable */
uint64_t OSXSAVE : 1;
/** Reserved */
uint64_t Reserved1 : 1;
/** SMEP Enable */
uint64_t SMEP : 1;
/** SMAP Enable */
uint64_t SMAP : 1;
/** Protection-Key Enable */
uint64_t PKE : 1;
/** Control-flow Enforcement Technology*/
uint32_t CET : 1;
/* Enable Protection Keys for Supervisor Mode Pages */
uint32_t PKS : 1;
/** Reserved */
uint64_t Reserved2 : 7; // TODO: This could be wrong
};
uint64_t raw;
} CR4;
typedef union CR8
{
struct
{
/** Task Priority Register */
uint64_t TPR : 4;
/** Reserved */
uint64_t Reserved : 60;
};
uint64_t raw;
} CR8;
typedef union XCR0
{
/*
On https://wiki.osdev.org/CPU_Registers_x86#XCR0 says that the PKRU bit is 9?
*/
struct
{
/** X87 FPU/MMX/SSE Support (must be 1) */
uint64_t X87 : 1;
/** XSAVE support for MXCSR and XMM registers */
uint64_t SSE : 1;
/** AVX support for YMM registers */
uint64_t AVX : 1;
/** MPX support for BND registers */
uint64_t BNDREG : 1;
/** MPX support for BNDCFGU and BNDSTATUS registers */
uint64_t BNDCSR : 1;
/** AVX-512 support for opmask registers */
uint64_t OpMask : 1;
/** AVX-512 enabled and XSAVE support for upper halves of lower ZMM registers */
uint64_t ZMM_HI256 : 1;
/** AVX-512 enabled and XSAVE support for upper ZMM registers */
uint64_t HI16_ZMM : 1;
/** XSAVE support for PKRU register */
uint64_t PKRU : 1;
/** Reserved */
uint64_t Reserved0 : 53;
/** AMD lightweight profiling */
uint64_t LWP : 1;
/** Reserved */
uint64_t Reserved1 : 1;
};
uint64_t raw;
} XCR0;
#if defined(a64)
nsa static inline CR0 readcr0()
{
uint64_t Result = 0;
asmv("mov %%cr0, %[Result]"
: [Result] "=q"(Result));
return (CR0){.raw = Result};
}
nsa static inline CR2 readcr2()
{
uint64_t Result = 0;
asmv("mov %%cr2, %[Result]"
: [Result] "=q"(Result));
return (CR2){.raw = Result};
}
nsa static inline CR3 readcr3()
{
uint64_t Result = 0;
asmv("mov %%cr3, %[Result]"
: [Result] "=q"(Result));
return (CR3){.raw = Result};
}
nsa static inline CR4 readcr4()
{
uint64_t Result = 0;
asmv("mov %%cr4, %[Result]"
: [Result] "=q"(Result));
return (CR4){.raw = Result};
}
nsa static inline CR8 readcr8()
{
uint64_t Result = 0;
asmv("mov %%cr8, %[Result]"
: [Result] "=q"(Result));
return (CR8){.raw = Result};
}
nsa static inline XCR0 readxcr0()
{
uint64_t Result = 0;
asmv("xgetbv"
: "=a"(Result)
: "c"(0)
: "edx");
return (XCR0){.raw = Result};
}
nsa static inline void writecr0(CR0 ControlRegister)
{
asmv("mov %[ControlRegister], %%cr0"
:
: [ControlRegister] "q"(ControlRegister.raw)
: "memory");
}
nsa static inline void writecr2(CR2 ControlRegister)
{
asmv("mov %[ControlRegister], %%cr2"
:
: [ControlRegister] "q"(ControlRegister.raw)
: "memory");
}
nsa static inline void writecr3(CR3 ControlRegister)
{
asmv("mov %[ControlRegister], %%cr3"
:
: [ControlRegister] "q"(ControlRegister.raw)
: "memory");
}
nsa static inline void writecr4(CR4 ControlRegister)
{
asmv("mov %[ControlRegister], %%cr4"
:
: [ControlRegister] "q"(ControlRegister.raw)
: "memory");
}
nsa static inline void writecr8(CR8 ControlRegister)
{
asmv("mov %[ControlRegister], %%cr8"
:
: [ControlRegister] "q"(ControlRegister.raw)
: "memory");
}
nsa static inline void writexcr0(XCR0 ControlRegister)
{
asmv("xsetbv"
:
: "a"(ControlRegister.raw), "c"(0)
: "edx");
}
#endif
}
}
#endif // !__FENNIX_KERNEL_CPU_x64_CR_H__

View File

@ -0,0 +1,427 @@
/*
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_CPU_x64_MSR_H__
#define __FENNIX_KERNEL_CPU_x64_MSR_H__
#include <types.h>
namespace CPU
{
namespace x64
{
enum MSRID
{
MSR_MONITOR_FILTER_SIZE = 0x6,
MSR_TIME_STAMP_COUNTER = 0x10,
MSR_PLATFORM_ID = 0x17,
MSR_APIC_BASE = 0x1B,
MSR_FEATURE_CONTROL = 0x3A,
MSR_TSC_ADJUST = 0x3B,
MSR_SPEC_CTRL = 0x48,
MSR_PRED_CMD = 0x49,
MSR_BIOS_UPDT_TRIG = 0x79,
MSR_BIOS_SIGN_ID = 0x8B,
MSR_SGXLEPUBKEYHASH0 = 0x8C,
MSR_SGXLEPUBKEYHASH1 = 0x8D,
MSR_SGXLEPUBKEYHASH2 = 0x8E,
MSR_SGXLEPUBKEYHASH3 = 0x8F,
MSR_SMM_MONITOR_CTL = 0x9B,
MSR_SMBASE = 0x9E,
MSR_PMC0 = 0xC1,
MSR_PMC1 = 0xC2,
MSR_PMC2 = 0xC3,
MSR_PMC3 = 0xC4,
MSR_PMC4 = 0xC5,
MSR_PMC5 = 0xC6,
MSR_PMC6 = 0xC7,
MSR_PMC7 = 0xC8,
MSR_UMWAIT_CONTROL = 0xE1,
MSR_MPERF = 0xE7,
MSR_APERF = 0xE8,
MSR_MTRRCAP = 0xFE,
MSR_ARCH_CAPABILITIES = 0x10A,
MSR_FLUSH_CMD = 0x10B,
MSR_SYSENTER_CS = 0x17A,
MSR_SYSENTER_ESP = 0x175,
MSR_SYSENTER_EIP = 0x176,
MSR_MCG_CAP = 0x179,
MSR_MCG_STATUS = 0x17A,
MSR_MCG_CTL = 0x17B,
MSR_PERFEVTSEL0 = 0x186,
MSR_PERFEVTSEL1 = 0x187,
MSR_PERFEVTSEL2 = 0x188,
MSR_PERFEVTSEL3 = 0x189,
MSR_PERF_STATUS = 0x198,
MSR_PERF_CTL = 0x199,
MSR_CLOCK_MODULATION = 0x19A,
MSR_THERM_INTERRUPT = 0x19B,
MSR_THERM_STATUS = 0x19C,
MSR_MISC_ENABLE = 0x1A0,
MSR_ENERGY_PERF_BIAS = 0x1B0,
MSR_PACKAGE_THERM_STATUS = 0x1B1,
MSR_PACKAGE_THERM_INTERRUPT = 0x1B2,
MSR_DEBUGCTL = 0x1D9,
MSR_SMRR_PHYSBASE = 0x1F2,
MSR_SMRR_PHYSMASK = 0x1F3,
MSR_PLATFORM_DCA_CAP = 0x1F8,
MSR_CPU_DCA_CAP = 0x1F9,
MSR_DCA_0_CAP = 0x1FA,
MSR_MTRR_PHYSBASE0 = 0x200,
MSR_MTRR_PHYSMASK0 = 0x201,
MSR_MTRR_PHYSBASE1 = 0x202,
MSR_MTRR_PHYSMASK1 = 0x203,
MSR_MTRR_PHYSBASE2 = 0x204,
MSR_MTRR_PHYSMASK2 = 0x205,
MSR_MTRR_PHYSBASE3 = 0x206,
MSR_MTRR_PHYSMASK3 = 0x207,
MSR_MTRR_PHYSBASE4 = 0x208,
MSR_MTRR_PHYSMASK4 = 0x209,
MSR_MTRR_PHYSBASE5 = 0x20A,
MSR_MTRR_PHYSMASK5 = 0x20B,
MSR_MTRR_PHYSBASE6 = 0x20C,
MSR_MTRR_PHYSMASK6 = 0x20D,
MSR_MTRR_PHYSBASE7 = 0x20E,
MSR_MTRR_PHYSMASK7 = 0x20F,
MSR_MTRR_PHYSBASE8 = 0x210,
MSR_MTRR_PHYSMASK8 = 0x211,
MSR_MTRR_PHYSBASE9 = 0x212,
MSR_MTRR_PHYSMASK9 = 0x213,
MSR_MTRR_FIX64K_00000 = 0x250,
MSR_MTRR_FIX16K_80000 = 0x258,
MSR_MTRR_FIX16K_A0000 = 0x259,
MSR_MTRR_FIX4K_C0000 = 0x268,
MSR_MTRR_FIX4K_C8000 = 0x269,
MSR_MTRR_FIX4K_D0000 = 0x26A,
MSR_MTRR_FIX4K_D8000 = 0x26B,
MSR_MTRR_FIX4K_E0000 = 0x26C,
MSR_MTRR_FIX4K_E8000 = 0x26D,
MSR_MTRR_FIX4K_F0000 = 0x26E,
MSR_MTRR_FIX4K_F8000 = 0x26F,
MSR_PAT = 0x277,
MSR_MC0_CTL2 = 0x280,
MSR_MC1_CTL2 = 0x281,
MSR_MC2_CTL2 = 0x282,
MSR_MC3_CTL2 = 0x283,
MSR_MC4_CTL2 = 0x284,
MSR_MC5_CTL2 = 0x285,
MSR_MC6_CTL2 = 0x286,
MSR_MC7_CTL2 = 0x287,
MSR_MC8_CTL2 = 0x288,
MSR_MC9_CTL2 = 0x289,
MSR_MC10_CTL2 = 0x28A,
MSR_MC11_CTL2 = 0x28B,
MSR_MC12_CTL2 = 0x28C,
MSR_MC13_CTL2 = 0x28D,
MSR_MC14_CTL2 = 0x28E,
MSR_MC15_CTL2 = 0x28F,
MSR_MC16_CTL2 = 0x290,
MSR_MC17_CTL2 = 0x291,
MSR_MC18_CTL2 = 0x292,
MSR_MC19_CTL2 = 0x293,
MSR_MC20_CTL2 = 0x294,
MSR_MC21_CTL2 = 0x295,
MSR_MC22_CTL2 = 0x296,
MSR_MC23_CTL2 = 0x297,
MSR_MC24_CTL2 = 0x298,
MSR_MC25_CTL2 = 0x299,
MSR_MC26_CTL2 = 0x29A,
MSR_MC27_CTL2 = 0x29B,
MSR_MC28_CTL2 = 0x29C,
MSR_MC29_CTL2 = 0x29D,
MSR_MC30_CTL2 = 0x29E,
MSR_MC31_CTL2 = 0x29F,
MSR_MTRR_DEF_TYPE = 0x2FF,
MSR_FIXED_CTR0 = 0x309,
MSR_FIXED_CTR1 = 0x30A,
MSR_FIXED_CTR2 = 0x30B,
MSR_PERF_CAPABILITIES = 0x345,
MSR_FIXED_CTR_CTRL = 0x38D,
MSR_PERF_GLOBAL_STATUS = 0x38E,
MSR_PERF_GLOBAL_CTRL = 0x38F,
MSR_PERF_GLOBAL_STATUS_RESET = 0x390,
MSR_PERF_GLOBAL_STATUS_SET = 0x391,
MSR_PERF_GLOBAL_INUSE = 0x392,
MSR_PEBS_ENABLE = 0x3F1,
MSR_MC0_CTL = 0x400,
MSR_MC0_STATUS = 0x401,
MSR_MC0_ADDR = 0x402,
MSR_MC0_MISC = 0x403,
MSR_MC1_CTL = 0x404,
MSR_MC1_STATUS = 0x405,
MSR_MC1_ADDR = 0x406,
MSR_MC1_MISC = 0x407,
MSR_MC2_CTL = 0x408,
MSR_MC2_STATUS = 0x409,
MSR_MC2_ADDR = 0x40A,
MSR_MC2_MISC = 0x40B,
MSR_MC3_CTL = 0x40C,
MSR_MC3_STATUS = 0x40D,
MSR_MC3_ADDR = 0x40E,
MSR_MC3_MISC = 0x40F,
MSR_MC4_CTL = 0x410,
MSR_MC4_STATUS = 0x411,
MSR_MC4_ADDR = 0x412,
MSR_MC4_MISC = 0x413,
MSR_MC5_CTL = 0x414,
MSR_MC5_STATUS = 0x415,
MSR_MC5_ADDR = 0x416,
MSR_MC5_MISC = 0x417,
MSR_MC6_CTL = 0x418,
MSR_MC6_STATUS = 0x419,
MSR_MC6_ADDR = 0x41A,
MSR_MC6_MISC = 0x41B,
MSR_MC7_CTL = 0x41C,
MSR_MC7_STATUS = 0x41D,
MSR_MC7_ADDR = 0x41E,
MSR_MC7_MISC = 0x41F,
MSR_MC8_CTL = 0x420,
MSR_MC8_STATUS = 0x421,
MSR_MC8_ADDR = 0x422,
MSR_MC8_MISC = 0x423,
MSR_MC9_CTL = 0x424,
MSR_MC9_STATUS = 0x425,
MSR_MC9_ADDR = 0x426,
MSR_MC9_MISC = 0x427,
MSR_MC10_CTL = 0x428,
MSR_MC10_STATUS = 0x429,
MSR_MC10_ADDR = 0x42A,
MSR_MC10_MISC = 0x42B,
MSR_MC11_CTL = 0x42C,
MSR_MC11_STATUS = 0x42D,
MSR_MC11_ADDR = 0x42E,
MSR_MC11_MISC = 0x42F,
MSR_MC12_CTL = 0x430,
MSR_MC12_STATUS = 0x431,
MSR_MC12_ADDR = 0x432,
MSR_MC12_MISC = 0x433,
MSR_MC13_CTL = 0x434,
MSR_MC13_STATUS = 0x435,
MSR_MC13_ADDR = 0x436,
MSR_MC13_MISC = 0x437,
MSR_MC14_CTL = 0x438,
MSR_MC14_STATUS = 0x439,
MSR_MC14_ADDR = 0x43A,
MSR_MC14_MISC = 0x43B,
MSR_MC15_CTL = 0x43C,
MSR_MC15_STATUS = 0x43D,
MSR_MC15_ADDR = 0x43E,
MSR_MC15_MISC = 0x43F,
MSR_MC16_CTL = 0x440,
MSR_MC16_STATUS = 0x441,
MSR_MC16_ADDR = 0x442,
MSR_MC16_MISC = 0x443,
MSR_MC17_CTL = 0x444,
MSR_MC17_STATUS = 0x445,
MSR_MC17_ADDR = 0x446,
MSR_MC17_MISC = 0x447,
MSR_MC18_CTL = 0x448,
MSR_MC18_STATUS = 0x449,
MSR_MC18_ADDR = 0x44A,
MSR_MC18_MISC = 0x44B,
MSR_MC19_CTL = 0x44C,
MSR_MC19_STATUS = 0x44D,
MSR_MC19_ADDR = 0x44E,
MSR_MC19_MISC = 0x44F,
MSR_MC20_CTL = 0x450,
MSR_MC20_STATUS = 0x451,
MSR_MC20_ADDR = 0x452,
MSR_MC20_MISC = 0x453,
MSR_MC21_CTL = 0x454,
MSR_MC21_STATUS = 0x455,
MSR_MC21_ADDR = 0x456,
MSR_MC21_MISC = 0x457,
MSR_MC22_CTL = 0x458,
MSR_MC22_STATUS = 0x459,
MSR_MC22_ADDR = 0x45A,
MSR_MC22_MISC = 0x45B,
MSR_MC23_CTL = 0x45C,
MSR_MC23_STATUS = 0x45D,
MSR_MC23_ADDR = 0x45E,
MSR_MC23_MISC = 0x45F,
MSR_MC24_CTL = 0x460,
MSR_MC24_STATUS = 0x461,
MSR_MC24_ADDR = 0x462,
MSR_MC24_MISC = 0x463,
MSR_MC25_CTL = 0x464,
MSR_MC25_STATUS = 0x465,
MSR_MC25_ADDR = 0x466,
MSR_MC25_MISC = 0x467,
MSR_MC26_CTL = 0x468,
MSR_MC26_STATUS = 0x469,
MSR_MC26_ADDR = 0x46A,
MSR_MC26_MISC = 0x46B,
MSR_MC27_CTL = 0x46C,
MSR_MC27_STATUS = 0x46D,
MSR_MC27_ADDR = 0x46E,
MSR_MC27_MISC = 0x46F,
MSR_MC28_CTL = 0x470,
MSR_MC28_STATUS = 0x471,
MSR_MC28_ADDR = 0x472,
MSR_MC28_MISC = 0x473,
MSR_VMX_BASIC = 0x480,
MSR_VMX_PINBASED_CTLS = 0x481,
MSR_VMX_PROCBASED_CTLS = 0x482,
MSR_VMX_EXIT_CTLS = 0x483,
MSR_VMX_ENTRY_CTLS = 0x484,
MSR_VMX_MISC = 0x485,
MSR_VMX_CR0_FIXED0 = 0x486,
MSR_VMX_CR0_FIXED1 = 0x487,
MSR_VMX_CR4_FIXED0 = 0x488,
MSR_VMX_CR4_FIXED1 = 0x489,
MSR_VMX_VMCS_ENUM = 0x48A,
MSR_VMX_PROCBASED_CTLS2 = 0x48B,
MSR_VMX_EPT_VPID_CAP = 0x48C,
MSR_VMX_TRUE_PINBASED_CTLS = 0x48D,
MSR_VMX_TRUE_PROCBASED_CTLS = 0x48E,
MSR_VMX_TRUE_EXIT_CTLS = 0x48F,
MSR_VMX_TRUE_ENTRY_CTLS = 0x490,
MSR_VMX_VMFUNC = 0x491,
MSR_A_PMC0 = 0x4C1,
MSR_A_PMC1 = 0x4C2,
MSR_A_PMC2 = 0x4C3,
MSR_A_PMC3 = 0x4C4,
MSR_A_PMC4 = 0x4C5,
MSR_A_PMC5 = 0x4C6,
MSR_A_PMC6 = 0x4C7,
MSR_A_PMC7 = 0x4C8,
MSR_MCG_EXT_CTL = 0x4D0,
MSR_SGX_SVN_STATUS = 0x500,
MSR_RTIT_OUTPUT_BASE = 0x560,
MSR_RTIT_OUTPUT_MASK_PTRS = 0x561,
MSR_RTIT_CTL = 0x570,
MSR_RTIT_STATUS = 0x571,
MSR_RTIT_CR3_MATCH = 0x572,
MSR_RTIT_ADDR0_A = 0x580,
MSR_RTIT_ADDR0_B = 0x581,
MSR_RTIT_ADDR1_A = 0x582,
MSR_RTIT_ADDR1_B = 0x583,
MSR_RTIT_ADDR2_A = 0x584,
MSR_RTIT_ADDR2_B = 0x585,
MSR_RTIT_ADDR3_A = 0x586,
MSR_RTIT_ADDR3_B = 0x587,
MSR_DS_AREA = 0x600,
MSR_TSC_DEADLINE = 0x6E0,
MSR_PM_ENABLE = 0x770,
MSR_HWP_CAPABILITIES = 0x771,
MSR_HWP_REQUEST_PKG = 0x772,
MSR_HWP_INTERRUPT = 0x773,
MSR_HWP_REQUEST = 0x774,
MSR_HWP_STATUS = 0x777,
MSR_X2APIC_APICID = 0x802,
MSR_X2APIC_VERSION = 0x803,
MSR_X2APIC_TPR = 0x808,
MSR_X2APIC_PPR = 0x80A,
MSR_X2APIC_EOI = 0x80B,
MSR_X2APIC_LDR = 0x80D,
MSR_X2APIC_SIVR = 0x80F,
MSR_X2APIC_ISR0 = 0x810,
MSR_X2APIC_ISR1 = 0x811,
MSR_X2APIC_ISR2 = 0x812,
MSR_X2APIC_ISR3 = 0x813,
MSR_X2APIC_ISR4 = 0x814,
MSR_X2APIC_ISR5 = 0x815,
MSR_X2APIC_ISR6 = 0x816,
MSR_X2APIC_ISR7 = 0x817,
MSR_X2APIC_TMR0 = 0x818,
MSR_X2APIC_TMR1 = 0x819,
MSR_X2APIC_TMR2 = 0x81A,
MSR_X2APIC_TMR3 = 0x81B,
MSR_X2APIC_TMR4 = 0x81C,
MSR_X2APIC_TMR5 = 0x81D,
MSR_X2APIC_TMR6 = 0x81E,
MSR_X2APIC_TMR7 = 0x81F,
MSR_X2APIC_IRR0 = 0x820,
MSR_X2APIC_IRR1 = 0x821,
MSR_X2APIC_IRR2 = 0x822,
MSR_X2APIC_IRR3 = 0x823,
MSR_X2APIC_IRR4 = 0x824,
MSR_X2APIC_IRR5 = 0x825,
MSR_X2APIC_IRR6 = 0x826,
MSR_X2APIC_IRR7 = 0x827,
MSR_X2APIC_ESR = 0x828,
MSR_X2APIC_LVT_CMCI = 0x82F,
MSR_X2APIC_ICR = 0x830,
MSR_X2APIC_LVT_TIMER = 0x832,
MSR_X2APIC_LVT_THERMAL = 0x833,
MSR_X2APIC_LVT_PMI = 0x834,
MSR_X2APIC_LVT_LINT0 = 0x835,
MSR_X2APIC_LVT_LINT1 = 0x836,
MSR_X2APIC_LVT_ERROR = 0x837,
MSR_X2APIC_INIT_COUNT = 0x838,
MSR_X2APIC_CUR_COUNT = 0x839,
MSR_X2APIC_DIV_CONF = 0x83E,
MSR_X2APIC_SELF_IPI = 0x83F,
MSR_DEBUG_INTERFACE = 0xC80,
MSR_L3_QOS_CFG = 0xC81,
MSR_L2_QOS_CFG = 0xC82,
MSR_QM_EVTSEL = 0xC8D,
MSR_QM_CTR = 0xC8E,
MSR_PQR_ASSOC = 0xC8F,
MSR_L3_MASK_0 = 0xC90,
MSR_L2_MASK_0 = 0xD10,
MSR_BNDCFGS = 0xD90,
MSR_XSS = 0xDA0,
MSR_PKG_HDC_CTL = 0xDB0,
MSR_PM_CTL1 = 0xDB1,
MSR_THREAD_STALL = 0xDB2,
/** @brief Extended Feature Enable Register (0xc0000080) */
MSR_EFER = 0xC0000080,
/** @brief legacy SYSCALL (0xC0000081) */
MSR_STAR = 0xC0000081,
/** @brief 64bit SYSCALL (0xC0000082) */
MSR_LSTAR = 0xC0000082,
/** @brief compatibility mode SYSCALL (0xC0000083) */
MSR_CSTAR = 0xC0000083,
/** @brief EFLAGS mask for syscall (0xC0000084) */
MSR_SYSCALL_MASK = 0xC0000084,
/** @brief 64bit FS base (0xC0000100) */
MSR_FS_BASE = 0xC0000100,
/** @brief 64bit GS base (0xC0000101) */
MSR_GS_BASE = 0xC0000101,
/** @brief SwapGS GS shadow (0xC0000102) */
MSR_SHADOW_GS_BASE = 0xC0000102,
/** @brief Auxiliary TSC (0xC0000103) */
MSR_TSC_AUX = 0xC0000103,
MSR_CR_PAT = 0x00000277,
MSR_CR_PAT_RESET = 0x0007040600070406ULL
};
#if defined(a64)
nsa static inline uint64_t rdmsr(uint32_t msr)
{
uint32_t Low, High;
asmv("rdmsr"
: "=a"(Low), "=d"(High)
: "c"(msr)
: "memory");
return ((uint64_t)Low) | (((uint64_t)High) << 32);
}
nsa static inline void wrmsr(uint32_t msr, uint64_t Value)
{
uint32_t Low = s_cst(uint32_t, Value), High = s_cst(uint32_t, Value >> 32);
asmv("wrmsr"
:
: "c"(msr), "a"(Low), "d"(High)
: "memory");
}
#endif
}
}
#endif // !__FENNIX_KERNEL_CPU_x64_MSR_H__

25
Kernel/include/crc32.h Normal file
View File

@ -0,0 +1,25 @@
/*
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_CRC32_H__
#define __FENNIX_KERNEL_CRC32_H__
#include <types.h>
EXTERNC uint32_t crc32(const uint8_t *Buffer, int Length);
#endif // !__FENNIX_KERNEL_CRC32_H__

523
Kernel/include/cwalk.h Normal file
View File

@ -0,0 +1,523 @@
/*
MIT License
Copyright (c) 2024 Leonard Iklé
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#pragma once
#ifndef CWK_LIBRARY_H
#define CWK_LIBRARY_H
#include <stdbool.h>
#include <stddef.h>
#if defined(_WIN32) || defined(__CYGWIN__)
#define CWK_EXPORT __declspec(dllexport)
#define CWK_IMPORT __declspec(dllimport)
#elif __GNUC__ >= 4
#define CWK_EXPORT __attribute__((visibility("default")))
#define CWK_IMPORT __attribute__((visibility("default")))
#else
#define CWK_EXPORT
#define CWK_IMPORT
#endif
#if defined(CWK_SHARED)
#if defined(CWK_EXPORTS)
#define CWK_PUBLIC CWK_EXPORT
#else
#define CWK_PUBLIC CWK_IMPORT
#endif
#else
#define CWK_PUBLIC
#endif
#ifdef __cplusplus
extern "C"
{
#endif
/**
* A segment represents a single component of a path. For instance, on linux a
* path might look like this "/var/log/", which consists of two segments "var"
* and "log".
*/
struct cwk_segment
{
const char *path;
const char *segments;
const char *begin;
const char *end;
size_t size;
};
/**
* The segment type can be used to identify whether a segment is a special
* segment or not.
*
* CWK_NORMAL - normal folder or file segment
* CWK_CURRENT - "./" current folder segment
* CWK_BACK - "../" relative back navigation segment
*/
enum cwk_segment_type
{
CWK_NORMAL,
CWK_CURRENT,
CWK_BACK
};
/**
* @brief Determines the style which is used for the path parsing and
* generation.
*/
enum cwk_path_style
{
CWK_STYLE_WINDOWS,
CWK_STYLE_UNIX
};
/**
* @brief Generates an absolute path based on a base.
*
* This function generates an absolute path based on a base path and another
* path. It is guaranteed to return an absolute path. If the second submitted
* path is absolute, it will override the base path. The result will be
* written to a buffer, which might be truncated if the buffer is not large
* enough to hold the full path. However, the truncated result will always be
* null-terminated. The returned value is the amount of characters which the
* resulting path would take if it was not truncated (excluding the
* null-terminating character).
*
* @param base The absolute base path on which the relative path will be
* applied.
* @param path The relative path which will be applied on the base path.
* @param buffer The buffer where the result will be written to.
* @param buffer_size The size of the result buffer.
* @return Returns the total amount of characters of the new absolute path.
*/
CWK_PUBLIC size_t cwk_path_get_absolute(const char *base, const char *path,
char *buffer, size_t buffer_size);
/**
* @brief Generates a relative path based on a base.
*
* This function generates a relative path based on a base path and another
* path. It determines how to get to the submitted path, starting from the
* base directory. The result will be written to a buffer, which might be
* truncated if the buffer is not large enough to hold the full path. However,
* the truncated result will always be null-terminated. The returned value is
* the amount of characters which the resulting path would take if it was not
* truncated (excluding the null-terminating character).
*
* @param base_directory The base path from which the relative path will
* start.
* @param path The target path where the relative path will point to.
* @param buffer The buffer where the result will be written to.
* @param buffer_size The size of the result buffer.
* @return Returns the total amount of characters of the full path.
*/
CWK_PUBLIC size_t cwk_path_get_relative(const char *base_directory,
const char *path, char *buffer, size_t buffer_size);
/**
* @brief Joins two paths together.
*
* This function generates a new path by combining the two submitted paths. It
* will remove double separators, and unlike cwk_path_get_absolute it permits
* the use of two relative paths to combine. The result will be written to a
* buffer, which might be truncated if the buffer is not large enough to hold
* the full path. However, the truncated result will always be
* null-terminated. The returned value is the amount of characters which the
* resulting path would take if it was not truncated (excluding the
* null-terminating character).
*
* @param path_a The first path which comes first.
* @param path_b The second path which comes after the first.
* @param buffer The buffer where the result will be written to.
* @param buffer_size The size of the result buffer.
* @return Returns the total amount of characters of the full, combined path.
*/
CWK_PUBLIC size_t cwk_path_join(const char *path_a, const char *path_b,
char *buffer, size_t buffer_size);
/**
* @brief Joins multiple paths together.
*
* This function generates a new path by joining multiple paths together. It
* will remove double separators, and unlike cwk_path_get_absolute it permits
* the use of multiple relative paths to combine. The last path of the
* submitted string array must be set to NULL. The result will be written to a
* buffer, which might be truncated if the buffer is not large enough to hold
* the full path. However, the truncated result will always be
* null-terminated. The returned value is the amount of characters which the
* resulting path would take if it was not truncated (excluding the
* null-terminating character).
*
* @param paths An array of paths which will be joined.
* @param buffer The buffer where the result will be written to.
* @param buffer_size The size of the result buffer.
* @return Returns the total amount of characters of the full, combined path.
*/
CWK_PUBLIC size_t cwk_path_join_multiple(const char **paths, char *buffer,
size_t buffer_size);
/**
* @brief Determines the root of a path.
*
* This function determines the root of a path by finding its length. The
* root always starts at the submitted path. If the path has no root, the
* length will be set to zero.
*
* @param path The path which will be inspected.
* @param length The output of the root length.
*/
CWK_PUBLIC void cwk_path_get_root(const char *path, size_t *length);
/**
* @brief Changes the root of a path.
*
* This function changes the root of a path. It does not normalize the result.
* The result will be written to a buffer, which might be truncated if the
* buffer is not large enough to hold the full path. However, the truncated
* result will always be null-terminated. The returned value is the amount of
* characters which the resulting path would take if it was not truncated
* (excluding the null-terminating character).
*
* @param path The original path which will get a new root.
* @param new_root The new root which will be placed in the path.
* @param buffer The output buffer where the result is written to.
* @param buffer_size The size of the output buffer where the result is
* written to.
* @return Returns the total amount of characters of the new path.
*/
CWK_PUBLIC size_t cwk_path_change_root(const char *path, const char *new_root,
char *buffer, size_t buffer_size);
/**
* @brief Determine whether the path is absolute or not.
*
* This function checks whether the path is an absolute path or not. A path is
* considered to be absolute if the root ends with a separator.
*
* @param path The path which will be checked.
* @return Returns true if the path is absolute or false otherwise.
*/
CWK_PUBLIC bool cwk_path_is_absolute(const char *path);
/**
* @brief Determine whether the path is relative or not.
*
* This function checks whether the path is a relative path or not. A path is
* considered to be relative if the root does not end with a separator.
*
* @param path The path which will be checked.
* @return Returns true if the path is relative or false otherwise.
*/
CWK_PUBLIC bool cwk_path_is_relative(const char *path);
/**
* @brief Gets the basename of a file path.
*
* This function gets the basename of a file path. A pointer to the beginning
* of the basename will be returned through the basename parameter. This
* pointer will be positioned on the first letter after the separator. The
* length of the file path will be returned through the length parameter. The
* length will be set to zero and the basename to NULL if there is no basename
* available.
*
* @param path The path which will be inspected.
* @param basename The output of the basename pointer.
* @param length The output of the length of the basename. This may be
* null if not required.
*/
CWK_PUBLIC void cwk_path_get_basename(const char *path, const char **basename,
size_t *length);
/**
* @brief Changes the basename of a file path.
*
* This function changes the basename of a file path. This function will not
* write out more than the specified buffer can contain. However, the
* generated string is always null-terminated - even if not the whole path is
* written out. The function returns the total number of characters the
* complete buffer would have, even if it was not written out completely. The
* path may be the same memory address as the buffer.
*
* @param path The original path which will be used for the modified path.
* @param new_basename The new basename which will replace the old one.
* @param buffer The buffer where the changed path will be written to.
* @param buffer_size The size of the result buffer where the changed path is
* written to.
* @return Returns the size which the complete new path would have if it was
* not truncated.
*/
CWK_PUBLIC size_t cwk_path_change_basename(const char *path,
const char *new_basename, char *buffer, size_t buffer_size);
/**
* @brief Gets the dirname of a file path.
*
* This function determines the dirname of a file path and returns the length
* up to which character is considered to be part of it. If no dirname is
* found, the length will be set to zero. The beginning of the dirname is
* always equal to the submitted path pointer.
*
* @param path The path which will be inspected.
* @param length The length of the dirname.
*/
CWK_PUBLIC void cwk_path_get_dirname(const char *path, size_t *length);
/**
* @brief Gets the extension of a file path.
*
* This function extracts the extension portion of a file path. A pointer to
* the beginning of the extension will be returned through the extension
* parameter if an extension is found and true is returned. This pointer will
* be positioned on the dot. The length of the extension name will be returned
* through the length parameter. If no extension is found both parameters
* won't be touched and false will be returned.
*
* @param path The path which will be inspected.
* @param extension The output of the extension pointer.
* @param length The output of the length of the extension.
* @return Returns true if an extension is found or false otherwise.
*/
CWK_PUBLIC bool cwk_path_get_extension(const char *path, const char **extension,
size_t *length);
/**
* @brief Determines whether the file path has an extension.
*
* This function determines whether the submitted file path has an extension.
* This will evaluate to true if the last segment of the path contains a dot.
*
* @param path The path which will be inspected.
* @return Returns true if the path has an extension or false otherwise.
*/
CWK_PUBLIC bool cwk_path_has_extension(const char *path);
/**
* @brief Changes the extension of a file path.
*
* This function changes the extension of a file name. The function will
* append an extension if the basename does not have an extension, or use the
* extension as a basename if the path does not have a basename. This function
* will not write out more than the specified buffer can contain. However, the
* generated string is always null-terminated - even if not the whole path is
* written out. The function returns the total number of characters the
* complete buffer would have, even if it was not written out completely. The
* path may be the same memory address as the buffer.
*
* @param path The path which will be used to make the change.
* @param new_extension The extension which will be placed within the new
* path.
* @param buffer The output buffer where the result will be written to.
* @param buffer_size The size of the output buffer where the result will be
* written to.
* @return Returns the total size which the output would have if it was not
* truncated.
*/
CWK_PUBLIC size_t cwk_path_change_extension(const char *path,
const char *new_extension, char *buffer, size_t buffer_size);
/**
* @brief Creates a normalized version of the path.
*
* This function creates a normalized version of the path within the specified
* buffer. This function will not write out more than the specified buffer can
* contain. However, the generated string is always null-terminated - even if
* not the whole path is written out. The returned value is the amount of
* characters which the resulting path would take if it was not truncated
* (excluding the null-terminating character). The path may be the same memory
* address as the buffer.
*
* The following will be true for the normalized path:
* 1) "../" will be resolved.
* 2) "./" will be removed.
* 3) double separators will be fixed with a single separator.
* 4) separator suffixes will be removed.
*
* @param path The path which will be normalized.
* @param buffer The buffer where the new path is written to.
* @param buffer_size The size of the buffer.
* @return The size which the complete normalized path has if it was not
* truncated.
*/
CWK_PUBLIC size_t cwk_path_normalize(const char *path, char *buffer,
size_t buffer_size);
/**
* @brief Finds common portions in two paths.
*
* This function finds common portions in two paths and returns the number
* characters from the beginning of the base path which are equal to the other
* path.
*
* @param path_base The base path which will be compared with the other path.
* @param path_other The other path which will compared with the base path.
* @return Returns the number of characters which are common in the base path.
*/
CWK_PUBLIC size_t cwk_path_get_intersection(const char *path_base,
const char *path_other);
/**
* @brief Gets the first segment of a path.
*
* This function finds the first segment of a path. The position of the
* segment is set to the first character after the separator, and the length
* counts all characters until the next separator (excluding the separator).
*
* @param path The path which will be inspected.
* @param segment The segment which will be extracted.
* @return Returns true if there is a segment or false if there is none.
*/
CWK_PUBLIC bool cwk_path_get_first_segment(const char *path,
struct cwk_segment *segment);
/**
* @brief Gets the last segment of the path.
*
* This function gets the last segment of a path. This function may return
* false if the path doesn't contain any segments, in which case the submitted
* segment parameter is not modified. The position of the segment is set to
* the first character after the separator, and the length counts all
* characters until the end of the path (excluding the separator).
*
* @param path The path which will be inspected.
* @param segment The segment which will be extracted.
* @return Returns true if there is a segment or false if there is none.
*/
CWK_PUBLIC bool cwk_path_get_last_segment(const char *path,
struct cwk_segment *segment);
/**
* @brief Advances to the next segment.
*
* This function advances the current segment to the next segment. If there
* are no more segments left, the submitted segment structure will stay
* unchanged and false is returned.
*
* @param segment The current segment which will be advanced to the next one.
* @return Returns true if another segment was found or false otherwise.
*/
CWK_PUBLIC bool cwk_path_get_next_segment(struct cwk_segment *segment);
/**
* @brief Moves to the previous segment.
*
* This function moves the current segment to the previous segment. If the
* current segment is the first one, the submitted segment structure will stay
* unchanged and false is returned.
*
* @param segment The current segment which will be moved to the previous one.
* @return Returns true if there is a segment before this one or false
* otherwise.
*/
CWK_PUBLIC bool cwk_path_get_previous_segment(struct cwk_segment *segment);
/**
* @brief Gets the type of the submitted path segment.
*
* This function inspects the contents of the segment and determines the type
* of it. Currently, there are three types CWK_NORMAL, CWK_CURRENT and
* CWK_BACK. A CWK_NORMAL segment is a normal folder or file entry. A
* CWK_CURRENT is a "./" and a CWK_BACK a "../" segment.
*
* @param segment The segment which will be inspected.
* @return Returns the type of the segment.
*/
CWK_PUBLIC enum cwk_segment_type cwk_path_get_segment_type(
const struct cwk_segment *segment);
/**
* @brief Changes the content of a segment.
*
* This function overrides the content of a segment to the submitted value and
* outputs the whole new path to the submitted buffer. The result might
* require less or more space than before if the new value length differs from
* the original length. The output is truncated if the new path is larger than
* the submitted buffer size, but it is always null-terminated. The source of
* the segment and the submitted buffer may be the same.
*
* @param segment The segment which will be modifier.
* @param value The new content of the segment.
* @param buffer The buffer where the modified path will be written to.
* @param buffer_size The size of the output buffer.
* @return Returns the total size which would have been written if the output
* was not truncated.
*/
CWK_PUBLIC size_t cwk_path_change_segment(struct cwk_segment *segment,
const char *value, char *buffer, size_t buffer_size);
/**
* @brief Checks whether the submitted pointer points to a separator.
*
* This function simply checks whether the submitted pointer points to a
* separator, which has to be null-terminated (but not necessarily after the
* separator). The function will return true if it is a separator, or false
* otherwise.
*
* @param symbol A pointer to a string.
* @return Returns true if it is a separator, or false otherwise.
*/
CWK_PUBLIC bool cwk_path_is_separator(const char *str);
/**
* @brief Guesses the path style.
*
* This function guesses the path style based on a submitted path-string. The
* guessing will look at the root and the type of slashes contained in the
* path and return the style which is more likely used in the path.
*
* @param path The path which will be inspected.
* @return Returns the style which is most likely used for the path.
*/
CWK_PUBLIC enum cwk_path_style cwk_path_guess_style(const char *path);
/**
* @brief Configures which path style is used.
*
* This function configures which path style is used. The following styles are
* currently supported.
*
* CWK_STYLE_WINDOWS: Use backslashes as a separator and volume for the root.
* CWK_STYLE_UNIX: Use slashes as a separator and a slash for the root.
*
* @param style The style which will be used from now on.
*/
CWK_PUBLIC void cwk_path_set_style(enum cwk_path_style style);
/**
* @brief Gets the path style configuration.
*
* This function gets the style configuration which is currently used for the
* paths. This configuration determines how paths are parsed and generated.
*
* @return Returns the current path style configuration.
*/
CWK_PUBLIC enum cwk_path_style cwk_path_get_style(void);
#ifdef __cplusplus
} // extern "C"
#endif
#endif

122
Kernel/include/debug.h Normal file
View File

@ -0,0 +1,122 @@
/*
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_DEBUGGER_H__
#define __FENNIX_KERNEL_DEBUGGER_H__
#include <types.h>
enum DebugLevel
{
DebugLevelNone = 0,
DebugLevelError,
DebugLevelWarning,
DebugLevelInfo,
DebugLevelDebug,
DebugLevelTrace,
DebugLevelFixme,
DebugLevelUbsan,
DebugLevelStub,
DebugLevelFunction,
};
#ifdef __cplusplus
namespace SysDbg
{
void Write(DebugLevel Level, const char *File, int Line, const char *Function, const char *Format, ...);
void WriteLine(DebugLevel Level, const char *File, int Line, const char *Function, const char *Format, ...);
void LockedWrite(DebugLevel Level, const char *File, int Line, const char *Function, const char *Format, ...);
void LockedWriteLine(DebugLevel Level, const char *File, int Line, const char *Function, const char *Format, ...);
}
#define error(Format, ...) SysDbg::WriteLine(DebugLevelError, __FILE__, __LINE__, __FUNCTION__, Format, ##__VA_ARGS__)
#define warn(Format, ...) SysDbg::WriteLine(DebugLevelWarning, __FILE__, __LINE__, __FUNCTION__, Format, ##__VA_ARGS__)
#define info(Format, ...) SysDbg::WriteLine(DebugLevelInfo, __FILE__, __LINE__, __FUNCTION__, Format, ##__VA_ARGS__)
#ifdef DEBUG
#define debug(Format, ...) SysDbg::WriteLine(DebugLevelDebug, __FILE__, __LINE__, __FUNCTION__, Format, ##__VA_ARGS__)
#define ubsan(Format, ...) SysDbg::WriteLine(DebugLevelUbsan, __FILE__, __LINE__, __FUNCTION__, Format, ##__VA_ARGS__)
#define func(Format, ...) SysDbg::WriteLine(DebugLevelFunction, __FILE__, __LINE__, __FUNCTION__, Format, ##__VA_ARGS__)
#else
#define debug(Format, ...)
#define ubsan(Format, ...)
#define func(Format, ...)
#endif
#define trace(Format, ...) SysDbg::WriteLine(DebugLevelTrace, __FILE__, __LINE__, __FUNCTION__, Format, ##__VA_ARGS__)
#define fixme(Format, ...) SysDbg::WriteLine(DebugLevelFixme, __FILE__, __LINE__, __FUNCTION__, Format, ##__VA_ARGS__)
#define stub SysDbg::WriteLine(DebugLevelStub, __FILE__, __LINE__, __FUNCTION__, "stub")
#define l_error(Format, ...) SysDbg::LockedWriteLine(DebugLevelError, __FILE__, __LINE__, __FUNCTION__, Format, ##__VA_ARGS__)
#define l_warn(Format, ...) SysDbg::LockedWriteLine(DebugLevelWarning, __FILE__, __LINE__, __FUNCTION__, Format, ##__VA_ARGS__)
#define l_info(Format, ...) SysDbg::LockedWriteLine(DebugLevelInfo, __FILE__, __LINE__, __FUNCTION__, Format, ##__VA_ARGS__)
#ifdef DEBUG
#define l_debug(Format, ...) SysDbg::LockedWriteLine(DebugLevelDebug, __FILE__, __LINE__, __FUNCTION__, Format, ##__VA_ARGS__)
#define l_ubsan(Format, ...) SysDbg::LockedWriteLine(DebugLevelUbsan, __FILE__, __LINE__, __FUNCTION__, Format, ##__VA_ARGS__)
#define l_function(Format, ...) SysDbg::LockedWriteLine(DebugLevelFunction, __FILE__, __LINE__, __FUNCTION__, Format, ##__VA_ARGS__)
#else
#define l_debug(Format, ...)
#define l_ubsan(Format, ...)
#define l_function(Format, ...)
#endif
#define l_trace(Format, ...) SysDbg::LockedWriteLine(DebugLevelTrace, __FILE__, __LINE__, __FUNCTION__, Format, ##__VA_ARGS__)
#define l_fixme(Format, ...) SysDbg::LockedWriteLine(DebugLevelFixme, __FILE__, __LINE__, __FUNCTION__, Format, ##__VA_ARGS__)
#define l_stub SysDbg::LockedWriteLine(DebugLevelStub, __FILE__, __LINE__, __FUNCTION__, "stub")
#else
void SysDbgWrite(enum DebugLevel Level, const char *File, int Line, const char *Function, const char *Format, ...);
void SysDbgWriteLine(enum DebugLevel Level, const char *File, int Line, const char *Function, const char *Format, ...);
void SysDbgLockedWrite(enum DebugLevel Level, const char *File, int Line, const char *Function, const char *Format, ...);
void SysDbgLockedWriteLine(enum DebugLevel Level, const char *File, int Line, const char *Function, const char *Format, ...);
#define error(Format, ...) SysDbgWriteLine(DebugLevelError, __FILE__, __LINE__, __FUNCTION__, Format, ##__VA_ARGS__)
#define warn(Format, ...) SysDbgWriteLine(DebugLevelWarning, __FILE__, __LINE__, __FUNCTION__, Format, ##__VA_ARGS__)
#define info(Format, ...) SysDbgWriteLine(DebugLevelInfo, __FILE__, __LINE__, __FUNCTION__, Format, ##__VA_ARGS__)
#ifdef DEBUG
#define debug(Format, ...) SysDbgWriteLine(DebugLevelDebug, __FILE__, __LINE__, __FUNCTION__, Format, ##__VA_ARGS__)
#define ubsan(Format, ...) SysDbgWriteLine(DebugLevelUbsan, __FILE__, __LINE__, __FUNCTION__, Format, ##__VA_ARGS__)
#define func(Format, ...) SysDbgWriteLine(DebugLevelFunction, __FILE__, __LINE__, __FUNCTION__, Format, ##__VA_ARGS__)
#else
#define debug(Format, ...)
#define ubsan(Format, ...)
#define func(Format, ...)
#endif
#define trace(Format, ...) SysDbgWriteLine(DebugLevelTrace, __FILE__, __LINE__, __FUNCTION__, Format, ##__VA_ARGS__)
#define fixme(Format, ...) SysDbgWriteLine(DebugLevelFixme, __FILE__, __LINE__, __FUNCTION__, Format, ##__VA_ARGS__)
#define stub SysDbgWriteLine(DebugLevelStub, __FILE__, __LINE__, __FUNCTION__, "stub")
#define l_error(Format, ...) SysDbgLockedWriteLine(DebugLevelError, __FILE__, __LINE__, __FUNCTION__, Format, ##__VA_ARGS__)
#define l_warn(Format, ...) SysDbgLockedWriteLine(DebugLevelWarning, __FILE__, __LINE__, __FUNCTION__, Format, ##__VA_ARGS__)
#define l_info(Format, ...) SysDbgLockedWriteLine(DebugLevelInfo, __FILE__, __LINE__, __FUNCTION__, Format, ##__VA_ARGS__)
#ifdef DEBUG
#define l_debug(Format, ...) SysDbgLockedWriteLine(DebugLevelDebug, __FILE__, __LINE__, __FUNCTION__, Format, ##__VA_ARGS__)
#define l_ubsan(Format, ...) SysDbgLockedWriteLine(DebugLevelUbsan, __FILE__, __LINE__, __FUNCTION__, Format, ##__VA_ARGS__)
#define l_function(Format, ...) SysDbgLockedWriteLine(DebugLevelFunction, __FILE__, __LINE__, __FUNCTION__, Format, ##__VA_ARGS__)
#else
#define l_debug(Format, ...)
#define l_ubsan(Format, ...)
#define l_function(Format, ...)
#endif
#define l_trace(Format, ...) SysDbgLockedWriteLine(DebugLevelTrace, __FILE__, __LINE__, __FUNCTION__, Format, ##__VA_ARGS__)
#define l_fixme(Format, ...) SysDbgLockedWriteLine(DebugLevelFixme, __FILE__, __LINE__, __FUNCTION__, Format, ##__VA_ARGS__)
#define l_stub SysDbgLockedWriteLine(DebugLevelStub, __FILE__, __LINE__, __FUNCTION__, "stub")
#endif // __cplusplus
EXTERNC void uart_wrapper(char c, void *unused);
#endif // !__FENNIX_KERNEL_DEBUGGER_H__

184
Kernel/include/disk.hpp Normal file
View File

@ -0,0 +1,184 @@
/*
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_DISK_H__
#define __FENNIX_KERNEL_DISK_H__
#include <types.h>
#include <vector>
namespace Disk
{
#define MBR_MAGIC0 0x55
#define MBR_MAGIC1 0xAA
// "EFI PART"
#define GPT_MAGIC 0x5452415020494645ULL
enum PartitionStyle
{
Unknown,
MBR,
GPT
};
enum PartitionFlags
{
Present,
Bootable,
EFISystemPartition
};
struct MasterBootRecordPartition
{
uint8_t Flags;
uint8_t CHSFirst[3];
uint8_t Type;
uint8_t CHSLast[3];
uint32_t LBAFirst;
uint32_t Sectors;
} __packed;
struct MasterBootRecord
{
uint8_t Bootstrap[440];
uint32_t UniqueID;
uint16_t Reserved;
MasterBootRecordPartition Partitions[4];
uint8_t Signature[2];
} __packed;
struct GUIDPartitionTableEntry
{
uint8_t PartitionType[16];
uint8_t UniquePartitionGUID[16];
uint64_t FirstLBA;
uint64_t LastLBA;
uint64_t Attributes;
uint16_t PartitionName[36];
} __packed;
struct GUIDPartitionTable
{
uint64_t Signature;
uint32_t Revision;
uint32_t HdrSize;
uint32_t HdrCRC32;
uint32_t Reserved;
uint64_t LBA;
uint64_t ALTLBA;
uint64_t FirstBlock;
uint64_t LastBlock;
uint64_t GUIDLow;
uint64_t GUIDHigh;
uint64_t PartLBA;
uint32_t PartCount;
uint32_t EntrySize;
uint32_t PartCRC32;
} __packed;
struct PartitionTable
{
MasterBootRecord MBR;
GUIDPartitionTable GPT;
};
class Partition
{
public:
char Label[72] = "Unidentified Partition";
uint64_t StartLBA = 0xdeadbeef;
uint64_t EndLBA = 0xdeadbeef;
size_t Sectors = 0xdeadbeef;
size_t Flags = 0xdeadbeef;
unsigned char Port = 0;
PartitionStyle Style = PartitionStyle::Unknown;
size_t Index = 0;
size_t Read(size_t Offset, size_t Count, uint8_t *Buffer)
{
fixme("Read from partition %s", Label);
return 0;
UNUSED(Offset);
UNUSED(Count);
UNUSED(Buffer);
}
size_t Write(size_t Offset, size_t Count, uint8_t *Buffer)
{
fixme("Read from partition %s", Label);
return 0;
UNUSED(Offset);
UNUSED(Count);
UNUSED(Buffer);
}
Partition() {}
~Partition() {}
};
class Drive
{
public:
char Name[64] = "Unidentified Drive";
uint8_t *Buffer = nullptr;
PartitionTable Table;
PartitionStyle Style = PartitionStyle::Unknown;
std::vector<Partition *> Partitions;
bool MechanicalDisk = false;
size_t UniqueIdentifier = 0xdeadbeef;
size_t Read(size_t Offset, size_t Count, uint8_t *Buffer)
{
fixme("Read from disk %s", Name);
return 0;
UNUSED(Offset);
UNUSED(Count);
UNUSED(Buffer);
}
size_t Write(size_t Offset, size_t Count, uint8_t *Buffer)
{
fixme("Read from disk %s", Name);
return 0;
UNUSED(Offset);
UNUSED(Count);
UNUSED(Buffer);
}
Drive()
{ // TODO: Allocate buffer
}
~Drive() {}
};
class Manager
{
private:
unsigned char AvailablePorts = 0;
int BytesPerSector = 0;
std::vector<Drive *> drives;
public:
void FetchDisks(unsigned long modUniqueID);
Manager();
~Manager();
};
}
#endif // !__FENNIX_KERNEL_DISK_H__

223
Kernel/include/display.hpp Normal file
View File

@ -0,0 +1,223 @@
/*
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_DISPLAY_H__
#define __FENNIX_KERNEL_DISPLAY_H__
#include <types.h>
#include <boot/binfo.h>
#include <memory.hpp>
#include <debug.h>
#include <cstring>
#include <vector>
extern uintptr_t _binary_files_tamsyn_font_1_11_Tamsyn10x20b_psf_end;
extern uintptr_t _binary_files_tamsyn_font_1_11_Tamsyn10x20b_psf_size;
extern uintptr_t _binary_files_tamsyn_font_1_11_Tamsyn10x20b_psf_start;
extern uintptr_t _binary_files_tamsyn_font_1_11_Tamsyn5x9b_psf_end;
extern uintptr_t _binary_files_tamsyn_font_1_11_Tamsyn5x9b_psf_size;
extern uintptr_t _binary_files_tamsyn_font_1_11_Tamsyn5x9b_psf_start;
extern uintptr_t _binary_files_tamsyn_font_1_11_Tamsyn5x9r_psf_end;
extern uintptr_t _binary_files_tamsyn_font_1_11_Tamsyn5x9r_psf_size;
extern uintptr_t _binary_files_tamsyn_font_1_11_Tamsyn5x9r_psf_start;
extern uintptr_t _binary_files_tamsyn_font_1_11_Tamsyn10x20r_psf_end;
extern uintptr_t _binary_files_tamsyn_font_1_11_Tamsyn10x20r_psf_size;
extern uintptr_t _binary_files_tamsyn_font_1_11_Tamsyn10x20r_psf_start;
extern uintptr_t _binary_files_tamsyn_font_1_11_Tamsyn6x12b_psf_end;
extern uintptr_t _binary_files_tamsyn_font_1_11_Tamsyn6x12b_psf_size;
extern uintptr_t _binary_files_tamsyn_font_1_11_Tamsyn6x12b_psf_start;
extern uintptr_t _binary_files_tamsyn_font_1_11_Tamsyn6x12r_psf_end;
extern uintptr_t _binary_files_tamsyn_font_1_11_Tamsyn6x12r_psf_size;
extern uintptr_t _binary_files_tamsyn_font_1_11_Tamsyn6x12r_psf_start;
extern uintptr_t _binary_files_tamsyn_font_1_11_Tamsyn7x13b_psf_end;
extern uintptr_t _binary_files_tamsyn_font_1_11_Tamsyn7x13b_psf_size;
extern uintptr_t _binary_files_tamsyn_font_1_11_Tamsyn7x13b_psf_start;
extern uintptr_t _binary_files_tamsyn_font_1_11_Tamsyn7x13r_psf_end;
extern uintptr_t _binary_files_tamsyn_font_1_11_Tamsyn7x13r_psf_size;
extern uintptr_t _binary_files_tamsyn_font_1_11_Tamsyn7x13r_psf_start;
extern uintptr_t _binary_files_tamsyn_font_1_11_Tamsyn7x14b_psf_end;
extern uintptr_t _binary_files_tamsyn_font_1_11_Tamsyn7x14b_psf_size;
extern uintptr_t _binary_files_tamsyn_font_1_11_Tamsyn7x14b_psf_start;
extern uintptr_t _binary_files_tamsyn_font_1_11_Tamsyn7x14r_psf_end;
extern uintptr_t _binary_files_tamsyn_font_1_11_Tamsyn7x14r_psf_size;
extern uintptr_t _binary_files_tamsyn_font_1_11_Tamsyn7x14r_psf_start;
extern uintptr_t _binary_files_tamsyn_font_1_11_Tamsyn8x15b_psf_end;
extern uintptr_t _binary_files_tamsyn_font_1_11_Tamsyn8x15b_psf_size;
extern uintptr_t _binary_files_tamsyn_font_1_11_Tamsyn8x15b_psf_start;
extern uintptr_t _binary_files_tamsyn_font_1_11_Tamsyn8x15r_psf_end;
extern uintptr_t _binary_files_tamsyn_font_1_11_Tamsyn8x15r_psf_size;
extern uintptr_t _binary_files_tamsyn_font_1_11_Tamsyn8x15r_psf_start;
extern uintptr_t _binary_files_tamsyn_font_1_11_Tamsyn8x16b_psf_end;
extern uintptr_t _binary_files_tamsyn_font_1_11_Tamsyn8x16b_psf_size;
extern uintptr_t _binary_files_tamsyn_font_1_11_Tamsyn8x16b_psf_start;
extern uintptr_t _binary_files_tamsyn_font_1_11_Tamsyn8x16r_psf_end;
extern uintptr_t _binary_files_tamsyn_font_1_11_Tamsyn8x16r_psf_size;
extern uintptr_t _binary_files_tamsyn_font_1_11_Tamsyn8x16r_psf_start;
namespace Video
{
#define PSF1_MAGIC0 0x36
#define PSF1_MAGIC1 0x04
#define PSF2_MAGIC0 0x72
#define PSF2_MAGIC1 0xb5
#define PSF2_MAGIC2 0x4a
#define PSF2_MAGIC3 0x86
enum DisplayFont
{
Tamsyn5x9r,
Tamsyn5x9b,
Tamsyn6x12r,
Tamsyn6x12b,
Tamsyn7x14r,
Tamsyn7x14b,
Tamsyn7x13r,
Tamsyn7x13b,
Tamsyn8x15r,
Tamsyn8x15b,
Tamsyn8x16r,
Tamsyn8x16b,
Tamsyn10x20r,
Tamsyn10x20b,
};
struct PSF1_HEADER
{
uint8_t magic[2];
uint8_t mode;
uint8_t charsize;
};
struct PSF2_HEADER
{
uint8_t magic[4];
uint32_t version;
uint32_t headersize;
uint32_t flags;
uint32_t length;
uint32_t charsize;
uint32_t height, width;
};
typedef struct _PSF1_FONT
{
PSF1_HEADER *Header;
void *GlyphBuffer;
} PSF1_FONT;
typedef struct _PSF2_FONT
{
PSF2_HEADER *Header;
void *GlyphBuffer;
} PSF2_FONT;
enum FontType
{
None,
PCScreenFont1,
PCScreenFont2
};
struct FontInfo
{
uintptr_t *StartAddress;
uintptr_t *EndAddress;
PSF1_FONT *PSF1Font;
PSF2_FONT *PSF2Font;
uint32_t Width, Height;
FontType Type;
};
class Font
{
private:
FontInfo Info;
public:
FontInfo GetInfo() { return Info; }
Font(uintptr_t *Start, uintptr_t *End, FontType Type);
~Font();
};
union Pixel
{
struct
{
uint8_t Alpha;
uint8_t Red;
uint8_t Green;
uint8_t Blue;
};
uint32_t raw;
};
class Display
{
private:
BootInfo::FramebufferInfo framebuffer;
void *Buffer;
size_t Size;
uint32_t Width, Height;
bool DirectWrite;
uint32_t RegionWidth = 64, RegionHeight = 64;
std::vector<bool> DirtyMap;
public:
decltype(Buffer) &GetBuffer = Buffer;
decltype(Size) &GetSize = Size;
decltype(Width) &GetWidth = Width;
decltype(Height) &GetHeight = Height;
BootInfo::FramebufferInfo GetFramebufferStruct() { return framebuffer; }
uint16_t GetBitsPerPixel();
size_t GetPitch();
void ClearBuffer();
void SetPixel(uint32_t X, uint32_t Y, uint32_t Color);
uint32_t GetPixel(uint32_t X, uint32_t Y);
void DrawRectangle(uint32_t X, uint32_t Y,
uint32_t Width, uint32_t Height,
uint32_t Color);
void UpdateRegion(size_t RegionRow, size_t RegionColumn);
void MarkRegionDirty(size_t RegionRow, size_t RegionCol);
void UpdateBuffer();
Display(BootInfo::FramebufferInfo Info,
bool DirectWrite = true);
~Display();
};
}
#endif // !__FENNIX_KERNEL_DISPLAY_H__

165
Kernel/include/driver.hpp Normal file
View File

@ -0,0 +1,165 @@
/*
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_H__
#define __FENNIX_KERNEL_DRIVER_H__
#include <types.h>
#include <interface/driver.h>
#include <interface/input.h>
#include <filesystem.hpp>
#include <unordered_map>
#include <memory.hpp>
#include <ints.hpp>
#include <lock.hpp>
#include <task.hpp>
#include <ring.hpp>
#include <debug.h>
#include <cpu.hpp>
#include <pci.hpp>
#include <vector>
#include <bitset>
#include <elf.h>
#include <io.h>
#include <list>
namespace Driver
{
char GetScanCode(uint8_t ScanCode, bool Upper);
bool IsValidChar(uint8_t ScanCode);
struct DriverHandlers
{
const InodeOperations *Ops = nullptr;
struct Inode *Node = nullptr;
RingBuffer<InputReport> *InputReports;
};
struct DriverObject
{
uintptr_t BaseAddress = 0;
uintptr_t EntryPoint = 0;
Memory::VirtualMemoryArea *vma;
/* Path has the same pointer as in the Node */
std::string Path;
std::unordered_map<uint8_t, void *> *InterruptHandlers;
std::unordered_map<dev_t, DriverHandlers> *DeviceOperations;
dev_t ID = 0;
char Name[32] = {'\0'};
char Description[64] = {'\0'};
char Author[32] = {'\0'};
struct
{
int Major, Minor, Patch;
} Version = {0, 0, 0};
char License[32] = {'\0'};
bool Initialized = false;
int ErrorCode = 0;
int (*Entry)() = nullptr;
int (*Final)() = nullptr;
int (*Panic)() = nullptr;
int (*Probe)() = nullptr;
};
class Manager
{
private:
NewLock(ModuleInitLock);
std::unordered_map<dev_t, DriverObject> Drivers;
/**
* 0 - generic null/zero/random/etc devices
* 1 - input/... devices
*/
dev_t DriverIDCounter = 2;
FileNode *devNode = nullptr;
FileNode *devInputNode = nullptr;
int LoadDriverFile(DriverObject &Drv, FileNode *File);
void InitializeDaemonFS();
dev_t RegisterInputDevice(std::unordered_map<dev_t, DriverHandlers> *, dev_t, size_t, const InodeOperations *);
dev_t RegisterBlockDevice(std::unordered_map<dev_t, DriverHandlers> *, dev_t, size_t, const InodeOperations *);
public:
RingBuffer<KeyboardReport> GlobalKeyboardInputReports;
RingBuffer<MouseReport> GlobalMouseInputReports;
struct DeviceInode
{
struct Inode Node;
FileNode *Parent;
Inode *ParentInode;
std::string Name;
std::vector<DeviceInode *> Children;
};
std::unordered_map<dev_t, DriverObject> &
GetDrivers() { return Drivers; }
void Daemon();
void PreloadDrivers();
void LoadAllDrivers();
void UnloadAllDrivers();
void Panic();
/** Prefixes:
* - dsk (any disk device)
* - dsk0p0 (disk 0, partition 0)
* - blk (block device)
* - eth (Ethernet device)
* - wlan (Wireless LAN device)
* - lo (Loopback device)
* - kb (Keyboard device)
* - ms (Mouse device)
* - js (Joystick device)
* - tp (Touchpad device)
* - tc (Touchscreen device)
* - cam (Camera device)
* - spk (Speaker device)
* - mic (Microphone device)
* - snd (Sound device)
* - tty (Serial device)
* - lp (Parallel device)
* - gpu (Graphics device)
* - fb (Framebuffer device)
* - usb (USB device)
* - usb0dsk0p0 (USB 0, disk 0, partition 0; for USB storage)
*/
dev_t CreateIncrementalDevice(dev_t DriverID, const std::string &Prefix, mode_t Mode, InodeOperations *Ops);
dev_t RegisterDevice(dev_t DriverID, DeviceType Type, const InodeOperations *Operations);
int ReportInputEvent(dev_t DriverID, InputReport *Report);
int UnregisterDevice(dev_t DriverID, dev_t Device);
Manager();
~Manager();
};
void ManagerDaemonWrapper();
}
void *GetSymbolByName(const char *Name, int Version);
#endif // !__FENNIX_KERNEL_DRIVER_H__

25
Kernel/include/dumper.hpp Normal file
View File

@ -0,0 +1,25 @@
/*
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_LIB_DUMPER_H__
#define __FENNIX_LIB_DUMPER_H__
#include <types.h>
void DumpData(const char *Description, void *Address, unsigned long Length);
#endif // !__FENNIX_LIB_DUMPER_H__

979
Kernel/include/elf.h Normal file
View File

@ -0,0 +1,979 @@
/*
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_ELF_H__
#define __FENNIX_KERNEL_ELF_H__
#include <types.h>
/* 32-bit ELF base types. */
typedef uint32_t Elf32_Addr;
typedef uint16_t Elf32_Half;
typedef uint32_t Elf32_Off;
typedef int32_t Elf32_Sword;
typedef uint32_t Elf32_Word;
typedef Elf32_Sword Elf32_pid_t;
/* 64-bit ELF base types. */
typedef uint64_t Elf64_Addr;
typedef uint16_t Elf64_Half;
typedef int16_t Elf64_SHalf;
typedef uint64_t Elf64_Off;
typedef int32_t Elf64_Sword;
typedef uint32_t Elf64_Word;
typedef uint64_t Elf64_Xword;
typedef int64_t Elf64_Sxword;
typedef Elf64_Sword Elf64_pid_t;
#define ELF_NGREG 23
typedef Elf32_Word Elf32_greg_t[ELF_NGREG];
typedef Elf64_Xword Elf64_greg_t[ELF_NGREG];
enum IdentificationIndex
{
EI_MAG0 = 0,
EI_MAG1 = 1,
EI_MAG2 = 2,
EI_MAG3 = 3,
EI_CLASS = 4,
EI_DATA = 5,
EI_VERSION = 6,
EI_OSABI = 7,
EI_ABIVERSION = 8,
EI_PAD = 9,
EI_NIDENT = 16
};
enum Elf_OSABI
{
ELFOSABI_NONE = 0,
ELFOSABI_SYSV = 0,
ELFOSABI_HPUX = 1,
ELFOSABI_NETBSD = 2,
ELFOSABI_GNU = 3,
ELFOSABI_LINUX = 3,
ELFOSABI_HURD = 4,
ELFOSABI_SOLARIS = 6,
ELFOSABI_AIX = 7,
ELFOSABI_IRIX = 8,
ELFOSABI_FREEBSD = 9,
ELFOSABI_TRU64 = 10,
ELFOSABI_MODESTO = 11,
ELFOSABI_OPENBSD = 12,
ELFOSABI_OPENVMS = 13,
ELFOSABI_NSK = 14,
ELFOSABI_AROS = 15,
ELFOSABI_FENIXOS = 16,
ELFOSABI_CLOUDABI = 17,
ELFOSABI_OPENVOS = 18,
ELFOSABI_C6000_ELFABI = 64,
ELFOSABI_C6000_LINUX = 65,
ELFOSABI_ARM = 97,
ELFOSABI_STANDALONE = 255
};
enum FileIdentifiers
{
ET_NONE = 0,
ET_REL = 1,
ET_EXEC = 2,
ET_DYN = 3,
ET_CORE = 4,
ET_LOPROC = 0xff00,
ET_HIPROC = 0xffff
};
enum RelocationTypes
{
R_386_NONE = 0,
R_386_32 = 1,
R_386_PC32 = 2,
R_386_GOT32 = 3,
R_386_PLT32 = 4,
R_386_COPY = 5,
R_386_GLOB_DAT = 6,
R_386_JMP_SLOT = 7,
R_386_RELATIVE = 8,
R_386_GOTOFF = 9,
R_386_GOTPC = 10,
R_386_32PLT = 11,
R_386_TLS_TPOFF = 14,
R_386_TLS_IE = 15,
R_386_TLS_GOTIE = 16,
R_386_TLS_LE = 17,
R_386_TLS_GD = 18,
R_386_TLS_LDM = 19,
R_386_16 = 20,
R_386_PC16 = 21,
R_386_8 = 22,
R_386_PC8 = 23,
R_386_TLS_GD_32 = 24,
R_386_TLS_GD_PUSH = 25,
R_386_TLS_GD_CALL = 26,
R_386_TLS_GD_POP = 27,
R_386_TLS_LDM_32 = 28,
R_386_TLS_LDM_PUSH = 29,
R_386_TLS_LDM_CALL = 30,
R_386_TLS_LDM_POP = 31,
R_386_TLS_LDO_32 = 32,
R_386_TLS_IE_32 = 33,
R_386_TLS_LE_32 = 34,
R_386_TLS_DTPMOD32 = 35,
R_386_TLS_DTPOFF32 = 36,
R_386_TLS_TPOFF32 = 37,
R_386_SIZE32 = 38,
R_386_TLS_GOTDESC = 39,
R_386_TLS_DESC_CALL = 40,
R_386_TLS_DESC = 41,
R_386_IRELATIVE = 42,
R_386_GOT32X = 43,
R_386_NUM = 44,
R_X86_64_NONE = 0,
R_X86_64_64 = 1,
R_X86_64_PC32 = 2,
R_X86_64_GOT32 = 3,
R_X86_64_PLT32 = 4,
R_X86_64_COPY = 5,
R_X86_64_GLOB_DAT = 6,
R_X86_64_JUMP_SLOT = 7,
R_X86_64_RELATIVE = 8,
R_X86_64_GOTPCREL = 9,
R_X86_64_32 = 10,
R_X86_64_32S = 11,
R_X86_64_16 = 12,
R_X86_64_PC16 = 13,
R_X86_64_8 = 14,
R_X86_64_PC8 = 15,
R_X86_64_DTPMOD64 = 16,
R_X86_64_DTPOFF64 = 17,
R_X86_64_TPOFF64 = 18,
R_X86_64_TLSGD = 19,
R_X86_64_TLSLD = 20,
R_X86_64_DTPOFF32 = 21,
R_X86_64_GOTTPOFF = 22,
R_X86_64_TPOFF32 = 23,
R_X86_64_PC64 = 24,
R_X86_64_GOTOFF64 = 25,
R_X86_64_GOTPC32 = 26,
R_X86_64_GOT64 = 27,
R_X86_64_GOTPCREL64 = 28,
R_X86_64_GOTPC64 = 29,
R_X86_64_GOTPLT64 = 30,
R_X86_64_PLTOFF64 = 31,
R_X86_64_SIZE32 = 32,
R_X86_64_SIZE64 = 33,
R_X86_64_GOTPC32_TLSDESC = 34,
R_X86_64_TLSDESC_CALL = 35,
R_X86_64_TLSDESC = 36,
R_X86_64_IRELATIVE = 37,
R_X86_64_RELATIVE64 = 38,
R_X86_64_GOTPCRELX = 41,
R_X86_64_REX_GOTPCRELX = 42,
R_X86_64_NUM = 43
};
enum SegmentFlags
{
PF_X = 1,
PF_W = 2,
PF_R = 4,
PF_MASKPROC = 0xf0000000
};
enum SymbolBindings
{
STB_LOCAL = 0,
STB_GLOBAL = 1,
STB_WEAK = 2,
STB_LOOS = 10,
STB_HIOS = 12,
STB_LOPROC = 13,
STB_HIPROC = 15
};
enum SymbolTypes
{
STT_NOTYPE = 0,
STT_OBJECT = 1,
STT_FUNC = 2,
STT_SECTION = 3,
STT_FILE = 4,
STT_COMMON = 5,
STT_LOOS = 10,
STT_HIOS = 12,
STT_LOPROC = 13,
STT_SPARC_REGISTER = 13,
STT_HIPROC = 15
};
enum SymbolVisibilities
{
STV_DEFAULT = 0,
STV_INTERNAL = 1,
STV_HIDDEN = 2,
STV_PROTECTED = 3
};
enum SegmentTypes
{
PT_NULL = 0,
PT_LOAD = 1,
PT_DYNAMIC = 2,
PT_INTERP = 3,
PT_NOTE = 4,
PT_SHLIB = 5,
PT_PHDR = 6,
PT_TLS = 7,
PT_LOPROC = 0x70000000,
PT_HIPROC = 0x7fffffff,
};
enum DynamicArrayTags
{
DT_NULL = 0,
DT_NEEDED = 1,
DT_PLTRELSZ = 2,
DT_PLTGOT = 3,
DT_HASH = 4,
DT_STRTAB = 5,
DT_SYMTAB = 6,
DT_RELA = 7,
DT_RELASZ = 8,
DT_RELAENT = 9,
DT_STRSZ = 10,
DT_SYMENT = 11,
DT_INIT = 12,
DT_FINI = 13,
DT_SONAME = 14,
DT_RPATH = 15,
DT_SYMBOLIC = 16,
DT_REL = 17,
DT_RELSZ = 18,
DT_RELENT = 19,
DT_PLTREL = 20,
DT_DEBUG = 21,
DT_TEXTREL = 22,
DT_JMPREL = 23,
DT_BIND_NOW = 24,
DT_INIT_ARRAY = 25,
DT_FINI_ARRAY = 26,
DT_INIT_ARRAYSZ = 27,
DT_FINI_ARRAYSZ = 28,
DT_RUNPATH = 29,
DT_FLAGS = 30,
DT_ENCODING = 32,
DT_PREINIT_ARRAY = 32,
DT_PREINIT_ARRAYSZ = 33,
DT_LOOS = 0x6000000d,
DT_SUNW_RTLDINF = 0x6000000e,
DT_HIOS = 0x6ffff000,
DT_VALRNGLO = 0x6ffffd00,
DT_CHECKSUM = 0x6ffffdf8,
DT_PLTPADSZ = 0x6ffffdf9,
DT_MOVEENT = 0x6ffffdfa,
DT_MOVESZ = 0x6ffffdfb,
DT_FEATURE_1 = 0x6ffffdfc,
DT_POSFLAG_1 = 0x6ffffdfd,
DT_SYMINSZ = 0x6ffffdfe,
DT_SYMINENT = 0x6ffffdff,
DT_VALRNGHI = 0x6ffffdff,
DT_ADDRRNGLO = 0x6ffffe00,
DT_CONFIG = 0x6ffffefa,
DT_DEPAUDIT = 0x6ffffefb,
DT_AUDIT = 0x6ffffefc,
DT_PLTPAD = 0x6ffffefd,
DT_MOVETAB = 0x6ffffefe,
DT_SYMINFO = 0x6ffffeff,
DT_ADDRRNGHI = 0x6ffffeff,
DT_RELACOUNT = 0x6ffffff9,
DT_RELCOUNT = 0x6ffffffa,
DT_FLAGS_1 = 0x6ffffffb,
DT_VERDEF = 0x6ffffffc,
DT_VERDEFNUM = 0x6ffffffd,
DT_VERNEED = 0x6ffffffe,
DT_VERNEEDNUM = 0x6fffffff,
DT_LOPROC = 0x70000000,
DT_SPARC_REGISTER = 0x70000001,
DT_AUXILIARY = 0x7ffffffd,
DT_USED = 0x7ffffffe,
DT_FILTER = 0x7fffffff,
DT_HIPROC = 0x7fffffff
};
/* Used for Elf64_Sym st_info */
#define ELF32_ST_BIND(info) ((info) >> 4)
#define ELF32_ST_TYPE(info) ((info) & 0xf)
#define ELF32_ST_INFO(bind, type) (((bind) << 4) + ((type) & 0xf))
#define ELF64_ST_BIND(info) ((info) >> 4)
#define ELF64_ST_TYPE(info) ((info) & 0xf)
#define ELF64_ST_INFO(bind, type) (((bind) << 4) + ((type) & 0xf))
/* Used for Elf64_Sym st_other */
#define ELF32_ST_VISIBILITY(o) ((o) & 0x3)
#define ELF64_ST_VISIBILITY(o) ((o) & 0x3)
#define DO_386_32(S, A) ((S) + (A))
#define DO_386_PC32(S, A, P) ((S) + (A) - (P))
#define DO_64_64(S, A) ((S) + (A))
#define DO_64_PC32(S, A, P) ((S) + (A) - (P))
#define ELF32_R_SYM(i) ((i) >> 8)
#define ELF32_R_TYPE(i) ((unsigned char)(i))
#define ELF32_R_INFO(s, t) (((s) << 8) + (unsigned char)(t))
#define ELF64_R_SYM(i) ((i) >> 32)
#define ELF64_R_TYPE(i) ((i) & 0xffffffffL)
#define ELF64_R_INFO(s, t) (((s) << 32) + ((t) & 0xffffffffL))
#define SHN_UNDEF 0
#define SHN_LORESERVE 0xff00
#define SHN_LOPROC 0xff00
#define SHN_BEFORE 0xff00
#define SHN_AFTER 0xff01
#define SHN_HIPROC 0xff1f
#define SHN_ABS 0xfff1
#define SHN_COMMON 0xfff2
#define SHN_HIRESERVE 0xffff
#define SHF_WRITE 0x1
#define SHF_ALLOC 0x2
#define SHF_EXECINSTR 0x4
#define SHF_MERGE 0x10
#define SHF_STRINGS 0x20
#define SHF_INFO_LINK 0x40
#define SHF_LINK_ORDER 0x80
#define SHF_OS_NONCONFORMING 0x100
#define SHF_GROUP 0x200
#define SHF_TLS 0x400
#define SHF_MASKOS 0x0ff00000
#define SHF_ORDERED 0x40000000
#define SHF_EXCLUDE 0x80000000
#define SHF_MASKPROC 0xf0000000
#define EM_NONE 0 /* No machine */
#define EM_M32 1 /* AT&T WE 32100 */
#define EM_SPARC 2 /* SPARC */
#define EM_386 3 /* Intel 80386 */
#define EM_68K 4 /* Motorola 68000 */
#define EM_88K 5 /* Motorola 88000 */
#define EM_IAMCU 6 /* Intel MCU */
#define EM_860 7 /* Intel 80860 */
#define EM_MIPS 8 /* MIPS I Architecture */
#define EM_S370 9 /* IBM System/370 Processor */
#define EM_MIPS_RS3_LE 10 /* MIPS RS3000 Little-endian */
#define EM_PARISC 15 /* Hewlett-Packard PA-RISC */
#define EM_VPP500 17 /* Fujitsu VPP500 */
#define EM_SPARC32PLUS 18 /* Enhanced instruction set SPARC */
#define EM_960 19 /* Intel 80960 */
#define EM_PPC 20 /* PowerPC */
#define EM_PPC64 21 /* 64-bit PowerPC */
#define EM_S390 22 /* IBM System/390 Processor */
#define EM_SPU 23 /* IBM SPU/SPC */
#define EM_V800 36 /* NEC V800 */
#define EM_FR20 37 /* Fujitsu FR20 */
#define EM_RH32 38 /* TRW RH-32 */
#define EM_RCE 39 /* Motorola RCE */
#define EM_ARM 40 /* ARM 32-bit architecture (AARCH32) */
#define EM_ALPHA 41 /* Digital Alpha */
#define EM_SH 42 /* Hitachi SH */
#define EM_SPARCV9 43 /* SPARC Version 9 */
#define EM_TRICORE 44 /* Siemens TriCore embedded processor */
#define EM_ARC 45 /* Argonaut RISC Core, Argonaut Technologies Inc. */
#define EM_H8_300 46 /* Hitachi H8/300 */
#define EM_H8_300H 47 /* Hitachi H8/300H */
#define EM_H8S 48 /* Hitachi H8S */
#define EM_H8_500 49 /* Hitachi H8/500 */
#define EM_IA_64 50 /* Intel IA-64 processor architecture */
#define EM_MIPS_X 51 /* Stanford MIPS-X */
#define EM_COLDFIRE 52 /* Motorola ColdFire */
#define EM_68HC12 53 /* Motorola M68HC12 */
#define EM_MMA 54 /* Fujitsu MMA Multimedia Accelerator */
#define EM_PCP 55 /* Siemens PCP */
#define EM_NCPU 56 /* Sony nCPU embedded RISC processor */
#define EM_NDR1 57 /* Denso NDR1 microprocessor */
#define EM_STARCORE 58 /* Motorola Star*Core processor */
#define EM_ME16 59 /* Toyota ME16 processor */
#define EM_ST100 60 /* STMicroelectronics ST100 processor */
#define EM_TINYJ 61 /* Advanced Logic Corp. TinyJ embedded processor family */
#define EM_X86_64 62 /* AMD x86-64 architecture */
#define EM_PDSP 63 /* Sony DSP Processor */
#define EM_PDP10 64 /* Digital Equipment Corp. PDP-10 */
#define EM_PDP11 65 /* Digital Equipment Corp. PDP-11 */
#define EM_FX66 66 /* Siemens FX66 microcontroller */
#define EM_ST9PLUS 67 /* STMicroelectronics ST9+ 8/16 bit microcontroller */
#define EM_ST7 68 /* STMicroelectronics ST7 8-bit microcontroller */
#define EM_68HC16 69 /* Motorola MC68HC16 Microcontroller */
#define EM_68HC11 70 /* Motorola MC68HC11 Microcontroller */
#define EM_68HC08 71 /* Motorola MC68HC08 Microcontroller */
#define EM_68HC05 72 /* Motorola MC68HC05 Microcontroller */
#define EM_SVX 73 /* Silicon Graphics SVx */
#define EM_ST19 74 /* STMicroelectronics ST19 8-bit microcontroller */
#define EM_VAX 75 /* Digital VAX */
#define EM_CRIS 76 /* Axis Communications 32-bit embedded processor */
#define EM_JAVELIN 77 /* Infineon Technologies 32-bit embedded processor */
#define EM_FIREPATH 78 /* Element 14 64-bit DSP Processor */
#define EM_ZSP 79 /* LSI Logic 16-bit DSP Processor */
#define EM_MMIX 80 /* Donald Knuth's educational 64-bit processor */
#define EM_HUANY 81 /* Harvard University machine-independent object files */
#define EM_PRISM 82 /* SiTera Prism */
#define EM_AVR 83 /* Atmel AVR 8-bit microcontroller */
#define EM_FR30 84 /* Fujitsu FR30 */
#define EM_D10V 85 /* Mitsubishi D10V */
#define EM_D30V 86 /* Mitsubishi D30V */
#define EM_V850 87 /* NEC v850 */
#define EM_M32R 88 /* Mitsubishi M32R */
#define EM_MN10300 89 /* Matsushita MN10300 */
#define EM_MN10200 90 /* Matsushita MN10200 */
#define EM_PJ 91 /* picoJava */
#define EM_OPENRISC 92 /* OpenRISC 32-bit embedded processor */
#define EM_ARC_COMPACT 93 /* ARC International ARCompact processor (old spelling/synonym: EM_ARC_A5) */
#define EM_XTENSA 94 /* Tensilica Xtensa Architecture */
#define EM_VIDEOCORE 95 /* Alphamosaic VideoCore processor */
#define EM_TMM_GPP 96 /* Thompson Multimedia General Purpose Processor */
#define EM_NS32K 97 /* National Semiconductor 32000 series */
#define EM_TPC 98 /* Tenor Network TPC processor */
#define EM_SNP1K 99 /* Trebia SNP 1000 processor */
#define EM_ST200 100 /* STMicroelectronics (www.st.com) ST200 microcontroller */
#define EM_IP2K 101 /* Ubicom IP2xxx microcontroller family */
#define EM_MAX 102 /* MAX Processor */
#define EM_CR 103 /* National Semiconductor CompactRISC microprocessor */
#define EM_F2MC16 104 /* Fujitsu F2MC16 */
#define EM_MSP430 105 /* Texas Instruments embedded microcontroller msp430 */
#define EM_BLACKFIN 106 /* Analog Devices Blackfin (DSP) processor */
#define EM_SE_C33 107 /* S1C33 Family of Seiko Epson processors */
#define EM_SEP 108 /* Sharp embedded microprocessor */
#define EM_ARCA 109 /* Arca RISC Microprocessor */
#define EM_UNICORE 110 /* Microprocessor series from PKU-Unity Ltd. and MPRC of Peking University */
#define EM_EXCESS 111 /* eXcess: 16/32/64-bit configurable embedded CPU */
#define EM_DXP 112 /* Icera Semiconductor Inc. Deep Execution Processor */
#define EM_ALTERA_NIOS2 113 /* Altera Nios II soft-core processor */
#define EM_CRX 114 /* National Semiconductor CompactRISC CRX microprocessor */
#define EM_XGATE 115 /* Motorola XGATE embedded processor */
#define EM_C166 116 /* Infineon C16x/XC16x processor */
#define EM_M16C 117 /* Renesas M16C series microprocessors */
#define EM_DSPIC30F 118 /* Microchip Technology dsPIC30F Digital Signal Controller */
#define EM_CE 119 /* Freescale Communication Engine RISC core */
#define EM_M32C 120 /* Renesas M32C series microprocessors */
#define EM_TSK3000 131 /* Altium TSK3000 core */
#define EM_RS08 132 /* Freescale RS08 embedded processor */
#define EM_SHARC 133 /* Analog Devices SHARC family of 32-bit DSP processors */
#define EM_ECOG2 134 /* Cyan Technology eCOG2 microprocessor */
#define EM_SCORE7 135 /* Sunplus S+core7 RISC processor */
#define EM_DSP24 136 /* New Japan Radio (NJR) 24-bit DSP Processor */
#define EM_VIDEOCORE3 137 /* Broadcom VideoCore III processor */
#define EM_LATTICEMICO32 138 /* RISC processor for Lattice FPGA architecture */
#define EM_SE_C17 139 /* Seiko Epson C17 family */
#define EM_TI_C6000 140 /* The Texas Instruments TMS320C6000 DSP family */
#define EM_TI_C2000 141 /* The Texas Instruments TMS320C2000 DSP family */
#define EM_TI_C5500 142 /* The Texas Instruments TMS320C55x DSP family */
#define EM_TI_ARP32 143 /* Texas Instruments Application Specific RISC Processor, 32bit fetch */
#define EM_TI_PRU 144 /* Texas Instruments Programmable Realtime Unit */
#define EM_MMDSP_PLUS 160 /* STMicroelectronics 64bit VLIW Data Signal Processor */
#define EM_CYPRESS_M8C 161 /* Cypress M8C microprocessor */
#define EM_R32C 162 /* Renesas R32C series microprocessors */
#define EM_TRIMEDIA 163 /* NXP Semiconductors TriMedia architecture family */
#define EM_QDSP6 164 /* QUALCOMM DSP6 Processor */
#define EM_8051 165 /* Intel 8051 and variants */
#define EM_STXP7X 166 /* STMicroelectronics STxP7x family of configurable and extensible RISC processors */
#define EM_NDS32 167 /* Andes Technology compact code size embedded RISC processor family */
#define EM_ECOG1 168 /* Cyan Technology eCOG1X family */
#define EM_ECOG1X 168 /* Cyan Technology eCOG1X family */
#define EM_MAXQ30 169 /* Dallas Semiconductor MAXQ30 Core Micro-controllers */
#define EM_XIMO16 170 /* New Japan Radio (NJR) 16-bit DSP Processor */
#define EM_MANIK 171 /* M2000 Reconfigurable RISC Microprocessor */
#define EM_CRAYNV2 172 /* Cray Inc. NV2 vector architecture */
#define EM_RX 173 /* Renesas RX family */
#define EM_METAG 174 /* Imagination Technologies META processor architecture */
#define EM_MCST_ELBRUS 175 /* MCST Elbrus general purpose hardware architecture */
#define EM_ECOG16 176 /* Cyan Technology eCOG16 family */
#define EM_CR16 177 /* National Semiconductor CompactRISC CR16 16-bit microprocessor */
#define EM_ETPU 178 /* Freescale Extended Time Processing Unit */
#define EM_SLE9X 179 /* Infineon Technologies SLE9X core */
#define EM_L10M 180 /* Intel L10M */
#define EM_K10M 181 /* Intel K10M */
#define EM_AARCH64 183 /* ARM 64-bit architecture (AARCH64) */
#define EM_AVR32 185 /* Atmel Corporation 32-bit microprocessor family */
#define EM_STM8 186 /* STMicroeletronics STM8 8-bit microcontroller */
#define EM_TILE64 187 /* Tilera TILE64 multicore architecture family */
#define EM_TILEPRO 188 /* Tilera TILEPro multicore architecture family */
#define EM_MICROBLAZE 189 /* Xilinx MicroBlaze 32-bit RISC soft processor core */
#define EM_CUDA 190 /* NVIDIA CUDA architecture */
#define EM_TILEGX 191 /* Tilera TILE-Gx multicore architecture family */
#define EM_CLOUDSHIELD 192 /* CloudShield architecture family */
#define EM_COREA_1ST 193 /* KIPO-KAIST Core-A 1st generation processor family */
#define EM_COREA_2ND 194 /* KIPO-KAIST Core-A 2nd generation processor family */
#define EM_ARC_COMPACT2 195 /* Synopsys ARCompact V2 */
#define EM_OPEN8 196 /* Open8 8-bit RISC soft processor core */
#define EM_RL78 197 /* Renesas RL78 family */
#define EM_VIDEOCORE5 198 /* Broadcom VideoCore V processor */
#define EM_78KOR 199 /* Renesas 78KOR family */
#define EM_56800EX 200 /* Freescale 56800EX Digital Signal Controller (DSC) */
#define EM_BA1 201 /* Beyond BA1 CPU architecture */
#define EM_BA2 202 /* Beyond BA2 CPU architecture */
#define EM_XCORE 203 /* XMOS xCORE processor family */
#define EM_MCHP_PIC 204 /* Microchip 8-bit PIC(r) family */
#define EM_INTEL205 205 /* Reserved by Intel */
#define EM_INTEL206 206 /* Reserved by Intel */
#define EM_INTEL207 207 /* Reserved by Intel */
#define EM_INTEL208 208 /* Reserved by Intel */
#define EM_INTEL209 209 /* Reserved by Intel */
#define EM_KM32 210 /* KM211 KM32 32-bit processor */
#define EM_KMX32 211 /* KM211 KMX32 32-bit processor */
#define EM_KMX16 212 /* KM211 KMX16 16-bit processor */
#define EM_KMX8 213 /* KM211 KMX8 8-bit processor */
#define EM_KVARC 214 /* KM211 KVARC processor */
#define EM_CDP 215 /* Paneve CDP architecture family */
#define EM_COGE 216 /* Cognitive Smart Memory Processor */
#define EM_COOL 217 /* Bluechip Systems CoolEngine */
#define EM_NORC 218 /* Nanoradio Optimized RISC */
#define EM_CSR_KALIMBA 219 /* CSR Kalimba architecture family */
#define EM_Z80 220 /* Zilog Z80 */
#define EM_VISIUM 221 /* Controls and Data Services VISIUMcore processor */
#define EM_FT32 222 /* FTDI Chip FT32 high performance 32-bit RISC architecture */
#define EM_MOXIE 223 /* Moxie processor family */
#define EM_AMDGPU 224 /* AMD GPU architecture */
#define EM_RISCV 243 /* RISC-V */
#define EV_NONE 0x0 /* Invalid ELF Version */
#define EV_CURRENT 0x1 /* ELF Current Version */
#define ELFMAG0 0x7F
#define ELFMAG1 'E'
#define ELFMAG2 'L'
#define ELFMAG3 'F'
#define ELFDATANONE 0
#define ELFDATA2LSB 1
#define ELFDATA2MSB 2
#define ELFCLASSNONE 0
#define ELFCLASS32 1
#define ELFCLASS64 2
#define ELFCLASSNUM 3
enum SpecialSections
{
SHT_NULL = 0,
SHT_PROGBITS = 1,
SHT_SYMTAB = 2,
SHT_STRTAB = 3,
SHT_RELA = 4,
SHT_HASH = 5,
SHT_DYNAMIC = 6,
SHT_NOTE = 7,
SHT_NOBITS = 8,
SHT_REL = 9,
SHT_SHLIB = 10,
SHT_DYNSYM = 11,
SHT_INIT_ARRAY = 14,
SHT_FINI_ARRAY = 15,
SHT_PREINIT_ARRAY = 16,
SHT_GROUP = 17,
SHT_SYMTAB_SHNDX = 18,
SHT_NUM = 19,
SHT_LOOS = 0x60000000,
SHT_GNU_ATTRIBUTES = 0x6ffffff5,
SHT_GNU_HASH = 0x6ffffff6,
SHT_GNU_LIBLIST = 0x6ffffff7,
SHT_CHECKSUM = 0x6ffffff8,
SHT_LOSUNW = 0x6ffffffa,
SHT_SUNW_move = 0x6ffffffa,
SHT_SUNW_COMDAT = 0x6ffffffb,
SHT_SUNW_syminfo = 0x6ffffffc,
SHT_GNU_verdef = 0x6ffffffd,
SHT_GNU_verneed = 0x6ffffffe,
SHT_GNU_versym = 0x6fffffff,
SHT_HISUNW = 0x6fffffff,
SHT_HIOS = 0x6fffffff,
SHT_LOPROC = 0x70000000,
SHT_HIPROC = 0x7fffffff,
SHT_LOUSER = 0x80000000,
SHT_HIUSER = 0x8fffffff
};
#define NT_PRSTATUS 1
#define NT_PRFPREG 2
#define NT_FPREGSET 2
#define NT_PRPSINFO 3
#define NT_PRXREG 4
#define NT_TASKSTRUCT 4
#define NT_PLATFORM 5
#define NT_AUXV 6
#define NT_GWINDOWS 7
#define NT_ASRS 8
#define NT_PSTATUS 10
#define NT_PSINFO 13
#define NT_PRCRED 14
#define NT_UTSNAME 15
#define NT_LWPSTATUS 16
#define NT_LWPSINFO 17
#define NT_PRFPXREG 20
#define NT_SIGINFO 0x53494749
#define NT_FILE 0x46494c45
#define NT_PRXFPREG 0x46e62b7f
#define NT_PPC_VMX 0x100
#define NT_PPC_SPE 0x101
#define NT_PPC_VSX 0x102
#define NT_PPC_TAR 0x103
#define NT_PPC_PPR 0x104
#define NT_PPC_DSCR 0x105
#define NT_PPC_EBB 0x106
#define NT_PPC_PMU 0x107
#define NT_PPC_TM_CGPR 0x108
#define NT_PPC_TM_CFPR 0x109
#define NT_PPC_TM_CVMX 0x10a
#define NT_PPC_TM_CVSX 0x10b
#define NT_PPC_TM_SPR 0x10c
#define NT_PPC_TM_CTAR 0x10d
#define NT_PPC_TM_CPPR 0x10e
#define NT_PPC_TM_CDSCR 0x10f
#define NT_386_TLS 0x200
#define NT_386_IOPERM 0x201
#define NT_X86_XSTATE 0x202
#define NT_S390_HIGH_GPRS 0x300
#define NT_S390_TIMER 0x301
#define NT_S390_TODCMP 0x302
#define NT_S390_TODPREG 0x303
#define NT_S390_CTRS 0x304
#define NT_S390_PREFIX 0x305
#define NT_S390_LAST_BREAK 0x306
#define NT_S390_SYSTEM_CALL 0x307
#define NT_S390_TDB 0x308
#define NT_S390_VXRS_LOW 0x309
#define NT_S390_VXRS_HIGH 0x30a
#define NT_S390_GS_CB 0x30b
#define NT_S390_GS_BC 0x30c
#define NT_S390_RI_CB 0x30d
#define NT_ARM_VFP 0x400
#define NT_ARM_TLS 0x401
#define NT_ARM_HW_BREAK 0x402
#define NT_ARM_HW_WATCH 0x403
#define NT_ARM_SYSTEM_CALL 0x404
#define NT_ARM_SVE 0x405
#define NT_ARM_PAC_MASK 0x406
#define NT_ARM_PACA_KEYS 0x407
#define NT_ARM_PACG_KEYS 0x408
#define NT_ARM_TAGGED_ADDR_CTRL 0x409
#define NT_ARM_PAC_ENABLED_KEYS 0x40a
#define NT_METAG_CBUF 0x500
#define NT_METAG_RPIPE 0x501
#define NT_METAG_TLS 0x502
#define NT_ARC_V2 0x600
#define NT_VMCOREDD 0x700
#define NT_MIPS_DSP 0x800
#define NT_MIPS_FP_MODE 0x801
#define NT_MIPS_MSA 0x802
#define NT_VERSION 1
typedef struct elf32_hdr
{
unsigned char e_ident[EI_NIDENT];
Elf32_Half e_type;
Elf32_Half e_machine;
Elf32_Word e_version;
Elf32_Addr e_entry;
Elf32_Off e_phoff;
Elf32_Off e_shoff;
Elf32_Word e_flags;
Elf32_Half e_ehsize;
Elf32_Half e_phentsize;
Elf32_Half e_phnum;
Elf32_Half e_shentsize;
Elf32_Half e_shnum;
Elf32_Half e_shstrndx;
} Elf32_Ehdr;
typedef struct elf64_hdr
{
unsigned char e_ident[EI_NIDENT];
Elf64_Half e_type;
Elf64_Half e_machine;
Elf64_Word e_version;
Elf64_Addr e_entry;
Elf64_Off e_phoff;
Elf64_Off e_shoff;
Elf64_Word e_flags;
Elf64_Half e_ehsize;
Elf64_Half e_phentsize;
Elf64_Half e_phnum;
Elf64_Half e_shentsize;
Elf64_Half e_shnum;
Elf64_Half e_shstrndx;
} Elf64_Ehdr;
typedef struct elf32_shdr
{
Elf32_Word sh_name;
Elf32_Word sh_type;
Elf32_Word sh_flags;
Elf32_Addr sh_addr;
Elf32_Off sh_offset;
Elf32_Word sh_size;
Elf32_Word sh_link;
Elf32_Word sh_info;
Elf32_Word sh_addralign;
Elf32_Word sh_entsize;
} Elf32_Shdr;
typedef struct elf64_shdr
{
Elf64_Word sh_name;
Elf64_Word sh_type;
Elf64_Xword sh_flags;
Elf64_Addr sh_addr;
Elf64_Off sh_offset;
Elf64_Xword sh_size;
Elf64_Word sh_link;
Elf64_Word sh_info;
Elf64_Xword sh_addralign;
Elf64_Xword sh_entsize;
} Elf64_Shdr;
typedef struct
{
Elf32_Word p_type;
Elf32_Off p_offset;
Elf32_Addr p_vaddr;
Elf32_Addr p_paddr;
Elf32_Word p_filesz;
Elf32_Word p_memsz;
Elf32_Word p_flags;
Elf32_Word p_align;
} Elf32_Phdr;
typedef struct
{
Elf64_Word p_type;
Elf64_Word p_flags;
Elf64_Off p_offset;
Elf64_Addr p_vaddr;
Elf64_Addr p_paddr;
Elf64_Xword p_filesz;
Elf64_Xword p_memsz;
Elf64_Xword p_align;
} Elf64_Phdr;
typedef struct elf32_rel
{
Elf32_Addr r_offset;
Elf32_Word r_info;
} Elf32_Rel;
typedef struct elf64_rel
{
Elf64_Addr r_offset;
Elf64_Xword r_info;
} Elf64_Rel;
typedef struct elf32_sym
{
Elf32_Word st_name;
Elf32_Addr st_value;
Elf32_Word st_size;
unsigned char st_info;
unsigned char st_other;
Elf32_Half st_shndx;
} Elf32_Sym;
typedef struct elf64_sym
{
Elf64_Word st_name;
unsigned char st_info;
unsigned char st_other;
Elf64_Half st_shndx;
Elf64_Addr st_value;
Elf64_Xword st_size;
} Elf64_Sym;
struct Elf32_Dyn
{
Elf32_Sword d_tag;
union
{
Elf32_Word d_val;
Elf32_Addr d_ptr;
} d_un;
};
struct Elf64_Dyn
{
Elf64_Sxword d_tag;
union
{
Elf64_Xword d_val;
Elf64_Addr d_ptr;
} d_un;
};
typedef struct
{
Elf32_Addr r_offset;
Elf32_Word r_info;
Elf32_Sword r_addend;
} Elf32_Rela;
typedef struct
{
Elf64_Addr r_offset;
Elf64_Xword r_info;
Elf64_Sxword r_addend;
} Elf64_Rela;
struct Elf32_Nhdr
{
Elf32_Word n_namesz;
Elf32_Word n_descsz;
Elf32_Word n_type;
};
struct Elf64_Nhdr
{
Elf64_Word n_namesz;
Elf64_Word n_descsz;
Elf64_Word n_type;
};
typedef struct
{
Elf32_Sword si_signo;
Elf32_Sword si_code;
Elf32_Sword si_errno;
} Elf32_Siginfo;
typedef struct
{
Elf64_Sword si_signo;
Elf64_Sword si_code;
Elf64_Sword si_errno;
} Elf64_Siginfo;
typedef struct
{
Elf32_Sword tv_sec;
Elf32_Sword tv_usec;
} Elf32_Prtimeval;
typedef struct
{
Elf64_Sxword tv_sec;
Elf64_Sxword tv_usec;
} Elf64_Prtimeval;
typedef struct
{
Elf32_Siginfo pr_info;
Elf32_Half pr_cursig;
Elf32_Word pr_sigpend;
Elf32_Word pr_sighold;
Elf32_pid_t pr_pid;
Elf32_pid_t pr_ppid;
Elf32_pid_t pr_pgrp;
Elf32_pid_t pr_sid;
Elf32_Prtimeval pr_utime;
Elf32_Prtimeval pr_stime;
Elf32_Prtimeval pr_cutime;
Elf32_Prtimeval pr_cstime;
Elf32_greg_t pr_reg;
Elf32_Word pr_fpvalid;
} Elf32_Prstatus;
typedef struct
{
Elf64_Siginfo pr_info;
Elf64_Half pr_cursig;
Elf64_Word pr_sigpend;
Elf64_Word pr_sighold;
Elf64_pid_t pr_pid;
Elf64_pid_t pr_ppid;
Elf64_pid_t pr_pgrp;
Elf64_pid_t pr_sid;
Elf64_Prtimeval pr_utime;
Elf64_Prtimeval pr_stime;
Elf64_Prtimeval pr_cutime;
Elf64_Prtimeval pr_cstime;
Elf64_greg_t pr_reg;
Elf64_Word pr_fpvalid;
} Elf64_Prstatus;
#define ELF_PRARGSZ 80
typedef struct
{
char pr_state;
char pr_sname;
char pr_zomb;
char pr_nice;
Elf32_Word pr_flag;
Elf32_Half pr_uid;
Elf32_Half pr_gid;
Elf32_pid_t pr_pid;
Elf32_pid_t pr_ppid;
Elf32_pid_t pr_pgrp;
Elf32_pid_t pr_sid;
char pr_fname[16];
char pr_psargs[ELF_PRARGSZ];
} Elf32_Prpsinfo;
typedef struct
{
char pr_state;
char pr_sname;
char pr_zomb;
char pr_nice;
Elf64_Xword pr_flag;
Elf64_Half pr_uid;
Elf64_Half pr_gid;
Elf64_pid_t pr_pid;
Elf64_pid_t pr_ppid;
Elf64_pid_t pr_pgrp;
Elf64_pid_t pr_sid;
char pr_fname[16];
char pr_psargs[ELF_PRARGSZ];
} Elf64_Prpsinfo;
#if defined(a64) || defined(aa64)
typedef Elf64_Addr Elf_Addr;
typedef Elf64_Half Elf_Half;
typedef Elf64_Off Elf_Off;
typedef Elf64_Sword Elf_Sword;
typedef Elf64_Word Elf_Word;
typedef Elf64_Ehdr Elf_Ehdr;
typedef Elf64_Shdr Elf_Shdr;
typedef Elf64_Phdr Elf_Phdr;
typedef Elf64_Rel Elf_Rel;
typedef Elf64_Sym Elf_Sym;
typedef Elf64_Dyn Elf_Dyn;
typedef Elf64_Rela Elf_Rela;
#elif defined(a32)
typedef Elf32_Addr Elf_Addr;
typedef Elf32_Half Elf_Half;
typedef Elf32_Off Elf_Off;
typedef Elf32_Sword Elf_Sword;
typedef Elf32_Word Elf_Word;
typedef Elf32_Ehdr Elf_Ehdr;
typedef Elf32_Shdr Elf_Shdr;
typedef Elf32_Phdr Elf_Phdr;
typedef Elf32_Rel Elf_Rel;
typedef Elf32_Sym Elf_Sym;
typedef Elf32_Dyn Elf_Dyn;
typedef Elf32_Rela Elf_Rela;
#endif
#endif // !__FENNIX_KERNEL_ELF_H__

126
Kernel/include/exec.hpp Normal file
View File

@ -0,0 +1,126 @@
/*
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_FILE_EXECUTE_H__
#define __FENNIX_KERNEL_FILE_EXECUTE_H__
#include <types.h>
#include <filesystem.hpp>
#include <task.hpp>
#include <errno.h>
#include <vector>
#include <elf.h>
namespace Execute
{
enum BinaryType : int
{
BinTypeInvalid,
BinTypeELF,
BinTypePE,
BinTypeNE,
BinTypeMZ,
BinTypeMachO,
BinTypeUnknown
};
struct SharedLibrary
{
char Identifier[64];
char Path[256];
uint64_t Timeout;
int RefCount;
uintptr_t MemoryImage;
size_t Length;
};
struct MmImage
{
void *Physical;
void *Virtual;
};
class ELFObject
{
private:
bool IsElfValid;
const char **ELFargv;
const char **ELFenvp;
std::vector<AuxiliaryVector> Elfauxv;
Tasking::IP ip;
void *ELFProgramHeaders;
void GenerateAuxiliaryVector_x86_32(Memory::VirtualMemoryArea *vma,
FileNode *fd, Elf32_Ehdr ELFHeader,
uint32_t EntryPoint,
uint32_t BaseAddress);
void GenerateAuxiliaryVector_x86_64(Memory::VirtualMemoryArea *vma,
FileNode *fd, Elf64_Ehdr ELFHeader,
uint64_t EntryPoint,
uint64_t BaseAddress);
void LoadExec_x86_32(FileNode *fd, Tasking::PCB *TargetProcess);
void LoadExec_x86_64(FileNode *fd, Tasking::PCB *TargetProcess);
void LoadDyn_x86_32(FileNode *fd, Tasking::PCB *TargetProcess);
void LoadDyn_x86_64(FileNode *fd, Tasking::PCB *TargetProcess);
bool LoadInterpreter(FileNode *fd, Tasking::PCB *TargetProcess);
public:
decltype(IsElfValid) &IsValid = IsElfValid;
decltype(ip) &InstructionPointer = ip;
decltype(ELFargv) &argv = ELFargv;
decltype(ELFenvp) &envp = ELFenvp;
decltype(Elfauxv) &auxv = Elfauxv;
ELFObject(std::string AbsolutePath,
Tasking::PCB *TargetProcess,
const char **argv,
const char **envp);
~ELFObject();
};
BinaryType GetBinaryType(FileNode *Path);
BinaryType GetBinaryType(std::string Path);
int Spawn(char *Path, const char **argv, const char **envp,
Tasking::PCB *Parent = nullptr, bool Fork = false,
Tasking::TaskCompatibility Compatibility = Tasking::Native,
bool Critical = false);
bool ELFIs64(void *Header);
Elf64_Shdr *GetELFSheader(Elf64_Ehdr *Header);
Elf64_Shdr *GetELFSection(Elf64_Ehdr *Header, uint64_t Index);
char *GetELFStringTable(Elf64_Ehdr *Header);
char *ELFLookupString(Elf64_Ehdr *Header, uintptr_t Offset);
Elf64_Sym *ELFLookupSymbol(Elf64_Ehdr *Header, std::string Name);
Elf64_Sym ELFLookupSymbol(FileNode *fd, std::string Name);
uintptr_t ELFGetSymbolValue(Elf64_Ehdr *Header, uint64_t Table, uint64_t Index);
std::vector<Elf64_Phdr> ELFGetSymbolType_x86_64(FileNode *fd, SegmentTypes Tag);
std::vector<Elf32_Phdr> ELFGetSymbolType_x86_32(FileNode *fd, SegmentTypes Tag);
std::vector<Elf64_Shdr> ELFGetSections_x86_64(FileNode *fd, std::string SectionName);
std::vector<Elf32_Shdr> ELFGetSections_x86_32(FileNode *fd, std::string SectionName);
std::vector<Elf64_Dyn> ELFGetDynamicTag_x86_64(FileNode *fd, DynamicArrayTags Tag);
std::vector<Elf32_Dyn> ELFGetDynamicTag_x86_32(FileNode *fd, DynamicArrayTags Tag);
}
#endif // !__FENNIX_KERNEL_FILE_EXECUTE_H__

View File

@ -0,0 +1,228 @@
/*
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_FILESYSTEM_H__
#define __FENNIX_KERNEL_FILESYSTEM_H__
#include <types.h>
#include <interface/fs.h>
#include <unordered_map>
#include <lock.hpp>
#include <errno.h>
#include <atomic>
#include <string>
#include <list>
static_assert(DTTOIF(DT_FIFO) == S_IFIFO);
static_assert(IFTODT(S_IFCHR) == DT_CHR);
#define __check_op(op, err, ...) \
if (fsi->Ops.op == nullptr) \
return -err; \
else \
return fsi->Ops.op(this->Node, ##__VA_ARGS__)
#define FSROOT(num) "\x06root-" #num "\x06"
class FileNode
{
public:
std::string Name, Path;
FileNode *Parent;
std::vector<FileNode *> Children;
Inode *Node;
FileSystemInfo *fsi;
std::string GetName();
std::string GetPath();
bool IsDirectory() { return S_ISDIR(Node->Mode); }
bool IsCharacterDevice() { return S_ISCHR(Node->Mode); }
bool IsBlockDevice() { return S_ISBLK(Node->Mode); }
bool IsRegularFile() { return S_ISREG(Node->Mode); }
bool IsFIFO() { return S_ISFIFO(Node->Mode); }
bool IsSymbolicLink() { return S_ISLNK(Node->Mode); }
bool IsSocket() { return S_ISSOCK(Node->Mode); }
int Lookup(const char *Name, Inode **Node) { __check_op(Lookup, ENOTSUP, Name, Node); }
int Create(const char *Name, mode_t Mode, Inode **Node) { __check_op(Create, EROFS, Name, Mode, Node); }
int Remove(const char *Name) { __check_op(Remove, EROFS, Name); }
int Rename(const char *OldName, const char *NewName) { __check_op(Rename, EROFS, OldName, NewName); }
ssize_t Read(auto Buffer, size_t Size, off_t Offset) { __check_op(Read, ENOTSUP, (void *)Buffer, Size, Offset); }
ssize_t Write(const auto Buffer, size_t Size, off_t Offset) { __check_op(Write, EROFS, (const void *)Buffer, Size, Offset); }
int Truncate(off_t Size) { __check_op(Truncate, EROFS, Size); }
int Open(int Flags, mode_t Mode) { __check_op(Open, ENOTSUP, Flags, Mode); }
int Close() { __check_op(Close, ENOTSUP); }
int Ioctl(unsigned long Request, void *Argp) { __check_op(Ioctl, ENOTSUP, Request, Argp); }
ssize_t ReadDir(struct kdirent *Buffer, size_t Size, off_t Offset, off_t Entries) { __check_op(ReadDir, ENOTSUP, Buffer, Size, Offset, Entries); }
int MkDir(const char *Name, mode_t Mode, struct Inode **Result) { __check_op(MkDir, EROFS, Name, Mode, Result); }
int RmDir(const char *Name) { __check_op(RmDir, EROFS, Name); }
int SymLink(const char *Name, const char *Target, struct Inode **Result) { __check_op(SymLink, EROFS, Name, Target, Result); }
ssize_t ReadLink(auto Buffer, size_t Size) { __check_op(ReadLink, ENOTSUP, (char *)Buffer, Size); }
off_t Seek(off_t Offset) { __check_op(Seek, ENOTSUP, Offset); }
int Stat(struct kstat *Stat) { __check_op(Stat, ENOTSUP, Stat); }
~FileNode() = delete;
};
#undef __check_op
namespace vfs
{
struct vfsInode
{
Inode Node;
std::string Name;
std::string FriendlyName;
std::vector<Inode *> Children;
};
class Virtual
{
private:
NewLock(VirtualLock);
struct FSMountInfo
{
FileSystemInfo *fsi;
Inode *Root;
};
struct CacheNode
{
FileNode *fn;
std::atomic_int References;
};
std::unordered_map<dev_t, FSMountInfo> DeviceMap;
std::atomic_bool RegisterLock = false;
FileNode *CacheSearchReturnLast(FileNode *Parent, const char **Path);
FileNode *CacheRecursiveSearch(FileNode *Root, const char *NameOrPath, bool IsName);
FileNode *CacheLookup(const char *Path);
FileNode *CreateCacheNode(FileNode *Parent, Inode *Node, const char *Name, mode_t Mode);
int RemoveCacheNode(FileNode *Node);
public:
vfsInode *FileSystemRoots = nullptr;
std::unordered_map<ino_t, FileNode *> FileRoots;
bool PathIsRelative(const char *Path);
bool PathIsAbsolute(const char *Path) { return !PathIsRelative(Path); }
/**
* Reserve a device number for a filesystem
*
* @note After this function is called, the filesystem must
* call LateRegisterFileSystem to release the lock
*/
dev_t EarlyReserveDevice();
/**
* Register a filesystem after the device number has been reserved
*/
int LateRegisterFileSystem(dev_t Device, FileSystemInfo *fsi, Inode *Root);
dev_t RegisterFileSystem(FileSystemInfo *fsi, Inode *Root);
int UnregisterFileSystem(dev_t Device);
void AddRoot(Inode *Root);
FileNode *GetRoot(size_t Index);
FileNode *Create(FileNode *Parent, const char *Name, mode_t Mode);
FileNode *ForceCreate(FileNode *Parent, const char *Name, mode_t Mode);
FileNode *Mount(FileNode *Parent, Inode *Node, const char *Path);
int Unmount(const char *Path);
FileNode *GetByPath(const char *Path, FileNode *Parent);
std::string GetByNode(FileNode *Node);
FileNode *CreateLink(const char *Path, FileNode *Parent, const char *Target);
FileNode *CreateLink(const char *Path, FileNode *Parent, FileNode *Target);
bool PathExists(const char *Path, FileNode *Parent);
int Remove(FileNode *Node);
void Initialize();
Virtual();
~Virtual();
};
class FileDescriptorTable
{
public:
struct Fildes
{
enum FildesType
{
FD_INODE,
FD_PIPE,
FD_SOCKET,
} Type;
mode_t Mode = 0;
int Flags = 0;
FileNode *Node = nullptr;
int References = 0;
off_t Offset = 0;
int operator==(const Fildes &other)
{
return Type == other.Type &&
Mode == other.Mode &&
Flags == other.Flags &&
Node == other.Node &&
References == other.References &&
Offset == other.Offset;
}
};
private:
FileNode *fdDir = nullptr;
void *Owner;
int AddFileDescriptor(const char *AbsolutePath, mode_t Mode, int Flags);
int RemoveFileDescriptor(int FileDescriptor);
int GetFreeFileDescriptor();
public:
std::unordered_map<int, Fildes> FileMap;
int GetFlags(int FileDescriptor);
int SetFlags(int FileDescriptor, int Flags);
void Fork(FileDescriptorTable *Parent);
int usr_open(const char *pathname, int flags, mode_t mode);
int usr_creat(const char *pathname, mode_t mode);
ssize_t usr_read(int fd, void *buf, size_t count);
ssize_t usr_write(int fd, const void *buf, size_t count);
int usr_close(int fd);
off_t usr_lseek(int fd, off_t offset, int whence);
int usr_stat(const char *pathname, struct kstat *statbuf);
int usr_fstat(int fd, struct kstat *statbuf);
int usr_lstat(const char *pathname, struct kstat *statbuf);
int usr_dup(int oldfd);
int usr_dup2(int oldfd, int newfd);
int usr_ioctl(int fd, unsigned long request, void *argp);
FileDescriptorTable(void *Owner);
~FileDescriptorTable() = default;
};
}
#endif // !__FENNIX_KERNEL_FILESYSTEM_H__

View File

@ -0,0 +1,91 @@
/*
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_FILESYSTEM_EXT2_H__
#define __FENNIX_KERNEL_FILESYSTEM_EXT2_H__
#include <types.h>
#include <filesystem.hpp>
namespace vfs
{
class EXT2
{
public:
struct SuperBlock
{
uint32_t Inodes;
uint32_t Blocks;
uint32_t ReservedBlocks;
uint32_t FreeBlock;
uint32_t FreeInodes;
uint32_t FirstDataBlock;
uint32_t LogBlockSize;
uint32_t LogFragSize;
uint32_t BlocksPerGroup;
uint32_t FragsPerGroup;
uint32_t InodesPerGroup;
uint32_t LastMountTime;
uint32_t LastWrittenTime;
uint16_t MountedTimes;
uint16_t MaximumMountedTimes;
uint16_t Magic;
uint16_t State;
uint16_t Errors;
uint16_t MinorRevLevel;
uint32_t LastCheck;
uint32_t CheckInternval;
uint32_t SystemID;
uint32_t RevLevel;
uint16_t ReservedBlocksUserID;
uint16_t ReservedBlocksGroupID;
uint32_t FirstInode;
uint16_t InodeSize;
uint16_t BlockGroups;
uint32_t FeatureCompatibility;
uint32_t FeatureIncompatibility;
uint32_t FeatureRoCompatibility;
uint8_t UUID[16];
char VolumeName[16];
char LastMounted[64];
uint32_t BitmapAlogrithm;
uint8_t PreallocatedBlocks;
uint8_t PreallocatedDirectoryBlocks;
uint16_t Padding;
uint8_t JournalUUID[16];
uint32_t JournalInum;
uint32_t JournalDev;
uint32_t LastOrphan;
uint32_t HashSeed[4];
uint8_t DefHashVersion;
uint8_t ReservedCharPad;
uint16_t ReservedWordPad;
uint32_t DefaultMountOptions;
uint32_t FirstMetaBg;
uint32_t Reserved[190];
};
EXT2(void *partition);
~EXT2();
};
}
#endif // !__FENNIX_KERNEL_FILESYSTEM_EXT2_H__

View File

@ -0,0 +1,48 @@
/*
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_FILESYSTEM_INITRD_H__
#define __FENNIX_KERNEL_FILESYSTEM_INITRD_H__
#include <types.h>
#include <filesystem.hpp>
namespace vfs
{
class Initrd
{
public:
struct InitrdHeader
{
uint32_t nfiles;
};
struct InitrdFileHeader
{
uint8_t magic;
char name[64];
uint32_t offset;
uint32_t length;
};
Initrd(uintptr_t Address);
~Initrd();
};
}
#endif // !__FENNIX_KERNEL_FILESYSTEM_INITRD_H__

View File

@ -0,0 +1,77 @@
/*
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_FILESYSTEM_IOCTL_H__
#define __FENNIX_KERNEL_FILESYSTEM_IOCTL_H__
#include <types.h>
#include <stropts.h>
#include <termios.h>
#define _IOC_NRBITS 8
#define _IOC_TYPEBITS 8
#define _IOC_SIZEBITS 14
#define _IOC_DIRBITS 2
#define _IOC_NRMASK \
((1 << _IOC_NRBITS) - 1)
#define _IOC_TYPEMASK \
((1 << _IOC_TYPEBITS) - 1)
#define _IOC_SIZEMASK \
((1 << _IOC_SIZEBITS) - 1)
#define _IOC_DIRMASK \
((1 << _IOC_DIRBITS) - 1)
#define _IOC_NRSHIFT 0
#define _IOC_TYPESHIFT \
(_IOC_NRSHIFT + _IOC_NRBITS)
#define _IOC_SIZESHIFT \
(_IOC_TYPESHIFT + _IOC_TYPEBITS)
#define _IOC_DIRSHIFT \
(_IOC_SIZESHIFT + _IOC_SIZEBITS)
#define _IOC(dir, type, nr, size) \
(((dir) << _IOC_DIRSHIFT) | \
((type) << _IOC_TYPESHIFT) | \
((nr) << _IOC_NRSHIFT) | \
((size) << _IOC_SIZESHIFT))
#define _IOC_NONE 0U
#define _IOC_WRITE 1U
#define _IOC_READ 2U
#define _IOC_TYPECHECK(t) (sizeof(t))
#define _IO(type, nr) \
_IOC(_IOC_NONE, (type), (nr), 0)
#define _IOR(type, nr, size) \
_IOC(_IOC_READ, (type), (nr), (_IOC_TYPECHECK(size)))
#define _IOW(type, nr, size) \
_IOC(_IOC_WRITE, (type), (nr), (_IOC_TYPECHECK(size)))
#define _IOWR(type, nr, size) \
_IOC(_IOC_READ | _IOC_WRITE, (type), (nr), (_IOC_TYPECHECK(size)))
#define _IOR_BAD(type, nr, size) \
_IOC(_IOC_READ, (type), (nr), sizeof(size))
#define _IOW_BAD(type, nr, size) \
_IOC(_IOC_WRITE, (type), (nr), sizeof(size))
#define _IOWR_BAD(type, nr, size) \
_IOC(_IOC_READ | _IOC_WRITE, (type), (nr), sizeof(size))
#define TIOCGPTN _IOR('T', 0x30, unsigned int)
#define TIOCSPTLCK _IOW('T', 0x31, int)
#endif // !__FENNIX_KERNEL_FILESYSTEM_IOCTL_H__

View File

@ -0,0 +1,137 @@
/*
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_FILESYSTEM_USTAR_H__
#define __FENNIX_KERNEL_FILESYSTEM_USTAR_H__
#include <filesystem.hpp>
namespace vfs
{
class USTAR
{
public:
enum TypeFlag
{
AREGTYPE = '\0',
REGTYPE = '0',
LNKTYPE = '1',
SYMTYPE = '2',
CHRTYPE = '3',
BLKTYPE = '4',
DIRTYPE = '5',
FIFOTYPE = '6',
CONTTYPE = '7'
};
enum ModeFlag
{
TSUID = 04000,
TSGID = 02000,
TSVTX = 01000,
TUREAD = 00400,
TUWRITE = 00200,
TUEXEC = 00100,
TGREAD = 00040,
TGWRITE = 00020,
TGEXEC = 00010,
TOREAD = 00004,
TOWRITE = 00002,
TOEXEC = 00001,
};
struct FileHeader
{
char name[100];
char mode[8];
char uid[8];
char gid[8];
char size[12];
char mtime[12];
char chksum[8];
char typeflag[1];
char link[100];
char signature[6];
char version[2];
char owner[32];
char group[32];
char dev_maj[8];
char dev_min[8];
char prefix[155];
char pad[12];
};
constexpr static int INODE_CHECKSUM = 0x7757A4;
struct USTARInode
{
struct Inode Node;
FileHeader *Header;
USTARInode *Parent;
std::string Name;
std::string Path;
std::vector<USTARInode *> Children;
bool Deleted;
int Checksum;
};
private:
std::unordered_map<ino_t, USTARInode *> Files;
inline uint32_t GetSize(const char *String)
{
uint32_t ret = 0;
while (*String)
{
ret *= 8;
ret += *String - '0';
String++;
}
return ret;
}
inline int StringToInt(const char *String)
{
int ret = 0;
for (int i = 0; String[i] != '\0'; ++i)
ret = ret * 10 + String[i] - '0';
return ret;
}
public:
dev_t DeviceID = -1;
ino_t NextInode = 0;
int Lookup(struct Inode *Parent, const char *Name, struct Inode **Result);
int Create(struct Inode *Parent, const char *Name, mode_t Mode, struct Inode **Result);
ssize_t Read(struct Inode *Node, void *Buffer, size_t Size, off_t Offset);
ssize_t ReadDir(struct Inode *Node, struct kdirent *Buffer, size_t Size, off_t Offset, off_t Entries);
int SymLink(struct Inode *Node, const char *Name, const char *Target, struct Inode **Result);
ssize_t ReadLink(struct Inode *Node, char *Buffer, size_t Size);
int Stat(struct Inode *Node, struct kstat *Stat);
bool TestArchive(uintptr_t Address);
void ReadArchive(uintptr_t Address, size_t Size);
USTAR(){};
~USTAR(){};
};
}
bool TestAndInitializeUSTAR(uintptr_t Address, size_t Size);
#endif // !__FENNIX_KERNEL_FILESYSTEM_USTAR_H__

121
Kernel/include/hashmap.hpp Normal file
View File

@ -0,0 +1,121 @@
/*
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/>.
*/
#pragma once
#define HASHMAP_ERROR -0x8A50
template <typename K, typename V>
class HashNode
{
public:
V Value;
K Key;
HashNode(K Key, V Value)
{
this->Value = Value;
this->Key = Key;
}
};
template <typename K, typename V>
class HashMap
{
int HashMapSize;
int HashMapCapacity;
HashNode<K, V> **Nodes;
HashNode<K, V> *DummyNode;
public:
HashMap()
{
HashMapCapacity = 20;
HashMapSize = 0;
Nodes = new HashNode<K, V> *[HashMapCapacity];
for (int i = 0; i < HashMapCapacity; i++)
Nodes[i] = nullptr;
DummyNode = new HashNode<K, V>(-1, -1);
}
~HashMap()
{
for (int i = 0; i < HashMapCapacity; i++)
if (Nodes[i] != nullptr)
delete Nodes[i], Nodes[i] = nullptr;
delete[] Nodes, Nodes = nullptr;
delete DummyNode, DummyNode = nullptr;
}
int HashCode(K Key) { return Key % HashMapCapacity; }
void AddNode(K Key, V Value)
{
HashNode<K, V> *tmp = new HashNode<K, V>(Key, Value);
int Index = HashCode(Key);
while (Nodes[Index] != nullptr && Nodes[Index]->Key != Key && Nodes[Index]->Key != (K)-1)
{
Index++;
Index %= HashMapCapacity;
}
if (Nodes[Index] == nullptr || Nodes[Index]->Key == (K)-1)
HashMapSize++;
Nodes[Index] = tmp;
}
V DeleteNode(int Key)
{
int Index = HashCode(Key);
while (Nodes[Index] != nullptr)
{
if (Nodes[Index]->Key == Key)
{
HashNode<K, V> *tmp = Nodes[Index];
Nodes[Index] = DummyNode;
HashMapSize--;
return tmp->Value;
}
Index++;
Index %= HashMapCapacity;
}
return HASHMAP_ERROR;
}
V Get(int Key)
{
int Index = HashCode(Key);
int Iterate = 0;
while (Nodes[Index] != nullptr)
{
if (Iterate++ > HashMapCapacity)
return HASHMAP_ERROR;
if (Nodes[Index]->Key == (K)Key)
return Nodes[Index]->Value;
Index++;
Index %= HashMapCapacity;
}
return HASHMAP_ERROR;
}
int Size() { return HashMapSize; }
bool IsEmpty() { return HashMapSize == 0; }
};

1067
Kernel/include/ini.h Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,259 @@
/*
This file is part of Fennix Drivers.
Fennix Drivers 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 Drivers 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 Drivers. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef __FENNIX_API_AIP_H__
#define __FENNIX_API_AIP_H__
#include <types.h>
#define PIC1_CMD 0x20
#define PIC1_DATA (PIC1_CMD + 1)
#define PIC2_CMD 0xA0
#define PIC2_DATA (PIC2_CMD + 1)
#define _PIC_EOI 0x20
#define PS2_DATA 0x60
#define PS2_STATUS 0x64
#define PS2_CMD PS2_STATUS
#define PS2_ACK 0xFA
#define PS2_TEST_PASSED 0x55
#define PS2_TEST_FAILED 0xFC
#define PS2_CMD_READ_CONFIG 0x20
#define PS2_CMD_READ_CONFIG_N(n) (PS2_CMD_READ_CONFIG + n)
#define PS2_CMD_WRITE_CONFIG 0x60
#define PS2_CMD_WRITE_CONFIG_N(n) (PS2_CMD_WRITE_CONFIG + n)
#define PS2_CMD_DISABLE_PORT_2 0xA7
#define PS2_CMD_ENABLE_PORT_2 0xA8
#define PS2_CMD_TEST_PORT_2 0xA9
#define PS2_CMD_TEST_CONTROLLER 0xAA
#define PS2_CMD_TEST_PORT_1 0xAB
#define PS2_CMD_DIAGNOSTIC_DUMP 0xAC
#define PS2_CMD_DISABLE_PORT_1 0xAD
#define PS2_CMD_ENABLE_PORT_1 0xAE
#define PS2_CMD_READ_INPUT_PORT 0xC0
#define PS2_CMD_COPY_INPUT_0_3_TO_4_7_STATUS 0xC1
#define PS2_CMD_COPY_INPUT_4_7_TO_4_7_STATUS 0xC2
#define PS2_CMD_READ_OUTPUT_PORT 0xD0
#define PS2_CMD_WRITE_NEXT_BYTE_TO_OUTPUT_PORT 0xD1
#define PS2_CMD_WRITE_NEXT_BYTE_TO_PS2_PORT_1_OUTPUT 0xD2
#define PS2_CMD_WRITE_NEXT_BYTE_TO_PS2_PORT_2_OUTPUT 0xD3
#define PS2_CMD_WRITE_NEXT_BYTE_TO_PS2_PORT_2_INPUT 0xD4
#define PS2_CMD_PULSE_OUTPUT_LINE(n) (0xF0 + n)
typedef union
{
struct
{
uint8_t OutputBufferFull : 1;
uint8_t InputBufferFull : 1;
uint8_t SystemFlag : 1;
uint8_t CommandData : 1;
uint8_t Unknown1 : 1;
uint8_t Unknown2 : 1;
uint8_t TimeoutError : 1;
uint8_t ParityError : 1;
};
uint8_t Raw;
} PS2_STATUSES;
typedef union
{
struct
{
uint8_t Port1Interrupt : 1;
uint8_t Port2Interrupt : 1;
uint8_t SystemFlag : 1;
uint8_t Zero0 : 1;
uint8_t Port1Clock : 1;
uint8_t Port2Clock : 1;
uint8_t Port1Translation : 1;
uint8_t Zero1 : 1;
};
uint8_t Raw;
} PS2_CONFIGURATION;
typedef union
{
struct
{
uint8_t SystemReset : 1;
uint8_t A20Gate : 1;
uint8_t Port2Clock : 1;
uint8_t Port2Data : 1;
uint8_t Port1OutputBufferFull : 1;
uint8_t Port2OutputBufferFull : 1;
uint8_t Port1InputBufferFull : 1;
uint8_t Port2InputBufferFull : 1;
};
uint8_t Raw;
} PS2_OUTPUT_PORT;
void PIC_EOI(uint8_t IRQ);
void IRQ_MASK(uint8_t IRQ);
void IRQ_UNMASK(uint8_t IRQ);
void PS2Wait(const bool Output);
void PS2WriteCommand(uint8_t Command);
void PS2WriteData(uint8_t Data);
uint8_t PS2ReadData();
uint8_t PS2ReadStatus();
uint8_t PS2ReadAfterACK();
void PS2ClearOutputBuffer();
int PS2ACKTimeout();
#define WaitOutput PS2Wait(DriverID, true)
#define WaitInput PS2Wait(DriverID, false)
#define PS2_KBD_CMD_SET_LEDS 0xED
#define PS2_KBD_CMD_ECHO 0xEE
#define PS2_KBD_CMD_SCAN_CODE_SET 0xF0
#define PS2_KBD_CMD_IDENTIFY 0xF2
#define PS2_KBD_CMD_TYPEMATIC 0xF3
#define PS2_KBD_CMD_ENABLE_SCANNING 0xF4
#define PS2_KBD_CMD_DISABLE_SCANNING 0xF5
#define PS2_KBD_CMD_DEFAULTS 0xF6
#define PS2_KBD_CMD_ALL_TYPEMATIC 0xF7
#define PS2_KBD_CMD_ALL_MAKE_RELEASE 0xF8
#define PS2_KBD_CMD_ALL_MAKE 0xF9
#define PS2_KBD_CMD_ALL_TYPEMATIC_MAKE_RELEASE 0xFA
#define PS2_KBD_CMD_SPECIFIC_TYPEMATIC 0xFB
#define PS2_KBD_CMD_SPECIFIC_MAKE_RELEASE 0xFC
#define PS2_KBD_CMD_SPECIFIC_MAKE 0xFD
#define PS2_KBD_CMD_RESEND 0xFE
#define PS2_KBD_CMD_RESET 0xFF
#define PS2_KBD_RESP_ACK 0xFA
#define PS2_KBD_RESP_ECHO 0xEE
#define PS2_KBD_RESP_RESEND 0xFE
#define PS2_KBD_RESP_TEST_PASSED 0xAA
#define PS2_KBD_RESP_TEST_FAILED 0xFC
#define PS2_KBD_RESP_TEST_FAILED_2 0xFD
typedef enum
{
PS2_KBD_LED_SCROLL_LOCK = 1,
PS2_KBD_LED_NUM_LOCK = 2,
PS2_KBD_LED_CAPS_LOCK = 4
} PS2_KBD_LEDS;
typedef enum
{
PS2_KBD_SCAN_CODE_GET_CURRENT = 0,
PS2_KBD_SCAN_CODE_SET_1 = 1,
PS2_KBD_SCAN_CODE_SET_2 = 2,
PS2_KBD_SCAN_CODE_SET_3 = 3,
PS2_KBD_SC_SET_1 = 0x43,
PS2_KBD_SC_SET_2 = 0x41,
PS2_KBD_SC_SET_3 = 0x3F
} PS2_KBD_SCAN_CODE_SET;
typedef union
{
struct
{
/**
* 00000b - 30Hz
* 11111b - 2Hz
*/
uint8_t RepeatRate : 5;
/**
* 00b - 250ms
* 01b - 500ms
* 10b - 750ms
* 11b - 1000ms
*/
uint8_t Delay : 2;
/**
* Must be zero
*/
uint8_t Zero : 1;
};
uint8_t Raw;
} PS2_KBD_TYPEMATIC;
#define PS2_MOUSE_CMD_SET_SCALING_1_1 0xE6
#define PS2_MOUSE_CMD_SET_SCALING_2_1 0xE7
#define PS2_MOUSE_CMD_SET_RESOLUTION 0xE8
#define PS2_MOUSE_CMD_GET_STATUS 0xE9
#define PS2_MOUSE_CMD_SET_STREAM_MODE 0xEA
#define PS2_MOUSE_CMD_READ_DATA 0xEB
#define PS2_MOUSE_CMD_RESET_WRAP_MODE 0xEC
#define PS2_MOUSE_CMD_SET_WRAP_MODE 0xEE
#define PS2_MOUSE_CMD_SET_REMOTE_MODE 0xF0
#define PS2_MOUSE_CMD_READ_ID 0xF2
/** Values: 10, 20, 40, 60, 80, 100, 200 */
#define PS2_MOUSE_CMD_SET_SAMPLE_RATE 0xF3
#define PS2_MOUSE_CMD_ENABLE_DATA_REPORTING 0xF4
#define PS2_MOUSE_CMD_DISABLE_DATA_REPORTING 0xF5
#define PS2_MOUSE_CMD_SET_DEFAULTS 0xF6
#define PS2_MOUSE_CMD_RESEND 0xFE
#define PS2_MOUSE_CMD_RESET 0xFF
#define PS2_MOUSE_RESP_ACK 0xFA
#define PS2_MOUSE_RESP_RESEND 0xFE
#define PS2_MOUSE_RESP_TEST_PASSED 0xAA
#define PS2_MOUSE_RESP_TEST_FAILED 0xFC
typedef enum
{
PS2_MOUSE_RES_1 = 0,
PS2_MOUSE_RES_2 = 1,
PS2_MOUSE_RES_4 = 2,
PS2_MOUSE_RES_8 = 3
} PS2_MOUSE_RESOLUTION;
typedef struct
{
union
{
struct
{
uint8_t LeftButton : 1;
uint8_t RightButton : 1;
uint8_t MiddleButton : 1;
uint8_t Always1 : 1;
uint8_t XSign : 1;
uint8_t YSign : 1;
uint8_t XOverflow : 1;
uint8_t YOverflow : 1;
} __attribute__((packed));
uint8_t Raw;
} Base;
uint8_t XMovement;
uint8_t YMovement;
union
{
struct
{
uint8_t Z : 4;
uint8_t Button4 : 1;
uint8_t Button5 : 1;
uint8_t Always0 : 1;
uint8_t Always0_2 : 1;
} __attribute__((packed));
uint8_t Raw;
} ZMovement;
} PS2_MOUSE_PACKET;
#endif // !__FENNIX_API_AIP_H__

View File

@ -0,0 +1,29 @@
/*
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_API_AUDIO_H__
#define __FENNIX_API_AUDIO_H__
#include <types.h>
#if __has_include(<interface/device.h>)
#include <interface/device.h>
#else
#include <device.h>
#endif
#endif // !__FENNIX_API_AUDIO_H__

View File

@ -0,0 +1,75 @@
/*
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_API_DEVICE_H__
#define __FENNIX_API_DEVICE_H__
#include <types.h>
#ifndef __FENNIX_API_FILESYSTEM_H__
#if __has_include(<interface/fs.h>)
#include <interface/fs.h>
#else
#include <fs.h>
#endif
#endif // !__FENNIX_API_FILESYSTEM_H__
typedef enum
{
DEVICE_TYPE_MASK = 0b1111111100000000000000000000000000000000,
DEVICE_TYPE_NONE = 0b0000000000000000000000000000000000000000,
DEVICE_TYPE_INPUT = 0b0000000100000000000000000000000000000000,
DEVICE_TYPE_AUDIO = 0b0000001000000000000000000000000000000000,
DEVICE_TYPE_NETWORK = 0b0000010000000000000000000000000000000000,
DEVICE_TYPE_BLOCK = 0b0000100000000000000000000000000000000000,
INPUT_TYPE_NONE = DEVICE_TYPE_INPUT + 0,
INPUT_TYPE_KEYBOARD = DEVICE_TYPE_INPUT + 2,
INPUT_TYPE_MOUSE = DEVICE_TYPE_INPUT + 4,
INPUT_TYPE_JOYSTICK = DEVICE_TYPE_INPUT + 8,
INPUT_TYPE_TOUCHSCREEN = DEVICE_TYPE_INPUT + 16,
INPUT_TYPE_GAMEPAD = DEVICE_TYPE_INPUT + 32,
INPUT_TYPE_ACCELEROMETER = DEVICE_TYPE_INPUT + 64,
INPUT_TYPE_GYROSCOPE = DEVICE_TYPE_INPUT + 128,
INPUT_TYPE_MAGNETOMETER = DEVICE_TYPE_INPUT + 256,
AUDIO_TYPE_NONE = DEVICE_TYPE_AUDIO + 0,
AUDIO_TYPE_PWM = DEVICE_TYPE_AUDIO + 2,
AUDIO_TYPE_DSP = DEVICE_TYPE_AUDIO + 4,
AUDIO_TYPE_PCM = DEVICE_TYPE_AUDIO + 8,
AUDIO_TYPE_MIDI = DEVICE_TYPE_AUDIO + 16,
NETWORK_TYPE_NONE = DEVICE_TYPE_NETWORK + 0,
NETWORK_TYPE_ETHERNET = DEVICE_TYPE_NETWORK + 2,
NETWORK_TYPE_WIFI = DEVICE_TYPE_NETWORK + 4,
NETWORK_TYPE_BLUETOOTH = DEVICE_TYPE_NETWORK + 8,
NETWORK_TYPE_UART = DEVICE_TYPE_NETWORK + 16,
BLOCK_TYPE_NONE = DEVICE_TYPE_BLOCK + 0,
BLOCK_TYPE_SDCARD = DEVICE_TYPE_BLOCK + 2,
BLOCK_TYPE_HDD = DEVICE_TYPE_BLOCK + 4,
BLOCK_TYPE_SSD = DEVICE_TYPE_BLOCK + 8,
BLOCK_TYPE_USB = DEVICE_TYPE_BLOCK + 16,
BLOCK_TYPE_NVME = DEVICE_TYPE_BLOCK + 32,
BLOCK_TYPE_CDROM = DEVICE_TYPE_BLOCK + 64,
BLOCK_TYPE_FLOPPY = DEVICE_TYPE_BLOCK + 128,
} DeviceType;
EXTERNC dev_t RegisterDevice(DeviceType Type, const struct InodeOperations *Operations);
EXTERNC int UnregisterDevice(dev_t Device);
#endif // !__FENNIX_API_DEVICE_H__

View File

@ -0,0 +1,76 @@
/*
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_API_DRIVER_FUNCTIONS_H__
#define __FENNIX_API_DRIVER_FUNCTIONS_H__
#include <types.h>
typedef struct
{
/* PCIDevice */ void *Device;
/* __PCIArray */ void *Next;
} __PCIArray;
/* ========================================== */
#define PCI_END 0x0000
#define KEY_NULL 0x00
typedef enum
{
IOCTL_AUDIO_GET_VOLUME = 0,
IOCTL_AUDIO_SET_VOLUME = 1,
IOCTL_AUDIO_GET_MUTE = 2,
IOCTL_AUDIO_SET_MUTE = 3,
IOCTL_AUDIO_GET_SAMPLE_RATE = 4,
IOCTL_AUDIO_SET_SAMPLE_RATE = 5,
IOCTL_AUDIO_GET_CHANNELS = 6,
IOCTL_AUDIO_SET_CHANNELS = 7,
} AudioIoctl;
typedef enum
{
IOCTL_NET_GET_MAC = 0,
} NetIoctl;
typedef enum
{
MAP_PRESENT = 1 << 0,
MAP_WRITE = 1 << 1,
MAP_USER = 1 << 2,
MAP_WRITE_THROUGH = 1 << 3,
MAP_CACHE_DISABLE = 1 << 4,
} PageMapFlags;
struct __DriverInfo
{
const char *Name;
const char *Description;
const char *Author;
struct __DriverVersion
{
int APIVersion;
int Major, Minor, Patch;
} Version;
const char *License;
};
#endif // !__FENNIX_API_DRIVER_FUNCTIONS_H__

View File

@ -0,0 +1,604 @@
/*
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_ERRNO_H__
#define __FENNIX_KERNEL_ERRNO_H__
/**
* The documentation for these error codes are from:
* https://pubs.opengroup.org/onlinepubs/9699919799/functions/V2_chap02.html
*
* Full list:
* https://pubs.opengroup.org/onlinepubs/9699919799.2018edition/basedefs/errno.h.html
*/
typedef enum
{
/**
* No Error
*/
EOK = 0,
/**
* Argument list too long. The sum of the number of bytes used by the
* new process image's argument list and environment list is greater
* than the system-imposed limit of {ARG_MAX} bytes.
* or:
* Lack of space in an output buffer.
* or:
* Argument is greater than the system-imposed maximum.
*/
E2BIG = 1,
/**
* Permission denied. An attempt was made to access a file in a way
* forbidden by its file access permissions.
*/
EACCES = 2,
/**
* Address in use. The specified address is in use.
*/
EADDRINUSE = 3,
/**
* Address not available. The specified address is not available from
* the local system.
*/
EADDRNOTAVAIL = 4,
/**
* Address family not supported. The implementation does not support
* the specified address family, or the specified address is not a
* valid address for the address family of the specified socket.
*/
EAFNOSUPPORT = 5,
/**
* Resource temporarily unavailable. This is a temporary condition
* and later calls to the same routine may complete normally.
*/
EAGAIN = 6,
/**
* Connection already in progress. A connection request is already in
* progress for the specified socket.
*/
EALREADY = 7,
/**
* Bad file descriptor. A file descriptor argument is out of range,
* refers to no open file, or a read (write) request is made to a
* file that is only open for writing (reading).
*/
EBADF = 8,
/**
* Bad message. During a read(), getmsg(), getpmsg(), or ioctl()
* I_RECVFD request to a STREAMS device, a message arrived at the
* head of the STREAM that is inappropriate for the function
* receiving the message.
* read()
* Message waiting to be read on a STREAM is not a data message.
* getmsg() or getpmsg()
* A file descriptor was received instead of a control message.
* ioctl()
* Control or data information was received instead of a file
* descriptor when I_RECVFD was specified.
*/
EBADMSG = 9,
/**
* Resource busy. An attempt was made to make use of a system
* resource that is not currently available, as it is being
* used by another process in a manner that would have
* conflicted with the request being made by this process.
*/
EBUSY = 10,
/**
* Operation canceled. The associated asynchronous operation was
* canceled before completion.
*/
ECANCELED = 11,
/**
* No child process. A wait(), waitid(), or waitpid() function was
* executed by a process that had no existing or unwaited-for
* child process.
*/
ECHILD = 12,
/**
* Connection aborted. The connection has been aborted.
*/
ECONNABORTED = 13,
/**
* Connection refused. An attempt to connect to a socket was refused
* because there was no process listening or because the queue of
* connection requests was full and the underlying protocol does not
* support retransmissions.
*/
ECONNREFUSED = 14,
/**
* Connection reset. The connection was forcibly closed by the peer.
*/
ECONNRESET = 15,
/**
* Resource deadlock would occur. An attempt was made to lock a system
* resource that would have resulted in a deadlock situation.
*/
EDEADLK = 16,
/**
* Destination address required. No bind address was established.
*/
EDESTADDRREQ = 17,
/**
* Domain error. An input argument is outside the defined domain of the
* mathematical function (defined in the ISO C standard).
*/
EDOM = 18,
/**
* Reserved.
*/
EDQUOT = 19,
/**
* File exists. An existing file was mentioned in an inappropriate
* context; for example, as a new link name in the link() function.
*/
EEXIST = 20,
/**
* Bad address. The system detected an invalid address in attempting
* to use an argument of a call. The reliable detection of this error
* cannot be guaranteed, and when not detected may result in the
* generation of a signal, indicating an address violation, which is
* sent to the process.
*/
EFAULT = 21,
/**
* File too large. The size of a file would exceed the maximum file
* size of an implementation or offset maximum established in the
* corresponding file description.
*/
EFBIG = 22,
/**
* Host is unreachable. The destination host cannot be reached
* (probably because the host is down or a remote router cannot
* reach it).
*/
EHOSTUNREACH = 23,
/**
* Identifier removed. Returned during XSI interprocess communication
* if an identifier has been removed from the system.
*/
EIDRM = 24,
/**
* Illegal byte sequence. A wide-character code has been detected that
* does not correspond to a valid character, or a byte sequence does
* not form a valid wide-character code (defined in the ISO C standard).
*/
EILSEQ = 25,
/**
* Operation in progress. This code is used to indicate that an
* asynchronous operation has not yet completed.
* or:
* O_NONBLOCK is set for the socket file descriptor and the connection
* cannot be immediately established.
*/
EINPROGRESS = 26,
/**
* Interrupted function call. An asynchronous signal was caught by the
* process during the execution of an interruptible function. If the
* signal handler performs a normal return, the interrupted function
* call may return this condition (see the Base Definitions volume
* of POSIX.1-2017, <signal.h>).
*/
EINTR = 27,
/**
* Invalid argument. Some invalid argument was supplied; for example,
* specifying an undefined signal in a signal() function or a
* kill() function.
*/
EINVAL = 28,
/**
* Input/output error. Some physical input or output error has occurred.
* This error may be reported on a subsequent operation on the same
* file descriptor. Any other error-causing operation on the same file
* descriptor may cause the [EIO] error indication to be lost.
*/
EIO = 29,
/**
* Socket is connected. The specified socket is already connected.
*/
EISCONN = 30,
/**
* Is a directory. An attempt was made to open a directory with write
* mode specified.
*/
EISDIR = 31,
/**
* Symbolic link loop. A loop exists in symbolic links encountered
* during pathname resolution. This error may also be returned if
* more than {SYMLOOP_MAX} symbolic links are encountered during
* pathname resolution.
*/
ELOOP = 32,
/**
* File descriptor value too large or too many open streams. An
* attempt was made to open a file descriptor with a value greater
* than or equal to {OPEN_MAX}, or an attempt was made to open more
* than the maximum number of streams allowed in the process.
*/
EMFILE = 33,
/**
* Too many links. An attempt was made to have the link count of a
* single file exceed {LINK_MAX}.
*/
EMLINK = 34,
/**
* Message too large. A message sent on a transport provider was
* larger than an internal message buffer or some other network limit.
* or:
* Inappropriate message buffer length.
*/
EMSGSIZE = 35,
/**
* Reserved.
*/
EMULTIHOP = 36,
/**
* Filename too long. The length of a pathname exceeds {PATH_MAX} and
* the implementation considers this to be an error, or a pathname
* component is longer than {NAME_MAX}. This error may also occur
* when pathname substitution, as a result of encountering a
* symbolic link during pathname resolution, results in a pathname
* string the size of which exceeds {PATH_MAX}.
*/
ENAMETOOLONG = 37,
/**
* Network is down. The local network interface used to reach the
* destination is down.
*/
ENETDOWN = 38,
/**
* The connection was aborted by the network.
*/
ENETRESET = 39,
/**
* Network unreachable. No route to the network is present.
*/
ENETUNREACH = 40,
/**
* Too many files open in system. Too many files are currently open
* in the system. The system has reached its predefined limit for
* simultaneously open files and temporarily cannot accept requests
* to open another one.
*/
ENFILE = 41,
/**
* No buffer space available. Insufficient buffer resources were
* available in the system to perform the socket operation.
*/
ENOBUFS = 42,
/**
* No message available. No message is available on the STREAM head
* read queue.
*/
ENODATA = 43,
/**
* No such device. An attempt was made to apply an inappropriate
* function to a device; for example, trying to read a write-only
* device such as a printer.
*/
ENODEV = 44,
/**
* No such file or directory. A component of a specified pathname
* does not exist, or the pathname is an empty string.
*/
ENOENT = 45,
/**
* Executable file format error. A request is made to execute a file
* that, although it has appropriate privileges, is not in the
* format required by the implementation for executable files.
*/
ENOEXEC = 46,
/**
* No locks available. A system-imposed limit on the number of
* simultaneous file and record locks has been reached and no more
* are currently available.
*/
ENOLCK = 47,
/**
* Reserved.
*/
ENOLINK = 48,
/**
* Not enough space. The new process image requires more memory than
* is allowed by the hardware or system-imposed memory management
* constraints.
*/
ENOMEM = 49,
/**
* No message of the desired type. The message queue does not contain
* a message of the required type during XSI interprocess communication.
*/
ENOMSG = 50,
/**
* Protocol not available. The protocol option specified to
* setsockopt() is not supported by the implementation.
*/
ENOPROTOOPT = 51,
/**
* No space left on a device. During the write() function on a
* regular file or when extending a directory, there is no free
* space left on the device.
*/
ENOSPC = 52,
/**
* No STREAM resources. Insufficient STREAMS memory resources are
* available to perform a STREAMS-related function. This is a
* temporary condition; it may be recovered from if other
* processes release resources.
*/
ENOSR = 53,
/**
* Not a STREAM. A STREAM function was attempted on a file descriptor
* that was not associated with a STREAMS device.
*/
ENOSTR = 54,
/**
* Functionality not supported. An attempt was made to use optional
* functionality that is not supported in this implementation.
*/
ENOSYS = 55,
/**
* Socket not connected. The socket is not connected.
*/
ENOTCONN = 56,
/**
* Not a directory. A component of the specified pathname exists, but
* it is not a directory, when a directory was expected; or an
* attempt was made to create a non-directory file, and the specified
* pathname contains at least one non- <slash> character and ends
* with one or more trailing <slash> characters.
*/
ENOTDIR = 57,
/**
* Directory not empty. A directory other than an empty directory
* was supplied when an empty directory was expected.
*/
ENOTEMPTY = 58,
/**
* State not recoverable. The state protected by a robust mutex
* is not recoverable.
*/
ENOTRECOVERABLE = 59,
/**
* Not a socket. The file descriptor does not refer to a socket.
*/
ENOTSOCK = 60,
/**
* Not supported. The implementation does not support the requested
* feature or value.
*/
ENOTSUP = 61,
/**
* Inappropriate I/O control operation. A control function has been
* attempted for a file or special file for which the operation
* is inappropriate.
*/
ENOTTY = 62,
/**
* No such device or address. Input or output on a special file
* refers to a device that does not exist, or makes a request
* beyond the capabilities of the device. It may also occur when,
* for example, a tape drive is not on-line.
*/
ENXIO = 63,
/**
* Operation not supported on socket. The type of socket (address
* family or protocol) does not support the requested operation.
*/
EOPNOTSUPP = 64,
/**
* Value too large to be stored in data type. An operation was
* attempted which would generate a value that is outside the
* range of values that can be represented in the relevant data
* type or that are allowed for a given data item.
*/
EOVERFLOW = 65,
/**
* Previous owner died. The owner of a robust mutex terminated
* while holding the mutex lock.
*/
EOWNERDEAD = 66,
/**
* Operation not permitted. An attempt was made to perform an
* operation limited to processes with appropriate privileges or
* to the owner of a file or other resource.
*/
EPERM = 67,
/**
* Broken pipe. A write was attempted on a socket, pipe, or FIFO
* for which there is no process to read the data.
*/
EPIPE = 68,
/**
* Protocol error. Some protocol error occurred. This error is
* device-specific, but is generally not related to a
* hardware failure.
*/
EPROTO = 69,
/**
* Protocol not supported. The protocol is not supported by the
* address family, or the protocol is not supported by
* the implementation.
*/
EPROTONOSUPPORT = 70,
/**
* Protocol wrong type for socket. The socket type is not
* supported by the protocol.
*/
EPROTOTYPE = 71,
/**
* Result too large or too small. The result of the function
* is too large (overflow) or too small (underflow) to be
* represented in the available space.
*/
ERANGE = 72,
/**
* Read-only file system. An attempt was made to modify a file
* or directory on a file system that is read-only.
*/
EROFS = 73,
/**
* Invalid seek. An attempt was made to access the file offset
* associated with a pipe or FIFO.
*/
ESPIPE = 74,
/**
* No such process. No process can be found corresponding to that
* specified by the given process ID.
*/
ESRCH = 75,
/**
* Reserved.
*/
ESTALE = 76,
/**
* STREAM ioctl() timeout. The timer set for a STREAMS ioctl() call
* has expired. The cause of this error is device-specific and could
* indicate either a hardware or software failure, or a timeout
* value that is too short for the specific operation. The status
* of the ioctl() operation is unspecified.
*/
ETIME = 77,
/**
* Connection timed out. The connection to a remote machine has
* timed out.
* If the connection timed out during execution of the function that
* reported this error (as opposed to timing out prior to the
* function being called), it is unspecified whether the function
* has completed some or all of the documented behavior associated
* with a successful completion of the function.
* or:
* Operation timed out. The time limit associated with the operation
* was exceeded before the operation completed.
*/
ETIMEDOUT = 78,
/**
* Text file busy. An attempt was made to execute a pure-procedure
* program that is currently open for writing, or an attempt has
* been made to open for writing a pure-procedure program that
* is being executed.
*/
ETXTBSY = 79,
/**
* Operation would block. An operation on a socket marked as
* non-blocking has encountered a situation such as no data available
* that otherwise would have caused the function to suspend execution.
*/
EWOULDBLOCK = 80,
/**
* Improper link. A link to a file on another file system was attempted.
*/
EXDEV = 81,
__ERRNO_MAX
} KernelErrors;
#include <types.h>
EXTERNC int *__errno_location(void) __attribute__((const));
#define errno (*__errno_location())
#ifdef __cplusplus
extern "C"
{
#endif
char *strerror(int errnum);
#ifdef __cplusplus
}
#endif
#endif // !__FENNIX_KERNEL_ERRNO_H__

View File

@ -0,0 +1,382 @@
/*
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_API_FILESYSTEM_H__
#define __FENNIX_API_FILESYSTEM_H__
#include <types.h>
#define SEEK_SET 0
#define SEEK_CUR 1
#define SEEK_END 2
/**
* File type mask for the upper 32 bits of mode_t.
*
* @note Maybe it will be used in the future.
*/
#define S_IFMT32 037777600000
/**
* File type mask.
*
* This mask is used to extract the file type
* from the mode field of a stat structure.
*
* Doing bitwise AND with this mask will return
* the file type.
* Example: st_mode & S_IFMT
*
* Doing bitwise negation and AND with this mask
* will return the permissions.
* Example: st_mode & ~S_IFMT
*/
#define S_IFMT 0170000
/* Whiteout */
#define S_IFWHT 0160000
/* Socket */
#define S_IFSOCK 0140000
/* Symbolic link */
#define S_IFLNK 0120000
/* Regular file */
#define S_IFREG 0100000
/* Block device */
#define S_IFBLK 0060000
/* Directory */
#define S_IFDIR 0040000
/* Character device */
#define S_IFCHR 0020000
/* FIFO */
#define S_IFIFO 0010000
#define S_ISUID 04000
#define S_ISGID 02000
#define S_ISVTX 01000
/** Owner: RWX */
#define S_IRWXU 0700
/** Owner: R */
#define S_IRUSR 0400
/** Owner: W */
#define S_IWUSR 0200
/** Owner: X */
#define S_IXUSR 0100
/** Group: RWX */
#define S_IRWXG 0070
/** Group: R */
#define S_IRGRP 0040
/** Group: W */
#define S_IWGRP 0020
/** Group: X */
#define S_IXGRP 0010
/** Other: RWX */
#define S_IRWXO 0007
/** Other: R */
#define S_IROTH 0004
/** Other: W */
#define S_IWOTH 0002
/** Other: X */
#define S_IXOTH 0001
#define O_RDONLY 00
#define O_WRONLY 01
#define O_RDWR 02
#define O_CREAT 0100
#define O_EXCL 0200
#define O_TRUNC 01000
#define O_APPEND 02000
#define O_NOFOLLOW 0400000
#define O_CLOEXEC 02000000
#define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR)
#define S_ISCHR(mode) (((mode) & S_IFMT) == S_IFCHR)
#define S_ISBLK(mode) (((mode) & S_IFMT) == S_IFBLK)
#define S_ISREG(mode) (((mode) & S_IFMT) == S_IFREG)
#define S_ISFIFO(mode) (((mode) & S_IFMT) == S_IFIFO)
#define S_ISLNK(mode) (((mode) & S_IFMT) == S_IFLNK)
#define S_ISSOCK(mode) (((mode) & S_IFMT) == S_IFSOCK)
#define DT_UNKNOWN 0x0
#define DT_FIFO 0x1
#define DT_CHR 0x2
#define DT_DIR 0x4
#define DT_BLK 0x6
#define DT_REG 0x8
#define DT_LNK 0xA
#define DT_SOCK 0xC
#define DT_WHT 0xE
#define IFTODT(x) ((x) >> 12 & 0xF)
#define DTTOIF(x) ((x) << 12)
#define SYMLOOP_MAX 40
#ifndef __cplusplus
#define static_assert _Static_assert
#endif
#ifdef __LP64__
static_assert(sizeof(dev_t) == 8, "dev_t must be 64 bits");
static_assert(sizeof(ino_t) == 8, "ino_t must be 64 bits");
static_assert(sizeof(mode_t) == 4, "mode_t must be 32 bits");
static_assert(sizeof(nlink_t) == 4, "nlink_t must be 32 bits");
static_assert(sizeof(uid_t) == 4, "uid_t must be 32 bits");
static_assert(sizeof(gid_t) == 4, "gid_t must be 32 bits");
static_assert(sizeof(off_t) == 8, "off_t must be 64 bits");
static_assert(sizeof(time_t) == 8, "time_t must be 64 bits");
static_assert(sizeof(blksize_t) == 8, "blksize_t must be 64 bits");
static_assert(sizeof(blkcnt_t) == 8, "blkcnt_t must be 64 bits");
#else
static_assert(sizeof(dev_t) == 4, "dev_t must be 32 bits");
static_assert(sizeof(ino_t) == 4, "ino_t must be 32 bits");
static_assert(sizeof(mode_t) == 2, "mode_t must be 16 bits");
static_assert(sizeof(nlink_t) == 2, "nlink_t must be 16 bits");
static_assert(sizeof(uid_t) == 2, "uid_t must be 16 bits");
static_assert(sizeof(gid_t) == 2, "gid_t must be 16 bits");
static_assert(sizeof(off_t) == 4, "off_t must be 32 bits");
static_assert(sizeof(time_t) == 4, "time_t must be 32 bits");
static_assert(sizeof(blksize_t) == 4, "blksize_t must be 32 bits");
static_assert(sizeof(blkcnt_t) == 4, "blkcnt_t must be 32 bits");
#endif
#undef static_assert
struct kstat
{
/** Device ID of the file. */
dev_t Device;
/** Inode number. */
ino_t Index;
/** File type and mode. */
mode_t Mode;
/** Number of hard links. */
nlink_t HardLinks;
/** User ID of the file's owner. */
uid_t UserID;
/** Group ID of the file's owner. */
gid_t GroupID;
/** Device ID for special files. */
dev_t RawDevice;
/** Size of the file in bytes. */
off_t Size;
/** Time of last access. */
time_t AccessTime;
/** Time of last modification. */
time_t ModifyTime;
/** Time of last status change. */
time_t ChangeTime;
/** Optimal I/O block size. */
blksize_t BlockSize;
/** Number of blocks allocated. */
blkcnt_t Blocks;
/** Additional file attributes. */
mode_t Attribute;
#ifdef __cplusplus
dev_t MakeDevice(int Major, int Minor)
{
return ((Major & 0xFFF) << 8) |
(Minor & 0xFF);
}
int GetMajor()
{
return ((unsigned int)(Device) >> 8) & 0xFFF;
}
int GetMinor()
{
return Device & 0xFF;
}
void SetFileType(mode_t Type)
{
Mode = (Mode & ~S_IFMT) |
(Type & S_IFMT);
}
mode_t GetFileType() { return Mode & S_IFMT; }
void ClearFileType() { Mode = Mode & ~S_IFMT; }
bool IsType(mode_t Type) { return (Mode & S_IFMT) == Type; }
void SetPermissions(mode_t Permissions)
{
Mode = (Mode & S_IFMT) |
(Permissions & ~S_IFMT);
}
mode_t GetPermissions() { return Mode & ~S_IFMT; }
void ClearPermissions() { Mode = Mode & S_IFMT; }
#endif // __cplusplus
};
struct kdirent
{
ino_t d_ino;
off_t d_off;
unsigned short d_reclen;
unsigned char d_type;
char d_name[];
};
struct Inode
{
dev_t Device, RawDevice;
ino_t Index;
mode_t Mode;
uint32_t Flags;
off_t Offset;
uintptr_t KernelData;
void *PrivateData;
#ifdef __cplusplus
/* ... */
void SetDevice(int Major, int Minor)
{
this->RawDevice = ((Major & 0xFFF) << 8) |
(Minor & 0xFF);
}
int GetMajor()
{
return ((unsigned int)(this->RawDevice) >> 8) & 0xFFF;
}
int GetMinor()
{
return this->RawDevice & 0xFF;
}
Inode()
{
Device = 0;
RawDevice = 0;
Index = 0;
Mode = 0;
Flags = 0;
Offset = 0;
KernelData = 0x0;
PrivateData = nullptr;
}
~Inode() = default;
#else // __cplusplus
#define INODE_MAKEDEV(major, minor) \
((dev_t)(((major & 0xFFF) << 8) | \
(minor & 0xFF)))
#define INODE_MAJOR(rdev) \
((int)(((rdev) >> 8) & 0xFFF))
#define INODE_MINOR(rdev) \
((int)((rdev) & 0xFF))
#endif // __cplusplus
};
struct InodeOperations
{
int (*Lookup)(struct Inode *Parent, const char *Name, struct Inode **Result);
int (*Create)(struct Inode *Parent, const char *Name, mode_t Mode, struct Inode **Result);
int (*Remove)(struct Inode *Parent, const char *Name);
int (*Rename)(struct Inode *Parent, const char *OldName, const char *NewName);
ssize_t (*Read)(struct Inode *Node, void *Buffer, size_t Size, off_t Offset);
ssize_t (*Write)(struct Inode *Node, const void *Buffer, size_t Size, off_t Offset);
int (*Truncate)(struct Inode *Node, off_t Size);
int (*Open)(struct Inode *Node, int Flags, mode_t Mode);
int (*Close)(struct Inode *Node);
int (*Ioctl)(struct Inode *Node, unsigned long Request, void *Argp);
ssize_t (*ReadDir)(struct Inode *Node, struct kdirent *Buffer, size_t Size, off_t Offset, off_t Entries);
int (*MkDir)(struct Inode *Parent, const char *Name, mode_t Mode, struct Inode **Result);
int (*RmDir)(struct Inode *Parent, const char *Name);
int (*SymLink)(struct Inode *Parent, const char *Name, const char *Target, struct Inode **Result);
ssize_t (*ReadLink)(struct Inode *Node, char *Buffer, size_t Size);
off_t (*Seek)(struct Inode *Node, off_t Offset);
int (*Stat)(struct Inode *Node, struct kstat *Stat);
} __attribute__((packed));
#define I_FLAG_ROOT 0x1
#define I_FLAG_MOUNTPOINT 0x2
#define I_FLAG_CACHE_KEEP 0x4
struct FileSystemInfo;
struct SuperBlockOperations
{
int (*AllocateInode)(struct FileSystemInfo *Info, struct Inode **Result);
int (*DeleteInode)(struct FileSystemInfo *Info, struct Inode *Node);
/**
* Synchronize the filesystem.
*
* Write all pending changes to the disk.
*
* @param Info Inode to synchronize. If NULL, synchronize all inodes.
*
* @return Zero on success, otherwise an error code.
*/
int (*Synchronize)(struct FileSystemInfo *Info, struct Inode *Node);
/**
* Destroy the filesystem.
*
* Unregister the filesystem and free all resources.
*
* @param Info Filesystem to destroy.
*
* @return Zero on success, otherwise an error code.
*/
int (*Destroy)(struct FileSystemInfo *Info);
} __attribute__((packed));
struct FileSystemInfo
{
const char *Name;
const char *RootName;
int Flags;
struct SuperBlockOperations SuperOps;
struct InodeOperations Ops;
void *PrivateData;
} __attribute__((packed));
dev_t RegisterFileSystem(struct FileSystemInfo *Info, struct Inode *Root);
int UnregisterFileSystem(dev_t Device);
#endif // !__FENNIX_API_FILESYSTEM_H__

View File

@ -0,0 +1,244 @@
/*
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_API_INPUT_H__
#define __FENNIX_API_INPUT_H__
#include <types.h>
#if __has_include(<interface/device.h>)
#include <interface/device.h>
#else
#include <device.h>
#endif
struct InodeOperations;
typedef enum
{
KEY_1,
KEY_2,
KEY_3,
KEY_4,
KEY_5,
KEY_6,
KEY_7,
KEY_8,
KEY_9,
KEY_0,
KEY_Q,
KEY_W,
KEY_E,
KEY_R,
KEY_T,
KEY_Y,
KEY_U,
KEY_I,
KEY_O,
KEY_P,
KEY_A,
KEY_S,
KEY_D,
KEY_F,
KEY_G,
KEY_H,
KEY_J,
KEY_K,
KEY_L,
KEY_Z,
KEY_X,
KEY_C,
KEY_V,
KEY_B,
KEY_N,
KEY_M,
KEY_F1,
KEY_F2,
KEY_F3,
KEY_F4,
KEY_F5,
KEY_F6,
KEY_F7,
KEY_F8,
KEY_F9,
KEY_F10,
KEY_F11,
KEY_F12,
KEYPAD_7,
KEYPAD_8,
KEYPAD_9,
KEYPAD_MINUS,
KEYPAD_4,
KEYPAD_5,
KEYPAD_6,
KEYPAD_PLUS,
KEYPAD_1,
KEYPAD_2,
KEYPAD_3,
KEYPAD_0,
KEYPAD_PERIOD,
KEYPAD_RETURN,
KEYPAD_ASTERISK,
KEYPAD_SLASH,
KEY_LEFT_CTRL,
KEY_RIGHT_CTRL,
KEY_LEFT_SHIFT,
KEY_RIGHT_SHIFT,
KEY_LEFT_ALT,
KEY_RIGHT_ALT,
KEY_ESCAPE,
KEY_MINUS,
KEY_EQUAL,
KEY_BACKSPACE,
KEY_TAB,
KEY_LEFT_BRACKET,
KEY_RIGHT_BRACKET,
KEY_RETURN,
KEY_SEMICOLON,
KEY_APOSTROPHE,
KEY_BACK_TICK,
KEY_BACKSLASH,
KEY_COMMA,
KEY_PERIOD,
KEY_SLASH,
KEY_SPACE,
KEY_CAPS_LOCK,
KEY_NUM_LOCK,
KEY_SCROLL_LOCK,
KEY_PRINT_SCREEN,
KEY_HOME,
KEY_UP_ARROW,
KEY_LEFT_ARROW,
KEY_RIGHT_ARROW,
KEY_DOWN_ARROW,
KEY_PAGE_UP,
KEY_PAGE_DOWN,
KEY_END,
KEY_INSERT,
KEY_DELETE,
KEY_LEFT_GUI,
KEY_RIGHT_GUI,
KEY_APPS,
KEY_MULTIMEDIA_PREV_TRACK,
KEY_MULTIMEDIA_NEXT_TRACK,
KEY_MULTIMEDIA_MUTE,
KEY_MULTIMEDIA_CALCULATOR,
KEY_MULTIMEDIA_PLAY,
KEY_MULTIMEDIA_STOP,
KEY_MULTIMEDIA_VOL_DOWN,
KEY_MULTIMEDIA_VOL_UP,
KEY_MULTIMEDIA_WWW_HOME,
KEY_MULTIMEDIA_WWW_SEARCH,
KEY_MULTIMEDIA_WWW_FAVORITES,
KEY_MULTIMEDIA_WWW_REFRESH,
KEY_MULTIMEDIA_WWW_STOP,
KEY_MULTIMEDIA_WWW_FORWARD,
KEY_MULTIMEDIA_WWW_BACK,
KEY_MULTIMEDIA_MY_COMPUTER,
KEY_MULTIMEDIA_EMAIL,
KEY_MULTIMEDIA_MEDIA_SELECT,
KEY_ACPI_POWER,
KEY_ACPI_SLEEP,
KEY_ACPI_WAKE,
KEY_PRESSED = 0x80,
} KeyScanCodes;
typedef struct
{
KeyScanCodes Key;
union
{
struct
{
char IsScanCode : 1;
};
char Value;
};
unsigned char Character;
} KeyboardReport;
typedef struct
{
long X, Y;
int8_t Z;
uint8_t Absolute : 1;
uint8_t LeftButton : 1;
uint8_t RightButton : 1;
uint8_t MiddleButton : 1;
uint8_t Button4 : 1;
uint8_t Button5 : 1;
uint8_t Button6 : 1;
uint8_t Button7 : 1;
uint8_t Button8 : 1;
} MouseReport;
typedef struct
{
} JoystickReport;
typedef struct
{
uint16_t X, Y;
uint8_t Pressure;
} TouchScreenReport;
typedef struct
{
} GamepadReport;
typedef struct
{
} AccelerometerReport;
typedef struct
{
} GyroscopeReport;
typedef struct
{
} MagnetometerReport;
typedef struct
{
DeviceType Type;
dev_t Device;
union
{
KeyboardReport Keyboard;
MouseReport Mouse;
JoystickReport Joystick;
TouchScreenReport TouchScreen;
GamepadReport Gamepad;
AccelerometerReport Accelerometer;
GyroscopeReport Gyroscope;
MagnetometerReport Magnetometer;
/* ... */
};
} InputReport;
EXTERNC int ReportInputEvent(InputReport *Report);
#endif // !__FENNIX_API_INPUT_H__

View File

@ -0,0 +1,29 @@
/*
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_API_NETWORK_H__
#define __FENNIX_API_NETWORK_H__
#include <types.h>
#if __has_include(<interface/device.h>)
#include <interface/device.h>
#else
#include <device.h>
#endif
#endif // !__FENNIX_API_NETWORK_H__

View File

@ -0,0 +1,184 @@
/*
This file is part of Fennix Drivers.
Fennix Drivers 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 Drivers 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 Drivers. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef __FENNIX_API_PCI_H__
#define __FENNIX_API_PCI_H__
#include <types.h>
/* https://sites.uclouvain.be/SystInfo/usr/include/linux/pci_regs.h.html */
typedef enum
{
/** @brief Enable response in I/O space */
PCI_COMMAND_IO = 0x1,
/** @brief Enable response in Memory space */
PCI_COMMAND_MEMORY = 0x2,
/** @brief Enable bus mastering */
PCI_COMMAND_MASTER = 0x4,
/** @brief Enable response to special cycles */
PCI_COMMAND_SPECIAL = 0x8,
/** @brief Use memory write and invalidate */
PCI_COMMAND_INVALIDATE = 0x10,
/** @brief Enable palette snooping */
PCI_COMMAND_VGA_PALETTE = 0x20,
/** @brief Enable parity checking */
PCI_COMMAND_PARITY = 0x40,
/** @brief Enable address/data stepping */
PCI_COMMAND_WAIT = 0x80,
/** @brief Enable SERR */
PCI_COMMAND_SERR = 0x100,
/** @brief Enable back-to-back writes */
PCI_COMMAND_FAST_BACK = 0x200,
/** @brief INTx Emulation Disable */
PCI_COMMAND_INTX_DISABLE = 0x400
} PCI_COMMANDS;
typedef struct
{
uint16_t VendorID;
uint16_t DeviceID;
uint16_t Command;
uint16_t Status;
uint8_t RevisionID;
uint8_t ProgIF;
uint8_t Subclass;
uint8_t Class;
uint8_t CacheLineSize;
uint8_t LatencyTimer;
uint8_t HeaderType;
uint8_t BIST;
} __attribute__((packed)) PCIDeviceHeader;
typedef struct
{
PCIDeviceHeader Header;
uint32_t BAR0;
uint32_t BAR1;
uint32_t BAR2;
uint32_t BAR3;
uint32_t BAR4;
uint32_t BAR5;
uint32_t CardbusCISPointer;
uint16_t SubsystemVendorID;
uint16_t SubsystemID;
uint32_t ExpansionROMBaseAddress;
uint8_t CapabilitiesPointer;
uint8_t Reserved0;
uint16_t Reserved1;
uint32_t Reserved2;
uint8_t InterruptLine;
uint8_t InterruptPin;
uint8_t MinGrant;
uint8_t MaxLatency;
} __attribute__((packed)) PCIHeader0;
typedef struct
{
PCIDeviceHeader Header;
uint32_t BAR0;
uint32_t BAR1;
uint8_t PrimaryBusNumber;
uint8_t SecondaryBusNumber;
uint8_t SubordinateBusNumber;
uint8_t SecondaryLatencyTimer;
uint8_t IOBase;
uint8_t IOLimit;
uint16_t SecondaryStatus;
uint16_t MemoryBase;
uint16_t MemoryLimit;
uint16_t PrefetchableMemoryBase;
uint16_t PrefetchableMemoryLimit;
uint32_t PrefetchableMemoryBaseUpper32;
uint32_t PrefetchableMemoryLimitUpper32;
uint16_t IOBaseUpper16;
uint16_t IOLimitUpper16;
uint8_t CapabilitiesPointer;
uint8_t Reserved0;
uint16_t Reserved1;
uint32_t ExpansionROMBaseAddress;
uint8_t InterruptLine;
uint8_t InterruptPin;
uint16_t BridgeControl;
} __attribute__((packed)) PCIHeader1;
typedef struct
{
PCIDeviceHeader Header;
uint32_t CardbusSocketRegistersBaseAddress;
uint8_t CapabilitiesPointer;
uint8_t Reserved0;
uint16_t SecondaryStatus;
uint8_t PCIbusNumber;
uint8_t CardbusBusNumber;
uint8_t SubordinateBusNumber;
uint8_t CardbusLatencyTimer;
uint32_t MemoryBase0;
uint32_t MemoryLimit0;
uint32_t MemoryBase1;
uint32_t MemoryLimit1;
uint32_t IOBase0;
uint32_t IOLimit0;
uint32_t IOBase1;
uint32_t IOLimit1;
uint8_t InterruptLine;
uint8_t InterruptPin;
uint16_t BridgeControl;
uint16_t SubsystemVendorID;
uint16_t SubsystemID;
uint32_t LegacyBaseAddress;
} __attribute__((packed)) PCIHeader2;
typedef struct
{
uint64_t BaseAddress;
uint16_t PCISegGroup;
uint8_t StartBus;
uint8_t EndBus;
uint32_t Reserved;
} __attribute__((packed)) DeviceConfig;
typedef struct
{
PCIDeviceHeader *Header;
DeviceConfig *Config;
uint32_t Bus;
uint32_t Device;
uint32_t Function;
} __attribute__((packed)) PCIDevice;
typedef struct
{
PCIDevice *Device;
/* PCIArray */ void *Next;
} __attribute__((packed)) PCIArray;
#ifdef __cplusplus
extern "C"
{
#endif
PCIArray *GetPCIDevices(uint16_t Vendors[], uint16_t Devices[]);
void InitializePCI(PCIDevice *Device);
uint32_t GetBAR(uint8_t Index, PCIDevice *Device);
uint8_t iLine(PCIDevice *Device);
uint8_t iPin(PCIDevice *Device);
#ifdef __cplusplus
}
#endif
#endif // !__FENNIX_API_PCI_H__

View File

@ -0,0 +1,111 @@
/*
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_API_SYSCALLS_LIST_H__
#define __FENNIX_API_SYSCALLS_LIST_H__
#ifndef syscall0
static inline long syscall0(long syscall)
{
long ret;
__asm__ __volatile__("syscall"
: "=a"(ret)
: "a"(syscall)
: "rcx", "r11", "memory");
return ret;
}
#endif
#ifndef syscall1
static inline long syscall1(long syscall, long arg1)
{
long ret;
__asm__ __volatile__("syscall"
: "=a"(ret)
: "a"(syscall), "D"(arg1)
: "rcx", "r11", "memory");
return ret;
}
#endif
#ifndef syscall2
static inline long syscall2(long syscall, long arg1, long arg2)
{
long ret;
__asm__ __volatile__("syscall"
: "=a"(ret)
: "a"(syscall), "D"(arg1), "S"(arg2)
: "rcx", "r11", "memory");
return ret;
}
#endif
#ifndef syscall3
static inline long syscall3(long syscall, long arg1, long arg2, long arg3)
{
long ret;
__asm__ __volatile__("syscall"
: "=a"(ret)
: "a"(syscall), "D"(arg1), "S"(arg2), "d"(arg3)
: "rcx", "r11", "memory");
return ret;
}
#endif
#ifndef syscall4
static inline long syscall4(long syscall, long arg1, long arg2, long arg3, long arg4)
{
long ret;
register long r10 __asm__("r10") = arg4;
__asm__ __volatile__("syscall"
: "=a"(ret)
: "a"(syscall), "D"(arg1), "S"(arg2), "d"(arg3), "r"(r10)
: "rcx", "r11", "memory");
return ret;
}
#endif
#ifndef syscall5
static inline long syscall5(long syscall, long arg1, long arg2, long arg3, long arg4, long arg5)
{
long ret;
register long r10 __asm__("r10") = arg4;
register long r8 __asm__("r8") = arg5;
__asm__ __volatile__("syscall"
: "=a"(ret)
: "a"(syscall), "D"(arg1), "S"(arg2), "d"(arg3), "r"(r10), "r"(r8)
: "rcx", "r11", "memory");
return ret;
}
#endif
#ifndef syscall6
static inline long syscall6(long syscall, long arg1, long arg2, long arg3, long arg4, long arg5, long arg6)
{
long ret;
register long r10 __asm__("r10") = arg4;
register long r8 __asm__("r8") = arg5;
register long r9 __asm__("r9") = arg6;
__asm__ __volatile__("syscall"
: "=a"(ret)
: "a"(syscall), "D"(arg1), "S"(arg2), "d"(arg3), "r"(r10), "r"(r8), "r"(r9)
: "rcx", "r11", "memory");
return ret;
}
#endif
#endif // !__FENNIX_API_SYSCALLS_LIST_H__

80
Kernel/include/intrin.hpp Normal file
View File

@ -0,0 +1,80 @@
/*
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_INTRIN_H__
#define __FENNIX_KERNEL_INTRIN_H__
#include <types.h>
#include <debug.h>
namespace FXSR
{
void _fxsave(void *mem_addr)
{
#ifdef a64
__builtin_ia32_fxsave(mem_addr);
#endif
}
void _fxrstor(void *mem_addr)
{
#ifdef a64
__builtin_ia32_fxrstor(mem_addr);
#endif
}
void _fxsave64(void *mem_addr)
{
#ifdef a64
asmv("fxsaveq (%0)"
:
: "r"(mem_addr)
: "memory");
#endif
}
void _fxrstor64(void *mem_addr)
{
#ifdef a64
asmv("fxrstorq (%0)"
:
: "r"(mem_addr)
: "memory");
#endif
}
}
namespace SMAP
{
void _clac(void)
{
#if defined(a86)
asmv("clac" ::
: "cc");
#endif // a64 || a32
}
void _stac(void)
{
#if defined(a86)
asmv("stac" ::
: "cc");
#endif // a64 || a32
}
}
#endif // !__FENNIX_KERNEL_INTRIN_H__

85
Kernel/include/ints.hpp Normal file
View File

@ -0,0 +1,85 @@
/*
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_INTERRUPTS_H__
#define __FENNIX_KERNEL_INTERRUPTS_H__
#include <types.h>
#include <cpu.hpp>
#include <pci.hpp>
namespace Interrupts
{
#ifdef DEBUG // For performance reasons
#define INT_FRAMES_MAX 512
#else
#define INT_FRAMES_MAX 8
#endif
#if defined(a64)
/* APIC::APIC */ extern void *apic[255]; // MAX_CPU
/* APIC::Timer */ extern void *apicTimer[255]; // MAX_CPU
#elif defined(a32)
/* APIC::APIC */ extern void *apic[255]; // MAX_CPU
/* APIC::Timer */ extern void *apicTimer[255]; // MAX_CPU
#elif defined(aa64)
#endif
void Initialize(int Core);
void Enable(int Core);
void InitializeTimer(int Core);
void RemoveAll();
void AddHandler(void (*Callback)(CPU::TrapFrame *),
int InterruptNumber, void *ctx = nullptr,
bool Critical = false);
void RemoveHandler(void (*Callback)(CPU::TrapFrame *),
int InterruptNumber);
void RemoveHandler(void (*Callback)(CPU::TrapFrame *));
void RemoveHandler(int InterruptNumber);
class Handler
{
private:
int InterruptNumber;
protected:
/**
* @brief Set a new interrupt number.
* @param InterruptNumber The interrupt number. NOT the IRQ number! (IRQ0 != 32)
*/
void SetInterruptNumber(int InterruptNumber) { this->InterruptNumber = InterruptNumber; }
int GetInterruptNumber() { return this->InterruptNumber; }
/**
* @brief Create a new interrupt handler.
* @param InterruptNumber The interrupt number. NOT the IRQ number! (IRQ0 != 32)
*/
Handler(int InterruptNumber, bool Critical = false);
Handler(PCI::PCIDevice Device, bool Critical = false);
Handler();
~Handler();
public:
virtual void OnInterruptReceived(CPU::TrapFrame *Frame);
virtual void OnInterruptReceived(CPU::SchedulerFrame *Frame);
};
}
#endif // !__FENNIX_KERNEL_INTERRUPTS_H__

158
Kernel/include/io.h Normal file
View File

@ -0,0 +1,158 @@
/*
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_IO_H__
#define __FENNIX_KERNEL_IO_H__
#include <types.h>
#if defined(a86)
#ifdef __cplusplus
extern "C"
{
#endif
static inline uint8_t inb(uint16_t Port)
{
uint8_t Result;
asm("in %%dx, %%al"
: "=a"(Result)
: "d"(Port));
return Result;
}
static inline uint16_t inw(uint16_t Port)
{
uint16_t Result;
asm("in %%dx, %%ax"
: "=a"(Result)
: "d"(Port));
return Result;
}
static inline uint32_t inl(uint16_t Port)
{
uint32_t Result;
asmv("inl %1, %0"
: "=a"(Result)
: "dN"(Port));
return Result;
}
static inline void outb(uint16_t Port, uint8_t Data)
{
asmv("out %%al, %%dx"
:
: "a"(Data), "d"(Port));
}
static inline void outw(uint16_t Port, uint16_t Data)
{
asmv("out %%ax, %%dx"
:
: "a"(Data), "d"(Port));
}
static inline void outl(uint16_t Port, uint32_t Data)
{
asmv("outl %1, %0"
:
: "dN"(Port), "a"(Data));
}
static inline void mmoutb(void *Address, uint8_t Value)
{
asmv("mov %1, %0"
: "=m"((*(uint8_t *)(Address)))
: "r"(Value)
: "memory");
}
static inline void mmoutw(void *Address, uint16_t Value)
{
asmv("mov %1, %0"
: "=m"((*(uint16_t *)(Address)))
: "r"(Value)
: "memory");
}
static inline void mmoutl(void *Address, uint32_t Value)
{
asmv("mov %1, %0"
: "=m"((*(uint32_t *)(Address)))
: "r"(Value)
: "memory");
}
#if defined(a64)
static inline void mmoutq(void *Address, uint64_t Value)
{
asmv("mov %1, %0"
: "=m"((*(uint64_t *)(Address)))
: "r"(Value)
: "memory");
}
#endif
static inline uint8_t mminb(void *Address)
{
uint8_t Result;
asmv("mov %1, %0"
: "=r"(Result)
: "m"((*(uint8_t *)(Address)))
: "memory");
return Result;
}
static inline uint16_t mminw(void *Address)
{
uint16_t Result;
asmv("mov %1, %0"
: "=r"(Result)
: "m"((*(uint16_t *)(Address)))
: "memory");
return Result;
}
static inline uint32_t mminl(void *Address)
{
uint32_t Result;
asmv("mov %1, %0"
: "=r"(Result)
: "m"((*(uint32_t *)(Address)))
: "memory");
return Result;
}
#if defined(a64)
static inline uint64_t mminq(void *Address)
{
uint64_t Result;
asmv("mov %1, %0"
: "=r"(Result)
: "m"((*(uint64_t *)(Address)))
: "memory");
return Result;
}
#endif
#ifdef __cplusplus
}
#endif
#endif // defined(a86)
#endif // !__FENNIX_KERNEL_IO_H__

155
Kernel/include/kcon.hpp Normal file
View File

@ -0,0 +1,155 @@
/*
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_KERNEL_CONSOLE_H__
#define __FENNIX_KERNEL_KERNEL_CONSOLE_H__
#include <display.hpp>
#include <tty.hpp>
namespace KernelConsole
{
enum TerminalColor
{
BLACK,
RED,
GREEN,
YELLOW,
BLUE,
MAGENTA,
CYAN,
GREY
};
struct ANSIArgument
{
int Value = 0;
bool Empty = true;
};
struct ANSIParser
{
enum ParserState
{
Escape,
Bracket,
Attribute,
EndValue
} State = Escape;
ANSIArgument Stack[8] = {};
int Index = 0;
};
struct TerminalAttribute
{
bool Bright = false;
TerminalColor Background = BLACK;
TerminalColor Foreground = GREY;
};
struct TerminalCell
{
char c = '\0';
TerminalAttribute attr{};
};
struct TerminalCursor
{
long X = 0;
long Y = 0;
};
typedef void (*PaintCallback)(TerminalCell *Cell, long X, long Y);
typedef void (*CursorCallback)(TerminalCursor *Cursor);
class FontRenderer
{
public:
Video::Font *CurrentFont = nullptr;
TerminalCursor Cursor = {0, 0};
char Paint(long CellX, long CellY, char Char, uint32_t Foreground, uint32_t Background);
};
class VirtualTerminal : public TTY::TeletypeDriver
{
private:
ANSIParser Parser{};
TerminalAttribute Attribute{};
TerminalCell *Cells = nullptr;
TerminalCursor Cursor{};
PaintCallback PaintCB = nullptr;
CursorCallback CursorCB = nullptr;
std::mutex Mutex;
public:
termios *GetTermios() { return &this->TerminalConfig; }
winsize *GetWinsize() { return &this->TerminalSize; }
int Open(int Flags, mode_t Mode) final;
int Close() final;
ssize_t Read(void *Buffer, size_t Size, off_t Offset) final;
ssize_t Write(const void *Buffer, size_t Size, off_t Offset) final;
int Ioctl(unsigned long Request, void *Argp) final;
void Clear(unsigned short StartX, unsigned short StartY, unsigned short EndX, unsigned short EndY);
void Scroll(unsigned short Lines);
void NewLine();
void Append(char c);
void csi_cup(ANSIArgument *Args, int ArgsCount);
void csi_ed(ANSIArgument *Args, int ArgsCount);
void csi_el(ANSIArgument *Args, int ArgsCount);
void csi_sgr(ANSIArgument *Args, int ArgsCount);
void csi_cuu(ANSIArgument *Args, int ArgsCount);
void csi_cud(ANSIArgument *Args, int ArgsCount);
void csi_cuf(ANSIArgument *Args, int ArgsCount);
void csi_cub(ANSIArgument *Args, int ArgsCount);
void csi_cnl(ANSIArgument *Args, int ArgsCount);
void csi_cpl(ANSIArgument *Args, int ArgsCount);
void csi_cha(ANSIArgument *Args, int ArgsCount);
void Process(char c);
VirtualTerminal(unsigned short Rows, unsigned short Columns,
unsigned short XPixels, unsigned short YPixels,
PaintCallback Paint, CursorCallback Print);
~VirtualTerminal();
};
/**
* 0 - Default
* 1...11 - User
* ...
* 15 - Panic
*/
extern VirtualTerminal *Terminals[16];
extern std::atomic<VirtualTerminal *> CurrentTerminal;
extern int TermColors[];
extern int TermBrightColors[];
bool SetTheme(std::string Theme);
/* Limited in functionality */
void EarlyInit();
/* Full working terminal */
void LateInit();
}
#endif // !__FENNIX_KERNEL_KERNEL_CONSOLE_H__

View File

@ -0,0 +1,47 @@
/*
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_KERNEL_CONFIG_H__
#define __FENNIX_KERNEL_KERNEL_CONFIG_H__
#include <types.h>
#include <memory.hpp>
enum KCSchedType
{
Mono = 0,
Multi = 1,
};
struct KernelConfig
{
Memory::MemoryAllocatorType AllocatorType;
bool SchedulerType;
char DriverDirectory[256];
char InitPath[256];
bool UseLinuxSyscalls;
bool InterruptsOnCrash;
int Cores;
int IOAPICInterruptCore;
bool UnlockDeadLock;
bool SIMD;
bool Quiet;
};
void ParseConfig(char *ConfigString, KernelConfig *ModConfig);
#endif // !__FENNIX_KERNEL_KERNEL_CONFIG_H__

View File

@ -0,0 +1,118 @@
/*
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_CXXABI_H__
#define __FENNIX_KERNEL_CXXABI_H__
#include <types.h>
#include <kexcept/unwind.h>
#include <typeinfo>
namespace __cxxabiv1
{
#define ATEXIT_MAX_FUNCS 128
typedef unsigned uarch_t;
struct atexit_func_entry_t
{
void (*destructor_func)(void *);
void *obj_ptr;
void *dso_handle;
};
struct __cxa_exception
{
#ifdef __LP64__
char __padding[8];
uintptr_t referenceCount;
#endif
std::type_info *exceptionType;
void (*exceptionDestructor)(void *);
std::terminate_handler unexpectedHandler;
std::terminate_handler terminateHandler;
__cxa_exception *nextException;
int handlerCount;
#ifdef __arm__
__cxa_exception *nextPropagatingException;
int propagationCount;
#else
int handlerSwitchValue;
const unsigned char *actionRecord;
const unsigned char *languageSpecificData;
void *catchTemp;
void *adjustedPtr;
#endif
#ifndef __LP64__
uintptr_t referenceCount;
#endif
_Unwind_Exception unwindHeader;
};
struct __cxa_dependent_exception
{
#ifdef __LP64__
char __padding[8];
void *primaryException;
#endif
std::type_info *exceptionType;
void (*exceptionDestructor)(void *);
std::unexpected_handler unexpectedHandler;
std::terminate_handler terminateHandler;
__cxa_exception *nextException;
int handlerCount;
#ifdef __arm__
_Unwind_Exception *nextCleanup;
int cleanupCount;
#endif
int handlerSwitchValue;
const char *actionRecord;
const char *languageSpecificData;
void *catchTemp;
void *adjustedPtr;
#ifndef __LP64__
void *primaryException;
#endif
_Unwind_Exception unwindHeader;
};
struct __cxa_eh_globals
{
__cxa_exception *caughtExceptions;
unsigned int uncaughtExceptions;
};
enum ExceptionState
{
ES_None,
ES_Caught,
ES_Rethrown
};
}
struct ExceptionInfo
{
std::terminate_handler terminateHandler;
std::unexpected_handler unexpectedHandler;
_Unwind_Exception *exceptionObject;
__cxxabiv1::ExceptionState state;
__cxxabiv1::__cxa_eh_globals globals;
};
ExceptionInfo *GetExceptionInfo();
#endif // !__FENNIX_KERNEL_CXXABI_H__

View File

@ -0,0 +1,74 @@
/*
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_UNWIND_H__
#define __FENNIX_KERNEL_UNWIND_H__
#include <types.h>
typedef enum
{
_URC_NO_REASON = 0,
_URC_FOREIGN_EXCEPTION_CAUGHT = 1,
_URC_FATAL_PHASE2_ERROR = 2,
_URC_FATAL_PHASE1_ERROR = 3,
_URC_NORMAL_STOP = 4,
_URC_END_OF_STACK = 5,
_URC_HANDLER_FOUND = 6,
_URC_INSTALL_CONTEXT = 7,
_URC_CONTINUE_UNWIND = 8
} _Unwind_Reason_Code;
typedef void *_Unwind_Context_Reg_Val;
typedef unsigned _Unwind_Exception_Class __attribute__((__mode__(__DI__)));
typedef unsigned _Unwind_Ptr __attribute__((__mode__(__pointer__)));
typedef unsigned _Unwind_Word __attribute__((__mode__(__unwind_word__)));
typedef signed _Unwind_Sword __attribute__((__mode__(__unwind_word__)));
typedef int _Unwind_Action;
#define _UA_SEARCH_PHASE 1
#define _UA_CLEANUP_PHASE 2
#define _UA_HANDLER_FRAME 4
#define _UA_FORCE_UNWIND 8
#define _UA_END_OF_STACK 16
typedef void (*_Unwind_Exception_Cleanup_Fn)(_Unwind_Reason_Code, struct _Unwind_Exception *);
typedef _Unwind_Reason_Code (*_Unwind_Personality_Fn)(int, _Unwind_Action,
_Unwind_Exception_Class,
struct _Unwind_Exception *,
struct _Unwind_Context *);
struct _Unwind_Exception
{
_Unwind_Exception_Class exception_class;
_Unwind_Exception_Cleanup_Fn exception_cleanup;
_Unwind_Word private_1;
_Unwind_Word private_2;
} __attribute__((__aligned__));
struct _Unwind_Context
{
int __stub;
};
struct _Unwind_FrameState
{
_Unwind_Personality_Fn personality;
};
#endif // !__FENNIX_KERNEL_UNWIND_H__

25
Kernel/include/kshell.hpp Normal file
View File

@ -0,0 +1,25 @@
/*
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_KERNEL_SHELL_H__
#define __FENNIX_KERNEL_KERNEL_SHELL_H__
#include <types.h>
void KShellThread();
#endif // !__FENNIX_KERNEL_KERNEL_SHELL_H__

256
Kernel/include/lock.hpp Normal file
View File

@ -0,0 +1,256 @@
/*
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_LOCK_H__
#define __FENNIX_KERNEL_LOCK_H__
#include <types.h>
#include <cpu.hpp>
#include <atomic>
#ifdef __cplusplus
/* Enabled ONLY on crash. */
extern bool ForceUnlock;
/**
* @brief Get how many locks are currently in use.
*
* @return size_t
*/
size_t GetLocksCount();
/** @brief Please use this macro to create a new lock. */
class LockClass
{
public:
struct SpinLockData
{
std::atomic_uint64_t LockData = 0x0;
std::atomic<const char *> CurrentHolder = "(nul)";
std::atomic<const char *> AttemptingToGet = "(nul)";
std::atomic_uintptr_t StackPointerHolder = 0;
std::atomic_uintptr_t StackPointerAttempt = 0;
std::atomic_size_t Count = 0;
std::atomic_long Core = 0;
};
private:
SpinLockData LockData;
std::atomic_bool IsLocked = false;
std::atomic_ulong DeadLocks = 0;
void DeadLock(SpinLockData &Lock);
void TimeoutDeadLock(SpinLockData &Lock, uint64_t Timeout);
void Yield();
public:
bool Locked() { return IsLocked.load(); }
SpinLockData *GetLockData() { return &LockData; }
int Lock(const char *FunctionName);
int Unlock();
int TimeoutLock(const char *FunctionName, uint64_t Timeout);
};
class spin_lock
{
private:
LockClass lc;
public:
bool locked()
{
return this->lc.Locked();
}
bool lock(const char *FunctionName)
{
return this->lc.Lock(FunctionName) == 0;
}
bool unlock()
{
return this->lc.Unlock() == 0;
}
spin_lock() = default;
spin_lock(const spin_lock &) = delete;
~spin_lock() = default;
};
class __sl_guard
{
private:
spin_lock &sl;
public:
__sl_guard(spin_lock &sl, const char *FunctionName) : sl(sl)
{
this->sl.lock(FunctionName);
}
~__sl_guard()
{
this->sl.unlock();
}
};
#define sl_guard(sl) __sl_guard CONCAT(sl_guard_, __COUNTER__)(sl, __FUNCTION__)
/** @brief Please use this macro to create a new smart lock. */
class SmartLockClass
{
private:
LockClass *LockPointer = nullptr;
public:
bool Locked()
{
return this->LockPointer->Locked();
}
SmartLockClass(LockClass &Lock, const char *FunctionName)
{
this->LockPointer = &Lock;
this->LockPointer->Lock(FunctionName);
}
~SmartLockClass() { this->LockPointer->Unlock(); }
};
class SmartTimeoutLockClass
{
private:
LockClass *LockPointer = nullptr;
public:
bool Locked()
{
return this->LockPointer->Locked();
}
SmartTimeoutLockClass(LockClass &Lock,
const char *FunctionName,
uint64_t Timeout)
{
this->LockPointer = &Lock;
this->LockPointer->TimeoutLock(FunctionName, Timeout);
}
~SmartTimeoutLockClass()
{
this->LockPointer->Unlock();
}
};
class SmartLockCriticalSectionClass
{
private:
LockClass *LockPointer = nullptr;
bool InterruptsEnabled = false;
public:
SmartLockCriticalSectionClass(LockClass &Lock,
const char *FunctionName)
{
if (CPU::Interrupts(CPU::Check))
InterruptsEnabled = true;
CPU::Interrupts(CPU::Disable);
this->LockPointer = &Lock;
this->LockPointer->Lock(FunctionName);
}
~SmartLockCriticalSectionClass()
{
this->LockPointer->Unlock();
if (InterruptsEnabled)
CPU::Interrupts(CPU::Enable);
}
};
class SmartCriticalSectionClass
{
private:
bool InterruptsEnabled = false;
public:
bool IsInterruptsEnabled()
{
return InterruptsEnabled;
}
SmartCriticalSectionClass()
{
if (CPU::Interrupts(CPU::Check))
InterruptsEnabled = true;
CPU::Interrupts(CPU::Disable);
}
~SmartCriticalSectionClass()
{
if (InterruptsEnabled)
CPU::Interrupts(CPU::Enable);
}
};
/**
* Create a new lock
*
* @note Can be used with SmartCriticalSection
*/
#define NewLock(Name) LockClass Name
/**
* Simple lock that is automatically released
* when the scope ends.
*/
#define SmartLock(LockClassName) \
SmartLockClass \
CONCAT(lock##_, __COUNTER__)(LockClassName, \
__FUNCTION__)
/**
* Simple lock with timeout that is automatically
* released when the scope ends.
*/
#define SmartTimeoutLock(LockClassName, Timeout) \
SmartTimeoutLockClass \
CONCAT(lock##_, __COUNTER__)(LockClassName, \
__FUNCTION__, \
Timeout)
/**
* Simple critical section that is
* automatically released when the scope ends
* and interrupts are restored if they
* were enabled.
*/
#define SmartCriticalSection(LockClassName) \
SmartLockCriticalSectionClass \
CONCAT(lock##_, \
__COUNTER__)(LockClassName, \
__FUNCTION__)
/**
* Automatically disable interrupts and
* restore them when the scope ends.
*/
#define CriticalSection SmartCriticalSectionClass
#endif // __cplusplus
#endif // !__FENNIX_KERNEL_LOCK_H__

76
Kernel/include/macho.h Normal file
View File

@ -0,0 +1,76 @@
/*
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_MACH_O_H__
#define __FENNIX_KERNEL_MACH_O_H__
#include <types.h>
#define MH_MAGIC 0xfeedface
#define MH_CIGAM 0xcefaedfe
#define CPU_TYPE_ANY ((cpu_type_t) - 1)
#define CPU_TYPE_VAX ((cpu_type_t)1)
#define CPU_TYPE_ROMP ((cpu_type_t)2)
#define CPU_TYPE_NS32032 ((cpu_type_t)4)
#define CPU_TYPE_NS32332 ((cpu_type_t)5)
#define CPU_TYPE_MC680x0 ((cpu_type_t)6)
#define CPU_TYPE_I386 ((cpu_type_t)7)
#define CPU_TYPE_X86_64 ((cpu_type_t)(CPU_TYPE_I386 | CPU_ARCH_ABI64))
#define CPU_TYPE_MIPS ((cpu_type_t)8)
#define CPU_TYPE_NS32532 ((cpu_type_t)9)
#define CPU_TYPE_HPPA ((cpu_type_t)11)
#define CPU_TYPE_ARM ((cpu_type_t)12)
#define CPU_TYPE_MC88000 ((cpu_type_t)13)
#define CPU_TYPE_SPARC ((cpu_type_t)14)
#define CPU_TYPE_I860 ((cpu_type_t)15)
#define CPU_TYPE_I860_LITTLE ((cpu_type_t)16)
#define CPU_TYPE_RS6000 ((cpu_type_t)17)
#define CPU_TYPE_MC98000 ((cpu_type_t)18)
#define CPU_TYPE_POWERPC ((cpu_type_t)18)
#define CPU_ARCH_ABI64 0x1000000
#define CPU_TYPE_POWERPC64 ((cpu_type_t)(CPU_TYPE_POWERPC | CPU_ARCH_ABI64))
#define CPU_TYPE_VEO ((cpu_type_t)255)
typedef int cpu_type_t;
typedef int cpu_subtype_t;
struct mach_header
{
uint32_t magic;
cpu_type_t cputype;
cpu_subtype_t cpusubtype;
uint32_t filetype;
uint32_t ncmds;
uint32_t sizeofcmds;
uint32_t flags;
};
struct mach_header_64
{
uint32_t magic;
cpu_type_t cputype;
cpu_subtype_t cpusubtype;
uint32_t filetype;
uint32_t ncmds;
uint32_t sizeofcmds;
uint32_t flags;
uint32_t reserved;
};
#endif // !__FENNIX_KERNEL_MACH_O_H__

54
Kernel/include/md5.h Normal file
View File

@ -0,0 +1,54 @@
/*
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_MD5_H__
#define __FENNIX_KERNEL_MD5_H__
#include <types.h>
/*
https://github.com/Zunawe/md5-c
*/
START_EXTERNC
typedef struct
{
size_t size; // Size of input in bytes
uint32_t buffer[4]; // Current accumulation of hash
uint8_t input[64]; // Input to be used in the next step
uint8_t digest[16]; // Result of algorithm
} MD5Context;
void md5Init(MD5Context *ctx);
void md5Update(MD5Context *ctx, uint8_t *input, size_t input_len);
void md5Finalize(MD5Context *ctx);
void md5Step(uint32_t *buffer, uint32_t *input);
uint8_t *md5String(char *input);
uint8_t *md5File(uint8_t *buffer, size_t input_len);
uint32_t F(uint32_t X, uint32_t Y, uint32_t Z);
uint32_t G(uint32_t X, uint32_t Y, uint32_t Z);
uint32_t H(uint32_t X, uint32_t Y, uint32_t Z);
uint32_t I(uint32_t X, uint32_t Y, uint32_t Z);
uint32_t rotateLeft(uint32_t x, uint32_t n);
END_EXTERNC
#endif // !__FENNIX_KERNEL_MD5_H__

96
Kernel/include/memory.hpp Normal file
View File

@ -0,0 +1,96 @@
/*
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_INTERNAL_MEMORY_H__
#define __FENNIX_KERNEL_INTERNAL_MEMORY_H__
#ifdef __cplusplus
#include <filesystem.hpp>
#include <boot/binfo.h>
#include <bitmap.hpp>
#include <lock.hpp>
#include <cstddef>
#include <atomic>
#include <new>
#endif // __cplusplus
#include <types.h>
#ifdef __cplusplus
extern uintptr_t _bootstrap_start, _bootstrap_end;
extern uintptr_t _kernel_start, _kernel_end;
extern uintptr_t _kernel_text_start, _kernel_text_end;
extern uintptr_t _kernel_data_start, _kernel_data_end;
extern uintptr_t _kernel_rodata_start, _kernel_rodata_end;
extern uintptr_t _kernel_bss_start, _kernel_bss_end;
namespace Memory
{
enum MemoryAllocatorType
{
None,
/** Allocate memory by pages. */
Pages,
XallocV1,
XallocV2,
liballoc11,
/**
* @warning Not working as expected.
*
* FIXME: This allocator is not working as expected.
*/
rpmalloc_,
};
}
#include <memory/physical.hpp>
#include <memory/virtual.hpp>
#include <memory/swap_pt.hpp>
#include <memory/kstack.hpp>
#include <memory/table.hpp>
#include <memory/macro.hpp>
#include <memory/stack.hpp>
#include <memory/vma.hpp>
#include <memory/brk.hpp>
void InitializeMemoryManagement();
void CreatePageTable(Memory::PageTable *pt);
extern Memory::Physical KernelAllocator;
extern Memory::KernelStackManager StackManager;
extern Memory::PageTable *KernelPageTable;
#endif // __cplusplus
#ifndef __FENNIX_KERNEL_STDLIB_H__
EXTERNC void *malloc(size_t Size);
EXTERNC void *calloc(size_t n, size_t Size);
EXTERNC void *realloc(void *Address, size_t Size);
EXTERNC void free(void *Address);
#endif // !__FENNIX_KERNEL_STDLIB_H__
#define kmalloc(Size) malloc(Size)
#define kcalloc(n, Size) calloc(n, Size)
#define krealloc(Address, Size) realloc(Address, Size)
#define kfree(Address) free(Address)
#endif // !__FENNIX_KERNEL_INTERNAL_MEMORY_H__

View File

@ -0,0 +1,57 @@
/*
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_MEMORY_PROGRAM_BREAK_H__
#define __FENNIX_KERNEL_MEMORY_PROGRAM_BREAK_H__
#include <types.h>
#include <debug.h>
#include <memory/table.hpp>
#include <memory/vma.hpp>
namespace Memory
{
class ProgramBreak
{
private:
PageTable *Table = nullptr;
VirtualMemoryArea *vma = nullptr;
uintptr_t HeapStart = 0x0;
uintptr_t Break = 0x0;
public:
/* fork() */
void SetTable(PageTable *Table) { this->Table = Table; }
/* Directly to syscall */
void *brk(void *Address);
void InitBrk(uintptr_t Address)
{
func("%#lx", Address);
HeapStart = Address;
Break = Address;
}
ProgramBreak(PageTable *Table, VirtualMemoryArea *mm);
~ProgramBreak();
};
}
#endif // !__FENNIX_KERNEL_MEMORY_PROGRAM_BREAK_H__

View File

@ -0,0 +1,69 @@
/*
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_MEMORY_KERNEL_STACK_MANAGER_H__
#define __FENNIX_KERNEL_MEMORY_KERNEL_STACK_MANAGER_H__
#include <memory.hpp>
namespace Memory
{
class KernelStackManager
{
public:
struct StackAllocation
{
void *PhysicalAddress;
void *VirtualAddress;
size_t Size;
};
private:
NewLock(StackLock);
std::list<StackAllocation> AllocatedStacks;
size_t TotalSize = 0;
uintptr_t CurrentStackTop = KERNEL_STACK_END;
public:
/**
* Allocate a new stack with detailed information
*
* @param Size Size in bytes to allocate
* @return {PhysicalAddress, VirtualAddress, Size}
*/
StackAllocation DetailedAllocate(size_t Size);
/**
* Allocate a new stack
*
* @param Size Size in bytes to allocate
* @return Pointer to the BASE of the stack
*/
void *Allocate(size_t Size);
/**
* Free a previously allocated stack
*
* @param Address Virtual Address
*/
void Free(void *Address);
KernelStackManager();
~KernelStackManager();
};
}
#endif // !__FENNIX_KERNEL_MEMORY_KERNEL_STACK_MANAGER_H__

View File

@ -0,0 +1,75 @@
/*
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_MEMORY_MACROS_H__
#define __FENNIX_KERNEL_MEMORY_MACROS_H__
#include <types.h>
// kilobyte
#define TO_KiB(d) ((d) / 1024)
// megabyte
#define TO_MiB(d) ((d) / 1024 / 1024)
// gigabyte
#define TO_GiB(d) ((d) / 1024 / 1024 / 1024)
// terabyte
#define TO_TiB(d) ((d) / 1024 / 1024 / 1024 / 1024)
// petabyte
#define TO_PiB(d) ((d) / 1024 / 1024 / 1024 / 1024 / 1024)
// exobyte
#define TO_EiB(d) ((d) / 1024 / 1024 / 1024 / 1024 / 1024 / 1024)
#define PAGE_SIZE 0x1000 /* 4 KiB */
#define PAGE_SIZE_4K PAGE_SIZE /* 4 KiB */
#define PAGE_SIZE_2M 0x200000 /* 2 MiB */
#define PAGE_SIZE_4M 0x400000 /* 4 MiB */
#define PAGE_SIZE_1G 0x40000000 /* 1 GiB */
#define STACK_SIZE 0x4000 /* 16 KiB */
#define LARGE_STACK_SIZE 0x20000 /* 128 KiB */
#define USER_STACK_SIZE 0x2000 /* 8 KiB */
/* To pages */
#define TO_PAGES(d) (((d) + PAGE_SIZE - 1) / PAGE_SIZE)
/* From pages */
#define FROM_PAGES(d) ((d) * PAGE_SIZE)
#if defined(a64) || defined(aa64)
#define KERNEL_VMA_OFFSET 0xFFFFFFFF80000000
#define USER_ALLOC_BASE 0xFFFFA00000000000 /* 256 GiB */
#define USER_ALLOC_END 0xFFFFB00000000000
#define KERNEL_STACK_BASE 0xFFFFB00000000000 /* 256 GiB */
#define KERNEL_STACK_END 0xFFFFC00000000000
#define USER_STACK_END 0xFFFFEFFF00000000 /* 256 MiB */
#define USER_STACK_BASE 0xFFFFEFFFFFFF0000
#elif defined(a32)
#define KERNEL_VMA_OFFSET 0xC0000000
#define USER_ALLOC_BASE 0x80000000
#define USER_ALLOC_END 0xA0000000
#define KERNEL_STACK_BASE 0xA0000000
#define KERNEL_STACK_END 0xB0000000
#define USER_STACK_BASE 0xEFFFFFFF
#define USER_STACK_END 0xE0000000
#endif
#endif // !__FENNIX_KERNEL_MEMORY_MACROS_H__

View File

@ -0,0 +1,174 @@
/*
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_MEMORY_PHYSICAL_H__
#define __FENNIX_KERNEL_MEMORY_PHYSICAL_H__
#include <types.h>
#include <bitmap.hpp>
#include <lock.hpp>
namespace Memory
{
class Physical
{
private:
NewLock(MemoryLock);
std::atomic_uint64_t TotalMemory = 0;
std::atomic_uint64_t FreeMemory = 0;
std::atomic_uint64_t ReservedMemory = 0;
std::atomic_uint64_t UsedMemory = 0;
uint64_t PageBitmapIndex = 0;
Bitmap PageBitmap;
void ReserveEssentials();
void FindBitmapRegion(uintptr_t &BitmapAddress,
size_t &BitmapAddressSize);
public:
Bitmap GetPageBitmap() { return PageBitmap; }
/**
* @brief Get Total Memory
*
* @return uint64_t
*/
uint64_t GetTotalMemory();
/**
* @brief Get Free Memory
*
* @return uint64_t
*/
uint64_t GetFreeMemory();
/**
* @brief Get Reserved Memory
*
* @return uint64_t
*/
uint64_t GetReservedMemory();
/**
* @brief Get Used Memory
*
* @return uint64_t
*/
uint64_t GetUsedMemory();
/**
* @brief Swap page
*
* @param Address Address of the page
* @return true if swap was successful
* @return false if swap was unsuccessful
*/
bool SwapPage(void *Address);
/**
* @brief Swap pages
*
* @param Address Address of the pages
* @param PageCount Number of pages
* @return true if swap was successful
* @return false if swap was unsuccessful
*/
bool SwapPages(void *Address, size_t PageCount);
/**
* @brief Unswap page
*
* @param Address Address of the page
* @return true if unswap was successful
* @return false if unswap was unsuccessful
*/
bool UnswapPage(void *Address);
/**
* @brief Unswap pages
*
* @param Address Address of the pages
* @param PageCount Number of pages
* @return true if unswap was successful
* @return false if unswap was unsuccessful
*/
bool UnswapPages(void *Address, size_t PageCount);
/**
* @brief Lock page
*
* @param Address Address of the page
*/
void LockPage(void *Address);
/**
* @brief Lock pages
*
* @param Address Address of the pages
* @param PageCount Number of pages
*/
void LockPages(void *Address, size_t PageCount);
void ReservePage(void *Address);
void ReservePages(void *Address, size_t PageCount);
void UnreservePage(void *Address);
void UnreservePages(void *Address, size_t PageCount);
/**
* @brief Request page
*
* @return void* Allocated page address
*/
void *RequestPage();
/**
* @brief Request pages
*
* @param PageCount Number of pages
* @return void* Allocated pages address
*/
void *RequestPages(std::size_t Count);
/**
* @brief Free page
*
* @param Address Address of the page
*/
void FreePage(void *Address);
/**
* @brief Free pages
*
* @param Address Address of the pages
* @param PageCount Number of pages
*/
void FreePages(void *Address, size_t Count);
/** @brief Do not use. */
void Init();
/** @brief Do not use. */
Physical();
/** @brief Do not use. */
~Physical();
};
}
#endif // !__FENNIX_KERNEL_MEMORY_PHYSICAL_H__

View File

@ -0,0 +1,115 @@
/*
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_MEMORY_STACK_GUARD_H__
#define __FENNIX_KERNEL_MEMORY_STACK_GUARD_H__
#include <types.h>
#include <list>
#include <memory/table.hpp>
#include <memory/vma.hpp>
namespace Memory
{
class StackGuard
{
private:
struct AllocatedPages
{
void *PhysicalAddress;
void *VirtualAddress;
};
void *StackBottom = nullptr;
void *StackTop = nullptr;
void *StackPhysicalBottom = nullptr;
void *StackPhysicalTop = nullptr;
uint64_t Size = 0;
bool UserMode = false;
bool Expanded = false;
VirtualMemoryArea *vma = nullptr;
std::list<AllocatedPages> AllocatedPagesList;
public:
std::list<AllocatedPages> GetAllocatedPages()
{
return AllocatedPagesList;
}
/** Fork stack guard */
void Fork(StackGuard *Parent);
/** For general info */
uint64_t GetSize() { return Size; }
/** For general info */
bool GetUserMode() { return UserMode; }
/** For general info */
bool IsExpanded() { return Expanded; }
/** For general info */
void *GetStackBottom() { return StackBottom; }
/** For RSP */
void *GetStackTop() { return StackTop; }
/**
* For general info (avoid if possible)
*
* @note This can be used only if the
* stack was NOT expanded.
*/
void *GetStackPhysicalBottom()
{
if (Expanded)
return nullptr;
return StackPhysicalBottom;
}
/**
* For general info (avoid if possible)
*
* @note This can be used only if the
* stack was NOT expanded.
*/
void *GetStackPhysicalTop()
{
if (Expanded)
return nullptr;
return StackPhysicalTop;
}
/**
* Called by exception handler */
bool Expand(uintptr_t FaultAddress);
/**
* Construct a new Stack Guard object
* @param User Stack for user mode?
*/
StackGuard(bool User, VirtualMemoryArea *vma);
/**
* Destroy the Stack Guard object
*/
~StackGuard();
};
}
#endif // !__FENNIX_KERNEL_MEMORY_STACK_GUARD_H__

View File

@ -0,0 +1,65 @@
/*
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_MEMORY_TEMP_PAGE_TABLE_H__
#define __FENNIX_KERNEL_MEMORY_TEMP_PAGE_TABLE_H__
#include <types.h>
#include <memory/table.hpp>
extern Memory::PageTable *KernelPageTable;
namespace Memory
{
class SwapPT
{
private:
PageTable *Replace = nullptr;
PageTable *Restore = nullptr;
bool Ignore;
public:
SwapPT(auto ReplaceWith,
auto _RestoreWith = nullptr)
: Replace((PageTable *)ReplaceWith)
{
PageTable *RestoreWith = (PageTable *)_RestoreWith;
this->Ignore = Replace == RestoreWith;
if (this->Ignore)
return;
if (RestoreWith)
Restore = RestoreWith;
else
Restore = KernelPageTable;
Replace->Update();
}
~SwapPT()
{
if (this->Ignore)
return;
Restore->Update();
}
};
}
#endif // !__FENNIX_KERNEL_MEMORY_TEMP_PAGE_TABLE_H__

View File

@ -0,0 +1,605 @@
/*
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_MEMORY_TABLE_H__
#define __FENNIX_KERNEL_MEMORY_TABLE_H__
#include <types.h>
namespace Memory
{
/**
* @brief https://wiki.osdev.org/images/4/41/64-bit_page_tables1.png
* @brief https://wiki.osdev.org/images/6/6b/64-bit_page_tables2.png
*/
enum PTFlag
{
/** @brief Present */
P = 1 << 0,
/** @brief Read/Write */
RW = 1 << 1,
/** @brief User/Supervisor */
US = 1 << 2,
/** @brief Write-Through */
PWT = 1 << 3,
/** @brief Cache Disable */
PCD = 1 << 4,
/** @brief Accessed */
A = 1 << 5,
/** @brief Dirty */
D = 1 << 6,
/** @brief Page Size */
PS = 1 << 7,
/** @brief Global */
G = 1 << 8,
/** @brief Available 0 */
CoW = 1 << 9,
/** @brief Available 1 */
KRsv = 1 << 10,
/** @brief Available 2 */
AVL2 = 1 << 11,
/** @brief Page Attribute Table */
PAT = 1 << 12,
/** @brief Available 3 */
AVL3 = (uint64_t)1 << 52,
/** @brief Available 4 */
AVL4 = (uint64_t)1 << 53,
/** @brief Available 5 */
AVL5 = (uint64_t)1 << 54,
/** @brief Available 6 */
AVL6 = (uint64_t)1 << 55,
/** @brief Available 7 */
AVL7 = (uint64_t)1 << 56,
/** @brief Available 8 */
AVL8 = (uint64_t)1 << 57,
/** @brief Available 9 */
AVL9 = (uint64_t)1 << 58,
/** @brief Protection Key 0 */
PK0 = (uint64_t)1 << 59,
/** @brief Protection Key 1 */
PK1 = (uint64_t)1 << 60,
/** @brief Protection Key 2 */
PK2 = (uint64_t)1 << 61,
/** @brief Protection Key 3 */
PK3 = (uint64_t)1 << 62,
/** @brief Execute Disable */
XD = (uint64_t)1 << 63
};
union __packed PageTableEntry
{
struct
{
#if defined(a64)
uintptr_t Present : 1; // 0
uintptr_t ReadWrite : 1; // 1
uintptr_t UserSupervisor : 1; // 2
uintptr_t WriteThrough : 1; // 3
uintptr_t CacheDisable : 1; // 4
uintptr_t Accessed : 1; // 5
uintptr_t Dirty : 1; // 6
uintptr_t PageAttributeTable : 1; // 7
uintptr_t Global : 1; // 8
uintptr_t CopyOnWrite : 1; // 9
uintptr_t KernelReserve : 1; // 10
uintptr_t Available2 : 1; // 11
uintptr_t Address : 40; // 12-51
uintptr_t Available3 : 1; // 52
uintptr_t Available4 : 1; // 53
uintptr_t Available5 : 1; // 54
uintptr_t Available6 : 1; // 55
uintptr_t Available7 : 1; // 56
uintptr_t Available8 : 1; // 57
uintptr_t Available9 : 1; // 58
uintptr_t ProtectionKey : 4; // 59-62
uintptr_t ExecuteDisable : 1; // 63
#elif defined(a32)
uintptr_t Present : 1; // 0
uintptr_t ReadWrite : 1; // 1
uintptr_t UserSupervisor : 1; // 2
uintptr_t WriteThrough : 1; // 3
uintptr_t CacheDisable : 1; // 4
uintptr_t Accessed : 1; // 5
uintptr_t Dirty : 1; // 6
uintptr_t PageAttributeTable : 1; // 7
uintptr_t Global : 1; // 8
uintptr_t CopyOnWrite : 1; // 9
uintptr_t KernelReserve : 1; // 10
uintptr_t Available2 : 1; // 11
uintptr_t Address : 20; // 12-31
#elif defined(aa64)
#endif
};
uintptr_t raw = 0;
/** @brief Set Address */
void SetAddress(uintptr_t _Address)
{
#if defined(a64)
_Address &= 0x000000FFFFFFFFFF;
this->raw &= 0xFFF0000000000FFF;
this->raw |= (_Address << 12);
#elif defined(a32)
_Address &= 0x000FFFFF;
this->raw &= 0xFFC00003;
this->raw |= (_Address << 12);
#elif defined(aa64)
_Address &= 0x000000FFFFFFFFFF;
this->raw &= 0xFFF0000000000FFF;
this->raw |= (_Address << 12);
#endif
}
/** @brief Get Address */
uintptr_t GetAddress()
{
#if defined(a64)
return (this->raw & 0x000FFFFFFFFFF000) >> 12;
#elif defined(a32)
return ((uintptr_t)(this->raw & 0x003FFFFF000) >> 12);
#elif defined(aa64)
return (this->raw & 0x000FFFFFFFFFF000) >> 12;
#endif
}
};
struct __packed PageTableEntryPtr
{
#if defined(a64)
PageTableEntry Entries[512];
#elif defined(a32)
PageTableEntry Entries[1024];
#elif defined(aa64)
#endif
};
union __packed PageDirectoryEntry
{
#if defined(a64)
struct
{
uintptr_t Present : 1; // 0
uintptr_t ReadWrite : 1; // 1
uintptr_t UserSupervisor : 1; // 2
uintptr_t WriteThrough : 1; // 3
uintptr_t CacheDisable : 1; // 4
uintptr_t Accessed : 1; // 5
uintptr_t CopyOnWrite : 1; // 6
uintptr_t PageSize : 1; // 7
uintptr_t KernelReserve : 1; // 8
uintptr_t Available2 : 1; // 9
uintptr_t Available3 : 1; // 10
uintptr_t Available4 : 1; // 11
uintptr_t Address : 40; // 12-51
uintptr_t Available5 : 1; // 52
uintptr_t Available6 : 1; // 53
uintptr_t Available7 : 1; // 54
uintptr_t Available8 : 1; // 55
uintptr_t Available9 : 1; // 56
uintptr_t Available10 : 1; // 57
uintptr_t Available11 : 1; // 58
uintptr_t Available12 : 1; // 59
uintptr_t Available13 : 1; // 60
uintptr_t Available14 : 1; // 61
uintptr_t Available15 : 1; // 62
uintptr_t ExecuteDisable : 1; // 63
};
struct
{
uintptr_t Present : 1; // 0
uintptr_t ReadWrite : 1; // 1
uintptr_t UserSupervisor : 1; // 2
uintptr_t WriteThrough : 1; // 3
uintptr_t CacheDisable : 1; // 4
uintptr_t Accessed : 1; // 5
uintptr_t Dirty : 1; // 6
uintptr_t PageSize : 1; // 7
uintptr_t Global : 1; // 8
uintptr_t CopyOnWrite : 1; // 9
uintptr_t KernelReserve : 1; // 10
uintptr_t Available2 : 1; // 11
uintptr_t PageAttributeTable : 1; // 12
uintptr_t Reserved0 : 8; // 13-20
uintptr_t Address : 31; // 21-51
uintptr_t Available3 : 1; // 52
uintptr_t Available4 : 1; // 53
uintptr_t Available5 : 1; // 54
uintptr_t Available6 : 1; // 55
uintptr_t Available7 : 1; // 56
uintptr_t Available8 : 1; // 57
uintptr_t Available9 : 1; // 58
uintptr_t ProtectionKey : 4; // 59-62
uintptr_t ExecuteDisable : 1; // 63
} TwoMiB;
#elif defined(a32)
struct
{
uintptr_t Present : 1; // 0
uintptr_t ReadWrite : 1; // 1
uintptr_t UserSupervisor : 1; // 2
uintptr_t WriteThrough : 1; // 3
uintptr_t CacheDisable : 1; // 4
uintptr_t Accessed : 1; // 5
uintptr_t CopyOnWrite : 1; // 6
uintptr_t PageSize : 1; // 7
uintptr_t KernelReserve : 1; // 8
uintptr_t Available2 : 1; // 9
uintptr_t Available3 : 1; // 10
uintptr_t Available4 : 1; // 11
uintptr_t Address : 20; // 12-31
};
struct
{
uintptr_t Present : 1; // 0
uintptr_t ReadWrite : 1; // 1
uintptr_t UserSupervisor : 1; // 2
uintptr_t WriteThrough : 1; // 3
uintptr_t CacheDisable : 1; // 4
uintptr_t Accessed : 1; // 5
uintptr_t Dirty : 1; // 6
uintptr_t PageSize : 1; // 7
uintptr_t Global : 1; // 8
uintptr_t CopyOnWrite : 1; // 9
uintptr_t KernelReserve : 1; // 10
uintptr_t Available2 : 1; // 11
uintptr_t PageAttributeTable : 1; // 12
uintptr_t Address0 : 8; // 13-20
uintptr_t Reserved0 : 1; // 21
uintptr_t Address1 : 10; // 22-31
} FourMiB;
#elif defined(aa64)
#endif
uintptr_t raw = 0;
/** @brief Set PageTableEntryPtr address */
void SetAddress(uintptr_t _Address)
{
#if defined(a64)
_Address &= 0x000000FFFFFFFFFF;
this->raw &= 0xFFF0000000000FFF;
this->raw |= (_Address << 12);
#elif defined(a32)
_Address &= 0x000FFFFF;
this->raw &= 0xFFC00003;
this->raw |= (_Address << 12);
#elif defined(aa64)
_Address &= 0x000000FFFFFFFFFF;
this->raw &= 0xFFF0000000000FFF;
this->raw |= (_Address << 12);
#endif
}
/** @brief Get PageTableEntryPtr address */
uintptr_t GetAddress()
{
#if defined(a64)
return (this->raw & 0x000FFFFFFFFFF000) >> 12;
#elif defined(a32)
return ((uintptr_t)(this->raw & 0x003FFFFF000) >> 12);
#elif defined(aa64)
return (this->raw & 0x000FFFFFFFFFF000) >> 12;
#endif
}
};
struct __packed PageDirectoryEntryPtr
{
PageDirectoryEntry Entries[512];
};
union __packed PageDirectoryPointerTableEntry
{
#if defined(a64)
struct
{
uintptr_t Present : 1; // 0
uintptr_t ReadWrite : 1; // 1
uintptr_t UserSupervisor : 1; // 2
uintptr_t WriteThrough : 1; // 3
uintptr_t CacheDisable : 1; // 4
uintptr_t Accessed : 1; // 5
uintptr_t CopyOnWrite : 1; // 6
uintptr_t PageSize : 1; // 7
uintptr_t KernelReserve : 1; // 8
uintptr_t Available2 : 1; // 9
uintptr_t Available3 : 1; // 10
uintptr_t Available4 : 1; // 11
uintptr_t Address : 40; // 12-51
uintptr_t Available5 : 1; // 52
uintptr_t Available6 : 1; // 53
uintptr_t Available7 : 1; // 54
uintptr_t Available8 : 1; // 55
uintptr_t Available9 : 1; // 56
uintptr_t Available10 : 1; // 57
uintptr_t Available11 : 1; // 58
uintptr_t Available12 : 1; // 59
uintptr_t Available13 : 1; // 60
uintptr_t Available14 : 1; // 61
uintptr_t Available15 : 1; // 62
uintptr_t ExecuteDisable : 1; // 63
};
struct
{
uintptr_t Present : 1; // 0
uintptr_t ReadWrite : 1; // 1
uintptr_t UserSupervisor : 1; // 2
uintptr_t WriteThrough : 1; // 3
uintptr_t CacheDisable : 1; // 4
uintptr_t Accessed : 1; // 5
uintptr_t Dirty : 1; // 6
uintptr_t PageSize : 1; // 7
uintptr_t Global : 1; // 8
uintptr_t CopyOnWrite : 1; // 9
uintptr_t KernelReserve : 1; // 10
uintptr_t Available2 : 1; // 11
uintptr_t PageAttributeTable : 1; // 12
uintptr_t Reserved0 : 17; // 13-29
uintptr_t Address : 22; // 30-51
uintptr_t Available3 : 1; // 52
uintptr_t Available4 : 1; // 53
uintptr_t Available5 : 1; // 54
uintptr_t Available6 : 1; // 55
uintptr_t Available7 : 1; // 56
uintptr_t Available8 : 1; // 57
uintptr_t Available9 : 1; // 58
uintptr_t ProtectionKey : 4; // 59-62
uintptr_t ExecuteDisable : 1; // 63
} OneGiB;
#elif defined(aa64)
#endif
uintptr_t raw = 0;
/** @brief Set PageDirectoryEntryPtr address */
void SetAddress(uintptr_t _Address)
{
#if defined(a64)
_Address &= 0x000000FFFFFFFFFF;
this->raw &= 0xFFF0000000000FFF;
this->raw |= (_Address << 12);
#elif defined(aa64)
_Address &= 0x000000FFFFFFFFFF;
this->raw &= 0xFFF0000000000FFF;
this->raw |= (_Address << 12);
#endif
}
/** @brief Get PageDirectoryEntryPtr address */
uintptr_t GetAddress()
{
#if defined(a64)
return (this->raw & 0x000FFFFFFFFFF000) >> 12;
#elif defined(a32)
return 0;
#elif defined(aa64)
return (this->raw & 0x000FFFFFFFFFF000) >> 12;
#endif
}
};
struct __packed PageDirectoryPointerTableEntryPtr
{
PageDirectoryPointerTableEntry Entries[512];
};
union __packed PageMapLevel4
{
#if defined(a64)
struct
{
uintptr_t Present : 1; // 0
uintptr_t ReadWrite : 1; // 1
uintptr_t UserSupervisor : 1; // 2
uintptr_t WriteThrough : 1; // 3
uintptr_t CacheDisable : 1; // 4
uintptr_t Accessed : 1; // 5
uintptr_t CopyOnWrite : 1; // 6
uintptr_t Reserved0 : 1; // 7
uintptr_t KernelReserve : 1; // 8
uintptr_t Available2 : 1; // 9
uintptr_t Available3 : 1; // 10
uintptr_t Available4 : 1; // 11
uintptr_t Address : 40; // 12-51
uintptr_t Available5 : 1; // 52
uintptr_t Available6 : 1; // 53
uintptr_t Available7 : 1; // 54
uintptr_t Available8 : 1; // 55
uintptr_t Available9 : 1; // 56
uintptr_t Available10 : 1; // 57
uintptr_t Available11 : 1; // 58
uintptr_t Available12 : 1; // 59
uintptr_t Available13 : 1; // 60
uintptr_t Available14 : 1; // 61
uintptr_t Available15 : 1; // 62
uintptr_t ExecuteDisable : 1; // 63
};
#elif defined(aa64)
#endif
uintptr_t raw = 0;
/** @brief Set PageDirectoryPointerTableEntryPtr address */
void SetAddress(uintptr_t _Address)
{
#if defined(a64)
_Address &= 0x000000FFFFFFFFFF;
this->raw &= 0xFFF0000000000FFF;
this->raw |= (_Address << 12);
#elif defined(aa64)
_Address &= 0x000000FFFFFFFFFF;
this->raw &= 0xFFF0000000000FFF;
this->raw |= (_Address << 12);
#endif
}
/** @brief Get PageDirectoryPointerTableEntryPtr address */
uintptr_t GetAddress()
{
#if defined(a64)
return (this->raw & 0x000FFFFFFFFFF000) >> 12;
#elif defined(a32)
return 0;
#elif defined(aa64)
return (this->raw & 0x000FFFFFFFFFF000) >> 12;
#endif
}
};
struct __packed PageMapLevel4Ptr
{
PageMapLevel4 Entries[512];
};
union __packed PageMapLevel5
{
#if defined(a64)
struct
{
uintptr_t Present : 1; // 0
uintptr_t ReadWrite : 1; // 1
uintptr_t UserSupervisor : 1; // 2
uintptr_t WriteThrough : 1; // 3
uintptr_t CacheDisable : 1; // 4
uintptr_t Accessed : 1; // 5
uintptr_t Available0 : 1; // 6
uintptr_t Reserved0 : 1; // 7
uintptr_t KernelReserve : 1; // 8
uintptr_t Available1 : 1; // 9
uintptr_t Available2 : 1; // 10
uintptr_t Available3 : 1; // 11
uintptr_t Address : 40; // 12-51
uintptr_t Available4 : 1; // 52
uintptr_t Available5 : 1; // 53
uintptr_t Available6 : 1; // 54
uintptr_t Available7 : 1; // 55
uintptr_t Available8 : 1; // 56
uintptr_t Available9 : 1; // 57
uintptr_t Available10 : 1; // 58
uintptr_t Available11 : 1; // 59
uintptr_t Available12 : 1; // 60
uintptr_t Available13 : 1; // 61
uintptr_t Available14 : 1; // 62
uintptr_t ExecuteDisable : 1; // 63
};
#elif defined(aa64)
#endif
uintptr_t raw = 0;
/** @brief Set PageMapLevel4Ptr address */
void SetAddress(uintptr_t _Address)
{
#if defined(a64)
_Address &= 0x000000FFFFFFFFFF;
this->raw &= 0xFFF0000000000FFF;
this->raw |= (_Address << 12);
#elif defined(aa64)
_Address &= 0x000000FFFFFFFFFF;
this->raw &= 0xFFF0000000000FFF;
this->raw |= (_Address << 12);
#endif
}
/** @brief Get PageMapLevel4Ptr address */
uintptr_t GetAddress()
{
#if defined(a64)
return (this->raw & 0x000FFFFFFFFFF000) >> 12;
#elif defined(a32)
return 0;
#elif defined(aa64)
return (this->raw & 0x000FFFFFFFFFF000) >> 12;
#endif
}
};
class PageTable
{
public:
#if defined(a64)
PageMapLevel4 Entries[512];
#elif defined(a32)
PageDirectoryEntry Entries[1024];
#elif defined(aa64)
#endif
/**
* @brief Update CR3 with this PageTable
*/
void Update();
/**
* @brief Fork this PageTable
*
* @return A new PageTable with the same content
*/
PageTable *Fork();
void *__getPhysical(void *Address);
/**
* @brief Get the Physical Address of a virtual address
*
* This function will return the physical address
* of a virtual address and not the virtual address
* of the current page table. This is intentional because
* the kernel page table has 1:1 mapping for the free
* memory.
*
* @tparam T
* @param Address The virtual address
* @return The physical address
*/
template <typename T>
T Get(T Address)
{
void *PhysAddr = __getPhysical((void *)Address);
if (PhysAddr == nullptr)
return {};
uintptr_t Diff = uintptr_t(Address);
Diff &= 0xFFF;
Diff = uintptr_t(PhysAddr) + Diff;
return (T)Diff;
}
} __aligned(0x1000);
}
#endif // !__FENNIX_KERNEL_MEMORY_TABLE_H__

View File

@ -0,0 +1,60 @@
/*
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_MEMORY_VA_H__
#define __FENNIX_KERNEL_MEMORY_VA_H__
#include <types.h>
#include <lock.hpp>
#include <list>
#include <memory/table.hpp>
namespace Memory
{
class VirtualAllocation
{
public:
struct AllocatedPages
{
void *PhysicalAddress;
void *VirtualAddress;
size_t PageCount;
bool Free;
};
private:
NewLock(MgrLock);
std::list<AllocatedPages> AllocatedPagesList;
void *BaseAddress;
void *CurrentBase;
public:
PageTable *Table;
AllocatedPages RequestPages(size_t Count);
void FreePages(void *Address, size_t Count);
void MapTo(AllocatedPages ap, PageTable *Table);
VirtualAllocation(void *Base);
~VirtualAllocation();
};
}
#endif // !__FENNIX_KERNEL_MEMORY_VA_H__

View File

@ -0,0 +1,307 @@
/*
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_MEMORY_VIRTUAL_H__
#define __FENNIX_KERNEL_MEMORY_VIRTUAL_H__
#include <types.h>
#include <lock.hpp>
#include <memory/table.hpp>
#include <memory/macro.hpp>
namespace Memory
{
class Virtual
{
private:
NewLock(MemoryLock);
PageTable *pTable = nullptr;
public:
enum MapType
{
NoMapType,
FourKiB,
TwoMiB,
FourMiB,
OneGiB
};
class PageMapIndexer
{
public:
#if defined(a64)
uintptr_t PMLIndex = 0;
uintptr_t PDPTEIndex = 0;
#endif
uintptr_t PDEIndex = 0;
uintptr_t PTEIndex = 0;
PageMapIndexer(uintptr_t VirtualAddress);
};
/**
* @brief Check if page has the specified flag.
*
* @param VirtualAddress Virtual address of the page
* @param Flag Flag to check
* @return true if page has the specified flag, false otherwise.
*/
bool Check(void *VirtualAddress, PTFlag Flag = PTFlag::P);
/**
* @brief Check if the region has the specified flag.
*
* @param VirtualAddress Virtual address of the region.
* @param Length Length of the region.
* @param Flag Flag to check.
* @return true if the region has the specified flag, false otherwise.
*/
bool CheckRegion(void *VirtualAddress, size_t Length,
PTFlag Flag = PTFlag::P)
{
for (size_t i = 0; i < Length; i += PAGE_SIZE_4K)
{
if (!this->Check((void *)((uintptr_t)VirtualAddress + i), Flag))
{
debug("address %#lx for pt %#lx has flag(s) %#lx",
(uintptr_t)VirtualAddress + i, this->pTable, Flag);
return false;
}
}
return true;
}
/**
* @brief Get physical address of the page.
* @param VirtualAddress Virtual address of the page.
* @return Physical address of the page.
*/
void *GetPhysical(void *VirtualAddress);
/**
* @brief Get map type of the page.
* @param VirtualAddress Virtual address of the page.
* @return Map type of the page.
*/
MapType GetMapType(void *VirtualAddress);
#ifdef a64
PageMapLevel5 *GetPML5(void *VirtualAddress, MapType Type = MapType::FourKiB);
PageMapLevel4 *GetPML4(void *VirtualAddress, MapType Type = MapType::FourKiB);
PageDirectoryPointerTableEntry *GetPDPTE(void *VirtualAddress, MapType Type = MapType::FourKiB);
#endif /* a64 */
PageDirectoryEntry *GetPDE(void *VirtualAddress, MapType Type = MapType::FourKiB);
PageTableEntry *GetPTE(void *VirtualAddress, MapType Type = MapType::FourKiB);
/**
* @brief Map page.
*
* @param VirtualAddress Virtual address of the page.
* @param PhysicalAddress Physical address of the page.
* @param Flags Flags of the page. Check PTFlag enum.
* @param Type Type of the page. Check MapType enum.
*/
void Map(void *VirtualAddress,
void *PhysicalAddress,
uint64_t Flag = PTFlag::P,
MapType Type = MapType::FourKiB);
/**
* @brief Map multiple pages.
*
* @param VirtualAddress First virtual address of the page.
* @param PhysicalAddress First physical address of the page.
* @param Length Length to map.
* @param Flags Flags of the page. Check PTFlag enum.
* @param Type Type of the page. Check MapType enum.
*/
__always_inline inline void Map(void *VirtualAddress,
void *PhysicalAddress,
size_t Length,
uint64_t Flags,
MapType Type = MapType::FourKiB)
{
int PageSize = PAGE_SIZE_4K;
if (Type == MapType::TwoMiB)
PageSize = PAGE_SIZE_2M;
else if (Type == MapType::FourMiB)
PageSize = PAGE_SIZE_4M;
else if (Type == MapType::OneGiB)
PageSize = PAGE_SIZE_1G;
for (uintptr_t i = 0; i < Length; i += PageSize)
{
this->Map((void *)((uintptr_t)VirtualAddress + i),
(void *)((uintptr_t)PhysicalAddress + i),
Flags, Type);
}
}
/**
* @brief Map multiple pages efficiently.
*
* This function will detect the best page size to map the pages.
*
* @note This function will not check if PSE or 1GB pages are enabled or supported.
*
* @param VirtualAddress First virtual address of the page.
* @param PhysicalAddress First physical address of the page.
* @param Length Length of the pages.
* @param Flags Flags of the page. Check PTFlag enum.
* @param Fit If true, the function will try to fit the pages in the smallest page size.
* @param FailOnModulo If true, the function will return NoMapType if the length is not a multiple of the page size.
* @return The best page size to map the pages.
*/
__always_inline inline MapType OptimizedMap(void *VirtualAddress,
void *PhysicalAddress,
size_t Length,
uint64_t Flags,
bool Fit = false,
bool FailOnModulo = false)
{
if (unlikely(Fit))
{
while (Length >= PAGE_SIZE_1G)
{
this->Map(VirtualAddress, PhysicalAddress, Length, Flags, Virtual::MapType::OneGiB);
VirtualAddress = (void *)((uintptr_t)VirtualAddress + PAGE_SIZE_1G);
PhysicalAddress = (void *)((uintptr_t)PhysicalAddress + PAGE_SIZE_1G);
Length -= PAGE_SIZE_1G;
}
while (Length >= PAGE_SIZE_4M)
{
this->Map(VirtualAddress, PhysicalAddress, Length, Flags, Virtual::MapType::FourMiB);
VirtualAddress = (void *)((uintptr_t)VirtualAddress + PAGE_SIZE_4M);
PhysicalAddress = (void *)((uintptr_t)PhysicalAddress + PAGE_SIZE_4M);
Length -= PAGE_SIZE_4M;
}
while (Length >= PAGE_SIZE_2M)
{
this->Map(VirtualAddress, PhysicalAddress, Length, Flags, Virtual::MapType::TwoMiB);
VirtualAddress = (void *)((uintptr_t)VirtualAddress + PAGE_SIZE_2M);
PhysicalAddress = (void *)((uintptr_t)PhysicalAddress + PAGE_SIZE_2M);
Length -= PAGE_SIZE_2M;
}
while (Length >= PAGE_SIZE_4K)
{
this->Map(VirtualAddress, PhysicalAddress, Length, Flags, Virtual::MapType::FourKiB);
VirtualAddress = (void *)((uintptr_t)VirtualAddress + PAGE_SIZE_4K);
PhysicalAddress = (void *)((uintptr_t)PhysicalAddress + PAGE_SIZE_4K);
Length -= PAGE_SIZE_4K;
}
return Virtual::MapType::FourKiB;
}
Virtual::MapType Type = Virtual::MapType::FourKiB;
if (Length >= PAGE_SIZE_1G)
{
Type = Virtual::MapType::OneGiB;
if (Length % PAGE_SIZE_1G != 0)
{
warn("Length is not a multiple of 1GB.");
if (FailOnModulo)
return Virtual::MapType::NoMapType;
}
}
else if (Length >= PAGE_SIZE_4M)
{
Type = Virtual::MapType::FourMiB;
if (Length % PAGE_SIZE_4M != 0)
{
warn("Length is not a multiple of 4MB.");
if (FailOnModulo)
return Virtual::MapType::NoMapType;
}
}
else if (Length >= PAGE_SIZE_2M)
{
Type = Virtual::MapType::TwoMiB;
if (Length % PAGE_SIZE_2M != 0)
{
warn("Length is not a multiple of 2MB.");
if (FailOnModulo)
return Virtual::MapType::NoMapType;
}
}
this->Map(VirtualAddress, PhysicalAddress, Length, Flags, Type);
return Type;
}
/**
* @brief Unmap page.
*
* @param VirtualAddress Virtual address of the page.
* @param Type Type of the page. Check MapType enum.
*/
void Unmap(void *VirtualAddress, MapType Type = MapType::FourKiB);
/**
* @brief Unmap multiple pages.
*
* @param VirtualAddress First virtual address of the page.
* @param Length Length to map.
* @param Type Type of the page. Check MapType enum.
*/
__always_inline inline void Unmap(void *VirtualAddress, size_t Length, MapType Type = MapType::FourKiB)
{
int PageSize = PAGE_SIZE_4K;
if (Type == MapType::TwoMiB)
PageSize = PAGE_SIZE_2M;
else if (Type == MapType::FourMiB)
PageSize = PAGE_SIZE_4M;
else if (Type == MapType::OneGiB)
PageSize = PAGE_SIZE_1G;
for (uintptr_t i = 0; i < Length; i += PageSize)
this->Unmap((void *)((uintptr_t)VirtualAddress + i), Type);
}
/**
* @brief Remap page.
*
* @param VirtualAddress Virtual address of the page.
* @param PhysicalAddress Physical address of the page.
* @param Flags Flags of the page. Check PTFlag enum.
* @param Type Type of the page. Check MapType enum.
*/
void Remap(void *VirtualAddress, void *PhysicalAddress, uint64_t Flags, MapType Type = MapType::FourKiB);
/**
* @brief Construct a new Virtual object
*
* @param Table Page table. If null, it will use the current page table.
*/
Virtual(PageTable *Table = nullptr);
/**
* @brief Destroy the Virtual object
*
*/
~Virtual();
};
}
#endif // !__FENNIX_KERNEL_MEMORY_VIRTUAL_H__

View File

@ -0,0 +1,121 @@
/*
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_MEMORY_VMA_H__
#define __FENNIX_KERNEL_MEMORY_VMA_H__
#include <types.h>
#include <filesystem.hpp>
#include <bitmap.hpp>
#include <lock.hpp>
#include <list>
#include <memory/table.hpp>
namespace Memory
{
class VirtualMemoryArea
{
public:
struct AllocatedPages
{
void *Address;
size_t PageCount;
bool Protected;
};
struct SharedRegion
{
void *Address = nullptr;
bool Read = 0, Write = 0, Exec = 0;
bool Fixed = 0, Shared = 0;
size_t Length = 0;
size_t ReferenceCount = 0;
};
private:
NewLock(MgrLock);
Bitmap PageBitmap;
std::list<AllocatedPages> AllocatedPagesList;
std::list<SharedRegion> SharedRegions;
public:
PageTable *Table = nullptr;
uint64_t GetAllocatedMemorySize();
void *RequestPages(size_t Count, bool User = false, bool Protect = false);
void FreePages(void *Address, size_t Count);
void DetachAddress(void *Address);
/**
* Create a Copy-on-Write region
*
* @param Address Hint address
* @param Length Length of the region
* @param Read Make the region readable
* @param Write Make the region writable
* @param Exec Make the region executable
* @param Fixed Fixed address
* @param Shared Shared region
* @return Address of the region
*/
void *CreateCoWRegion(void *Address, size_t Length,
bool Read, bool Write, bool Exec,
bool Fixed, bool Shared);
bool HandleCoW(uintptr_t PFA);
void FreeAllPages();
void Fork(VirtualMemoryArea *Parent);
void Reserve(void *Address, size_t Length);
void Unreserve(void *Address, size_t Length);
int Map(void *VirtualAddress, void *PhysicalAddress,
size_t Length, uint64_t Flags);
int Remap(void *VirtualAddress, void *PhysicalAddress, uint64_t Flags);
int Unmap(void *VirtualAddress, size_t Length);
void *__UserCheckAndGetAddress(void *Address, size_t Length);
int __UserCheck(void *Address, size_t Length);
template <typename T>
T UserCheckAndGetAddress(T Address, size_t Length = 0)
{
if (Length == 0)
Length = sizeof(T);
void *PhysAddr = __UserCheckAndGetAddress((void *)Address, Length);
if (PhysAddr == nullptr)
return {};
return T(PhysAddr);
}
template <typename T>
int UserCheck(T Address, size_t Length = 0)
{
if (Length == 0)
Length = sizeof(T);
return __UserCheck((void *)Address, Length);
}
VirtualMemoryArea(PageTable *Table);
~VirtualMemoryArea();
};
}
#endif // !__FENNIX_KERNEL_MEMORY_VMA_H__

248
Kernel/include/msexec.h Normal file
View File

@ -0,0 +1,248 @@
/*
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_MSEXEC_H__
#define __FENNIX_KERNEL_MSEXEC_H__
#include <types.h>
/* Some of the code is from: https://github.com/dotnet/llilc/blob/main/include/clr/ntimage.h */
#define near /* __near */
#define far /* __far */
#define NEAR near
#define FAR far
#define CONST const
typedef char CHAR;
typedef unsigned char UCHAR;
typedef wchar_t WCHAR;
typedef unsigned short USHORT;
typedef long LONG;
typedef unsigned long DWORD;
typedef int BOOL;
typedef unsigned char BYTE;
typedef unsigned short WORD;
typedef float FLOAT;
typedef FLOAT *PFLOAT;
typedef BOOL near *PBOOL;
typedef BOOL far *LPBOOL;
typedef BYTE near *PBYTE;
typedef BYTE far *LPBYTE;
typedef int near *PINT;
typedef int far *LPINT;
typedef WORD near *PWORD;
typedef WORD far *LPWORD;
typedef long far *LPLONG;
typedef DWORD near *PDWORD;
typedef DWORD far *LPDWORD;
typedef void far *LPVOID;
typedef CONST void far *LPCVOID;
typedef int INT;
typedef unsigned int UINT;
typedef unsigned int *PUINT;
typedef short SHORT;
typedef DWORD ULONG;
typedef double DOUBLE;
#define IMAGE_DOS_SIGNATURE 0x5A4D /* MZ */
#define IMAGE_OS2_SIGNATURE 0x454E /* NE */
#define IMAGE_OS2_SIGNATURE_LE 0x454C /* LE */
#define IMAGE_NT_SIGNATURE 0x00004550 /* PE00 */
#define IMAGE_EDOS_SIGNATURE 0x44454550 /* PEED */
#define IMAGE_SIZEOF_FILE_HEADER 20
#define IMAGE_FILE_MACHINE_UNKNOWN 0
#define IMAGE_FILE_MACHINE_I860 0x14d
#define IMAGE_FILE_MACHINE_I386 0x14c
#define IMAGE_FILE_MACHINE_R3000 0x162
#define IMAGE_FILE_MACHINE_R4000 0x166
#define IMAGE_FILE_MACHINE_R10000 0x0168
#define IMAGE_FILE_MACHINE_ALPHA 0x184
#define IMAGE_FILE_MACHINE_POWERPC 0x01F0
#define IMAGE_FILE_MACHINE_POWERPCBE 0x01F2
#define IMAGE_FILE_MACHINE_SH3 0x01a2
#define IMAGE_FILE_MACHINE_SH3E 0x01a4
#define IMAGE_FILE_MACHINE_SH4 0x01a6
#define IMAGE_FILE_MACHINE_ARM 0x01c0
#define IMAGE_FILE_MACHINE_THUMB 0x01c2
#define IMAGE_FILE_MACHINE_IA64 0x0200
#define IMAGE_FILE_MACHINE_MIPS16 0x0266
#define IMAGE_FILE_MACHINE_MIPSFPU 0x0366
#define IMAGE_FILE_MACHINE_MIPSFPU16 0x0466
#define IMAGE_FILE_MACHINE_ALPHA64 0x0284
#define IMAGE_FILE_MACHINE_AXP64 IMAGE_FILE_MACHINE_ALPHA64
#define IMAGE_FILE_MACHINE_AMD64 0x8664
#define IMAGE_FILE_MACHINE_CEF 0xC0EF
#define IMAGE_NUMBEROF_DIRECTORY_ENTRIES 16
#define IMAGE_DIRECTORY_ENTRY_EXPORT 0
#define IMAGE_DIRECTORY_ENTRY_IMPORT 1
#define IMAGE_DIRECTORY_ENTRY_RESOURCE 2
#define IMAGE_DIRECTORY_ENTRY_EXCEPTION 3
#define IMAGE_DIRECTORY_ENTRY_SECURITY 4
#define IMAGE_DIRECTORY_ENTRY_BASERELOC 5
#define IMAGE_DIRECTORY_ENTRY_DEBUG 6
#define IMAGE_DIRECTORY_ENTRY_ARCHITECTURE 7
#define IMAGE_DIRECTORY_ENTRY_GLOBALPTR 8
#define IMAGE_DIRECTORY_ENTRY_TLS 9
#define IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG 10
#define IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT 11
#define IMAGE_DIRECTORY_ENTRY_IAT 12
#define IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT 13
#define IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR 14
typedef struct _IMAGE_DOS_HEADER /* DOS .EXE header */
{
USHORT e_magic; /* Magic number */
USHORT e_cblp; /* Bytes on last page of file */
USHORT e_cp; /* Pages in file */
USHORT e_crlc; /* Relocations */
USHORT e_cparhdr; /* Size of header in paragraphs */
USHORT e_minalloc; /* Minimum extra paragraphs needed */
USHORT e_maxalloc; /* Maximum extra paragraphs needed */
USHORT e_ss; /* Initial (relative) SS value */
USHORT e_sp; /* Initial SP value */
USHORT e_csum; /* Checksum */
USHORT e_ip; /* Initial IP value */
USHORT e_cs; /* Initial (relative) CS value */
USHORT e_lfarlc; /* File address of relocation table */
USHORT e_ovno; /* Overlay number */
USHORT e_res[4]; /* Reserved words */
USHORT e_oemid; /* OEM identifier (for e_oeminfo) */
USHORT e_oeminfo; /* OEM information; e_oemid specific */
USHORT e_res2[10]; /* Reserved words */
USHORT e_lfanew; /* File address of new exe header */
} IMAGE_DOS_HEADER, *PIMAGE_DOS_HEADER;
typedef struct _IMAGE_OS2_HEADER /* OS/2 .EXE header */
{
USHORT ne_magic; /* Magic number */
UCHAR ne_ver; /* Version number */
UCHAR ne_rev; /* Revision number */
USHORT ne_enttab; /* Offset of Entry Table */
USHORT ne_cbenttab; /* Number of bytes in Entry Table */
UINT ne_crc; /* Checksum of whole file */
USHORT ne_flags; /* Flag word */
USHORT ne_autodata; /* Automatic data segment number */
USHORT ne_heap; /* Initial heap allocation */
USHORT ne_stack; /* Initial stack allocation */
UINT ne_csip; /* Initial CS:IP setting */
UINT ne_sssp; /* Initial SS:SP setting */
USHORT ne_cseg; /* Count of file segments */
USHORT ne_cmod; /* Entries in Module Reference Table */
USHORT ne_cbnrestab; /* Size of non-resident name table */
USHORT ne_segtab; /* Offset of Segment Table */
USHORT ne_rsrctab; /* Offset of Resource Table */
USHORT ne_restab; /* Offset of resident name table */
USHORT ne_modtab; /* Offset of Module Reference Table */
USHORT ne_imptab; /* Offset of Imported Names Table */
UINT ne_nrestab; /* Offset of Non-resident Names Table */
USHORT ne_cmovent; /* Count of movable entries */
USHORT ne_align; /* Segment alignment shift count */
USHORT ne_cres; /* Count of resource segments */
UCHAR ne_exetyp; /* Target Operating system */
UCHAR ne_flagsothers; /* Other .EXE flags */
USHORT ne_pretthunks; /* offset to return thunks */
USHORT ne_psegrefbytes; /* offset to segment ref. bytes */
USHORT ne_swaparea; /* Minimum code swap area size */
USHORT ne_expver; /* Expected Windows version number */
} IMAGE_OS2_HEADER, *PIMAGE_OS2_HEADER;
typedef struct _IMAGE_SECTION_HEADER
{
#define IMAGE_SIZEOF_SHORT_NAME 8
uint8_t Name[IMAGE_SIZEOF_SHORT_NAME];
union
{
uint32_t PhysicalAddress;
uint32_t VirtualSize;
} Misc;
uint32_t VirtualAddress;
uint32_t SizeOfRawData;
uint32_t PointerToRawData;
uint32_t PointerToRelocations;
uint32_t PointerToLinenumbers;
uint16_t NumberOfRelocations;
uint16_t NumberOfLinenumbers;
uint32_t Characteristics;
} IMAGE_SECTION_HEADER, *PIMAGE_SECTION_HEADER;
typedef struct _IMAGE_FILE_HEADER
{
uint16_t Machine;
uint16_t NumberOfSections;
uint32_t TimeDateStamp;
uint32_t PointerToSymbolTable;
uint32_t NumberOfSymbols;
uint16_t SizeOfOptionalHeader;
uint16_t Characteristics;
} IMAGE_FILE_HEADER, *PIMAGE_FILE_HEADER;
typedef struct _IMAGE_DATA_DIRECTORY
{
uint32_t VirtualAddress;
uint32_t Size;
} IMAGE_DATA_DIRECTORY, *PIMAGE_DATA_DIRECTORY;
typedef struct _IMAGE_OPTIONAL_HEADER
{
uint16_t Magic;
uint8_t MajorLinkerVersion;
uint8_t MinorLinkerVersion;
uint32_t SizeOfCode;
uint32_t SizeOfInitializedData;
uint32_t SizeOfUninitializedData;
uint32_t AddressOfEntryPoint;
uint32_t BaseOfCode;
uint32_t BaseOfData;
uint32_t ImageBase;
uint32_t SectionAlignment;
uint32_t FileAlignment;
uint16_t MajorOperatingSystemVersion;
uint16_t MinorOperatingSystemVersion;
uint16_t MajorImageVersion;
uint16_t MinorImageVersion;
uint16_t MajorSubsystemVersion;
uint16_t MinorSubsystemVersion;
uint32_t Win32VersionValue;
uint32_t SizeOfImage;
uint32_t SizeOfHeaders;
uint32_t CheckSum;
uint16_t Subsystem;
uint16_t DllCharacteristics;
uint32_t SizeOfStackReserve;
uint32_t SizeOfStackCommit;
uint32_t SizeOfHeapReserve;
uint32_t SizeOfHeapCommit;
uint32_t LoaderFlags;
uint32_t NumberOfRvaAndSizes;
IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];
} IMAGE_OPTIONAL_HEADER, *PIMAGE_OPTIONAL_HEADER;
typedef struct _IMAGE_NT_HEADERS
{
uint32_t Signature;
IMAGE_FILE_HEADER FileHeader;
IMAGE_OPTIONAL_HEADER OptionalHeader;
} IMAGE_NT_HEADERS, *PIMAGE_NT_HEADERS;
#endif // !__FENNIX_KERNEL_MSEXEC_H__

106
Kernel/include/net/arp.hpp Normal file
View File

@ -0,0 +1,106 @@
/*
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_NETWORK_ARP_H__
#define __FENNIX_KERNEL_NETWORK_ARP_H__
#include <net/eth.hpp>
#include <net/nc.hpp>
#include <types.h>
#include <vector>
namespace NetworkARP
{
enum ARPOperation
{
REQUEST = 0x1,
REPLY = 0x2
};
enum ARPHardwareType
{
HTYPE_ETHERNET = 1,
HTYPE_802_3 = 6,
HTYPE_ARCNET = 7,
HTYPE_FRAME_RELAY = 15,
HTYPE_ATM = 16,
HTYPE_HDLC = 17,
HTYPE_FIBRE_CHANNEL = 18,
HTYPE_ATM_2 = 19,
HTYPE_SERIAL_LINE = 20
};
struct ARPHeader
{
uint16_t HardwareType;
uint16_t ProtocolType;
uint8_t HardwareSize;
uint8_t ProtocolSize;
uint16_t Operation;
uint48_t SenderMAC : 48;
uint32_t SenderIP;
uint48_t TargetMAC : 48;
uint32_t TargetIP;
} __packed;
struct DiscoveredAddress
{
MediaAccessControl MAC;
InternetProtocol IP;
};
class ARP : public NetworkEthernet::EthernetEvents
{
private:
NetworkEthernet::Ethernet *Ethernet;
enum DAType
{
DA_ADD = 1,
DA_DEL = 2,
DA_SEARCH = 3,
DA_UPDATE = 4
};
std::vector<NetworkARP::DiscoveredAddress *> DiscoveredAddresses;
DiscoveredAddress *ManageDiscoveredAddresses(DAType Type, InternetProtocol IP, MediaAccessControl MAC);
DiscoveredAddress *Search(InternetProtocol TargetIP);
DiscoveredAddress *Update(InternetProtocol TargetIP, MediaAccessControl TargetMAC);
bool OnEthernetPacketReceived(uint8_t *Data, size_t Length);
public:
ARP(NetworkEthernet::Ethernet *Ethernet);
~ARP();
/**
* @brief Resolve an IP address to a MAC address.
*
* @param IP The IP address to resolve. (Little-endian)
* @return uint48_t The MAC address of the IP address.
*/
uint48_t Resolve(InternetProtocol IP);
/**
* @brief Broadcast an ARP packet.
*
* @param IP The IP address to broadcast.
*/
void Broadcast(InternetProtocol IP);
};
}
#endif // !__FENNIX_KERNEL_NETWORK_ARP_H__

182
Kernel/include/net/dhcp.hpp Normal file
View File

@ -0,0 +1,182 @@
/*
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_DHCP_H__
#define __FENNIX_KERNEL_DHCP_H__
#include <net/ipv4.hpp>
#include <net/udp.hpp>
#include <net/nc.hpp>
#include <types.h>
namespace NetworkDHCP
{
struct DHCPHeader
{
uint8_t Opcode;
uint8_t HardwareType;
uint8_t HardwareAddressLength;
uint8_t Hops;
uint32_t TransactionID;
uint16_t Seconds;
uint16_t Flags;
uint32_t ClientIP;
uint32_t YourIP;
uint32_t ServerIP;
uint32_t GatewayIP;
uint8_t ClientHardwareAddress[16];
uint8_t ServerHostName[64];
uint8_t BootFileName[128];
uint8_t Options[64];
} __packed;
enum DHCPOperation
{
DHCP_OP_BOOTREQUEST = 1,
DHCP_OP_BOOTREPLY = 2
};
/* TODO: Complete list from https://en.wikipedia.org/wiki/Dynamic_Host_Configuration_Protocol#Options */
enum DHCPOption
{
DHCP_OPTION_PAD = 0,
DHCP_OPTION_SUBNETMASK = 1,
DHCP_OPTION_TIME_OFFSET = 2,
DHCP_OPTION_ROUTER = 3,
DHCP_OPTION_TIME_SERVER = 4,
DHCP_OPTION_NAME_SERVER = 5,
DHCP_OPTION_DOMAIN_NAME_SERVER = 6,
DHCP_OPTION_LOG_SERVER = 7,
DHCP_OPTION_COOKIE_SERVER = 8,
DHCP_OPTION_LPR_SERVER = 9,
DHCP_OPTION_IMPRESS_SERVER = 10,
DHCP_OPTION_RESOURCE_LOCATION_SERVER = 11,
DHCP_OPTION_HOST_NAME = 12,
DHCP_OPTION_BOOT_FILE_SIZE = 13,
DHCP_OPTION_MERIT_DUMP_FILE = 14,
DHCP_OPTION_DOMAIN_NAME = 15,
DHCP_OPTION_SWAP_SERVER = 16,
DHCP_OPTION_ROOT_PATH = 17,
DHCP_OPTION_EXTENSION_PATH = 18,
DHCP_OPTION_IP_FORWARDING = 19,
DHCP_OPTION_NON_LOCAL_SOURCE_ROUTING = 20,
DHCP_OPTION_POLICY_FILTER = 21,
DHCP_OPTION_MAX_DATAGRAM_REASSEMBLY_SIZE = 22,
DHCP_OPTION_DEFAULT_IP_TTL = 23,
DHCP_OPTION_PATH_MTU_AGING_TIMEOUT = 24,
DHCP_OPTION_PATH_MTU_PLATEAU_TABLE = 25,
DHCP_OPTION_INTERFACE_MTU = 26,
DHCP_OPTION_ALL_SUBNETS_ARE_LOCAL = 27,
DHCP_OPTION_BROADCAST_ADDRESS = 28,
DHCP_OPTION_PERFORM_MASK_DISCOVERY = 29,
DHCP_OPTION_MASK_SUPPLIER = 30,
DHCP_OPTION_ROUTER_DISCOVERY = 31,
DHCP_OPTION_ROUTER_SOLICITATION_ADDRESS = 32,
DHCP_OPTION_STATIC_ROUTE = 33,
DHCP_OPTION_TRAILER_ENCAPSULATION = 34,
DHCP_OPTION_ARP_CACHE_TIMEOUT = 35,
DHCP_OPTION_ETHERNET_ENCAPSULATION = 36,
DHCP_OPTION_DEFAULT_TCP_TTL = 37,
DHCP_OPTION_TCP_KEEPALIVE_INTERVAL = 38,
DHCP_OPTION_TCP_KEEPALIVE_GARBAGE = 39,
DHCP_OPTION_NIS_DOMAIN = 40,
DHCP_OPTION_NIS_SERVERS = 41,
DHCP_OPTION_NTP_SERVERS = 42,
DHCP_OPTION_VENDOR_SPECIFIC = 43,
DHCP_OPTION_NETBIOS_NAME_SERVERS = 44,
DHCP_OPTION_NETBIOS_DD_SERVER = 45,
DHCP_OPTION_NETBIOS_NODE_TYPE = 46,
DHCP_OPTION_NETBIOS_SCOPE = 47,
DHCP_OPTION_X_FONT_SERVERS = 48,
DHCP_OPTION_X_DISPLAY_MANAGER = 49,
DHCP_OPTION_REQUESTED_IP = 50,
DHCP_OPTION_IP_LEASE_TIME = 51,
DHCP_OPTION_OPTION_OVERLOAD = 52,
DHCP_OPTION_MESSAGE_TYPE = 53,
DHCP_OPTION_SERVER_IDENTIFIER = 54,
DHCP_OPTION_PARAMETER_REQUEST_LIST = 55,
DHCP_OPTION_MESSAGE = 56,
DHCP_OPTION_MAX_MESSAGE_SIZE = 57,
DHCP_OPTION_T1_TIMEOUT = 58,
DHCP_OPTION_T2_TIMEOUT = 59,
DHCP_OPTION_VENDOR_CLASS_IDENTIFIER = 60,
DHCP_OPTION_CLIENT_IDENTIFIER = 61,
DHCP_OPTION_NETWORK_TIME_SERVER = 62,
DHCP_OPTION_END = 255
};
enum DHCPMessageType
{
DHCP_MESSAGE_TYPE_DISCOVER = 1,
DHCP_MESSAGE_TYPE_OFFER = 2,
DHCP_MESSAGE_TYPE_REQUEST = 3,
DHCP_MESSAGE_TYPE_DECLINE = 4,
DHCP_MESSAGE_TYPE_ACK = 5,
DHCP_MESSAGE_TYPE_NAK = 6,
DHCP_MESSAGE_TYPE_RELEASE = 7,
DHCP_MESSAGE_TYPE_INFORM = 8,
DHCP_MESSAGE_TYPE_FORCERENEW = 9,
DHCP_MESSAGE_TYPE_LEASEQUERY = 10,
DHCP_MESSAGE_TYPE_LEASEUNASSIGNED = 11,
DHCP_MESSAGE_TYPE_LEASEUNKNOWN = 12,
DHCP_MESSAGE_TYPE_LEASEACTIVE = 13,
DHCP_MESSAGE_TYPE_BULKLEASEQUERY = 14,
DHCP_MESSAGE_TYPE_LEASEQUERYDONE = 15,
DHCP_MESSAGE_TYPE_ACTIVELEASEQUERY = 16,
DHCP_MESSAGE_TYPE_LEASEQUERYSTATUS = 17,
DHCP_MESSAGE_TYPE_DHCPTLS = 18
};
#define DHCP_TRANSACTION_ID 0xFE2EC005
class DHCP : public NetworkUDP::UDPEvents
{
private:
NetworkUDP::Socket *UDPSocket;
NetworkInterfaceManager::DeviceInterface *Interface;
bool Received = false;
void CreatePacket(DHCPHeader *Packet, uint8_t MessageType, uint32_t RequestIP);
void *GetOption(DHCPHeader *Packet, uint8_t Type);
void OnUDPPacketReceived(NetworkUDP::Socket *Socket, uint8_t *Data, size_t Length);
public:
/** @brief IP address (Little-endian) */
InternetProtocol IP = {};
/** @brief Gateway address (Little-endian) */
InternetProtocol Gateway = {};
/** @brief Subnet mask (Little-endian) */
InternetProtocol SubNetworkMask = {};
/** @brief DNS server address (Little-endian) */
InternetProtocol DomainNameSystem = {};
DHCP(NetworkUDP::Socket *Socket, NetworkInterfaceManager::DeviceInterface *Interface);
~DHCP();
void Request();
void Request(InternetProtocol IP);
};
}
#endif // !__FENNIX_KERNEL_DHCP_H__

View File

@ -0,0 +1,37 @@
/*
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_DNS_H__
#define __FENNIX_KERNEL_DNS_H__
#include <net/udp.hpp>
#include <types.h>
namespace NetworkDNS
{
class DNS : public NetworkUDP::UDPEvents
{
private:
NetworkUDP::Socket *UDPSocket;
public:
DNS(NetworkUDP::Socket *Socket);
~DNS();
};
}
#endif // !__FENNIX_KERNEL_DNS_H__

108
Kernel/include/net/eth.hpp Normal file
View File

@ -0,0 +1,108 @@
/*
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_NETWORK_ETHERNET_H__
#define __FENNIX_KERNEL_NETWORK_ETHERNET_H__
#include <types.h>
#include <net/nc.hpp>
namespace NetworkEthernet
{
enum FrameType
{
TYPE_IPV4 = 0x0800,
TYPE_ARP = 0x0806,
TYPE_RARP = 0x8035,
TYPE_IPV6 = 0x86DD
};
struct EthernetHeader
{
uint48_t DestinationMAC : 48;
uint48_t SourceMAC : 48;
uint16_t Type;
} __packed;
struct EthernetPacket
{
EthernetHeader Header;
uint8_t Data[];
};
class EthernetEvents
{
private:
FrameType FType;
protected:
EthernetEvents(FrameType Type);
~EthernetEvents();
public:
FrameType GetFrameType() { return FType; }
virtual void OnEthernetPacketSent(EthernetPacket *Packet)
{
UNUSED(Packet);
netdbg("Event not handled. [%p]", Packet);
}
virtual bool OnEthernetPacketReceived(uint8_t *Data, size_t Length)
{
UNUSED(Data);
UNUSED(Length);
netdbg("Event not handled. [%p, %d]", Data, Length);
return false;
}
};
class Ethernet : public NetworkInterfaceManager::Events
{
private:
NetworkInterfaceManager::DeviceInterface *Interface;
void Receive(uint8_t *Data, size_t Length);
void OnInterfaceReceived(NetworkInterfaceManager::DeviceInterface *Interface, uint8_t *Data, size_t Length);
public:
/** @brief Get driver interface
* @return Driver interface
*/
NetworkInterfaceManager::DeviceInterface *GetInterface()
{
netdbg("Interface: %#lx (MAC: %s; IPv4: %s; IPv6: %s)", this->Interface,
this->Interface->MAC.ToString(),
this->Interface->IP.v4.ToStringLittleEndian(),
this->Interface->IP.v6.ToStringLittleEndian());
return this->Interface;
}
Ethernet(NetworkInterfaceManager::DeviceInterface *Interface);
~Ethernet();
/**
* @brief Send an Ethernet packet.
*
* @param MAC The MAC address of the destination. (Big-endian)
* @param Type The type of the packet.
* @param Data The data to send.
* @param Length The length of the data.
*/
void Send(MediaAccessControl MAC, FrameType Type, uint8_t *Data, size_t Length);
};
}
#endif // !__FENNIX_KERNEL_NETWORK_ETHERNET_H__

View File

@ -0,0 +1,71 @@
/*
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_ICMPv4_H__
#define __FENNIX_KERNEL_ICMPv4_H__
#include <net/nc.hpp>
#include <types.h>
namespace NetworkICMPv4
{
enum ICMPv4Type
{
TYPE_ECHO_REPLY = 0,
TYPE_DESTINATION_UNREACHABLE = 3,
TYPE_SOURCE_QUENCH = 4,
TYPE_REDIRECT = 5,
TYPE_ECHO = 8,
TYPE_ROUTER_ADVERTISEMENT = 9,
TYPE_ROUTER_SELECTION = 10,
TYPE_TIME_EXCEEDED = 11,
TYPE_PARAMETER_PROBLEM = 12,
TYPE_TIMESTAMP = 13,
TYPE_TIMESTAMP_REPLY = 14
};
struct ICMPHeader
{
uint8_t Type;
uint8_t Code;
uint16_t Checksum;
uint16_t Identifier;
uint16_t SequenceNumber;
};
struct ICMPPacket
{
ICMPHeader Header;
uint8_t Data[];
};
class ICMPv4
{
private:
NetworkInterfaceManager::DeviceInterface *Interface;
public:
NetworkInterfaceManager::DeviceInterface *GetInterface() { return this->Interface; }
ICMPv4(NetworkInterfaceManager::DeviceInterface *Interface);
~ICMPv4();
void Send(/* ???? */);
void Receive(ICMPPacket *Packet);
};
}
#endif // !__FENNIX_KERNEL_ICMPv4_H__

View File

@ -0,0 +1,56 @@
/*
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_ICMPv6_H__
#define __FENNIX_KERNEL_ICMPv6_H__
#include <net/nc.hpp>
#include <types.h>
namespace NetworkICMPv6
{
struct ICMPHeader
{
uint8_t Type;
uint8_t Code;
uint16_t Checksum;
uint16_t Identifier;
uint16_t SequenceNumber;
};
struct ICMPPacket
{
ICMPHeader Header;
uint8_t Data[];
};
class ICMPv6
{
private:
NetworkInterfaceManager::DeviceInterface *Interface;
public:
NetworkInterfaceManager::DeviceInterface *GetInterface() { return this->Interface; }
ICMPv6(NetworkInterfaceManager::DeviceInterface *Interface);
~ICMPv6();
void Send(uint8_t *Data, size_t Length);
void Receive(uint8_t *Data);
};
}
#endif // !__FENNIX_KERNEL_ICMPv6_H__

137
Kernel/include/net/ipv4.hpp Normal file
View File

@ -0,0 +1,137 @@
/*
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_IPv4_H__
#define __FENNIX_KERNEL_IPv4_H__
#include <net/ipv4.hpp>
#include <net/arp.hpp>
#include <net/nc.hpp>
#include <types.h>
namespace NetworkIPv4
{
struct IPv4Header
{
uint8_t IHL : 4;
uint8_t Version : 4;
uint8_t TypeOfService;
uint16_t TotalLength;
uint16_t Identification;
uint8_t Flags;
uint8_t FragmentOffset;
uint8_t TimeToLive;
uint8_t Protocol;
uint16_t HeaderChecksum;
uint32_t SourceIP;
uint32_t DestinationIP;
/* On wikipedia page we have this: https://en.wikipedia.org/wiki/File:IPv4_Packet-en.svg
but only the code above works... */
// uint8_t Version : 4;
// uint8_t IHL : 4;
// uint16_t TypeOfService : 8;
// uint16_t TotalLength : 12;
// uint16_t Identification : 16;
// uint16_t Flags : 3;
// uint16_t FragmentOffset : 13;
// uint8_t TimeToLive : 8;
// uint8_t Protocol : 8;
// uint16_t HeaderChecksum;
// uint32_t SourceIP;
// uint32_t DestinationIP;
};
struct IPv4Packet
{
IPv4Header Header;
uint8_t Data[];
};
enum IPv4Protocols
{
PROTOCOL_ICMP = 1,
PROTOCOL_IGMP = 2,
PROTOCOL_TCP = 6,
PROTOCOL_UDP = 17,
PROTOCOL_IPV6 = 41,
PROTOCOL_ROUTING = 43,
PROTOCOL_FRAGMENT = 44,
PROTOCOL_ESP = 50,
PROTOCOL_AH = 51,
PROTOCOL_ICMPV6 = 58,
PROTOCOL_NONE = 59,
PROTOCOL_DSTOPTS = 60,
PROTOCOL_ND = 77,
PROTOCOL_ICLFXBM = 78,
PROTOCOL_PIM = 103,
PROTOCOL_COMP = 108,
PROTOCOL_SCTP = 132,
PROTOCOL_UDPLITE = 136,
PROTOCOL_RAW = 255
};
class IPv4 : public NetworkEthernet::EthernetEvents
{
private:
NetworkARP::ARP *ARP;
NetworkEthernet::Ethernet *Ethernet;
virtual bool OnEthernetPacketReceived(uint8_t *Data, size_t Length);
public:
InternetProtocol GatewayIP;
InternetProtocol SubNetworkMaskIP;
IPv4(NetworkARP::ARP *ARP, NetworkEthernet::Ethernet *Ethernet);
~IPv4();
/**
* @brief Send an IPv4 packet.
*
* @param Data The data to send.
* @param Length The length of the data.
* @param Protocol The protocol of the packet.
* @param DestinationIP The IP address of the destination. (Big-endian)
*/
void Send(uint8_t *Data, size_t Length, uint8_t Protocol, InternetProtocol DestinationIP);
};
class IPv4Events
{
private:
uint8_t Protocol;
protected:
IPv4Events(IPv4Protocols Protocol);
~IPv4Events();
public:
uint8_t GetProtocol() { return Protocol; }
virtual bool OnIPv4PacketReceived(InternetProtocol SourceIP, InternetProtocol DestinationIP, uint8_t *Data, size_t Length)
{
UNUSED(SourceIP);
UNUSED(DestinationIP);
UNUSED(Data);
UNUSED(Length);
warn("Not implemented");
return false;
}
};
}
#endif // !__FENNIX_KERNEL_IPv4_H__

View File

@ -0,0 +1,44 @@
/*
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_IPv6_H__
#define __FENNIX_KERNEL_IPv6_H__
#include <types.h>
namespace NetworkIPv6
{
struct IPv6Header
{
uint32_t Version;
uint8_t TrafficClass;
uint16_t FlowLabel;
uint16_t PayloadLength;
uint8_t NextHeader;
uint8_t HopLimit;
uint32_t SourceIP;
uint32_t DestinationIP;
};
struct IPv6Packet
{
IPv6Header Header;
uint8_t Data[];
};
}
#endif // !__FENNIX_KERNEL_IPv6_H__

116
Kernel/include/net/nc.hpp Normal file
View File

@ -0,0 +1,116 @@
/*
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_NETWORK_CONTROLLER_H__
#define __FENNIX_KERNEL_NETWORK_CONTROLLER_H__
#include <net/net.hpp>
#include <memory.hpp>
#include <task.hpp>
#include <types.h>
#include <debug.h>
#include <vector>
namespace NetworkInterfaceManager
{
struct DeviceInterface
{
/** @brief Device interface name */
char Name[128];
/** @brief Device interface index */
uint64_t ID;
/** @brief Device interface MAC address (Big-endian) */
MediaAccessControl MAC;
/** @brief Device interface IP address (Big-endian) */
InternetProtocol IP;
/** @brief Reserved */
unsigned long DriverID;
};
class Events
{
protected:
Events(DeviceInterface *Interface);
~Events();
public:
virtual void OnInterfaceAdded(DeviceInterface *Interface)
{
UNUSED(Interface);
netdbg("Event for %s not handled.", Interface->Name);
}
virtual void OnInterfaceRemoved(DeviceInterface *Interface)
{
UNUSED(Interface);
netdbg("Event for %s not handled.", Interface->Name);
}
virtual void OnInterfaceChanged(DeviceInterface *Interface)
{
UNUSED(Interface);
netdbg("Event for %s not handled.", Interface->Name);
}
virtual void OnInterfaceReceived(DeviceInterface *Interface, uint8_t *Data, size_t Length)
{
UNUSED(Interface);
UNUSED(Data);
UNUSED(Length);
netdbg("Event for %s not handled.", Interface->Name);
}
virtual void OnInterfaceSent(DeviceInterface *Interface, uint8_t *Data, size_t Length)
{
UNUSED(Interface);
UNUSED(Data);
UNUSED(Length);
netdbg("Event for %s not handled.", Interface->Name);
}
};
class NetworkInterface
{
private:
Memory::VirtualMemoryArea *vma;
int CardIDs = 0;
std::vector<DeviceInterface *> Interfaces;
Tasking::TCB *NetSvcThread;
void StopNetworkStack();
void FetchNetworkCards(unsigned long modUniqueID);
public:
NetworkInterface();
~NetworkInterface();
void StartService();
void Send(DeviceInterface *Interface, uint8_t *Data, size_t Length);
void Receive(DeviceInterface *Interface, uint8_t *Data, size_t Length);
void DrvSend(unsigned int DriverID, unsigned char *Data, unsigned short Size);
void DrvReceive(unsigned int DriverID, unsigned char *Data, unsigned short Size);
void StartNetworkStack();
};
}
#endif // !__FENNIX_KERNEL_NETWORK_CONTROLLER_H__

232
Kernel/include/net/net.hpp Normal file
View File

@ -0,0 +1,232 @@
/*
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_NETWORK_H__
#define __FENNIX_KERNEL_NETWORK_H__
#include <types.h>
#include <printf.h>
// #define DEBUG_NETWORK 1
#ifdef DEBUG_NETWORK
#define netdbg(m, ...) debug(m, ##__VA_ARGS__)
void DbgNetwork();
void DbgDumpData(const char *Description, void *Address, unsigned long Length);
#else
#define netdbg(m, ...)
static inline void DbgNetwork() { return; }
static inline void DbgDumpData(const char *Description, void *Address, unsigned long Length)
{
UNUSED(Description);
UNUSED(Address);
UNUSED(Length);
return;
}
#endif
enum Endianness
{
LITTLE_ENDIAN,
BIG_ENDIAN
};
struct MediaAccessControl
{
uint8_t Address[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
Endianness Endianess = LITTLE_ENDIAN;
inline bool operator==(const MediaAccessControl &lhs) const
{
return lhs.Address[0] == this->Address[0] &&
lhs.Address[1] == this->Address[1] &&
lhs.Address[2] == this->Address[2] &&
lhs.Address[3] == this->Address[3] &&
lhs.Address[4] == this->Address[4] &&
lhs.Address[5] == this->Address[5];
}
inline bool operator==(const uint48_t &lhs) const
{
MediaAccessControl MAC;
MAC.Address[0] = (uint8_t)((lhs >> 40) & 0xFF);
MAC.Address[1] = (uint8_t)((lhs >> 32) & 0xFF);
MAC.Address[2] = (uint8_t)((lhs >> 24) & 0xFF);
MAC.Address[3] = (uint8_t)((lhs >> 16) & 0xFF);
MAC.Address[4] = (uint8_t)((lhs >> 8) & 0xFF);
MAC.Address[5] = (uint8_t)(lhs & 0xFF);
return MAC.Address[0] == this->Address[0] &&
MAC.Address[1] == this->Address[1] &&
MAC.Address[2] == this->Address[2] &&
MAC.Address[3] == this->Address[3] &&
MAC.Address[4] == this->Address[4] &&
MAC.Address[5] == this->Address[5];
}
inline bool operator!=(const MediaAccessControl &lhs) const { return !(*this == lhs); }
inline bool operator!=(const uint48_t &lhs) const { return !(*this == lhs); }
inline uint48_t ToHex()
{
return ((uint48_t)this->Address[0] << 40) |
((uint48_t)this->Address[1] << 32) |
((uint48_t)this->Address[2] << 24) |
((uint48_t)this->Address[3] << 16) |
((uint48_t)this->Address[4] << 8) |
((uint48_t)this->Address[5]);
}
inline MediaAccessControl FromHex(uint48_t Hex)
{
this->Address[0] = (uint8_t)((Hex >> 40) & 0xFF);
this->Address[1] = (uint8_t)((Hex >> 32) & 0xFF);
this->Address[2] = (uint8_t)((Hex >> 24) & 0xFF);
this->Address[3] = (uint8_t)((Hex >> 16) & 0xFF);
this->Address[4] = (uint8_t)((Hex >> 8) & 0xFF);
this->Address[5] = (uint8_t)(Hex & 0xFF);
return *this;
}
inline bool Valid()
{
// TODO: More complex MAC validation
return (this->Address[0] != 0 ||
this->Address[1] != 0 ||
this->Address[2] != 0 ||
this->Address[3] != 0 ||
this->Address[4] != 0 ||
this->Address[5] != 0) &&
(this->Address[0] != 0xFF ||
this->Address[1] != 0xFF ||
this->Address[2] != 0xFF ||
this->Address[3] != 0xFF ||
this->Address[4] != 0xFF ||
this->Address[5] != 0xFF);
}
char *ToString()
{
static char Buffer[18];
sprintf(Buffer, "%02X:%02X:%02X:%02X:%02X:%02X", this->Address[0], this->Address[1], this->Address[2], this->Address[3], this->Address[4], this->Address[5]);
return Buffer;
}
};
/* There's a confusion between LSB and MSB. Not sure if "ToStringLittleEndian" and "ToStringBigEndian" are implemented correctly.
Because x86 is a LSB architecture, I'm assuming that the "ToStringLittleEndian" is correct? */
struct InternetProtocol
{
struct Version4
{
uint8_t Address[4] = {255, 255, 255, 255};
Endianness Endianess = LITTLE_ENDIAN;
inline bool operator==(const InternetProtocol::Version4 &lhs) const
{
return lhs.Address[0] == this->Address[0] &&
lhs.Address[1] == this->Address[1] &&
lhs.Address[2] == this->Address[2] &&
lhs.Address[3] == this->Address[3];
}
inline bool operator==(const uint32_t &lhs) const
{
InternetProtocol::Version4 IP;
IP.Address[0] = (uint8_t)((lhs >> 24) & 0xFF);
IP.Address[1] = (uint8_t)((lhs >> 16) & 0xFF);
IP.Address[2] = (uint8_t)((lhs >> 8) & 0xFF);
IP.Address[3] = (uint8_t)(lhs & 0xFF);
return IP.Address[0] == this->Address[0] &&
IP.Address[1] == this->Address[1] &&
IP.Address[2] == this->Address[2] &&
IP.Address[3] == this->Address[3];
}
inline bool operator!=(const InternetProtocol::Version4 &lhs) const { return !(*this == lhs); }
inline bool operator!=(const uint32_t &lhs) const { return !(*this == lhs); }
inline uint32_t ToHex()
{
return ((uint32_t)this->Address[0] << 24) |
((uint32_t)this->Address[1] << 16) |
((uint32_t)this->Address[2] << 8) |
((uint32_t)this->Address[3]);
}
inline InternetProtocol::Version4 FromHex(uint32_t Hex)
{
this->Address[0] = (uint8_t)((Hex >> 24) & 0xFF);
this->Address[1] = (uint8_t)((Hex >> 16) & 0xFF);
this->Address[2] = (uint8_t)((Hex >> 8) & 0xFF);
this->Address[3] = (uint8_t)(Hex & 0xFF);
return *this;
}
char *ToStringLittleEndian()
{
static char Buffer[16];
sprintf(Buffer, "%d.%d.%d.%d", this->Address[0], this->Address[1], this->Address[2], this->Address[3]);
return Buffer;
}
char *ToStringBigEndian()
{
static char Buffer[16];
sprintf(Buffer, "%d.%d.%d.%d", this->Address[3], this->Address[2], this->Address[1], this->Address[0]);
return Buffer;
}
} v4;
struct Version6
{
uint16_t Address[8] = {0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF};
Endianness Endianess = LITTLE_ENDIAN;
inline bool operator==(const InternetProtocol::Version6 &lhs) const
{
return lhs.Address[0] == this->Address[0] &&
lhs.Address[1] == this->Address[1] &&
lhs.Address[2] == this->Address[2] &&
lhs.Address[3] == this->Address[3] &&
lhs.Address[4] == this->Address[4] &&
lhs.Address[5] == this->Address[5] &&
lhs.Address[6] == this->Address[6] &&
lhs.Address[7] == this->Address[7];
}
inline bool operator!=(const InternetProtocol::Version6 &lhs) const { return !(*this == lhs); }
char *ToStringLittleEndian()
{
static char Buffer[40];
sprintf(Buffer, "%04X:%04X:%04X:%04X:%04X:%04X:%04X:%04X", this->Address[0], this->Address[1], this->Address[2], this->Address[3], this->Address[4], this->Address[5], this->Address[6], this->Address[7]);
return Buffer;
}
char *ToStringBigEndian()
{
static char Buffer[40];
sprintf(Buffer, "%04X:%04X:%04X:%04X:%04X:%04X:%04X:%04X", this->Address[7], this->Address[6], this->Address[5], this->Address[4], this->Address[3], this->Address[2], this->Address[1], this->Address[0]);
return Buffer;
}
} v6;
};
uint16_t CalculateChecksum(uint16_t *Data, size_t Length);
#endif // !__FENNIX_KERNEL_NETWORK_H__

166
Kernel/include/net/ntp.hpp Normal file
View File

@ -0,0 +1,166 @@
/*
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_NTP_H__
#define __FENNIX_KERNEL_NTP_H__
#include <net/udp.hpp>
#include <types.h>
namespace NetworkNTP
{
struct NTPHeader
{
/** @brief Leap indicator
* 00 - no warning
* 01 - last minute has 61 seconds
* 10 - last minute has 59 seconds
* 11 - alarm condition (clock not synchronized)
*/
uint8_t LeapIndicator : 2;
/** @brief Version number of the protocol
* 3 - IPv4 only
* 4 - IPv4, IPv6 and OSI
* 5 - IPv4, IPv6 and OSI
* 6 - IPv4, IPv6 and OSI
* 7 - IPv4, IPv6 and OSI
*/
uint8_t VersionNumber : 3;
/** @brief Mode
* 0 - reserved
* 1 - symmetric active
* 2 - symmetric passive
* 3 - client
* 4 - server
* 5 - broadcast
* 6 - reserved for NTP control message
* 7 - reserved for private use
*/
uint8_t Mode : 3;
/** @brief Stratum
* 0 - unspecified or unavailable
* 1 - primary reference (e.g. radio clock)
* 2-15 - secondary reference (via NTP or SNTP)
* 16 - unsynchronized
* 17-255 - reserved
*/
uint8_t Stratum;
/** @brief Polling interval
* 4 - 16 seconds
* 5 - 32 seconds
* 6 - 64 seconds
* 7 - 128 seconds
* 8 - 256 seconds
* 9 - 512 seconds
* 10 - 1024 seconds
* 11 - 2048 seconds
* 12 - 4096 seconds
* 13 - 8192 seconds
* 14 - 16384 seconds
* 15 - 32768 seconds
*/
uint8_t Poll;
/** @brief Precision
* -6 - 0.015625 seconds
* -5 - 0.03125 seconds
* -4 - 0.0625 seconds
* -3 - 0.125 seconds
* -2 - 0.25 seconds
* -1 - 0.5 seconds
* 0 - 1 second
* 1 - 2 seconds
* 2 - 4 seconds
* 3 - 8 seconds
* 4 - 16 seconds
* 5 - 32 seconds
* 6 - 64 seconds
* 7 - 128 seconds
*/
uint8_t Precision;
/** @brief Root delay
* Total round trip delay to the primary reference source
*/
uint32_t RootDelay;
/** @brief Root dispersion
* Nominal error relative to the primary reference source
*/
uint32_t RootDispersion;
/** @brief Reference identifier
* 0x00000000 - unspecified
* 0x00000001 - radio clock
* 0x00000002 - atomic clock
* 0x00000003 - GPS receiver
* 0x00000004 - local oscillator
* 0x00000005 - LORAN-C receiver
* 0x00000006 - microprocessor
* 0x00000007 - internet
* 0x00000008 - FLL
* 0x00000009 - other
* 0x0000000A - WWV
* 0x0000000B - WWVB
* 0x0000000C - WWVH
* 0x0000000D - NIST dialup
* 0x0000000E - telephone
* 0x0000000F - reserved
*/
uint32_t ReferenceIdentifier;
/** @brief Reference timestamp
* The time at which the clock was last set or corrected
*/
uint32_t ReferenceTimestamp[2];
/** @brief Originate timestamp
* The time at which the request departed the client for the server
*/
uint32_t OriginateTimestamp[2];
/** @brief Receive timestamp
* The time at which the request arrived at the server
*/
uint32_t ReceiveTimestamp[2];
/** @brief Transmit timestamp
* The time at which the reply departed the server for the client
*/
uint32_t TransmitTimestamp[2];
/** @brief Message authentication code
* Key identifier
* @note Only when the NTP authentication scheme is used
*/
// uint32_t MessageAuthenticationCode;
} __packed;
class NTP : public NetworkUDP::UDPEvents
{
private:
NetworkUDP::Socket *UDPSocket;
bool TimeReceived = false;
NTPHeader NTPPacket;
virtual void OnUDPPacketReceived(NetworkUDP::Socket *Socket, uint8_t *Data, size_t Length);
public:
NTP(NetworkUDP::Socket *Socket);
~NTP();
/**
* @brief Get the time from the NTP server
*
* @return Unix Timestamp
*/
int ReadTime();
};
}
#endif // !__FENNIX_KERNEL_NTP_H__

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/>.
*/
#ifndef __FENNIX_KERNEL_TCP_H__
#define __FENNIX_KERNEL_TCP_H__
#include <types.h>
namespace NetworkTCP
{
}
#endif // !__FENNIX_KERNEL_TCP_H__

View File

@ -0,0 +1,97 @@
/*
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_UDP_H__
#define __FENNIX_KERNEL_UDP_H__
#include <net/ipv4.hpp>
#include <net/udp.hpp>
#include <net/nc.hpp>
#include <types.h>
namespace NetworkUDP
{
struct UDPHeader
{
uint16_t SourcePort;
uint16_t DestinationPort;
uint16_t Length;
uint16_t Checksum;
} __packed;
struct UDPPacket
{
UDPHeader Header;
uint8_t Data[];
};
class Socket;
class UDPEvents
{
protected:
UDPEvents();
~UDPEvents();
public:
virtual void OnUDPPacketReceived(Socket *Socket, uint8_t *Data, size_t Length)
{
UNUSED(Socket);
UNUSED(Data);
UNUSED(Length);
warn("Not implemented");
}
};
class UDP : public NetworkIPv4::IPv4Events
{
private:
NetworkIPv4::IPv4 *ipv4;
NetworkInterfaceManager::DeviceInterface *Interface;
public:
NetworkInterfaceManager::DeviceInterface *GetInterface() { return this->Interface; }
UDP(NetworkIPv4::IPv4 *ipv4, NetworkInterfaceManager::DeviceInterface *Interface);
~UDP();
virtual Socket *Connect(InternetProtocol IP, uint16_t Port);
virtual Socket *Listen(uint16_t Port);
virtual void Disconnect(Socket *Socket);
virtual void Send(Socket *Socket, uint8_t *Data, size_t Length);
virtual void Bind(Socket *Socket, UDPEvents *EventHandler);
virtual bool OnIPv4PacketReceived(InternetProtocol SourceIP, InternetProtocol DestinationIP, uint8_t *Data, size_t Length);
};
class Socket
{
public:
InternetProtocol LocalIP;
uint16_t LocalPort = 0;
InternetProtocol RemoteIP;
uint16_t RemotePort = 0;
bool Listening = false;
UDPEvents *EventHandler = nullptr;
UDP *SocketUDP = nullptr;
Socket(UDP *_UDP);
~Socket();
};
}
#endif // !__FENNIX_KERNEL_UDP_H__

247
Kernel/include/pci.hpp Normal file
View File

@ -0,0 +1,247 @@
/*
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_PCI_H__
#define __FENNIX_KERNEL_PCI_H__
#include <types.h>
#include <memory.hpp>
#include <debug.h>
#include <list>
namespace PCI
{
namespace Descriptors
{
enum PCIVendors
{
Apple = 0x106B,
BusLogic = 0x104B,
SymbiosLogic = 0x1000,
RedHat = 0x1AF4,
REDHat2 = 0x1B36,
Realtek = 0x10EC,
VirtualBox = 0x80EE,
Ensoniq = 0x1274,
QEMU = 0x1234,
VMware = 0x15AD,
IntelCorporation = 0x8086,
AdvancedMicroDevices = 0x1022,
NVIDIACorporation = 0x10DE
};
const char *const DeviceClasses[]{
"Unclassified",
"Mass Storage Controller",
"Network Controller",
"Display Controller",
"Multimedia Controller",
"Memory Controller",
"Bridge Device",
"Simple Communication Controller",
"Base System Peripheral",
"Input Device Controller",
"Docking Station",
"Processor",
"Serial Bus Controller",
"Wireless Controller",
"Intelligent Controller",
"Satellite Communication Controller",
"Encryption Controller",
"Signal Processing Controller",
"Processing Accelerator",
"Non Essential Instrumentation"};
const char *MassStorageControllerSubclassName(uint8_t SubclassCode);
const char *NetworkControllerSubclassName(uint8_t SubclassCode);
const char *DisplayControllerSubclassName(uint8_t SubclassCode);
const char *CommunicationControllerSubclassName(uint8_t SubclassCode);
const char *BaseSystemPeripheralSubclassName(uint8_t SubclassCode);
const char *SerialBusControllerSubclassName(uint8_t SubclassCode);
const char *BridgeDeviceSubclassName(uint8_t SubclassCode);
const char *WirelessControllerSubclassName(uint8_t SubclassCode);
const char *GetVendorName(uint32_t VendorID);
const char *GetDeviceName(uint32_t VendorID, uint32_t DeviceID);
const char *GetSubclassName(uint8_t ClassCode, uint8_t SubclassCode);
const char *GetProgIFName(uint8_t ClassCode, uint8_t SubclassCode, uint8_t ProgIF);
}
/* https://sites.uclouvain.be/SystInfo/usr/include/linux/pci_regs.h.html */
enum PCICommands
{
/** @brief Enable response in I/O space */
PCI_COMMAND_IO = 0x1,
/** @brief Enable response in Memory space */
PCI_COMMAND_MEMORY = 0x2,
/** @brief Enable bus mastering */
PCI_COMMAND_MASTER = 0x4,
/** @brief Enable response to special cycles */
PCI_COMMAND_SPECIAL = 0x8,
/** @brief Use memory write and invalidate */
PCI_COMMAND_INVALIDATE = 0x10,
/** @brief Enable palette snooping */
PCI_COMMAND_VGA_PALETTE = 0x20,
/** @brief Enable parity checking */
PCI_COMMAND_PARITY = 0x40,
/** @brief Enable address/data stepping */
PCI_COMMAND_WAIT = 0x80,
/** @brief Enable SERR */
PCI_COMMAND_SERR = 0x100,
/** @brief Enable back-to-back writes */
PCI_COMMAND_FAST_BACK = 0x200,
/** @brief INTx Emulation Disable */
PCI_COMMAND_INTX_DISABLE = 0x400
};
struct PCIDeviceHeader
{
uint16_t VendorID;
uint16_t DeviceID;
uint16_t Command;
uint16_t Status;
uint8_t RevisionID;
uint8_t ProgIF;
uint8_t Subclass;
uint8_t Class;
uint8_t CacheLineSize;
uint8_t LatencyTimer;
uint8_t HeaderType;
uint8_t BIST;
} __packed;
/** PCI Header Type 0 */
struct PCIHeader0
{
PCIDeviceHeader Header;
uint32_t BAR0;
uint32_t BAR1;
uint32_t BAR2;
uint32_t BAR3;
uint32_t BAR4;
uint32_t BAR5;
uint32_t CardbusCISPointer;
uint16_t SubsystemVendorID;
uint16_t SubsystemID;
uint32_t ExpansionROMBaseAddress;
uint8_t CapabilitiesPointer;
uint8_t Reserved0;
uint16_t Reserved1;
uint32_t Reserved2;
uint8_t InterruptLine;
uint8_t InterruptPin;
uint8_t MinGrant;
uint8_t MaxLatency;
} __packed;
/** PCI Header Type 1 (PCI-to-PCI Bridge) */
struct PCIHeader1
{
PCIDeviceHeader Header;
uint32_t BAR0;
uint32_t BAR1;
uint8_t PrimaryBusNumber;
uint8_t SecondaryBusNumber;
uint8_t SubordinateBusNumber;
uint8_t SecondaryLatencyTimer;
uint8_t IOBase;
uint8_t IOLimit;
uint16_t SecondaryStatus;
uint16_t MemoryBase;
uint16_t MemoryLimit;
uint16_t PrefetchableMemoryBase;
uint16_t PrefetchableMemoryLimit;
uint32_t PrefetchableMemoryBaseUpper32;
uint32_t PrefetchableMemoryLimitUpper32;
uint16_t IOBaseUpper16;
uint16_t IOLimitUpper16;
uint8_t CapabilitiesPointer;
uint8_t Reserved0;
uint16_t Reserved1;
uint32_t ExpansionROMBaseAddress;
uint8_t InterruptLine;
uint8_t InterruptPin;
uint16_t BridgeControl;
} __packed;
/** PCI Header Type 2 (PCI-to-CardBus Bridge) */
struct PCIHeader2
{
PCIDeviceHeader Header;
uint32_t CardbusSocketRegistersBaseAddress;
uint8_t CapabilitiesPointer;
uint8_t Reserved0;
uint16_t SecondaryStatus;
uint8_t PCIbusNumber;
uint8_t CardbusBusNumber;
uint8_t SubordinateBusNumber;
uint8_t CardbusLatencyTimer;
uint32_t MemoryBase0;
uint32_t MemoryLimit0;
uint32_t MemoryBase1;
uint32_t MemoryLimit1;
uint32_t IOBase0;
uint32_t IOLimit0;
uint32_t IOBase1;
uint32_t IOLimit1;
uint8_t InterruptLine;
uint8_t InterruptPin;
uint16_t BridgeControl;
uint16_t SubsystemVendorID;
uint16_t SubsystemID;
uint32_t LegacyBaseAddress;
} __packed;
struct DeviceConfig
{
uint64_t BaseAddress;
uint16_t PCISegGroup;
uint8_t StartBus;
uint8_t EndBus;
uint32_t Reserved;
} __packed;
struct PCIDevice
{
PCIDeviceHeader *Header;
DeviceConfig *Config;
uint32_t Bus;
uint32_t Device;
uint32_t Function;
} __packed;
class Manager
{
private:
std::list<PCIDevice> Devices;
public:
std::list<PCIDevice> GetDevices() { return Devices; }
void MapPCIAddresses(PCIDevice Device, Memory::PageTable *Table);
void EnumerateFunction(uint64_t DeviceAddress, uint32_t Function, PCIDevice dev);
void EnumerateDevice(uint64_t BusAddress, uint32_t Device, PCIDevice dev);
void EnumerateBus(uint64_t BaseAddress, uint32_t Bus, PCIDevice dev);
std::list<PCIDevice> FindPCIDevice(uint8_t Class, uint8_t Subclass, uint8_t ProgIF);
std::list<PCIDevice> FindPCIDevice(uint16_t VendorID, uint16_t DeviceID);
std::list<PCIDevice> FindPCIDevice(std::list<uint16_t> VendorIDs, std::list<uint16_t> DeviceIDs);
Manager();
~Manager();
};
}
#endif // !__FENNIX_KERNEL_PCI_H__

69
Kernel/include/power.hpp Normal file
View File

@ -0,0 +1,69 @@
/*
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_POWER_H__
#define __FENNIX_KERNEL_POWER_H__
#include <types.h>
namespace Power
{
class Power
{
private:
void *acpi = nullptr;
void *dsdt = nullptr;
void *madt = nullptr;
public:
/**
* @brief Get Advanced Configuration and Power Interface. (Available only on x32 and x64)
*
* @return void* (ACPI::ACPI *)
*/
void *GetACPI() { return this->acpi; }
/**
* @brief Get Differentiated System Description Table. (Available only on x32 and x64)
*
* @return void* (ACPI::DSDT *)
*/
void *GetDSDT() { return this->dsdt; }
/**
* @brief Get Multiple APIC Description Table. (Available only on x32 and x64)
*
* @return void* (ACPI::MADT *)
*/
void *GetMADT() { return this->madt; }
/**
* @brief Reboot the system.
*/
void Reboot();
/**
* @brief Shutdown the system.
*/
void Shutdown();
void InitDSDT();
Power();
};
}
#endif // !__FENNIX_KERNEL_POWER_H__

194
Kernel/include/printf.h Normal file
View File

@ -0,0 +1,194 @@
/**
* @author (c) Eyal Rozenberg <eyalroz1@gmx.com>
* 2021-2022, Haifa, Palestine/Israel
* @author (c) Marco Paland (info@paland.com)
* 2014-2019, PALANDesign Hannover, Germany
*
* @note Others have made smaller contributions to this file: see the
* contributors page at https://github.com/eyalroz/printf/graphs/contributors
* or ask one of the authors.
*
* @brief Small stand-alone implementation of the printf family of functions
* (`(v)printf`, `(v)s(n)printf` etc., geared towards use on embedded systems with
* a very limited resources.
*
* @note the implementations are thread-safe; re-entrant; use no functions from
* the standard library; and do not dynamically allocate any memory.
*
* @license The MIT License (MIT)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef PRINTF_H_
#define PRINTF_H_
#include <types.h>
#ifdef __cplusplus
extern "C"
{
#endif
#ifdef __GNUC__
#define ATTR_PRINTF(one_based_format_index, first_arg) \
__attribute__((format(__printf__, (one_based_format_index), (first_arg))))
#define ATTR_VPRINTF(one_based_format_index) ATTR_PRINTF((one_based_format_index), 0)
#else
#define ATTR_PRINTF((one_based_format_index), (first_arg))
#define ATTR_VPRINTF(one_based_format_index)
#endif
#ifndef PRINTF_ALIAS_STANDARD_FUNCTION_NAMES
#define PRINTF_ALIAS_STANDARD_FUNCTION_NAMES 0
#endif
#if PRINTF_ALIAS_STANDARD_FUNCTION_NAMES
#define printf printf
#define sprintf sprintf
#define vsprintf vsprintf
#define snprintf_ snprintf
#define vsnprintf vsnprintf
#define vprintf vprintf
#endif
// If you want to include this implementation file directly rather than
// link against, this will let you control the functions' visibility,
// e.g. make them static so as not to clash with other objects also
// using them.
#ifndef PRINTF_VISIBILITY
#define PRINTF_VISIBILITY
#endif
/**
* Prints/send a single character to some opaque output entity
*
* @note This function is not implemented by the library, only declared; you must provide an
* implementation if you wish to use the @ref printf / @ref vprintf function (and possibly
* for linking against the library, if your toolchain does not support discarding unused functions)
*
* @note The output could be as simple as a wrapper for the `write()` system call on a Unix-like
* system, or even libc's @ref putchar , for replicating actual functionality of libc's @ref printf
* function; but on an embedded system it may involve interaction with a special output device,
* like a UART, etc.
*
* @note in libc's @ref putchar, the parameter type is an int; this was intended to support the
* representation of either a proper character or EOF in a variable - but this is really not
* meaningful to pass into @ref putchar and is discouraged today. See further discussion in:
* @link https://stackoverflow.com/q/17452847/1593077
*
* @param c the single character to print
*/
// PRINTF_VISIBILITY
// void putchar(char c);
/**
* An implementation of the C standard's printf/vprintf
*
* @note you must implement a @ref putchar_ function for using this function - it invokes @ref putchar_
* rather than directly performing any I/O (which insulates it from any dependence on the operating system
* and external libraries).
*
* @param format A string specifying the format of the output, with %-marked specifiers of how to interpret
* additional arguments.
* @param arg Additional arguments to the function, one for each %-specifier in @p format string
* @return The number of characters written into @p s, not counting the terminating null character
*/
///@{
PRINTF_VISIBILITY
int printf(const char *format, ...) ATTR_PRINTF(1, 2);
PRINTF_VISIBILITY
int vprintf(const char *format, va_list arg) ATTR_VPRINTF(1);
///@}
/**
* An implementation of the C standard's sprintf/vsprintf
*
* @note For security considerations (the potential for exceeding the buffer bounds), please consider using
* the size-constrained variant, @ref snprintf / @ref vsnprintf , instead.
*
* @param s An array in which to store the formatted string. It must be large enough to fit the formatted
* output!
* @param format A string specifying the format of the output, with %-marked specifiers of how to interpret
* additional arguments.
* @param arg Additional arguments to the function, one for each specifier in @p format
* @return The number of characters written into @p s, not counting the terminating null character
*/
///@{
PRINTF_VISIBILITY
int sprintf(char *s, const char *format, ...) ATTR_PRINTF(2, 3);
PRINTF_VISIBILITY
int vsprintf(char *s, const char *format, va_list arg) ATTR_VPRINTF(2);
///@}
/**
* An implementation of the C standard's snprintf/vsnprintf
*
* @param s An array in which to store the formatted string. It must be large enough to fit either the
* entire formatted output, or at least @p n characters. Alternatively, it can be NULL, in which case
* nothing will be printed, and only the number of characters which _could_ have been printed is
* tallied and returned.
* @param n The maximum number of characters to write to the array, including a terminating null character
* @param format A string specifying the format of the output, with %-marked specifiers of how to interpret
* additional arguments.
* @param arg Additional arguments to the function, one for each specifier in @p format
* @return The number of characters that COULD have been written into @p s, not counting the terminating
* null character. A value equal or larger than @p n indicates truncation. Only when the returned value
* is non-negative and less than @p n, the null-terminated string has been fully and successfully printed.
*/
///@{
PRINTF_VISIBILITY
int snprintf(char *s, size_t count, const char *format, ...) ATTR_PRINTF(3, 4);
PRINTF_VISIBILITY
int vsnprintf(char *s, size_t count, const char *format, va_list arg) ATTR_VPRINTF(3);
///@}
/**
* printf/vprintf with user-specified output function
*
* An alternative to @ref printf, in which the output function is specified dynamically
* (rather than @ref putchar_ being used)
*
* @param out An output function which takes one character and a type-erased additional parameters
* @param extra_arg The type-erased argument to pass to the output function @p out with each call
* @param format A string specifying the format of the output, with %-marked specifiers of how to interpret
* additional arguments.
* @param arg Additional arguments to the function, one for each specifier in @p format
* @return The number of characters for which the output f unction was invoked, not counting the terminating null character
*
*/
PRINTF_VISIBILITY
int fctprintf(void (*out)(char c, void *extra_arg), void *extra_arg, const char *format, ...) ATTR_PRINTF(3, 4);
PRINTF_VISIBILITY
int vfctprintf(void (*out)(char c, void *extra_arg), void *extra_arg, const char *format, va_list arg) ATTR_VPRINTF(3);
#if PRINTF_ALIAS_STANDARD_FUNCTION_NAMES
#undef printf
#undef sprintf
#undef vsprintf
#undef snprintf_
#undef vsnprintf
#undef vprintf
#endif
#ifdef __cplusplus
}
#endif
#endif // PRINTF_H_

31
Kernel/include/rand.hpp 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/>.
*/
#ifndef __FENNIX_KERNEL_RANDOM_H__
#define __FENNIX_KERNEL_RANDOM_H__
#include <types.h>
namespace Random
{
uint16_t rand16();
uint32_t rand32();
uint64_t rand64();
void ChangeSeed(uint64_t CustomSeed);
}
#endif // !__FENNIX_KERNEL_RANDOM_H__

181
Kernel/include/ring.hpp Normal file
View File

@ -0,0 +1,181 @@
/*
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_RING_BUFFER_H__
#define __FENNIX_KERNEL_RING_BUFFER_H__
#include <types.h>
#include <lock.hpp>
/**
* @brief A generic ring buffer implementation with thread safety.
*
* @tparam T Type of the data stored in the buffer.
*/
template <typename T>
class RingBuffer
{
private:
spin_lock *Lock;
T *Buffer;
size_t BufferSize;
size_t BufferCount;
size_t Head;
size_t Tail;
public:
/**
* @brief Construct a new RingBuffer object.
*
* Initializes the buffer and the spin lock. The default buffer size is 16.
*
* @param Size Initial size (capacity) of the buffer.
*/
RingBuffer(size_t Size = 16)
: Lock(new spin_lock()),
Buffer(new T[Size]),
BufferSize(Size),
BufferCount(0),
Head(0),
Tail(0) {}
/**
* @brief Destroy the RingBuffer object.
*
* Releases the allocated memory for the buffer and the spin lock.
*/
~RingBuffer()
{
delete Lock;
delete[] Buffer;
}
/**
* @brief Write data to the ring buffer.
*
* Writes up to `nReads` elements from `Data` into the buffer. If the buffer
* is full, the function stops writing.
*
* @param Data Pointer to the data to be written.
* @param nReads Number of elements to write.
* @return size_t Number of elements actually written.
*/
size_t Write(const T *Data, size_t nReads)
{
sl_guard(*Lock);
size_t written = 0;
while (nReads > 0)
{
if (BufferCount == BufferSize)
break;
Buffer[Head] = *Data++;
Head = (Head + 1) % BufferSize;
BufferCount++;
written++;
nReads--;
}
return written;
}
/**
* @brief Read data from the ring buffer.
*
* Reads up to `nReads` elements from the buffer into `Data`. If the buffer
* is empty, the function stops reading.
*
* @param Data Pointer to the memory where read elements will be stored.
* @param nReads Number of elements to read.
* @return size_t Number of elements actually read.
*/
size_t Read(T *Data, size_t nReads)
{
sl_guard(*Lock);
size_t read = 0;
while (nReads > 0)
{
if (BufferCount == 0)
break;
*Data++ = Buffer[Tail];
Tail = (Tail + 1) % BufferSize;
BufferCount--;
read++;
nReads--;
}
return read;
}
/**
* @brief Peek at data in the ring buffer without removing it.
*
* Peeks up to `nReads` elements from the buffer into `Data` without
* modifying the buffer state. If the buffer is empty, the function stops peeking.
*
* @param Data Pointer to the memory where peeked elements will be stored.
* @param nReads Number of elements to peek.
* @return size_t Number of elements actually peeked.
*/
size_t Peek(T *Data, size_t nReads)
{
sl_guard(*Lock);
size_t read = 0;
size_t tail = Tail;
while (nReads > 0)
{
if (BufferCount == 0)
break;
*Data++ = Buffer[tail];
tail = (tail + 1) % BufferSize;
read++;
nReads--;
}
return read;
}
/**
* @brief Get the current number of elements in the buffer.
*
* @return size_t The number of elements in the buffer.
*/
size_t Count()
{
sl_guard(*Lock);
return BufferCount;
}
/**
* @brief Get the available space left in the buffer.
*
* @return size_t The number of free slots in the buffer.
*/
size_t Free()
{
sl_guard(*Lock);
return BufferSize - BufferCount;
}
};
#endif // !__FENNIX_KERNEL_RING_BUFFER_H__

View File

@ -0,0 +1,156 @@
/*
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/>.
*/
#pragma once
#include <task.hpp>
#include <lock.hpp>
namespace Tasking::Scheduler
{
class Base
{
public:
Task *ctx = nullptr;
std::atomic_size_t SchedulerTicks = 0;
std::atomic_size_t LastTaskTicks = 0;
std::atomic_int LastCore = 0;
std::atomic_bool StopScheduler = false;
std::atomic_bool SchedulerUpdateTrapFrame = false;
/**
* Remove a thread from the scheduler
*
* @note This function is NOT thread safe
* @note This function does not check if
* the thread is valid nor if it has
* Terminated status
*/
virtual bool RemoveThread(TCB *tcb)
{
assert(!"RemoveThread not implemented");
};
/**
* @note This function is NOT thread safe
*/
virtual bool RemoveProcess(PCB *pcb)
{
assert(!"RemoveProcess not implemented");
}
virtual PCB *GetProcessByID(TID ID)
{
assert(!"GetProcessByID not implemented");
}
virtual TCB *GetThreadByID(TID ID, PCB *Parent)
{
assert(!"GetThreadByID not implemented");
}
virtual std::vector<PCB *> &GetProcessList()
{
assert(!"GetProcessList not implemented");
}
virtual void StartIdleProcess()
{
assert(!"StartIdleProcess not implemented");
}
virtual void StartScheduler()
{
assert(!"StartScheduler not implemented");
}
virtual void Yield()
{
assert(!"Yield not implemented");
}
virtual void PushProcess(PCB *pcb)
{
assert(!"PushProcess not implemented");
}
virtual void PopProcess(PCB *pcb)
{
assert(!"PopProcess not implemented");
}
virtual std::pair<PCB *, TCB *> GetIdle()
{
assert(!"GetIdle not implemented");
}
Base(Task *_ctx)
: ctx(_ctx) {}
~Base() {}
};
class Custom : public Base,
public Interrupts::Handler
{
private:
NewLock(SchedulerLock);
public:
std::vector<PCB *> ProcessList;
PCB *IdleProcess = nullptr;
TCB *IdleThread = nullptr;
bool RemoveThread(TCB *tcb) final;
bool RemoveProcess(PCB *pcb) final;
PCB *GetProcessByID(TID ID) final;
TCB *GetThreadByID(TID ID, PCB *Parent) final;
std::vector<PCB *> &GetProcessList() final;
void StartIdleProcess() final;
void StartScheduler() final;
void Yield() final;
void PushProcess(PCB *pcb) final;
void PopProcess(PCB *pcb) final;
std::pair<PCB *, TCB *> GetIdle() final;
void OneShot(int TimeSlice);
void UpdateUsage(TaskInfo *Info,
TaskExecutionMode Mode,
int Core);
bool FindNewProcess(void *CPUDataPointer);
bool GetNextAvailableThread(void *CPUDataPointer);
bool GetNextAvailableProcess(void *CPUDataPointer);
bool SchedulerSearchProcessThread(void *CPUDataPointer);
void UpdateProcessState();
void WakeUpThreads();
void CleanupTerminated();
void Schedule(CPU::SchedulerFrame *Frame);
void OnInterruptReceived(CPU::SchedulerFrame *Frame) final;
Custom(Task *ctx);
virtual ~Custom();
};
class RoundRobin : public Base,
public Interrupts::Handler
{
};
}

490
Kernel/include/signal.hpp Normal file
View File

@ -0,0 +1,490 @@
/*
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_SIGNAL_H__
#define __FENNIX_KERNEL_SIGNAL_H__
#include <unordered_map>
#include <syscalls.hpp>
#include <lock.hpp>
#include <types.h>
#include <bitset>
#include <list>
enum Signals : int
{
SIG_NULL = 0,
/* Process abort signal. */
SIGABRT = 1,
/* Alarm clock. */
SIGALRM = 2,
/* Access to an undefined portion of a memory object. */
SIGBUS = 3,
/* Child process terminated, stopped, or continued. */
SIGCHLD = 4,
/* Continue executing, if stopped. */
SIGCONT = 5,
/* Erroneous arithmetic operation. */
SIGFPE = 6,
/* Hangup. */
SIGHUP = 7,
/* Illegal instruction. */
SIGILL = 8,
/* Terminal interrupt signal. */
SIGINT = 9,
/* Kill (cannot be caught or ignored). */
SIGKILL = 10,
/* Write on a pipe with no one to read it. */
SIGPIPE = 11,
/* Terminal quit signal. */
SIGQUIT = 12,
/* Invalid memory reference. */
SIGSEGV = 13,
/* Stop executing (cannot be caught or ignored). */
SIGSTOP = 14,
/* Termination signal. */
SIGTERM = 15,
/* Terminal stop signal. */
SIGTSTP = 16,
/* Background process attempting read. */
SIGTTIN = 17,
/* Background process attempting write. */
SIGTTOU = 18,
/* User-defined signal 1. */
SIGUSR1 = 19,
/* User-defined signal 2. */
SIGUSR2 = 20,
/* Pollable event. */
SIGPOLL = 21,
/* Profiling timer expired. */
SIGPROF = 22,
/* Bad system call. */
SIGSYS = 23,
/* Trace/breakpoint trap. */
SIGTRAP = 24,
/* High bandwidth data is available at a socket. */
SIGURG = 25,
/* Virtual timer expired. */
SIGVTALRM = 26,
/* CPU time limit exceeded. */
SIGXCPU = 27,
/* File size limit exceeded. */
SIGXFSZ = 28,
/**
* Reserved
* These are just to match Linux's signal numbers.
*/
SIGCOMP1 = 29,
SIGCOMP2 = 30,
SIGCOMP3 = 31,
/* Real-time signals. */
SIGRTMIN = 32,
SIGRT_1 = 33,
SIGRT_2 = 34,
SIGRT_3 = 35,
SIGRT_4 = 36,
SIGRT_5 = 37,
SIGRT_6 = 38,
SIGRT_7 = 39,
SIGRT_8 = 40,
SIGRT_9 = 41,
SIGRT_10 = 42,
SIGRT_11 = 43,
SIGRT_12 = 44,
SIGRT_13 = 45,
SIGRT_14 = 46,
SIGRT_15 = 47,
SIGRT_16 = 48,
SIGRT_17 = 49,
SIGRT_18 = 50,
SIGRT_19 = 51,
SIGRT_20 = 52,
SIGRT_21 = 53,
SIGRT_22 = 54,
SIGRT_23 = 55,
SIGRT_24 = 56,
SIGRT_25 = 57,
SIGRT_26 = 58,
SIGRT_27 = 59,
SIGRT_28 = 60,
SIGRT_29 = 61,
SIGRT_30 = 62,
SIGRT_31 = 63,
SIGRTMAX = 64,
/* Maximum signal number. */
SIGNAL_MAX = SIGRTMAX
};
enum SignalDispositions
{
/**
* Terminate the process.
*/
SIG_TERM,
/**
* Ignore the signal.
*/
SIG_IGN,
/**
* Dump core.
*/
SIG_CORE,
/**
* Stop the process.
*/
SIG_STOP,
/**
* Continue the process.
*/
SIG_CONT
};
enum SignalActions
{
SIG_BLOCK,
SIG_UNBLOCK,
SIG_SETMASK
};
enum SignalActionDisposition : long
{
SAD_ERR = -1,
SAD_DFL = 0,
SAD_IGN = 1,
};
#define SA_NOCLDSTOP 1
#define SA_NOCLDWAIT 2
#define SA_SIGINFO 4
#define SA_RESTORER 0x04000000
#define SA_ONSTACK 0x08000000
#define SA_RESTART 0x10000000
#define SA_NODEFER 0x40000000
#define SA_RESETHAND 0x80000000
#define __SI_PAD_SIZE \
(128 - 2 * sizeof(int) - sizeof(long))
typedef unsigned long sigset_t;
union sigval
{
int sival_int;
void *sival_ptr;
};
struct sched_param
{
int sched_priority;
};
struct pthread_attr_t
{
uint64_t sig;
size_t guard_sz;
bool detach;
sched_param sched;
};
struct sigevent
{
int sigev_notify;
int sigev_signo;
union sigval sigev_value;
void (*sigev_notify_function)(union sigval);
pthread_attr_t *sigev_notify_attributes;
};
typedef struct
{
int si_signo;
int si_errno;
int si_code;
union
{
char __pad[__SI_PAD_SIZE];
struct
{
union
{
struct
{
pid_t si_pid;
uid_t si_uid;
} __piduid;
struct
{
int si_timerid;
int si_overrun;
} __timer;
} __first;
union
{
union sigval si_value;
struct
{
int si_status;
clock_t si_utime, si_stime;
} __sigchld;
} __second;
} __si_common;
struct
{
void *si_addr;
short si_addr_lsb;
union
{
struct
{
void *si_lower;
void *si_upper;
} __addr_bnd;
unsigned si_pkey;
} __first;
} __sigfault;
struct
{
long si_band;
int si_fd;
} __sigpoll;
struct
{
void *si_call_addr;
int si_syscall;
unsigned si_arch;
} __sigsys;
} __si_fields;
} siginfo_t;
struct SignalAction
{
union
{
void (*Handler)(int);
void (*Action)(int, siginfo_t *, void *);
sigset_t Disposition;
} sa_handler;
std::bitset<64> Mask;
unsigned long Flags;
void (*Restorer)(void);
};
namespace Tasking
{
class Signal
{
private:
struct SignalInfo
{
int sig = SIG_NULL;
union sigval val
{
0
};
pid_t tid = -1;
};
struct StackInfo
{
#ifdef a64
CPU::x64::FXState fx;
CPU::x64::SchedulerFrame tf;
uintptr_t GSBase, FSBase, ShadowGSBase;
#else
CPU::x32::FXState fx;
CPU::x32::SchedulerFrame tf;
uintptr_t GSBase, FSBase;
#endif
sigset_t SignalMask;
int Compatibility;
#ifdef DEBUG
// For debugging purposes
char dbg[6] = {'S', 'I', 'G', 'N', 'A', 'L'};
#endif
} __aligned(16) __packed;
NewLock(SignalLock);
void *ctx;
Signals LastSignal = SIG_NULL;
// Signal trampoline
void *TrampAddr = nullptr;
size_t TrampSz = 0;
std::list<SignalInfo> Queue;
SignalAction sa[64 + 1]{};
// std::bitset<SIGNAL_MAX> GlobalMask;
// SignalDispositions Disposition[SIGNAL_MAX];
std::list<SignalInfo> Watchers;
std::unordered_map<Signals, SignalDispositions> Disposition = {
{SIGHUP, SIG_TERM},
{SIGINT, SIG_TERM},
{SIGQUIT, SIG_TERM},
{SIGILL, SIG_CORE},
{SIGTRAP, SIG_CORE},
{SIGABRT, SIG_CORE},
{SIGBUS, SIG_CORE},
{SIGFPE, SIG_CORE},
{SIGKILL, SIG_TERM},
{SIGUSR1, SIG_TERM},
{SIGSEGV, SIG_CORE},
{SIGUSR2, SIG_TERM},
{SIGPIPE, SIG_TERM},
{SIGALRM, SIG_TERM},
{SIGTERM, SIG_TERM},
{SIGCOMP1, SIG_IGN},
{SIGCHLD, SIG_IGN},
{SIGCONT, SIG_CONT},
{SIGSTOP, SIG_STOP},
{SIGTSTP, SIG_STOP},
{SIGTTIN, SIG_STOP},
{SIGTTOU, SIG_STOP},
{SIGURG, SIG_IGN},
{SIGXCPU, SIG_CORE},
{SIGXFSZ, SIG_CORE},
{SIGVTALRM, SIG_TERM},
{SIGPROF, SIG_TERM},
{SIGCOMP2, SIG_IGN},
{SIGPOLL, SIG_TERM},
{SIGCOMP3, SIG_IGN},
{SIGSYS, SIG_CORE},
{SIGRTMIN, SIG_IGN},
{SIGRT_1, SIG_IGN},
{SIGRT_2, SIG_IGN},
{SIGRT_3, SIG_IGN},
{SIGRT_4, SIG_IGN},
{SIGRT_5, SIG_IGN},
{SIGRT_6, SIG_IGN},
{SIGRT_7, SIG_IGN},
{SIGRT_8, SIG_IGN},
{SIGRT_9, SIG_IGN},
{SIGRT_10, SIG_IGN},
{SIGRT_11, SIG_IGN},
{SIGRT_12, SIG_IGN},
{SIGRT_13, SIG_IGN},
{SIGRT_14, SIG_IGN},
{SIGRT_15, SIG_IGN},
{SIGRT_16, SIG_IGN},
{SIGRT_17, SIG_IGN},
{SIGRT_18, SIG_IGN},
{SIGRT_19, SIG_IGN},
{SIGRT_20, SIG_IGN},
{SIGRT_21, SIG_IGN},
{SIGRT_22, SIG_IGN},
{SIGRT_23, SIG_IGN},
{SIGRT_24, SIG_IGN},
{SIGRT_25, SIG_IGN},
{SIGRT_26, SIG_IGN},
{SIGRT_27, SIG_IGN},
{SIGRT_28, SIG_IGN},
{SIGRT_29, SIG_IGN},
{SIGRT_30, SIG_IGN},
{SIGRT_31, SIG_IGN},
{SIGRTMAX, SIG_IGN}};
bool LinuxSig();
int MakeExitCode(Signals sig);
void InitTrampoline();
SignalInfo GetAvailableSignal(void *thread);
public:
void *GetContext() { return ctx; }
Signals GetLastSignal() { return LastSignal; }
int AddWatcher(Signal *who, Signals sig);
int RemoveWatcher(Signal *who, Signals sig);
int AddSignal(Signals sig, union sigval val = {0}, pid_t tid = -1);
int RemoveSignal(Signals sig);
bool HandleSignal(CPU::SchedulerFrame *tf, void *thread);
void RestoreHandleSignal(SyscallsFrame *tf, void *thread);
int SetAction(Signals sig, const SignalAction *act);
int GetAction(Signals sig, SignalAction *act);
/**
* Send a signal to the process
*
* @param sig The signal to send
* (compatibility specific)
* @param val The value to send
* @param tid The thread ID to send the signal to
*
* @return 0 on success, -errno on error
*/
int SendSignal(Signals sig, sigval val = {0}, pid_t tid = -1);
int WaitAnySignal();
bool HasPendingSignal() { return !Queue.empty(); }
/**
* Wait for a signal
*
* @param sig The signal to wait for
* @param val The value to wait for
*
* @return 0 on success, -errno on error
*/
int WaitSignal(Signals sig, union sigval *val);
/**
* Wait for a signal with a timeout
*
* @param sig The signal to wait for
* @param val The value to wait for
* @param timeout The timeout to wait for
*
* @return 0 on success, -errno on error
*/
int WaitSignalTimeout(Signals sig, union sigval *val, uint64_t timeout);
Signal(void *ctx);
~Signal();
friend class ThreadSignal;
};
class ThreadSignal
{
private:
Signal &pSig;
public:
std::bitset<64> Mask = 0;
sigset_t Block(sigset_t sig);
sigset_t Unblock(sigset_t sig);
sigset_t SetMask(sigset_t sig);
sigset_t GetMask();
ThreadSignal(Signal &sig) : pSig(sig) {}
};
}
#endif // !__FENNIX_KERNEL_SIGNAL_H__

79
Kernel/include/smp.hpp Normal file
View File

@ -0,0 +1,79 @@
/*
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_SMP_H__
#define __FENNIX_KERNEL_SMP_H__
#include <task.hpp>
#include <kexcept/cxxabi.h>
#include <types.h>
#include <atomic>
/** @brief Maximum supported number of CPU cores by the kernel */
#define MAX_CPU 255
#define CPU_DATA_CHECKSUM 0xC0FFEE
struct CPUArchData
{
#if defined(a64)
__aligned(16) CPU::x64::FXState FPU{};
#elif defined(a32)
__aligned(16) CPU::x32::FXState FPU{};
#elif defined(aa64)
#endif
};
struct CPUData
{
/** Used by CPU */
uintptr_t Stack;
/** CPU ID. */
int ID;
/** Local CPU error code. */
long ErrorCode;
/** Current running process */
std::atomic<Tasking::PCB *> CurrentProcess;
/** Current running thread */
std::atomic<Tasking::TCB *> CurrentThread;
/** Exception information. */
ExceptionInfo Exception;
/** Architecture-specific data. */
CPUArchData Data;
/** Checksum. Used to verify the integrity of the data. Must be equal to CPU_DATA_CHECKSUM (0xC0FFEE). */
int Checksum;
/** Is CPU online? */
bool IsActive;
} __aligned(16);
CPUData *GetCurrentCPU();
CPUData *GetCPU(long ID);
namespace SMP
{
extern int CPUCores;
void Initialize(void *madt);
}
#endif // !__FENNIX_KERNEL_SMP_H__

View File

@ -0,0 +1,44 @@
/*
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 <initializer_list>
#include <cassert>
#include <cstddef>
template <typename T, std::size_t N>
class static_vector
{
private:
T m_data[N];
std::size_t m_size;
public:
constexpr static_vector() : m_size(0) {}
constexpr static_vector(std::initializer_list<T> list) : m_size(0)
{
for (const T &value : list)
{
assert(m_size < N);
m_data[m_size++] = value;
}
}
constexpr T &operator[](std::size_t index) { return m_data[index]; }
constexpr const T &operator[](std::size_t index) const { return m_data[index]; }
constexpr std::size_t size() const { return m_size; }
};

9376
Kernel/include/stb/image.h Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,50 @@
/*
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/>.
*/
#pragma once
#include <types.h>
#include <vector>
namespace SymbolResolver
{
class Symbols
{
private:
struct SymbolTable
{
uintptr_t Address = 0;
char *FunctionName = (char *)"<unknown>";
};
std::vector<SymbolTable> SymTable;
void *Image = nullptr;
bool SymbolTableExists = false;
public:
decltype(SymbolTableExists) &SymTableExists = this->SymbolTableExists;
std::vector<SymbolTable> &GetSymTable() { return this->SymTable; }
void *GetImage() { return this->Image; }
const char *GetSymbol(uintptr_t Address);
uintptr_t GetSymbol(const char *Name);
void AddSymbol(uintptr_t Address, const char *Name);
void AddSymbolInfoFromGRUB(uint64_t Num, uint64_t EntSize, uint64_t Shndx, uintptr_t Sections);
void AppendSymbols(uintptr_t ImageAddress, uintptr_t BaseAddress = 0);
Symbols(uintptr_t ImageAddress);
Symbols() {}
~Symbols();
};
}

View File

@ -0,0 +1,76 @@
/*
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_SYSCALLS_H__
#define __FENNIX_KERNEL_SYSCALLS_H__
#include <types.h>
typedef struct SyscallsFrame
{
#if defined(a64)
uint64_t r15;
uint64_t r14;
uint64_t r13;
uint64_t r12;
uint64_t r11;
uint64_t r10;
uint64_t r9;
uint64_t r8;
uint64_t rbp;
uint64_t rdi;
uint64_t rsi;
uint64_t rdx;
uint64_t rcx;
uint64_t rbx;
uint64_t rax;
uint64_t ReturnAddress;
uint64_t CodeSegment;
uint64_t Flags;
uint64_t StackPointer;
uint64_t StackSegment;
#elif defined(a32)
uint32_t ebp;
uint32_t edi;
uint32_t esi;
uint32_t edx;
uint32_t ecx;
uint32_t ebx;
uint32_t eax;
uint32_t ReturnAddress;
uint32_t CodeSegment;
uint32_t Flags;
uint32_t StackPointer;
uint32_t StackSegment;
#elif defined(aa64)
uint32_t ReturnAddress;
uint32_t StackPointer;
#endif
} SyscallsFrame;
#define SysFrm SyscallsFrame
uintptr_t HandleNativeSyscalls(SyscallsFrame *Frame);
uintptr_t HandleLinuxSyscalls(SyscallsFrame *Frame);
/**
* @brief Initialize syscalls for the current CPU. (Function is available on x32, x64 & aarch64)
*/
void InitializeSystemCalls();
#endif // !__FENNIX_KERNEL_SYSCALLS_H__

32
Kernel/include/targp.h Normal file
View File

@ -0,0 +1,32 @@
/*
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 TinyArgumentParser_H__
#define TinyArgumentParser_H__
#ifdef __cplusplus
extern "C"
{
#endif
void targp_parse(const char *cmd, char **argv, int *argc);
#ifdef __cplusplus
}
#endif
#endif // !TinyArgumentParser_H__

668
Kernel/include/task.hpp Normal file
View File

@ -0,0 +1,668 @@
/*
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_TASKING_H__
#define __FENNIX_KERNEL_TASKING_H__
#include <types.h>
#include <filesystem.hpp>
#include <memory/va.hpp>
#include <symbols.hpp>
#include <memory.hpp>
#include <signal.hpp>
#include <ints.hpp>
#include <kexcept/cxxabi.h>
#include <debug.h>
#include <cwalk.h>
#include <vector>
#include <atomic>
#include <vector>
#include <abi.h>
#define RLIM_INFINITY (~0ULL)
typedef unsigned long long rlim_t;
struct rlimit
{
rlim_t rlim_cur;
rlim_t rlim_max;
};
namespace Tasking
{
using vfs::FileDescriptorTable;
/** Instruction Pointer */
typedef __UINTPTR_TYPE__ IP;
/** Process ID */
typedef pid_t PID;
/** Thread ID */
typedef pid_t TID;
enum TaskArchitecture
{
UnknownArchitecture,
x32,
x64,
ARM32,
ARM64,
_ArchitectureMin = UnknownArchitecture,
_ArchitectureMax = ARM64
};
enum TaskCompatibility
{
UnknownPlatform,
Native,
Linux,
Windows,
_CompatibilityMin = UnknownPlatform,
_CompatibilityMax = Windows
};
enum TaskExecutionMode
{
UnknownExecutionMode,
Kernel,
System,
User,
_ExecuteModeMin = UnknownExecutionMode,
_ExecuteModeMax = User
};
enum TaskState : short
{
UnknownStatus,
/**
* Ready
*
* Used when the task is ready
* to be scheduled
*/
Ready,
/**
* Running
*
* Used when the task is running
* on the CPU
*/
Running,
/**
* Sleeping
*
* Used when the task is sleeping
* for a given amount of time
*/
Sleeping,
/**
* Blocked
*
* Used when the task is blocked
* by another task or until an
* event occurs
*/
Blocked,
/**
* Stopped
*
* Used when the task is stopped
* by the user
*/
Stopped,
/**
* Waiting
*
* Used when the task is not ready
* to be scheduled by implementation
* e.g. Creating a separate page table
* or waiting for a thread to be created
*/
Waiting,
/**
* Zombie
*
* Used when the task is waiting
* for the parent to read the exit
* code
*/
Zombie,
/**
* Core Dump
*
* Used when the task is waiting
* for the parent to read the core
* dump
*/
CoreDump,
/**
* Terminated
*
* Used when the task is terminated
* and is waiting to be cleaned up
* by the scheduler
*/
Terminated,
/**
* Frozen
*
* Used internally by the kernel
*/
Frozen,
_StatusMin = UnknownStatus,
_StatusMax = Frozen
};
enum TaskPriority
{
UnknownPriority = 0,
Idle = 1,
Low = 2,
Normal = 5,
High = 8,
Critical = 10,
_PriorityMin = UnknownPriority,
_PriorityMax = Critical
};
enum KillCode : int
{
KILL_SCHEDULER_DESTRUCTION = -0xFFFF,
KILL_CXXABI_EXCEPTION = -0xECE97,
KILL_BY_OTHER_PROCESS = -0x7A55,
KILL_SYSCALL = -0xCA11,
KILL_CRASH = -0xDEAD,
KILL_OOM = -0x1008,
KILL_ERROR = -0x1,
KILL_SUCCESS = 0,
};
struct TaskInfo
{
uint64_t OldUserTime = 0;
uint64_t OldKernelTime = 0;
uint64_t SleepUntil = 0;
uint64_t KernelTime = 0, UserTime = 0, SpawnTime = 0, LastUpdateTime = 0;
uint64_t Year = 0, Month = 0, Day = 0, Hour = 0, Minute = 0, Second = 0;
bool Affinity[256] = {true}; // MAX_CPU
TaskPriority Priority = TaskPriority::Normal;
TaskArchitecture Architecture = TaskArchitecture::UnknownArchitecture;
TaskCompatibility Compatibility = TaskCompatibility::UnknownPlatform;
cwk_path_style PathStyle = CWK_STYLE_UNIX;
FileNode *RootNode = nullptr;
};
struct ThreadLocalStorage
{
/**
* Physical base address of the
* TLS segment with the data
*/
uintptr_t pBase;
/**
* Virtual base where the TLS
* segment should be mapped
*/
uintptr_t vBase;
/**
* Alignment of the TLS segment
*/
uintptr_t Align;
/**
* Size of the TLS segment
*/
uintptr_t Size;
/**
* File size of the TLS segment
*/
uintptr_t fSize;
};
/**
* TCB struct for gs register
*/
struct gsTCB
{
/** Used by syscall handler
* gs+0x0
*/
void *SyscallStack;
/** Used by syscall handler
* gs+0x8
*/
void *TempStack;
/* For future use */
/** Used by syscall handler
* gs+0x10
*/
uintptr_t Flags;
/* gs+0x18 */
uintptr_t Padding;
/* gs+0x20 */
void *SyscallStackBase;
/* gs+0x28 */
intptr_t ScPages;
/**
* The current thread class
* gs+0x30
*/
class TCB *t;
#ifdef DEBUG
/* gs+0x38 */
uintptr_t __stub;
#endif
};
class TCB
{
private:
class Task *ctx = nullptr;
/**
* This variable is used to
* store the amount of allocated
* memory for the process. This
* includes the memory allocated
* for the class itself, etc...
*
* @note Allocated memory is
* not the same as used memory.
*/
size_t AllocatedMemory = 0;
void SetupUserStack_x86_64(const char **argv,
const char **envp,
const std::vector<AuxiliaryVector> &auxv,
TaskCompatibility Compatibility);
void SetupUserStack_x86_32(const char **argv,
const char **envp,
const std::vector<AuxiliaryVector> &auxv,
TaskCompatibility Compatibility);
void SetupUserStack_aarch64(const char **argv,
const char **envp,
const std::vector<AuxiliaryVector> &auxv,
TaskCompatibility Compatibility);
/**
* This function should be called after
* GS and FS are set up
*/
void SetupThreadLocalStorage();
public:
class Task *GetContext() { return ctx; }
/* Basic info */
TID ID = -1;
const char *Name = nullptr;
class PCB *Parent = nullptr;
IP EntryPoint = 0;
/* Status */
std::atomic_int ExitCode;
std::atomic<TaskState> State = TaskState::Waiting;
int ErrorNumber;
/* Memory */
Memory::VirtualMemoryArea *vma;
Memory::StackGuard *Stack;
/* Signal */
ThreadSignal Signals;
/* CPU state */
#if defined(a64)
CPU::x64::SchedulerFrame Registers{};
uintptr_t ShadowGSBase, GSBase, FSBase;
#elif defined(a32)
CPU::x32::SchedulerFrame Registers{};
uintptr_t ShadowGSBase, GSBase, FSBase;
#elif defined(aa64)
uintptr_t Registers; // TODO
#endif
__aligned(16) CPU::x64::FXState FPU;
/* Info & Security info */
struct
{
TaskExecutionMode ExecutionMode = UnknownExecutionMode;
bool IsCritical = false;
bool IsDebugEnabled = false;
bool IsKernelDebugEnabled = false;
} Security{};
TaskInfo Info{};
ThreadLocalStorage TLS{};
/* Compatibility structures */
struct
{
int *set_child_tid{};
int *clear_child_tid{};
pid_t tgid = 0;
} Linux{};
/* Kernel Exceptions */
ExceptionInfo KernelException{};
int SendSignal(int sig);
void SetState(TaskState state);
void SetExitCode(int code);
void Rename(const char *name);
void SetPriority(TaskPriority priority);
int GetExitCode() { return ExitCode.load(); }
void SetCritical(bool Critical);
void SetDebugMode(bool Enable);
void SetKernelDebugMode(bool Enable);
size_t GetSize();
void Block() { State.store(TaskState::Blocked); }
void Unblock() { State.store(TaskState::Ready); }
void SYSV_ABI_Call(uintptr_t Arg1 = 0,
uintptr_t Arg2 = 0,
uintptr_t Arg3 = 0,
uintptr_t Arg4 = 0,
uintptr_t Arg5 = 0,
uintptr_t Arg6 = 0,
void *Function = nullptr);
TCB(class Task *ctx,
PCB *Parent,
IP EntryPoint,
const char **argv = nullptr,
const char **envp = nullptr,
const std::vector<AuxiliaryVector> &auxv = std::vector<AuxiliaryVector>(),
TaskArchitecture Architecture = TaskArchitecture::x64,
TaskCompatibility Compatibility = TaskCompatibility::Native,
bool ThreadNotReady = false);
~TCB();
};
class PCB
{
private:
class Task *ctx = nullptr;
bool OwnPageTable = false;
/**
* This variable is used to
* store the amount of allocated
* memory for the process. This
* includes the memory allocated
* for the class itself, etc...
*
* @note Allocated memory is
* not the same as used memory.
*/
size_t AllocatedMemory = 0;
public:
/* Basic info */
PID ID = -1;
const char *Name = nullptr;
PCB *Parent = nullptr;
FileNode *ProcDirectory = nullptr;
/* Statuses */
std::atomic_int ExitCode;
std::atomic<TaskState> State = Waiting;
/* Info & Security info */
struct
{
TaskExecutionMode ExecutionMode = UnknownExecutionMode;
bool IsCritical = false;
bool IsDebugEnabled = false;
bool IsKernelDebugEnabled = false;
bool CanAdjustHardLimits = false;
struct
{
uint16_t UserID = UINT16_MAX;
uint16_t GroupID = UINT16_MAX;
} Real, Effective;
pid_t ProcessGroupID = 0;
pid_t SessionID = 0;
} Security{};
struct
{
rlim_t OpenFiles = 128;
rlim_t Threads = 64;
rlim_t Memory = 1073741824; /* 1 GiB */
} SoftLimits{};
struct
{
rlim_t OpenFiles = 4096;
rlim_t Threads = 1024;
rlim_t Memory = 8589934592; /* 8 GiB */
} HardLimits{};
TaskInfo Info{};
ThreadLocalStorage TLS{};
struct
{
bool vforked = false;
TCB *CallingThread = nullptr;
} Linux{};
/* Filesystem */
FileNode *CWD;
FileNode *Executable;
FileDescriptorTable *FileDescriptors;
/* stdio */
FileNode *stdin;
FileNode *stdout;
FileNode *stderr;
/*TTY::TeletypeDriver*/ void *tty;
/* Memory */
Memory::PageTable *PageTable;
Memory::VirtualMemoryArea *vma;
Memory::ProgramBreak *ProgramBreak;
/* Other */
Signal Signals;
mode_t FileCreationMask = S_IRUSR | S_IWUSR |
S_IRGRP | S_IWGRP |
S_IROTH | S_IWOTH;
/* Threads & Children */
std::vector<TCB *> Threads;
std::vector<PCB *> Children;
public:
class Task *GetContext() { return ctx; }
int SendSignal(int sig);
void SetState(TaskState state);
void SetExitCode(int code);
void Rename(const char *name);
void SetWorkingDirectory(FileNode *node);
void SetExe(const char *path);
size_t GetSize();
TCB *GetThread(TID ID);
PCB(class Task *ctx,
PCB *Parent,
const char *Name,
TaskExecutionMode ExecutionMode,
bool UseKernelPageTable = false,
uint16_t UserID = -1, uint16_t GroupID = -1);
~PCB();
};
class Task
{
private:
NewLock(TaskingLock);
PID NextPID = 0;
PCB *KernelProcess = nullptr;
void *Scheduler = nullptr;
void *__sched_ctx = nullptr;
Memory::VirtualAllocation va = (void *)0xFFFFA00000000000;
constexpr TaskArchitecture GetKArch()
{
#if defined(a64)
return x64;
#elif defined(a32)
return x32;
#elif defined(aa64)
return ARM64;
#endif
}
void PushProcess(PCB *pcb);
void PopProcess(PCB *pcb);
public:
void *GetScheduler() { return Scheduler; }
PCB *GetKernelProcess() { return KernelProcess; }
std::vector<PCB *> GetProcessList();
void Panic();
bool IsPanic();
/**
* Yield the current thread and switch
* to another thread if available
*/
void Yield();
/**
* Update the current thread's trap frame
* without switching to another thread
*/
void UpdateFrame();
void SignalShutdown();
void KillThread(TCB *tcb, enum KillCode Code)
{
tcb->SetState(TaskState::Terminated);
tcb->SetExitCode(Code);
debug("Killing thread %s(%d) with exit code %d",
tcb->Name, tcb->ID, Code);
}
void KillProcess(PCB *pcb, enum KillCode Code)
{
pcb->SetState(TaskState::Terminated);
pcb->SetExitCode(Code);
debug("Killing process %s(%d) with exit code %d",
pcb->Name, pcb->ID, Code);
}
/**
* Get the Current Process object
* @return PCB*
*/
PCB *GetCurrentProcess();
/**
* Get the Current Thread object
* @return TCB*
*/
TCB *GetCurrentThread();
PCB *GetProcessByID(PID ID);
TCB *GetThreadByID(TID ID, PCB *Parent);
/** Wait for process to terminate */
void WaitForProcess(PCB *pcb);
/** Wait for thread to terminate */
void WaitForThread(TCB *tcb);
void WaitForProcessStatus(PCB *pcb, TaskState State);
void WaitForThreadStatus(TCB *tcb, TaskState State);
/**
* Sleep for a given amount of milliseconds
*
* @param Milliseconds Amount of milliseconds to sleep
*/
void Sleep(uint64_t Milliseconds, bool NoSwitch = false);
PCB *CreateProcess(PCB *Parent,
const char *Name,
TaskExecutionMode TrustLevel,
bool UseKernelPageTable = false,
uint16_t UserID = UINT16_MAX,
uint16_t GroupID = UINT16_MAX);
TCB *CreateThread(PCB *Parent,
IP EntryPoint,
const char **argv = nullptr,
const char **envp = nullptr,
const std::vector<AuxiliaryVector> &auxv = std::vector<AuxiliaryVector>(),
TaskArchitecture Architecture = TaskArchitecture::x64,
TaskCompatibility Compatibility = TaskCompatibility::Native,
bool ThreadNotReady = false);
void StartScheduler();
Task(const IP EntryPoint);
~Task();
friend PCB;
friend TCB;
};
}
/*
If these macros are used,
you have to add:
"#include <smp.hpp>" too
if necessary.
*/
#define thisProcess GetCurrentCPU()->CurrentProcess.load()
#define thisThread GetCurrentCPU()->CurrentThread.load()
#endif // !__FENNIX_KERNEL_TASKING_H__

171
Kernel/include/time.hpp Normal file
View File

@ -0,0 +1,171 @@
/*
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_TIME_H__
#define __FENNIX_KERNEL_TIME_H__
#include <types.h>
#include <debug.h>
#include <cassert>
namespace Time
{
struct Clock
{
int Year, Month, Day, Hour, Minute, Second;
size_t Counter;
};
Clock ReadClock();
Clock ConvertFromUnix(int Timestamp);
enum Units
{
Femtoseconds,
Picoseconds,
Nanoseconds,
Microseconds,
Milliseconds,
Seconds,
Minutes,
Hours,
Days,
Months,
Years
};
/** @deprecated this shouldn't be used */
inline uint64_t ConvertUnit(const Units Unit)
{
switch (Unit)
{
case Femtoseconds:
return 1;
case Picoseconds:
return 1000;
case Nanoseconds:
return 1000000;
case Microseconds:
return 1000000000;
case Milliseconds:
return 1000000000000;
case Seconds:
return 1000000000000000;
case Minutes:
return 1000000000000000000;
// case Hours:
// return 1000000000000000000000;
// case Days:
// return 1000000000000000000000000;
// case Months:
// return 1000000000000000000000000000;
// case Years:
// return 1000000000000000000000000000000;
default:
assert(!"Invalid time unit");
}
}
class HighPrecisionEventTimer
{
private:
struct HPET
{
uint64_t GeneralCapabilities;
uint64_t Reserved0;
uint64_t GeneralConfiguration;
uint64_t Reserved1;
uint64_t GeneralIntStatus;
uint64_t Reserved2;
uint64_t Reserved3[24];
uint64_t MainCounterValue;
uint64_t Reserved4;
};
uint32_t clk = 0;
HPET *hpet = nullptr;
uint64_t ClassCreationTime = 0;
public:
bool Sleep(size_t Duration, Units Unit);
uint64_t GetCounter();
uint64_t CalculateTarget(uint64_t Target, Units Unit);
uint64_t GetNanosecondsSinceClassCreation();
HighPrecisionEventTimer(void *hpet);
~HighPrecisionEventTimer();
};
class TimeStampCounter
{
private:
uint64_t clk = 0;
uint64_t ClassCreationTime = 0;
public:
bool Sleep(size_t Duration, Units Unit);
uint64_t GetCounter();
uint64_t CalculateTarget(uint64_t Target, Units Unit);
uint64_t GetNanosecondsSinceClassCreation();
TimeStampCounter();
~TimeStampCounter();
};
class time
{
public:
enum TimeActiveTimer
{
NONE = 0b0,
RTC = 0b1,
PIT = 0b10,
HPET = 0b100,
ACPI = 0b1000,
APIC = 0b10000,
TSC = 0b100000
};
private:
int SupportedTimers = 0;
TimeActiveTimer ActiveTimer = NONE;
HighPrecisionEventTimer *hpet;
TimeStampCounter *tsc;
public:
int GetSupportedTimers() { return SupportedTimers; }
TimeActiveTimer GetActiveTimer() { return ActiveTimer; }
bool ChangeActiveTimer(TimeActiveTimer Timer)
{
if (!(SupportedTimers & Timer))
return false;
ActiveTimer = Timer;
return true;
}
bool Sleep(size_t Duration, Units Unit);
uint64_t GetCounter();
uint64_t CalculateTarget(uint64_t Target, Units Unit);
uint64_t GetNanosecondsSinceClassCreation();
void FindTimers(void *acpi);
time();
~time();
};
}
#endif // !__FENNIX_KERNEL_TIME_H__

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