push
This commit is contained in:
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
Reference in New Issue
Block a user