This commit is contained in:
alexvoste
2026-05-07 02:22:25 +03:00
commit 1a9fd27a31
226 changed files with 29188 additions and 0 deletions
+199
View File
@@ -0,0 +1,199 @@
#ifndef ACPI_H
#define ACPI_H
#include <stdint.h>
#include <stddef.h>
#include <stdbool.h>
#include <limine.h>
typedef struct {
char signature[4];
uint32_t length;
uint8_t revision;
uint8_t checksum;
char oem_id[6];
char oem_table_id[8];
uint32_t oem_revision;
uint32_t creator_id;
uint32_t creator_revision;
} __attribute__((packed)) acpi_sdt_header_t;
typedef struct {
char signature[8];
uint8_t checksum;
char oem_id[6];
uint8_t revision;
uint32_t rsdt_address;
} __attribute__((packed)) acpi_rsdp_t;
typedef struct {
acpi_rsdp_t rsdp_v1;
uint32_t length;
uint64_t xsdt_address;
uint8_t extended_checksum;
uint8_t reserved[3];
} __attribute__((packed)) acpi_rsdp2_t;
typedef struct {
acpi_sdt_header_t header;
uint32_t sdt_pointers[];
} __attribute__((packed)) acpi_rsdt_t;
typedef struct {
acpi_sdt_header_t header;
uint64_t sdt_pointers[];
} __attribute__((packed)) acpi_xsdt_t;
typedef struct {
uint8_t address_space_id;
uint8_t register_bit_width;
uint8_t register_bit_offset;
uint8_t access_size;
uint64_t address;
} __attribute__((packed)) acpi_gas_t;
typedef struct {
acpi_sdt_header_t header;
uint32_t firmware_ctrl;
uint32_t dsdt;
uint8_t reserved;
uint8_t preferred_power_management_profile;
uint16_t sci_interrupt;
uint32_t smi_command_port;
uint8_t acpi_enable;
uint8_t acpi_disable;
uint8_t s4bios_req;
uint8_t pstate_control;
uint32_t pm1a_event_block;
uint32_t pm1b_event_block;
uint32_t pm1a_control_block;
uint32_t pm1b_control_block;
uint32_t pm2_control_block;
uint32_t pm_timer_block;
uint32_t gpe0_block;
uint32_t gpe1_block;
uint8_t pm1_event_length;
uint8_t pm1_control_length;
uint8_t pm2_control_length;
uint8_t pm_timer_length;
uint8_t gpe0_length;
uint8_t gpe1_length;
uint8_t gpe1_base;
uint8_t cstate_control;
uint16_t worst_c2_latency;
uint16_t worst_c3_latency;
uint16_t flush_size;
uint16_t flush_stride;
uint8_t duty_offset;
uint8_t duty_width;
uint8_t day_alarm;
uint8_t month_alarm;
uint8_t century;
uint16_t boot_architecture_flags;
uint8_t reserved2;
uint32_t flags;
acpi_gas_t reset_reg;
uint8_t reset_value;
uint16_t arm_boot_architecture_flags;
uint8_t fadt_minor_version;
uint64_t x_firmware_ctrl;
uint64_t x_dsdt;
acpi_gas_t x_pm1a_event_block;
acpi_gas_t x_pm1b_event_block;
acpi_gas_t x_pm1a_control_block;
acpi_gas_t x_pm1b_control_block;
acpi_gas_t x_pm2_control_block;
acpi_gas_t x_pm_timer_block;
acpi_gas_t x_gpe0_block;
acpi_gas_t x_gpe1_block;
} __attribute__((packed)) acpi_fadt_t;
typedef struct {
acpi_sdt_header_t header;
uint32_t local_apic_address;
uint32_t flags;
uint8_t entries[];
} __attribute__((packed)) acpi_madt_t;
#define MADT_ENTRY_LAPIC 0
#define MADT_ENTRY_IOAPIC 1
#define MADT_ENTRY_ISO 2
#define MADT_ENTRY_NMI 4
#define MADT_ENTRY_LAPIC_ADDR 5
#define MADT_ENTRY_IOAPIC_MMIO 6
typedef struct {
uint8_t type;
uint8_t length;
} __attribute__((packed)) madt_entry_header_t;
typedef struct {
madt_entry_header_t header;
uint8_t processor_id;
uint8_t apic_id;
uint32_t flags;
} __attribute__((packed)) madt_lapic_entry_t;
typedef struct {
madt_entry_header_t header;
uint8_t ioapic_id;
uint8_t reserved;
uint32_t ioapic_address;
uint32_t global_system_interrupt_base;
} __attribute__((packed)) madt_ioapic_entry_t;
typedef struct {
madt_entry_header_t header;
uint8_t bus;
uint8_t source;
uint32_t global_system_interrupt;
uint16_t flags;
} __attribute__((packed)) madt_iso_entry_t;
typedef struct {
acpi_sdt_header_t header;
uint8_t hardware_rev_id;
uint8_t comparator_count : 5;
uint8_t counter_size : 1;
uint8_t reserved : 1;
uint8_t legacy_replacement : 1;
uint16_t pci_vendor_id;
uint8_t address_space_id;
uint8_t register_bit_width;
uint8_t register_bit_offset;
uint8_t reserved2;
uint64_t address;
uint8_t hpet_number;
uint16_t minimum_tick;
uint8_t page_protection;
} __attribute__((packed)) acpi_hpet_t;
typedef struct {
acpi_sdt_header_t header;
uint64_t reserved;
} __attribute__((packed)) acpi_mcfg_t;
typedef struct {
uint64_t base_address;
uint16_t pci_segment_group;
uint8_t start_pci_bus;
uint8_t end_pci_bus;
uint32_t reserved;
} __attribute__((packed)) mcfg_entry_t;
typedef struct {
acpi_sdt_header_t header;
uint8_t definition_block[];
} __attribute__((packed)) acpi_ssdt_t;
void acpi_init(void);
bool acpi_is_available(void);
void* acpi_find_table(const char* signature, uint64_t index);
void acpi_print_tables(void);
extern volatile struct limine_rsdp_request rsdp_request;
void acpi_shutdown(void);
void acpi_reboot(void);
#endif
+113
View File
@@ -0,0 +1,113 @@
#ifndef APIC_H
#define APIC_H
#include <stdint.h>
#include <stdbool.h>
#include "../acpi/acpi.h"
#define LAPIC_ID 0x0020
#define LAPIC_VERSION 0x0030
#define LAPIC_TPR 0x0080
#define LAPIC_EOI 0x00B0
#define LAPIC_SIVR 0x00F0
#define LAPIC_ISR0 0x0100
#define LAPIC_TIMER 0x0320
#define LAPIC_THERMAL 0x0330
#define LAPIC_PERFORMANCE 0x0340
#define LAPIC_LINT0 0x0350
#define LAPIC_LINT1 0x0360
#define LAPIC_ERROR 0x0370
#define LAPIC_TIMER_ICR 0x0380
#define LAPIC_TIMER_CCR 0x0390
#define LAPIC_TIMER_DCR 0x03E0
#define LAPIC_ENABLE (1 << 8)
#define LAPIC_SPURIOUS_VECTOR 0xFF
#define LAPIC_TIMER_MASKED (1 << 16)
#define LAPIC_TIMER_PERIODIC (1 << 17)
#define LAPIC_TIMER_DIV1 0x0
#define LAPIC_TIMER_DIV2 0x1
#define LAPIC_TIMER_DIV4 0x2
#define LAPIC_TIMER_DIV8 0x3
#define LAPIC_TIMER_DIV16 0x4
#define LAPIC_TIMER_DIV32 0x5
#define LAPIC_TIMER_DIV64 0x6
#define LAPIC_TIMER_DIV128 0x7
#define IOAPIC_ID 0x00
#define IOAPIC_VERSION 0x01
#define IOAPIC_ARB 0x02
#define IOAPIC_REDIR_START 0x10
#define IOAPIC_INT_MASKED (1 << 16)
#define IOAPIC_TRIGGER_LEVEL (1 << 15)
#define IOAPIC_POLARITY_LOW (1 << 13)
#define IOAPIC_DELIVERY_FIXED 0x0
#define IOAPIC_DELIVERY_NMI 0x4
#define HPET_CAPABILITIES 0x000
#define HPET_PERIOD 0x004
#define HPET_CONFIG 0x010
#define HPET_INTERRUPT_STATUS 0x020
#define HPET_MAIN_COUNTER 0x0F0
#define HPET_TIMER0_CONFIG 0x100
#define HPET_TIMER0_COMPARATOR 0x108
#define HPET_ENABLE_CNF (1ULL << 0)
#define HPET_LEGACY_CNF (1ULL << 1)
#define HPET_TN_INT_ENABLE_CNF (1 << 2)
#define HPET_TN_INT_TYPE_CNF (1 << 3)
#define HPET_TN_PERIODIC_CNF (1 << 4)
#define HPET_TN_32BIT_CNF (1 << 8)
#define HPET_TN_FSB_ENABLE_CNF (1 << 14)
#define HPET_TN_FSB_INT_DEL_CNF (1 << 15)
void apic_init(void);
bool apic_is_available(void);
bool hpet_is_available(void);
bool hpet_init(void);
void lapic_write(uint32_t reg, uint32_t value);
uint32_t lapic_read(uint32_t reg);
void lapic_eoi(void);
void lapic_enable(void);
uint32_t lapic_get_id(void);
void lapic_timer_init(uint32_t vector, uint32_t count, bool periodic, uint8_t divisor);
void lapic_timer_stop(void);
uint32_t lapic_timer_get_current(void);
void lapic_send_ipi(uint32_t target_lapic_id, uint8_t vector);
void lapic_send_ipi_to_all_but_self(uint8_t vector);
void lapic_send_nmi_to_all_but_self(void);
void ioapic_write(uintptr_t base, uint32_t reg, uint32_t value);
uint32_t ioapic_read(uintptr_t base, uint32_t reg);
uint32_t ioapic_get_max_redirects(uintptr_t base);
void ioapic_redirect_irq(uint8_t irq, uint8_t vector, uint32_t flags);
void ioapic_mask_irq(uint8_t irq);
void ioapic_unmask_irq(uint8_t irq);
void apic_setup_irq(uint8_t irq, uint8_t vector, bool mask, uint32_t flags);
void apic_timer_calibrate(void);
uint64_t hpet_read_counter(void);
uint64_t hpet_get_frequency(void);
uint64_t hpet_elapsed_ns(void);
void hpet_sleep_ns(uint64_t nanoseconds);
void hpet_sleep_us(uint64_t microseconds);
void hpet_sleep_ms(uint64_t milliseconds);
extern uintptr_t lapic_base;
extern uintptr_t ioapic_base;
extern uintptr_t hpet_base;
extern uint32_t hpet_period;
extern uint64_t g_hpet_boot_counter;
void ipi_reschedule_all(void);
void ipi_reschedule_cpu(uint32_t lapic_id);
void ipi_reschedule_single(uint32_t target_lapic_id);
void ipi_tlb_shootdown_broadcast(const uintptr_t* addrs, size_t count);
void ipi_tlb_shootdown_single(uint32_t target_lapic_id, uintptr_t addr);
#endif
+77
View File
@@ -0,0 +1,77 @@
#ifndef ATA_H
#define ATA_H
#include <stdint.h>
#include <stddef.h>
#include <stdbool.h>
#define ATA_PRIMARY_IO 0x1F0
#define ATA_PRIMARY_CTRL 0x3F6
#define ATA_SECONDARY_IO 0x170
#define ATA_SECONDARY_CTRL 0x376
#define ATA_REG_DATA 0x00
#define ATA_REG_ERROR 0x01
#define ATA_REG_FEATURES 0x01
#define ATA_REG_SECCOUNT 0x02
#define ATA_REG_LBA_LO 0x03
#define ATA_REG_LBA_MID 0x04
#define ATA_REG_LBA_HI 0x05
#define ATA_REG_DRIVE 0x06
#define ATA_REG_STATUS 0x07
#define ATA_REG_COMMAND 0x07
#define ATA_REG_ALT_STATUS 0x00
#define ATA_REG_DEV_CTRL 0x00
#define ATA_SR_BSY 0x80
#define ATA_SR_DRDY 0x40
#define ATA_SR_DF 0x20
#define ATA_SR_DSC 0x10
#define ATA_SR_DRQ 0x08
#define ATA_SR_CORR 0x04
#define ATA_SR_IDX 0x02
#define ATA_SR_ERR 0x01
#define ATA_CMD_READ_PIO 0x20
#define ATA_CMD_READ_PIO_EXT 0x24
#define ATA_CMD_WRITE_PIO 0x30
#define ATA_CMD_WRITE_PIO_EXT 0x34
#define ATA_CMD_CACHE_FLUSH 0xE7
#define ATA_CMD_CACHE_FLUSH_EXT 0xEA
#define ATA_CMD_IDENTIFY 0xEC
#define ATA_CMD_IDENTIFY_PACKET 0xA1
#define ATA_DRIVE_MASTER 0xA0
#define ATA_DRIVE_SLAVE 0xB0
#define ATA_LBA_BIT 0x40
#define ATA_MAX_DRIVES 4
#define ATA_SECTOR_SIZE 512
typedef struct {
bool present;
bool is_atapi;
bool lba48;
uint16_t io_base;
uint16_t ctrl_base;
uint8_t drive_select;
uint8_t irq;
uint64_t sectors;
uint64_t size_bytes;
char model[41];
char serial[21];
char firmware[9];
uint16_t identify[256];
} ata_drive_t;
void ata_init(void);
ata_drive_t *ata_get_drive(int index);
int ata_get_drive_count(void);
int ata_read_sectors(ata_drive_t *drive, uint64_t lba, uint32_t count, void *buffer);
int ata_write_sectors(ata_drive_t *drive, uint64_t lba, uint32_t count, const void *buffer);
int ata_flush(ata_drive_t *drive);
#endif
+38
View File
@@ -0,0 +1,38 @@
#ifndef BLKDEV_H
#define BLKDEV_H
#include <stdint.h>
#include <stddef.h>
#include <stdbool.h>
#define BLKDEV_MAX 8
#define BLKDEV_NAME_MAX 32
#define BLKDEV_SECTOR_SIZE 512
typedef struct blkdev blkdev_t;
typedef struct blkdev_ops {
int (*read_sectors) (blkdev_t *dev, uint64_t lba, uint32_t count, void *buf);
int (*write_sectors)(blkdev_t *dev, uint64_t lba, uint32_t count, const void *buf);
int (*flush) (blkdev_t *dev);
} blkdev_ops_t;
struct blkdev {
char name[BLKDEV_NAME_MAX];
bool present;
uint64_t sector_count;
uint64_t size_bytes;
uint32_t sector_size;
const blkdev_ops_t *ops;
void *priv;
};
int blkdev_register(blkdev_t *dev);
blkdev_t *blkdev_get_by_name(const char *name);
blkdev_t *blkdev_get(int index);
int blkdev_count(void);
void blkdev_init(void);
int blkdev_read(blkdev_t *dev, uint64_t offset, void *buf, size_t len);
int blkdev_write(blkdev_t *dev, uint64_t offset, const void *buf, size_t len);
#endif
+11
View File
@@ -0,0 +1,11 @@
#ifndef DISK_H
#define DISK_H
#include "../drivers/blkdev.h"
void disk_init(void);
int disk_mount(const char *devname, const char *path);
int disk_umount(const char *path);
int disk_format(const char *devname, const char *label);
#endif
+52
View File
@@ -0,0 +1,52 @@
#ifndef PARTITION_H
#define PARTITION_H
#include <stdint.h>
#include <stdbool.h>
#include "blkdev.h"
#define MBR_SIGNATURE 0xAA55
#define MBR_SIGNATURE_OFF 510
#define MBR_PARTITION_OFF 446
#define MBR_MAX_PARTITIONS 4
#define MBR_TYPE_EMPTY 0x00
#define MBR_TYPE_FAT12 0x01
#define MBR_TYPE_FAT16_S 0x04
#define MBR_TYPE_EXTENDED 0x05
#define MBR_TYPE_FAT16 0x06
#define MBR_TYPE_FAT32_CHS 0x0B
#define MBR_TYPE_FAT32_LBA 0x0C
#define MBR_TYPE_FAT16_LBA 0x0E
#define MBR_TYPE_LINUX 0x83
#define MBR_TYPE_ESP 0xEF
typedef struct __attribute__((packed)) {
uint8_t boot_flag;
uint8_t chs_start[3];
uint8_t type;
uint8_t chs_end[3];
uint32_t lba_start;
uint32_t sector_count;
} mbr_partition_t;
typedef struct __attribute__((packed)) {
uint8_t bootstrap[440];
uint32_t disk_signature;
uint16_t reserved;
mbr_partition_t partitions[4];
uint16_t signature;
} mbr_t;
_Static_assert(sizeof(mbr_t) == 512, "mbr size must be 512");
int partition_scan(blkdev_t *disk);
int partition_write_mbr(blkdev_t *disk, const mbr_partition_t parts[4],
uint32_t disk_signature);
int partition_read_mbr(blkdev_t *disk, mbr_t *out);
blkdev_t *partition_get(const char *name);
#endif
+91
View File
@@ -0,0 +1,91 @@
#ifndef PS2_H
#define PS2_H
#include <stdint.h>
#include <stdbool.h>
#include <stddef.h>
#define PS2_DATA_PORT 0x60
#define PS2_STATUS_PORT 0x64
#define PS2_CMD_PORT 0x64
#define PS2_STATUS_OUTPUT_FULL (1 << 0)
#define PS2_STATUS_INPUT_FULL (1 << 1)
#define PS2_CMD_READ_CONFIG 0x20
#define PS2_CMD_WRITE_CONFIG 0x60
#define PS2_CMD_DISABLE_PORT2 0xA7
#define PS2_CMD_ENABLE_PORT2 0xA8
#define PS2_CMD_TEST_PORT2 0xA9
#define PS2_CMD_SELF_TEST 0xAA
#define PS2_CMD_TEST_PORT1 0xAB
#define PS2_CMD_DISABLE_PORT1 0xAD
#define PS2_CMD_ENABLE_PORT1 0xAE
#define PS2_CMD_WRITE_PORT2 0xD4
#define PS2_CFG_PORT1_IRQ (1 << 0)
#define PS2_CFG_PORT2_IRQ (1 << 1)
#define PS2_CFG_PORT1_XLAT (1 << 6)
#define PS2_KEY_RELEASE_BIT 0x80
#define SC_LSHIFT 0x2A
#define SC_RSHIFT 0x36
#define SC_CAPS 0x3A
#define SC_LCTRL 0x1D
#define SC_LALT 0x38
#define SC_ESCAPE 0x01
#define SC_F1 0x3B
#define SC_F2 0x3C
#define SC_F3 0x3D
#define SC_F4 0x3E
#define SC_F5 0x3F
#define SC_F6 0x40
#define SC_F7 0x41
#define SC_F8 0x42
#define SC_F9 0x43
#define SC_F10 0x44
#define SC_F11 0x57
#define SC_F12 0x58
#define MOUSE_BTN_LEFT (1 << 0)
#define MOUSE_BTN_RIGHT (1 << 1)
#define MOUSE_BTN_MIDDLE (1 << 2)
#define MOUSE_X_SIGN (1 << 4)
#define MOUSE_Y_SIGN (1 << 5)
#define MOUSE_X_OVERFLOW (1 << 6)
#define MOUSE_Y_OVERFLOW (1 << 7)
typedef enum {
MOUSE_SCROLL_NONE = 0,
MOUSE_SCROLL_UP,
MOUSE_SCROLL_DOWN,
} mouse_scroll_t;
typedef struct {
int32_t x, y;
bool btn_left, btn_right, btn_middle;
mouse_scroll_t scroll;
} mouse_state_t;
typedef struct {
bool shift, caps_lock, ctrl, alt;
} kb_state_t;
#define KB_BUF_SIZE 64
typedef struct {
char buf[KB_BUF_SIZE];
uint8_t head, tail;
} kb_buf_t;
bool ps2_init(void);
const kb_state_t* ps2_kb_get_state(void);
const mouse_state_t* ps2_mouse_get_state(void);
bool kb_buf_empty(void);
char kb_buf_getc(void);
bool kb_buf_try_getc(char *out);
bool kb_buf_has_ctrlc(void);
void kb_buf_consume_ctrlc(void);
#endif
+17
View File
@@ -0,0 +1,17 @@
#ifndef TIMER_H
#define TIMER_H
#include <stdint.h>
#include <stdbool.h>
bool timer_init(void);
uint64_t timer_get_ticks(void);
void timer_sleep_ms(uint64_t milliseconds);
void timer_sleep_us(uint64_t microseconds);
void timer_sleep_ns(uint64_t nanoseconds);
extern volatile uint32_t g_ctrlc_pending;
#endif
+118
View File
@@ -0,0 +1,118 @@
#ifndef ELF_H
#define ELF_H
#include <stdint.h>
#include <stddef.h>
#include <stdbool.h>
#include "../memory/vmm.h"
#include "../memory/paging.h"
#define ELF_MAGIC 0x464C457F
#define EI_CLASS 4
#define EI_DATA 5
#define EI_VERSION 6
#define EI_OSABI 7
#define EI_NIDENT 16
#define ELFCLASS64 2
#define ELFDATA2LSB 1
#define EV_CURRENT 1
#define ET_EXEC 2
#define ET_DYN 3
#define EM_X86_64 62
#define PT_NULL 0
#define PT_LOAD 1
#define PT_DYNAMIC 2
#define PT_INTERP 3
#define PT_NOTE 4
#define PT_PHDR 6
#define PT_TLS 7
#define PF_X (1 << 0)
#define PF_W (1 << 1)
#define PF_R (1 << 2)
#define SHT_NULL 0
#define SHT_PROGBITS 1
#define SHT_SYMTAB 2
#define SHT_STRTAB 3
#define SHT_RELA 4
#define SHT_NOBITS 8
typedef struct {
uint8_t e_ident[EI_NIDENT];
uint16_t e_type;
uint16_t e_machine;
uint32_t e_version;
uint64_t e_entry;
uint64_t e_phoff;
uint64_t e_shoff;
uint32_t e_flags;
uint16_t e_ehsize;
uint16_t e_phentsize;
uint16_t e_phnum;
uint16_t e_shentsize;
uint16_t e_shnum;
uint16_t e_shstrndx;
} __attribute__((packed)) elf64_ehdr_t;
typedef struct {
uint32_t p_type;
uint32_t p_flags;
uint64_t p_offset;
uint64_t p_vaddr;
uint64_t p_paddr;
uint64_t p_filesz;
uint64_t p_memsz;
uint64_t p_align;
} __attribute__((packed)) elf64_phdr_t;
typedef struct {
uint32_t sh_name;
uint32_t sh_type;
uint64_t sh_flags;
uint64_t sh_addr;
uint64_t sh_offset;
uint64_t sh_size;
uint32_t sh_link;
uint32_t sh_info;
uint64_t sh_addralign;
uint64_t sh_entsize;
} __attribute__((packed)) elf64_shdr_t;
typedef enum {
ELF_OK = 0,
ELF_ERR_NULL,
ELF_ERR_TOO_SMALL,
ELF_ERR_BAD_MAGIC,
ELF_ERR_NOT_64,
ELF_ERR_NOT_LE,
ELF_ERR_BAD_VERSION,
ELF_ERR_NOT_EXEC,
ELF_ERR_WRONG_ARCH,
ELF_ERR_NO_LOAD,
ELF_ERR_MAP_FAIL,
ELF_ERR_NO_MEM,
} elf_error_t;
typedef struct {
uintptr_t entry;
vmm_pagemap_t* pagemap;
uintptr_t load_base;
uintptr_t stack_top;
size_t stack_size;
elf_error_t error;
uintptr_t load_end;
} elf_load_result_t;
elf_load_result_t elf_load(const void* data, size_t size, size_t stack_sz);
void elf_unload(elf_load_result_t* result);
const char* elf_strerror(elf_error_t err);
#endif
+9
View File
@@ -0,0 +1,9 @@
#ifndef DEVFS_H
#define DEVFS_H
#include "vfs.h"
vnode_t *devfs_create_root(void);
void devfs_register(const char *name, vnode_t *node);
#endif
+161
View File
@@ -0,0 +1,161 @@
#ifndef EXT2_H
#define EXT2_H
#include <stdint.h>
#include <stddef.h>
#include <stdbool.h>
#include "../drivers/blkdev.h"
#include "vfs.h"
#define EXT2_SUPER_MAGIC 0xEF53
#define EXT2_SUPER_OFFSET 1024
#define EXT2_ROOT_INO 2
#define EXT2_GOOD_OLD_REV 0
#define EXT2_DYNAMIC_REV 1
#define EXT2_VALID_FS 1
#define EXT2_ERROR_FS 2
#define EXT2_S_IFSOCK 0xC000
#define EXT2_S_IFLNK 0xA000
#define EXT2_S_IFREG 0x8000
#define EXT2_S_IFBLK 0x6000
#define EXT2_S_IFDIR 0x4000
#define EXT2_S_IFCHR 0x2000
#define EXT2_S_IFIFO 0x1000
#define EXT2_FT_UNKNOWN 0
#define EXT2_FT_REG_FILE 1
#define EXT2_FT_DIR 2
#define EXT2_FT_CHRDEV 3
#define EXT2_FT_BLKDEV 4
#define EXT2_FT_FIFO 5
#define EXT2_FT_SOCK 6
#define EXT2_FT_SYMLINK 7
#define EXT2_NDIR_BLOCKS 12
#define EXT2_IND_BLOCK 12
#define EXT2_DIND_BLOCK 13
#define EXT2_TIND_BLOCK 14
#define EXT2_N_BLOCKS 15
#define EXT2_NAME_LEN 255
typedef struct __attribute__((packed)) {
uint32_t s_inodes_count;
uint32_t s_blocks_count;
uint32_t s_r_blocks_count;
uint32_t s_free_blocks_count;
uint32_t s_free_inodes_count;
uint32_t s_first_data_block;
uint32_t s_log_block_size;
uint32_t s_log_frag_size;
uint32_t s_blocks_per_group;
uint32_t s_frags_per_group;
uint32_t s_inodes_per_group;
uint32_t s_mtime;
uint32_t s_wtime;
uint16_t s_mnt_count;
uint16_t s_max_mnt_count;
uint16_t s_magic;
uint16_t s_state;
uint16_t s_errors;
uint16_t s_minor_rev_level;
uint32_t s_lastcheck;
uint32_t s_checkinterval;
uint32_t s_creator_os;
uint32_t s_rev_level;
uint16_t s_def_resuid;
uint16_t s_def_resgid;
uint32_t s_first_ino;
uint16_t s_inode_size;
uint16_t s_block_group_nr;
uint32_t s_feature_compat;
uint32_t s_feature_incompat;
uint32_t s_feature_ro_compat;
uint8_t s_uuid[16];
char s_volume_name[16];
char s_last_mounted[64];
uint32_t s_algo_bitmap;
uint8_t s_prealloc_blocks;
uint8_t s_prealloc_dir_blocks;
uint16_t s_padding1;
uint8_t s_journal_uuid[16];
uint32_t s_journal_inum;
uint32_t s_journal_dev;
uint32_t s_last_orphan;
uint32_t s_hash_seed[4];
uint8_t s_def_hash_version;
uint8_t s_reserved_pad[3];
uint32_t s_default_mount_options;
uint32_t s_first_meta_bg;
uint8_t s_reserved[760];
} ext2_superblock_t;
_Static_assert(sizeof(ext2_superblock_t) == 1024, "ext2 superblock size");
typedef struct __attribute__((packed)) {
uint32_t bg_block_bitmap;
uint32_t bg_inode_bitmap;
uint32_t bg_inode_table;
uint16_t bg_free_blocks_count;
uint16_t bg_free_inodes_count;
uint16_t bg_used_dirs_count;
uint16_t bg_pad;
uint8_t bg_reserved[12];
} ext2_group_desc_t;
_Static_assert(sizeof(ext2_group_desc_t) == 32, "ext2 group desc size");
typedef struct __attribute__((packed)) {
uint16_t i_mode;
uint16_t i_uid;
uint32_t i_size;
uint32_t i_atime;
uint32_t i_ctime;
uint32_t i_mtime;
uint32_t i_dtime;
uint16_t i_gid;
uint16_t i_links_count;
uint32_t i_blocks;
uint32_t i_flags;
uint32_t i_osd1;
uint32_t i_block[EXT2_N_BLOCKS];
uint32_t i_generation;
uint32_t i_file_acl;
uint32_t i_dir_acl;
uint32_t i_faddr;
uint8_t i_osd2[12];
} ext2_inode_t;
_Static_assert(sizeof(ext2_inode_t) == 128, "ext2 inode size");
typedef struct __attribute__((packed)) {
uint32_t inode;
uint16_t rec_len;
uint8_t name_len;
uint8_t file_type;
char name[EXT2_NAME_LEN];
} ext2_dir_entry_t;
typedef struct {
blkdev_t *dev;
ext2_superblock_t sb;
ext2_group_desc_t *gdt;
uint32_t block_size;
uint32_t groups_count;
uint32_t inodes_per_block;
uint32_t inode_size;
uint32_t ptrs_per_block;
bool dirty;
} ext2_t;
typedef struct {
ext2_t *fs;
uint32_t ino;
} ext2_vdata_t;
int ext2_format(blkdev_t *dev, const char *label);
vnode_t *ext2_mount(blkdev_t *dev);
void ext2_unmount(ext2_t *fs);
void ext2_sync(ext2_t *fs);
#endif
+146
View File
@@ -0,0 +1,146 @@
#ifndef FAT32_H
#define FAT32_H
#include <stdint.h>
#include <stddef.h>
#include <stdbool.h>
#include "../drivers/blkdev.h"
#include "vfs.h"
#define FAT32_SECTOR_SIZE 512
#define FAT32_EOC 0x0FFFFFFF
#define FAT32_EOC_MIN 0x0FFFFFF8
#define FAT32_FREE_CLUSTER 0x00000000
#define FAT32_BAD_CLUSTER 0x0FFFFFF7
#define FAT32_CLUSTER_MASK 0x0FFFFFFF
#define FAT32_FSINFO_LEAD_SIG 0x41615252
#define FAT32_FSINFO_STRUCT_SIG 0x61417272
#define FAT32_FSINFO_TRAIL_SIG 0xAA550000
#define FAT_ATTR_READ_ONLY 0x01
#define FAT_ATTR_HIDDEN 0x02
#define FAT_ATTR_SYSTEM 0x04
#define FAT_ATTR_VOLUME_ID 0x08
#define FAT_ATTR_DIRECTORY 0x10
#define FAT_ATTR_ARCHIVE 0x20
#define FAT_ATTR_LONG_NAME 0x0F
typedef struct __attribute__((packed)) {
uint8_t bs_jmp[3];
uint8_t bs_oem[8];
uint16_t bpb_bytes_per_sector;
uint8_t bpb_sectors_per_cluster;
uint16_t bpb_reserved_sectors;
uint8_t bpb_num_fats;
uint16_t bpb_root_entries;
uint16_t bpb_total_sectors_16;
uint8_t bpb_media;
uint16_t bpb_fat_size_16;
uint16_t bpb_sectors_per_track;
uint16_t bpb_num_heads;
uint32_t bpb_hidden_sectors;
uint32_t bpb_total_sectors_32;
uint32_t bpb_fat_size_32;
uint16_t bpb_ext_flags;
uint16_t bpb_fs_version;
uint32_t bpb_root_cluster;
uint16_t bpb_fs_info;
uint16_t bpb_backup_boot;
uint8_t bpb_reserved[12];
uint8_t bs_drive_num;
uint8_t bs_reserved1;
uint8_t bs_boot_sig;
uint32_t bs_vol_id;
uint8_t bs_vol_label[11];
uint8_t bs_fs_type[8];
uint8_t bs_boot_code[420];
uint16_t bs_signature;
} fat32_bpb_t;
_Static_assert(sizeof(fat32_bpb_t) == 512, "fat32 bpb size");
typedef struct __attribute__((packed)) {
uint32_t lead_sig;
uint8_t reserved1[480];
uint32_t struct_sig;
uint32_t free_count;
uint32_t next_free;
uint8_t reserved2[12];
uint32_t trail_sig;
} fat32_fsinfo_t;
_Static_assert(sizeof(fat32_fsinfo_t) == 512, "fat32 fsinfo size");
typedef struct __attribute__((packed)) {
uint8_t name[11];
uint8_t attr;
uint8_t nt_reserved;
uint8_t create_time_tenth;
uint16_t create_time;
uint16_t create_date;
uint16_t access_date;
uint16_t cluster_hi;
uint16_t modify_time;
uint16_t modify_date;
uint16_t cluster_lo;
uint32_t file_size;
} fat32_dirent_t;
_Static_assert(sizeof(fat32_dirent_t) == 32, "fat32 dirent size");
typedef struct __attribute__((packed)) {
uint8_t order;
uint8_t name1[10];
uint8_t attr;
uint8_t type;
uint8_t checksum;
uint8_t name2[12];
uint16_t cluster_lo;
uint8_t name3[4];
} fat32_lfn_t;
_Static_assert(sizeof(fat32_lfn_t) == 32, "fat32 lfn size");
typedef struct {
blkdev_t *dev;
uint32_t bytes_per_sector;
uint32_t sectors_per_cluster;
uint32_t bytes_per_cluster;
uint32_t reserved_sectors;
uint32_t num_fats;
uint32_t fat_size_sectors;
uint32_t total_sectors;
uint32_t root_cluster;
uint32_t first_fat_sector;
uint32_t first_data_sector;
uint32_t total_clusters;
uint32_t fsinfo_sector;
uint32_t next_free_hint;
uint32_t free_count;
bool dirty;
bool readonly;
uint8_t *shared_buf;
} fat32_t;
typedef struct {
fat32_t *fs;
uint32_t first_cluster;
uint32_t dir_cluster;
uint32_t dir_entry_offset;
uint32_t file_size;
uint8_t attr;
uint32_t cached_cluster;
uint32_t cached_index;
bool size_dirty;
uint8_t *io_buf;
} fat32_vdata_t;
int fat32_format(blkdev_t *dev, const char *label);
vnode_t *fat32_mount(blkdev_t *dev);
void fat32_unmount(fat32_t *fs);
int fat32_sync(fat32_t *fs);
#endif
+9
View File
@@ -0,0 +1,9 @@
#ifndef INITRAMFS_H
#define INITRAMFS_H
#include <stddef.h>
#include <stdint.h>
int initramfs_mount(const void *data, size_t size);
#endif
+11
View File
@@ -0,0 +1,11 @@
#ifndef RAMFS_H
#define RAMFS_H
#include "vfs.h"
#define RAMFS_MAX_CHILDREN 64
#define RAMFS_MAX_FILE_SIZE (4 * 1024 * 1024)
vnode_t *ramfs_create_root(void);
#endif
+181
View File
@@ -0,0 +1,181 @@
#ifndef VFS_H
#define VFS_H
#include <stdint.h>
#include <stddef.h>
#include <stdbool.h>
#include "../syscall/errno.h"
#define VFS_MAX_PATH 512
#define VFS_MAX_NAME 256
#define VFS_MAX_MOUNTS 16
#define VFS_MAX_OPEN_FILES 512
#define O_RDONLY 0x000
#define O_WRONLY 0x001
#define O_RDWR 0x002
#define O_ACCMODE 0x003
#define O_CREAT 0x040
#define O_TRUNC 0x200
#define O_APPEND 0x400
#define O_DIRECTORY 0x10000
#define O_NONBLOCK 0x800
#define SEEK_SET 0
#define SEEK_CUR 1
#define SEEK_END 2
#define FD_CLOEXEC (1 << 0)
#define TASK_MAX_FDS 256
typedef enum {
VFS_NODE_FILE = 0,
VFS_NODE_DIR = 1,
VFS_NODE_CHARDEV = 2,
VFS_NODE_BLKDEV = 3,
VFS_NODE_SYMLINK = 4,
VFS_NODE_PIPE = 5,
} vnode_type_t;
typedef struct {
uint64_t st_ino;
vnode_type_t st_type;
uint32_t st_mode;
uint32_t st_uid;
uint32_t st_gid;
uint64_t st_size;
uint64_t st_blocks;
} vfs_stat_t;
typedef struct {
uint64_t d_ino;
uint8_t d_type;
char d_name[VFS_MAX_NAME];
} vfs_dirent_t;
typedef struct vnode vnode_t;
typedef struct vfs_mount vfs_mount_t;
typedef struct vnode_ops {
int64_t (*read) (vnode_t *node, void *buf, size_t len, uint64_t offset);
int64_t (*write) (vnode_t *node, const void *buf, size_t len, uint64_t offset);
int (*truncate)(vnode_t *node, uint64_t new_size);
int (*lookup) (vnode_t *dir, const char *name, vnode_t **out);
int (*readdir) (vnode_t *dir, uint64_t index, vfs_dirent_t *out);
int (*mkdir) (vnode_t *dir, const char *name, uint32_t mode);
int (*create) (vnode_t *dir, const char *name, uint32_t mode, vnode_t **out);
int (*unlink) (vnode_t *dir, const char *name);
int (*rename) (vnode_t *src_dir, const char *src_name,
vnode_t *dst_dir, const char *dst_name);
int (*stat) (vnode_t *node, vfs_stat_t *out);
void (*ref) (vnode_t *node);
void (*unref) (vnode_t *node);
int64_t (*ioctl) (vnode_t *node, uint64_t req, void *arg);
} vnode_ops_t;
struct vnode {
vnode_type_t type;
uint32_t mode;
uint32_t uid;
uint32_t gid;
uint64_t size;
uint64_t ino;
const vnode_ops_t *ops;
void *fs_data;
volatile int refcount;
vfs_mount_t *mounted;
};
struct vfs_mount {
char path[VFS_MAX_PATH];
char device[32];
char fstype[16];
vnode_t *root;
bool used;
void *fs_priv;
void (*unmount)(void *fs_priv);
void (*sync)(void *fs_priv);
};
typedef struct {
vnode_t *vnode;
uint64_t offset;
int flags;
volatile int refcount;
} vfs_file_t;
typedef struct {
vfs_file_t *file;
int fd_flags;
} fd_entry_t;
typedef struct fd_table fd_table_t;
struct fd_table {
fd_entry_t entries[TASK_MAX_FDS];
};
void vfs_init (void);
int vfs_mount (const char *path, vnode_t *fs_root);
int vfs_mount_fs(const char *path, vnode_t *fs_root,
void *fs_priv, void (*unmount_fn)(void *),
void (*sync_fn)(void *));
int vfs_umount (const char *path);
int vfs_lookup (const char *path, vnode_t **out);
int vfs_open (const char *path, int flags, uint32_t mode, vfs_file_t **out);
void vfs_close (vfs_file_t *file);
int64_t vfs_read (vfs_file_t *file, void *buf, size_t len);
int64_t vfs_write (vfs_file_t *file, const void *buf, size_t len);
int64_t vfs_seek (vfs_file_t *file, int64_t offset, int whence);
int vfs_stat (const char *path, vfs_stat_t *out);
int vfs_fstat (vfs_file_t *file, vfs_stat_t *out);
int64_t vfs_ioctl (vfs_file_t *file, uint64_t req, void *arg);
int vfs_readdir(vfs_file_t *file, vfs_dirent_t *out);
int vfs_mkdir (const char *path, uint32_t mode);
void vnode_ref (vnode_t *node);
void vnode_unref (vnode_t *node);
vfs_file_t *vfs_file_alloc(void);
void vfs_file_free (vfs_file_t *file);
fd_table_t *fd_table_create (void);
fd_table_t *fd_table_clone (const fd_table_t *src);
void fd_table_cloexec(fd_table_t *table);
void fd_table_destroy(fd_table_t *table);
int fd_alloc (fd_table_t *table, vfs_file_t *file, int min_fd);
vfs_file_t *fd_get (const fd_table_t *table, int fd);
int fd_close (fd_table_t *table, int fd);
int fd_dup2 (fd_table_t *table, int oldfd, int newfd);
int fd_set_flags(fd_table_t *table, int fd, int flags);
int fd_get_flags(const fd_table_t *table, int fd);
void vfs_sync_all(void);
int vfs_init_stdio(void *task_ptr);
typedef struct {
char path[VFS_MAX_PATH];
char device[32];
char fstype[16];
uint32_t flags;
} vfs_mount_info_t;
int vfs_set_mount_info(const char *path, const char *device, const char *fstype);
int vfs_list_mounts(vfs_mount_info_t *out, int max);
typedef struct {
uint64_t f_bsize;
uint64_t f_blocks;
uint64_t f_bfree;
uint64_t f_bavail;
uint64_t f_files;
uint64_t f_ffree;
uint32_t f_flag;
uint32_t f_namemax;
} vfs_statvfs_t;
int vfs_statvfs(const char *path, vfs_statvfs_t *out);
#endif
+78
View File
@@ -0,0 +1,78 @@
#ifndef GDT_H
#define GDT_H
#include <stdint.h>
#define GDT_CODE_SEGMENT 0x08
#define GDT_DATA_SEGMENT 0x10
#define GDT_USER_DATA_SEGMENT 0x18
#define GDT_USER_CODE_SEGMENT 0x20
#define GDT_USER_DATA_RPL3 (GDT_USER_DATA_SEGMENT | 3)
#define GDT_USER_CODE_RPL3 (GDT_USER_CODE_SEGMENT | 3)
#define GDT_STAR_SYSRET_BASE GDT_DATA_SEGMENT
#define GDT_STAR_SYSCALL_CS GDT_CODE_SEGMENT
#define TSS_SELECTOR_BASE 0x28
#define KERNEL_STACK_SIZE (4096 * 8)
#define KERNEL_STACK_PAGES (KERNEL_STACK_SIZE / 0x1000)
#define GDT_LIMIT_LOW(limit) (limit & 0xFFFF)
#define GDT_BASE_LOW(base) (base & 0xFFFF)
#define GDT_BASE_MIDDLE(base) ((base >> 16) & 0xFF)
#define GDT_FLAGS_HI_LIMIT(limit, flags) \
(((limit >> 16) & 0xF) | ((flags << 4) & 0xF0))
#define GDT_BASE_HIGH(base) ((base >> 24) & 0xFF)
#define GDT_ENTRY(base, limit, access, flags) \
{GDT_LIMIT_LOW(limit), \
GDT_BASE_LOW(base), \
GDT_BASE_MIDDLE(base), \
access, \
GDT_FLAGS_HI_LIMIT(limit, flags), \
GDT_BASE_HIGH(base)}
typedef struct {
uint32_t reserved0;
uint64_t rsp0;
uint64_t rsp1;
uint64_t rsp2;
uint64_t reserved1;
uint64_t ist[7];
uint64_t reserved2;
uint32_t iobase;
} __attribute__((packed)) tss_t;
typedef struct {
uint16_t limit_low;
uint16_t base_low;
uint8_t base_middle;
uint8_t access;
uint8_t limit_high_and_flags;
uint8_t base_high;
} __attribute__((packed)) gdt_entry_t;
typedef struct {
uint16_t limit_low;
uint16_t base_low;
uint8_t base_middle;
uint8_t access;
uint8_t limit_high_and_flags;
uint8_t base_high;
uint32_t base_higher;
uint32_t zero;
} __attribute__((packed)) tss_entry_t;
typedef struct {
uint16_t size;
gdt_entry_t *pointer;
} __attribute__((packed)) gdt_pointer_t;
extern gdt_pointer_t gdtr;
extern void load_tss(uint16_t sel);
void gdt_init(void);
void gdt_load(void);
#endif
+58
View File
@@ -0,0 +1,58 @@
#ifndef FB_H
#define FB_H
#include <stdint.h>
#include <stddef.h>
#include <limine.h>
#define RGB(r, g, b) (((r) << 16) | ((g) << 8) | (b))
#define COLOR_BLACK RGB( 0, 0, 0)
#define COLOR_WHITE RGB(255, 255, 255)
#define COLOR_RED RGB(255, 0, 0)
#define COLOR_GREEN RGB( 0, 255, 0)
#define COLOR_BLUE RGB( 0, 0, 255)
#define COLOR_CYAN RGB( 0, 255, 255)
#define COLOR_MAGENTA RGB(255, 0, 255)
#define COLOR_YELLOW RGB(255, 255, 0)
#define COLOR_ORANGE RGB(255, 165, 0)
#define COLOR_GRAY RGB(128, 128, 128)
#define COLOR_DARKGRAY RGB( 64, 64, 64)
#define COLOR_BROWN RGB(165, 42, 42)
struct psf_header {
uint32_t magic;
uint32_t version;
uint32_t headersize;
uint32_t flags;
uint32_t numglyph;
uint32_t bytesperglyph;
uint32_t height;
uint32_t width;
} __attribute__((packed));
extern uint8_t _binary_font_psf_start[];
extern uint8_t _binary_font_psf_end[];
static inline const uint8_t* get_font_data(void) {
return (const uint8_t*)&_binary_font_psf_start;
}
static inline size_t get_font_data_size(void) {
return _binary_font_psf_end - _binary_font_psf_start;
}
static inline const struct psf_header* get_psf_header(void) {
return (const struct psf_header*)&_binary_font_psf_start;
}
int psf_validate(void);
void fb_draw_pixel(struct limine_framebuffer *fb, uint32_t x, uint32_t y, uint32_t color);
void fb_fill_rect(struct limine_framebuffer *fb, uint32_t x, uint32_t y, uint32_t w, uint32_t h, uint32_t color);
void fb_clear(struct limine_framebuffer *fb, uint32_t color);
void fb_draw_char(struct limine_framebuffer *fb, char c, uint32_t x, uint32_t y, uint32_t color);
void fb_draw_string(struct limine_framebuffer *fb, const char *str, uint32_t x, uint32_t y, uint32_t color);
void fb_init_backbuffer(struct limine_framebuffer *fb);
void fb_flush(struct limine_framebuffer *fb);
void fb_flush_lines(struct limine_framebuffer *fb, uint32_t y_start, uint32_t y_end);
#endif
+47
View File
@@ -0,0 +1,47 @@
#ifndef IDT_H
#define IDT_H
#include <stdint.h>
#include <stdbool.h>
#define IDT_MAX_DESCRIPTORS 256
#define IS_FLAG_SETTED(x, flag) ((x) | (flag))
#define FLAG_SET(x, flag) ((x) |= (flag))
#define FLAG_UNSET(x, flag) ((x) &= ~(flag))
typedef enum {
IDT_FLAG_GATE_TASK = 0x5,
IDT_FLAG_GATE_16BIT_INT = 0x6,
IDT_FLAG_GATE_16BIT_TRAP = 0x7,
IDT_FLAG_GATE_32BIT_INT = 0xE,
IDT_FLAG_GATE_32BIT_TRAP = 0xF,
IDT_FLAG_RING0 = (0 << 5),
IDT_FLAG_RING1 = (1 << 5),
IDT_FLAG_RING2 = (2 << 5),
IDT_FLAG_RING3 = (3 << 5),
IDT_FLAG_PRESENT = 0x80,
} IDT_FLAGS;
typedef struct {
uint16_t base_low;
uint16_t kernel_cs;
uint8_t ist;
uint8_t attributes;
uint16_t base_mid;
uint32_t base_high;
uint32_t reserved;
}__attribute__((packed)) idt_entry_t;
typedef struct {
uint16_t limit;
idt_entry_t *base;
}__attribute__((packed)) idtr_t;
extern idtr_t idtr;
void setup_interrupt_descriptor_table(uint64_t kernel_code_segment);
void idt_load(void);
#endif
+77
View File
@@ -0,0 +1,77 @@
#ifndef INTERRUPTS_H
#define INTERRUPTS_H
#include <stdint.h>
struct int_frame_t {
uint64_t ds;
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 interrupt;
uint64_t error;
uint64_t rip;
uint64_t cs;
uint64_t rflags;
uint64_t rsp;
uint64_t ss;
} __attribute__((packed));
typedef void (*int_handler_f)(struct int_frame_t* frame);
typedef struct {
uint64_t vector;
int_handler_f handler;
} int_desc_t;
#define __CHECK_HANDLER(fn) \
_Static_assert( \
__builtin_types_compatible_p( \
typeof(fn), void (*)(struct int_frame_t *)), \
"Invalid interrupt handler signature")
#define __CONCAT(a, b) a##b
#define __UNIQUE_NAME(base) __CONCAT(base, __COUNTER__)
#define DEFINE_ISR(_vector, _name) \
static void _name(struct int_frame_t *frame); \
static const int_desc_t __UNIQUE_NAME(__isr_desc_##_name) \
__attribute__((used, section(".isr_handlers"))) = { \
.vector = (_vector), \
.handler = _name, \
}; \
static void _name(struct int_frame_t *frame)
#define DEFINE_IRQ(_vector, _name) \
static void _name(struct int_frame_t *frame); \
static const int_desc_t __UNIQUE_NAME(__irq_desc_##_name) \
__attribute__((used, section(".irq_handlers"))) = { \
.vector = (_vector), \
.handler = _name, \
}; \
static void _name(struct int_frame_t *frame)
#define IPI_RESCHEDULE_VECTOR 0x40
#define IPI_TLB_SHOOTDOWN 0x41
void init_interrupt_system();
#endif
+31
View File
@@ -0,0 +1,31 @@
#ifndef IRQ_H
#define IRQ_H
#include <stdint.h>
#include "interrupts.h"
#define IRQ_INTERRUPTS_COUNT 224
static const char* irq_default_names[] __attribute__((unused)) = {
"IRQ0 timer",
"IRQ1 keyboard",
"IRQ2 cascade",
"IRQ3 COM2",
"IRQ4 COM1",
"IRQ5 LPT2",
"IRQ6 floppy",
"IRQ7 LPT1",
"IRQ8 RTC",
"IRQ9 ACPI",
"IRQ10 reserved",
"IRQ11 reserved",
"IRQ12 mouse",
"IRQ13 FPU",
"IRQ14 ATA1",
"IRQ15 ATA2"
};
void irq_common_handler(struct int_frame_t* regs);
void setup_defined_irq_handlers(void);
#endif
+81
View File
@@ -0,0 +1,81 @@
#ifndef ISR_H
#define ISR_H
#include "interrupts.h"
#define ISR_EXCEPTION_COUNT 32
enum {
EXCEPTION_DIVIDE_ERROR = 0,
EXCEPTION_DEBUG,
EXCEPTION_NMI,
EXCEPTION_BREAKPOINT,
EXCEPTION_OVERFLOW,
EXCEPTION_BOUND_RANGE,
EXCEPTION_INVALID_OPCODE,
EXCEPTION_DEVICE_NOT_AVAILABLE,
EXCEPTION_DOUBLE_FAULT,
EXCEPTION_COPROCESSOR_SEGMENT_OVERRUN,
EXCEPTION_INVALID_TSS,
EXCEPTION_SEGMENT_NOT_PRESENT,
EXCEPTION_STACK_SEGMENT_FAULT,
EXCEPTION_GENERAL_PROTECTION_FAULT,
EXCEPTION_PAGE_FAULT,
EXCEPTION_RESERVED15,
EXCEPTION_X87_FPU_ERROR,
EXCEPTION_ALIGNMENT_CHECK,
EXCEPTION_MACHINE_CHECK,
EXCEPTION_SIMD_FPU_EXCEPTION,
EXCEPTION_VIRTUALIZATION_EXCEPTION,
EXCEPTION_RESERVED21,
EXCEPTION_RESERVED22,
EXCEPTION_RESERVED23,
EXCEPTION_RESERVED24,
EXCEPTION_RESERVED25,
EXCEPTION_RESERVED26,
EXCEPTION_RESERVED27,
EXCEPTION_RESERVED28,
EXCEPTION_RESERVED29,
EXCEPTION_SECURITY_EXCEPTION = 30,
EXCEPTION_RESERVED31
};
static const char* exception_names[] __attribute__((unused)) = {
"Divide Error",
"Debug",
"Non-Maskable Interrupt",
"Breakpoint",
"Overflow",
"Bound Range Exceeded",
"Invalid Opcode",
"Device Not Available",
"Double Fault",
"Coprocessor Segment Overrun",
"Invalid TSS",
"Segment Not Present",
"Stack Segment Fault",
"General Protection Fault",
"Page Fault",
"Reserved",
"x87 Floating-Point Exception",
"Alignment Check",
"Machine Check",
"SIMD Floating-Point Exception",
"Virtualization Exception",
"Reserved",
"Reserved",
"Reserved",
"Reserved",
"Reserved",
"Reserved",
"Reserved",
"Reserved",
"Reserved",
"Security Exception",
"Reserved"
};
void isr_common_handler(struct int_frame_t* regs);
void setup_defined_isr_handlers(void);
#endif
+40
View File
@@ -0,0 +1,40 @@
#ifndef PORTS_H
#define PORTS_H
#include <stdint.h>
static inline uint8_t inb(uint16_t port) {
uint8_t result;
asm volatile ("inb %1, %0" : "=a"(result) : "Nd"(port));
return result;
}
static inline void outb(uint16_t port, uint8_t data) {
asm volatile ("outb %0, %1" : : "a"(data), "Nd"(port));
}
static inline uint16_t inw(uint16_t port) {
uint16_t result;
asm volatile ("inw %1, %0" : "=a"(result) : "Nd"(port));
return result;
}
static inline void outw(uint16_t port, uint16_t data) {
asm volatile ("outw %0, %1" : : "a"(data), "Nd"(port));
}
static inline uint32_t inl(uint16_t port) {
uint32_t result;
asm volatile ("inl %1, %0" : "=a"(result) : "Nd"(port));
return result;
}
static inline void outl(uint16_t port, uint32_t data) {
asm volatile ("outl %0, %1" : : "a"(data), "Nd"(port));
}
static inline void io_wait(void) {
outb(0x80, 0);
}
#endif
+51
View File
@@ -0,0 +1,51 @@
#ifndef SERIAL_H
#define SERIAL_H
#include <stdint.h>
#include <stddef.h>
#include <stdbool.h>
#include <stdarg.h>
#define COM1 0x3F8
#define COM2 0x2F8
#define COM3 0x3E8
#define COM4 0x2E8
#define SERIAL_DATA_PORT(base) (base)
#define SERIAL_FIFO_COMMAND_PORT(base) (base + 2)
#define SERIAL_LINE_COMMAND_PORT(base) (base + 3)
#define SERIAL_MODEM_COMMAND_PORT(base) (base + 4)
#define SERIAL_LINE_STATUS_PORT(base) (base + 5)
#define SERIAL_LSR_DATA_READY 0x01
#define SERIAL_LSR_OVERRUN_ERROR 0x02
#define SERIAL_LSR_PARITY_ERROR 0x04
#define SERIAL_LSR_FRAMING_ERROR 0x08
#define SERIAL_LSR_BREAK_INDICATOR 0x10
#define SERIAL_LSR_TRANSMIT_HOLDING_EMPTY 0x20
#define SERIAL_LSR_TRANSMIT_EMPTY 0x40
#define SERIAL_LSR_FIFO_ERROR 0x80
void serial_initialize(uint16_t port, uint32_t baud_rate);
int serial_received_port(uint16_t port);
char serial_read_port(uint16_t port);
int serial_is_transmit_empty_port(uint16_t port);
void serial_write_port(uint16_t port, char c);
void serial_writestring_port(uint16_t port, const char* str);
void serial_printf_port(uint16_t port, const char* format, ...);
int serial_received(void);
char serial_read(void);
int serial_is_transmit_empty(void);
void serial_write(char c);
void serial_writestring(const char* str);
void serial_writebuf(const char* buf, size_t len);
void serial_printf(const char* format, ...);
uint16_t serial_get_default_port(void);
void serial_set_default_port(uint16_t port);
void serial_force_unlock(void);
#endif
+44
View File
@@ -0,0 +1,44 @@
#ifndef PAGING_H
#define PAGING_H
#include <stdint.h>
#include <stddef.h>
#include <stdbool.h>
#include "vmm.h"
#include "../include/interrupts/interrupts.h"
#define PAGING_PRESENT VMM_PRESENT
#define PAGING_WRITE VMM_WRITE
#define PAGING_USER VMM_USER
#define PAGING_NOEXEC VMM_NOEXEC
#define PAGING_KERNEL (PAGING_PRESENT | PAGING_WRITE)
#define PAGING_USER_RW (PAGING_PRESENT | PAGING_WRITE | PAGING_USER)
#define PAGING_USER_RO (PAGING_PRESENT | PAGING_USER)
#define PAGING_USER_NOEXEC (PAGING_PRESENT | PAGING_USER | PAGING_NOEXEC)
#define PAGING_LARGE_PAGE_SIZE 0x200000
#define PAGING_HUGE_PAGE_SIZE 0x40000000
typedef struct {
uintptr_t virtual_start;
uintptr_t virtual_end;
uintptr_t physical_start;
uint64_t flags;
size_t page_count;
bool allocated;
} paging_region_t;
void paging_init(void);
bool paging_map_range(vmm_pagemap_t* pagemap, uintptr_t virt_start, uintptr_t phys_start, size_t page_count, uint64_t flags);
bool paging_unmap_range(vmm_pagemap_t* pagemap, uintptr_t virt_start, size_t page_count);
bool paging_change_flags(vmm_pagemap_t* pagemap, uintptr_t virt_start, size_t page_count, uint64_t new_flags);
paging_region_t* paging_create_region(vmm_pagemap_t* pagemap, uintptr_t virt_start, size_t size, uint64_t flags);
bool paging_destroy_region(vmm_pagemap_t* pagemap, paging_region_t* region);
void* paging_alloc_pages(vmm_pagemap_t* pagemap, size_t page_count, uint64_t flags, uintptr_t preferred_virt);
void paging_free_pages(vmm_pagemap_t* pagemap, void* virt_addr, size_t page_count);
bool paging_reserve_range(vmm_pagemap_t* pagemap, uintptr_t virt_start, uintptr_t virt_end);
bool paging_is_range_free(vmm_pagemap_t* pagemap, uintptr_t virt_start, uintptr_t virt_end);
void paging_print_stats(vmm_pagemap_t* pagemap);
void paging_dump_range(vmm_pagemap_t* pagemap, uintptr_t virt_start, uintptr_t virt_end);
#endif
+89
View File
@@ -0,0 +1,89 @@
#ifndef PMM_H
#define PMM_H
#include <stdint.h>
#include <stddef.h>
#include <stdbool.h>
#include <limine.h>
#define PAGE_SIZE 4096UL
#define PAGE_SHIFT 12
#define PMM_PAGE_ALIGN(x) (((x) + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1))
#define PMM_MAX_ORDER 10
#define PMM_MAX_ORDER_NR (PMM_MAX_ORDER + 1)
#define SLAB_MIN_SIZE 8
#define SLAB_MAX_SIZE 4096
#define SLAB_NUM_CACHES 10
#define PMM_FREE_MIN_PHYS 0x100000ULL
typedef struct pmm_block {
struct pmm_block *next;
struct pmm_block *prev;
int order;
} pmm_block_t;
typedef struct {
pmm_block_t head;
size_t count;
} pmm_free_list_t;
typedef struct {
uintptr_t hhdm_offset;
uintptr_t mem_start;
uintptr_t mem_end;
size_t total_pages;
size_t usable_pages;
size_t free_pages;
pmm_free_list_t orders[PMM_MAX_ORDER_NR];
} pmm_buddy_state_t;
typedef struct slab {
struct slab *next;
struct slab *prev;
void *freelist;
uint16_t obj_size;
uint16_t total;
uint16_t used;
uint16_t _pad;
} slab_t;
typedef struct {
size_t obj_size;
slab_t *partial;
slab_t *full;
size_t total_allocs;
size_t total_frees;
} slab_cache_t;
void pmm_init(struct limine_memmap_response *memmap,
struct limine_hhdm_response *hhdm);
void *pmm_alloc(size_t pages);
void *pmm_alloc_zero(size_t pages);
void *pmm_alloc_aligned(size_t pages, size_t alignment);
void pmm_free(void *addr, size_t pages);
void pmm_free_single(void *addr);
void *pmm_phys_to_virt(uintptr_t phys);
uintptr_t pmm_virt_to_phys(void *vaddr);
uint64_t pmm_get_hhdm_offset(void);
size_t pmm_get_total_pages(void);
size_t pmm_get_usable_pages(void);
size_t pmm_get_free_pages(void);
size_t pmm_get_used_pages(void);
void pmm_print_stats(void);
void slab_init(void);
void *kmalloc(size_t size);
void *kzalloc(size_t size);
void *krealloc(void *ptr, size_t new_size);
void kfree(void *ptr);
void slab_print_stats(void);
extern slab_cache_t g_caches[SLAB_NUM_CACHES];
#endif
+41
View File
@@ -0,0 +1,41 @@
#ifndef VMM_H
#define VMM_H
#include <stdint.h>
#include <stddef.h>
#include <stdbool.h>
#define VMM_PRESENT (1ULL << 0)
#define VMM_WRITE (1ULL << 1)
#define VMM_USER (1ULL << 2)
#define VMM_PWT (1ULL << 3)
#define VMM_PCD (1ULL << 4)
#define VMM_ACCESSED (1ULL << 5)
#define VMM_DIRTY (1ULL << 6)
#define VMM_PSE (1ULL << 7)
#define VMM_GLOBAL (1ULL << 8)
#define VMM_NOEXEC (1ULL << 63)
typedef uint64_t vmm_pte_t;
typedef struct {
vmm_pte_t* pml4;
} vmm_pagemap_t;
extern uintptr_t kernel_pml4_phys;
void vmm_init(void);
vmm_pagemap_t* vmm_create_pagemap(void);
void vmm_switch_pagemap(vmm_pagemap_t* map);
bool vmm_map_page(vmm_pagemap_t* map, uintptr_t virt, uintptr_t phys, uint64_t flags);
void vmm_unmap_page(vmm_pagemap_t* map, uintptr_t virt);
void vmm_unmap_page_noflush(vmm_pagemap_t* map, uintptr_t virt);
bool vmm_virt_to_phys(vmm_pagemap_t* map, uintptr_t virt, uintptr_t* phys_out);
bool vmm_get_page_flags(vmm_pagemap_t* map, uintptr_t virt, uint64_t* flags_out);
vmm_pagemap_t* vmm_get_kernel_pagemap(void);
vmm_pagemap_t* vmm_clone_pagemap(vmm_pagemap_t* src);
void vmm_free_pagemap(vmm_pagemap_t* map);
void vmm_sync_kernel_mappings(vmm_pagemap_t* map);
void vmm_test(void);
#endif
+19
View File
@@ -0,0 +1,19 @@
#ifndef PANIC_H
#define PANIC_H
#include <stdint.h>
#include "../interrupts/interrupts.h"
__attribute__((noreturn))
void kernel_panic(const char *msg);
__attribute__((noreturn))
void kernel_panic_regs(const char *msg, struct int_frame_t *regs);
#define KPANIC(msg) \
kernel_panic("[" __FILE__ ":" STRINGIFY(__LINE__) "] " msg)
#define STRINGIFY_IMPL(x) #x
#define STRINGIFY(x) STRINGIFY_IMPL(x)
#endif
+49
View File
@@ -0,0 +1,49 @@
#ifndef CAPABILITIES_H
#define CAPABILITIES_H
#include <stdint.h>
#include <stdbool.h>
#define UID_ROOT 0
#define GID_ROOT 0
#define UID_NOBODY 65534
#define GID_NOBODY 65534
#define CAP_IOPORT (1ULL << 0)
#define CAP_RAWMEM (1ULL << 1)
#define CAP_DMA (1ULL << 2)
#define CAP_IRQ (1ULL << 3)
#define CAP_KILL_ANY (1ULL << 4)
#define CAP_SET_PRIO (1ULL << 5)
#define CAP_TASK_SPAWN (1ULL << 6)
#define CAP_TASK_INFO (1ULL << 7)
#define CAP_MMAP_EXEC (1ULL << 8)
#define CAP_MMAP_PHYS (1ULL << 9)
#define CAP_FS_ROOT (1ULL << 10)
#define CAP_FS_OWNER (1ULL << 11)
#define CAP_NET_RAW (1ULL << 12)
#define CAP_NET_BIND (1ULL << 13)
#define CAP_SYSADMIN (1ULL << 14)
#define CAP_REBOOT (1ULL << 15)
#define CAP_MODULE (1ULL << 16)
#define CAP_SETUID (1ULL << 17)
#define CAP_AUDIT (1ULL << 18)
#define CAP_PTRACE (1ULL << 19)
#define CAP_DBG_SERIAL (1ULL << 20)
#define CAP_ALL (~0ULL)
#define CAP_BASIC_SET (CAP_MMAP_EXEC | CAP_TASK_SPAWN)
#define CAP_SERVICE_SET (CAP_BASIC_SET | CAP_TASK_INFO | CAP_SET_PRIO | CAP_NET_BIND)
static inline bool cap_has(uint64_t caps, uint64_t cap) {
return (caps & cap) == cap;
}
static inline uint64_t cap_drop(uint64_t caps, uint64_t cap) {
return caps & ~cap;
}
static inline uint64_t cap_initial(uint32_t uid) {
return (uid == UID_ROOT) ? CAP_ALL : CAP_BASIC_SET;
}
#endif
+183
View File
@@ -0,0 +1,183 @@
#ifndef TASK_H
#define TASK_H
#include <stdint.h>
#include <stdbool.h>
#include <stddef.h>
#include "capabilities.h"
#include "../memory/vmm.h"
#include "../smp/smp.h"
#ifndef __ATOMIC_RELAXED
#define __ATOMIC_RELAXED 0
#define __ATOMIC_ACQUIRE 2
#define __ATOMIC_RELEASE 3
#endif
typedef struct { volatile bool _val; } atomic_bool;
static inline void atomic_init_bool(atomic_bool *a, bool v) {
__atomic_store_n(&a->_val, v, __ATOMIC_RELAXED);
}
static inline bool atomic_load_bool_acq(const atomic_bool *a) {
return __atomic_load_n(&a->_val, __ATOMIC_ACQUIRE);
}
static inline void atomic_store_bool_rel(atomic_bool *a, bool v) {
__atomic_store_n(&a->_val, v, __ATOMIC_RELEASE);
}
static inline bool atomic_cas_bool(atomic_bool *a, bool *expected, bool desired) {
return __atomic_compare_exchange_n(
&a->_val, expected, desired,
false, __ATOMIC_ACQUIRE, __ATOMIC_RELAXED);
}
typedef struct fd_table fd_table_t;
typedef struct {
uint8_t data[512] __attribute__((aligned(16)));
} fpu_state_t;
typedef enum {
TASK_RUNNING = 0,
TASK_READY,
TASK_BLOCKED,
TASK_ZOMBIE,
TASK_DEAD,
} task_state_t;
typedef enum {
TASK_TYPE_KERNEL = 0,
TASK_TYPE_USER = 1,
} task_type_t;
#define MAX_PRIORITY 31
#define DEFAULT_PRIORITY 16
#define TASK_DEFAULT_TIMESLICE 10
typedef struct task {
uint64_t rsp;
uint64_t rip;
uint64_t rbp_save;
uint64_t cr3;
int priority;
bool runnable;
uint8_t is_userspace;
uint8_t _pad0[2];
uint32_t cpu_id;
char name[32];
uint32_t time_slice;
uint32_t time_slice_init;
uint8_t _pad1[4];
uint64_t total_runtime;
fpu_state_t* fpu_state;
bool fpu_used;
uint8_t _pad2[3];
uint32_t last_cpu;
uint64_t cpu_affinity;
void (*entry)(void*);
void *arg;
uintptr_t stack_base;
uint64_t user_rsp;
task_state_t state;
uint8_t _pad3[4];
struct task* next;
uint32_t pid;
uint32_t ppid;
uint32_t uid;
uint32_t gid;
uint64_t capabilities;
struct task* parent;
struct task* children;
struct task* sibling;
int exit_code;
volatile bool pending_kill;
uint8_t _pad4[3];
uintptr_t brk_start;
uintptr_t brk_current;
uintptr_t brk_max;
vmm_pagemap_t* pagemap;
uint32_t flags;
uint32_t wait_for_pid;
uint64_t wakeup_time_ns;
uint64_t user_saved_rip;
uint64_t user_saved_rbp;
uint64_t user_saved_rbx;
uint64_t user_saved_r12;
uint64_t user_saved_r13;
uint64_t user_saved_r14;
uint64_t user_saved_r15;
uint64_t user_saved_r11;
fd_table_t *fd_table;
atomic_bool on_cpu;
} task_t;
#define TASK_FLAG_TRACE (1 << 0)
#define TASK_FLAG_VFORK (1 << 1)
#define TASK_FLAG_FORK (1 << 2)
#define TASK_FLAG_STARTED (1 << 3)
#define TASK_FLAG_OWN_PAGEMAP (1 << 4)
#define TASK_FLAG_STACK_DEFERRED (1 << 5)
#define TASK_FLAG_DESTROYED (1U << 31)
_Static_assert(offsetof(task_t, rsp) == 0, "task_t: rsp");
_Static_assert(offsetof(task_t, entry) == 120, "task_t: entry — update TASK_ENTRY_OFFSET");
_Static_assert(offsetof(task_t, arg) == 128, "task_t: arg — update TASK_ARG_OFFSET");
_Static_assert(offsetof(task_t, stack_base) == 136, "task_t: stack_base");
_Static_assert(offsetof(task_t, user_rsp) == 144, "task_t: user_rsp — update TASK_USER_RSP_OFFSET");
_Static_assert(offsetof(task_t, user_saved_rip) == 272, "task_t: user_saved_rip");
_Static_assert(offsetof(task_t, user_saved_rbp) == 280, "task_t: user_saved_rbp — update TASK_USER_SAVED_RBP_OFFSET");
extern task_t* ready_queues[MAX_PRIORITY + 1];
extern task_t* current_task[MAX_CPUS];
void sched_init(void);
void sched_reschedule(void);
void sched_print_stats(void);
void task_yield(void);
task_t* task_create(const char* name, void (*entry)(void*), void* arg, int priority);
task_t* task_create_user(const char* name, uintptr_t entry, uintptr_t user_rsp, uint64_t cr3, int priority, vmm_pagemap_t* pagemap, uint32_t uid, uint32_t gid);
__attribute__((noreturn)) void task_exit(void);
void task_kill(task_t* task);
void task_destroy(task_t* task);
task_t* task_fork(task_t* parent);
task_t* task_find_by_pid(uint32_t pid);
uint32_t task_alloc_pid(void);
void task_reparent(task_t* child, task_t* new_parent);
#include "spinlock.h"
extern spinlock_t children_lock;
void task_wakeup_waiters(uint32_t pid);
void task_unblock(task_t* t);
void sched_wakeup_sleepers(uint64_t now_ns);
task_t* task_find_foreground(void);
extern volatile uint32_t g_foreground_pid;
void task_set_foreground(uint32_t pid);
extern void context_switch(task_t* old, task_t* next, task_t** current_task_slot, uint64_t new_cr3);
extern void first_task_start(task_t* task);
extern void task_trampoline(void);
extern void task_trampoline_user(void);
extern void task_trampoline_fork(void);
extern void fpu_save(fpu_state_t* state);
extern void fpu_restore(fpu_state_t* state);
#endif
+44
View File
@@ -0,0 +1,44 @@
#ifndef SPINLOCK_H
#define SPINLOCK_H
#include <stdint.h>
typedef struct {
volatile uint32_t ticket;
volatile uint32_t serving;
} spinlock_t;
#define SPINLOCK_INIT { .ticket = 0, .serving = 0 }
static inline void spinlock_acquire(spinlock_t* lock) {
uint32_t my_ticket = __atomic_fetch_add(&lock->ticket, 1, __ATOMIC_RELAXED);
while (__atomic_load_n(&lock->serving, __ATOMIC_ACQUIRE) != my_ticket)
asm volatile("pause");
}
static inline void spinlock_release(spinlock_t* lock) {
__atomic_fetch_add(&lock->serving, 1, __ATOMIC_RELEASE);
}
static inline int spinlock_try_acquire(spinlock_t* lock) {
uint32_t serving = __atomic_load_n(&lock->serving, __ATOMIC_RELAXED);
uint32_t ticket = __atomic_load_n(&lock->ticket, __ATOMIC_RELAXED);
if (serving != ticket) return 0;
uint32_t expected = serving;
return __atomic_compare_exchange_n(&lock->ticket, &expected, serving + 1,
0, __ATOMIC_ACQUIRE, __ATOMIC_RELAXED);
}
static inline uint64_t spinlock_acquire_irqsave(spinlock_t* lock) {
uint64_t flags;
asm volatile("pushfq; pop %0; cli" : "=r"(flags) :: "memory");
spinlock_acquire(lock);
return flags;
}
static inline void spinlock_release_irqrestore(spinlock_t* lock, uint64_t flags) {
spinlock_release(lock);
asm volatile("push %0; popfq" :: "r"(flags) : "memory", "cc");
}
#endif
+55
View File
@@ -0,0 +1,55 @@
#ifndef PERCPU_H
#define PERCPU_H
#include <stdint.h>
#include "../include/smp/smp.h"
#define PERCPU_SECTION __attribute__((section(".percpu")))
typedef struct {
uint64_t syscall_kernel_rsp;
uint64_t syscall_user_rsp;
uint32_t cpu_id;
uint32_t _pad;
void* current_task;
uint64_t some_counter;
bool need_resched;
uint8_t _pad2[7];
uint64_t user_saved_rbp;
uint64_t user_saved_rbx;
uint64_t user_saved_r12;
uint64_t user_saved_r13;
uint64_t user_saved_r14;
uint64_t user_saved_r15;
uint64_t user_saved_r11;
uint64_t user_saved_rip;
uint8_t _pad3[8];
void* deferred_free_task;
uint64_t sched_stack_top;
} __attribute__((aligned(64))) percpu_t;
_Static_assert(__builtin_offsetof(percpu_t, syscall_kernel_rsp) == 0, "percpu: kernel_rsp");
_Static_assert(__builtin_offsetof(percpu_t, syscall_user_rsp) == 8, "percpu: user_rsp");
_Static_assert(__builtin_offsetof(percpu_t, current_task) == 24, "percpu: current_task");
_Static_assert(__builtin_offsetof(percpu_t, need_resched) == 40, "percpu: need_resched");
_Static_assert(__builtin_offsetof(percpu_t, user_saved_rbp) == 48, "percpu: saved_rbp");
_Static_assert(__builtin_offsetof(percpu_t, user_saved_rbx) == 56, "percpu: saved_rbx");
_Static_assert(__builtin_offsetof(percpu_t, user_saved_r12) == 64, "percpu: saved_r12");
_Static_assert(__builtin_offsetof(percpu_t, user_saved_r13) == 72, "percpu: saved_r13");
_Static_assert(__builtin_offsetof(percpu_t, user_saved_r14) == 80, "percpu: saved_r14");
_Static_assert(__builtin_offsetof(percpu_t, user_saved_r15) == 88, "percpu: saved_r15");
_Static_assert(__builtin_offsetof(percpu_t, user_saved_r11) == 96, "percpu: saved_r11");
_Static_assert(__builtin_offsetof(percpu_t, user_saved_rip) == 104, "percpu: saved_rip");
extern percpu_t percpu;
extern percpu_t* percpu_regions[MAX_CPUS];
extern bool g_has_fsgsbase;
percpu_t* get_percpu(void);
percpu_t* get_percpu_mut(void);
void init_percpu_regions(void);
void set_percpu_base(percpu_t* base);
#define current_cpu_id() (get_percpu()->cpu_id)
#endif
+60
View File
@@ -0,0 +1,60 @@
#ifndef SMP_H
#define SMP_H
#include <stdint.h>
#include <stdbool.h>
#include <stddef.h>
#include <limine.h>
#define AP_STACK_SIZE 16384
#define MAX_CPUS 256
#define MAX_TLB_ADDRESSES 32
typedef struct {
volatile bool pending;
uintptr_t addresses[MAX_TLB_ADDRESSES];
size_t count;
} tlb_shootdown_t;
extern tlb_shootdown_t tlb_shootdown_queue[MAX_CPUS];
typedef enum {
CPU_UNINITIALIZED = 0,
CPU_BOOTED,
CPU_ONLINE,
CPU_OFFLINE,
CPU_FAULTED
} cpu_state_t;
typedef struct {
uint32_t lapic_id;
uint32_t processor_id;
uint32_t acpi_id;
cpu_state_t state;
bool is_bsp;
uint64_t stack_top;
uint32_t cpu_index;
uint16_t tss_selector;
} cpu_info_t;
typedef struct {
uint32_t cpu_count;
uint32_t online_count;
uint32_t bsp_lapic_id;
uint64_t lapic_base;
cpu_info_t cpus[256];
} smp_info_t;
void smp_init(struct limine_mp_response* mp_response);
void smp_boot_aps(struct limine_mp_response* mp_response);
smp_info_t* smp_get_info(void);
cpu_info_t* smp_get_current_cpu(void);
uint32_t smp_get_cpu_count(void);
uint32_t smp_get_online_count(void);
bool smp_is_bsp(void);
void smp_print_info(void);
void smp_print_info_fb(void);
void smp_wait_for_ready(void);
void ap_entry_point(struct limine_mp_info* cpu_info);
void sched_notify_ready(void);
#endif
+17
View File
@@ -0,0 +1,17 @@
#ifndef FPU_H
#define FPU_H
#include <stdint.h>
#include <stdbool.h>
void fpu_init(void);
bool fpu_detect(void);
void fpu_set_control_word(uint16_t cw);
uint16_t fpu_get_control_word(void);
void fpu_set_status_word(uint16_t sw);
uint16_t fpu_get_status_word(void);
void fpu_set_tag_word(uint16_t tw);
uint16_t fpu_get_tag_word(void);
void fpu_reset(void);
#endif
+31
View File
@@ -0,0 +1,31 @@
#ifndef SSE_H
#define SSE_H
#include <stdint.h>
#include <stdbool.h>
#include <stddef.h>
#define MXCSR_DEFAULT 0x1F80
#define MXCSR_FLUSH_TO_ZERO (1 << 15)
#define MXCSR_DENORMALS_ARE_ZERO (1 << 6)
bool sse_supported(void);
bool sse2_supported(void);
bool sse3_supported(void);
bool ssse3_supported(void);
bool sse4_1_supported(void);
bool sse4_2_supported(void);
bool avx_supported(void);
bool avx2_supported(void);
void sse_init(void);
void sse_set_mxcsr(uint32_t mxcsr);
uint32_t sse_get_mxcsr(void);
void sse_memcpy_fast(void* dest, const void* src, size_t n);
void sse_memset_fast(void* dest, int value, size_t n);
bool mmx_supported(void);
void mmx_enter(void);
void mmx_exit(void);
void print_simd_cpuid(void);
void enable_fsgsbase(void);
#endif
+66
View File
@@ -0,0 +1,66 @@
#ifndef ERRNO_H
#define ERRNO_H
#define EPERM 1
#define ENOENT 2
#define ESRCH 3
#define EINTR 4
#define EIO 5
#define ENXIO 6
#define E2BIG 7
#define ENOEXEC 8
#define EBADF 9
#define ECHILD 10
#define EAGAIN 11
#define ENOMEM 12
#define EACCES 13
#define EFAULT 14
#define EBUSY 16
#define EEXIST 17
#define EXDEV 18
#define ENODEV 19
#define ENOTDIR 20
#define EISDIR 21
#define EINVAL 22
#define ENFILE 23
#define EMFILE 24
#define ENOTTY 25
#define EFBIG 27
#define ENOSPC 28
#define ESPIPE 29
#define EROFS 30
#define EMLINK 31
#define EPIPE 32
#define ERANGE 34
#define EDEADLK 35
#define ENAMETOOLONG 36
#define ENOLCK 37
#define ENOSYS 38
#define ENOTEMPTY 39
#define ELOOP 40
#define ENOMSG 42
#define EIDRM 43
#define ENOSTR 60
#define ENODATA 61
#define ETIME 62
#define ENOSR 63
#define EREMOTE 66
#define ENOLINK 67
#define EPROTO 71
#define EMULTIHOP 72
#define EBADMSG 74
#define EOVERFLOW 75
#define EILSEQ 84
#define EUSERS 87
#define ENOTSOCK 88
#define EOPNOTSUPP 95
#define EADDRINUSE 98
#define ECONNREFUSED 111
#define ETIMEDOUT 110
#define ECERVUS_BASE 200
#define ECAPABILITY 200
#define ETASKDEAD 201
#define EBADCR3 202
#endif
+12
View File
@@ -0,0 +1,12 @@
#ifndef SYSCALL_H
#define SYSCALL_H
#include <stdint.h>
#include "syscall_nums.h"
#include "../sched/capabilities.h"
void syscall_init(void);
int64_t syscall_handler_c(uint64_t nr, uint64_t a1, uint64_t a2, uint64_t a3, uint64_t a4, uint64_t a5, uint64_t user_rip);
#endif
+142
View File
@@ -0,0 +1,142 @@
#ifndef SYSCALL_NUMS_H
#define SYSCALL_NUMS_H
#define SYS_EXIT 0
#define SYS_EXIT_GROUP 1
#define SYS_GETPID 2
#define SYS_GETPPID 3
#define SYS_FORK 4
#define SYS_WAIT 5
#define SYS_EXECVE 14
#define SYS_YIELD 6
#define SYS_GETUID 7
#define SYS_GETGID 8
#define SYS_SETUID 9
#define SYS_SETGID 10
#define SYS_CAP_GET 11
#define SYS_CAP_DROP 12
#define SYS_TASK_INFO 13
#define SYS_READ 20
#define SYS_WRITE 21
#define SYS_OPEN 22
#define SYS_CLOSE 23
#define SYS_SEEK 24
#define SYS_STAT 25
#define SYS_FSTAT 26
#define SYS_IOCTL 27
#define SYS_DUP 28
#define SYS_DUP2 29
#define SYS_PIPE 30
#define SYS_FCNTL 31
#define SYS_READDIR 32
#define SYS_MMAP 40
#define SYS_MUNMAP 41
#define SYS_MPROTECT 42
#define SYS_BRK 43
#define SYS_CLOCK_GET 60
#define SYS_SLEEP_NS 61
#define SYS_UPTIME 62
#define SYS_MEMINFO 63
#define SYS_FUTEX_WAIT 80
#define SYS_FUTEX_WAKE 81
#define SYS_CERVUS_BASE 512
#define SYS_DBG_PRINT 512
#define SYS_DBG_DUMP 513
#define SYS_TASK_SPAWN 514
#define SYS_TASK_KILL 515
#define SYS_SHMEM_CREATE 516
#define SYS_SHMEM_MAP 517
#define SYS_SHMEM_UNMAP 518
#define SYS_IPC_SEND 519
#define SYS_IPC_RECV 520
#define SYS_IOPORT_READ 521
#define SYS_IOPORT_WRITE 522
#define SYS_SHUTDOWN 523
#define SYS_REBOOT 524
#define SYS_DISK_MOUNT 530
#define SYS_DISK_UMOUNT 531
#define SYS_DISK_FORMAT 532
#define SYS_DISK_INFO 533
#define SYS_UNLINK 534
#define SYS_RMDIR 535
#define SYS_MKDIR 536
#define SYS_RENAME 537
#define SYS_DISK_READ_RAW 540
#define SYS_DISK_WRITE_RAW 541
#define SYS_DISK_PARTITION 542
#define SYS_DISK_MKFS_FAT32 543
#define SYS_DISK_LIST_PARTS 544
#define SYS_DISK_BIOS_INSTALL 545
#define SYS_LIST_MOUNTS 546
#define SYS_STATVFS 547
#define SYSCALL_TABLE_SIZE 548
#define PROT_NONE 0x0
#define PROT_READ 0x1
#define PROT_WRITE 0x2
#define PROT_EXEC 0x4
#define MAP_PRIVATE 0x02
#define MAP_ANONYMOUS 0x20
#define MAP_FIXED 0x10
#define MAP_FAILED ((void*)-1)
#define WNOHANG 0x1
#define CLOCK_REALTIME 0
#define CLOCK_MONOTONIC 1
typedef struct {
uint32_t pid;
uint32_t ppid;
uint32_t uid;
uint32_t gid;
uint64_t capabilities;
char name[32];
uint32_t state;
uint32_t priority;
uint64_t total_runtime_ns;
} cervus_task_info_t;
typedef struct {
int64_t tv_sec;
int64_t tv_nsec;
} cervus_timespec_t;
typedef struct {
uint64_t total_bytes;
uint64_t free_bytes;
uint64_t used_bytes;
uint64_t usable_bytes;
uint64_t page_size;
} cervus_meminfo_t;
typedef struct __attribute__((packed)) {
uint8_t boot_flag;
uint8_t type;
uint32_t lba_start;
uint32_t sector_count;
} cervus_mbr_part_t;
typedef struct __attribute__((packed)) {
char disk_name[32];
char part_name[32];
uint32_t part_num;
uint8_t type;
uint8_t bootable;
uint64_t lba_start;
uint64_t sector_count;
uint64_t size_bytes;
} cervus_part_info_t;
#endif