summaryrefslogtreecommitdiff
path: root/kernel/src
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/src')
-rw-r--r--kernel/src/arch/aarch64/aarch64.cpp54
-rw-r--r--kernel/src/arch/aarch64/paging.cpp148
-rw-r--r--kernel/src/arch/riscv64/features.hpp33
-rw-r--r--kernel/src/arch/riscv64/paging.cpp163
-rw-r--r--kernel/src/arch/riscv64/riscv64.cpp56
-rw-r--r--kernel/src/arch/x86_64/asm/scheduling.asm121
-rw-r--r--kernel/src/arch/x86_64/asm/syscall.asm56
-rw-r--r--kernel/src/arch/x86_64/assembly.hpp30
-rw-r--r--kernel/src/arch/x86_64/cpu/gdt.asm (renamed from kernel/src/arch/x86_64/cpu/asm/gdt.asm)8
-rw-r--r--kernel/src/arch/x86_64/cpu/gdt.cpp61
-rw-r--r--kernel/src/arch/x86_64/cpu/gdt.hpp56
-rw-r--r--kernel/src/arch/x86_64/cpu/idt.asm (renamed from kernel/src/arch/x86_64/interrupts/asm/idt.asm)2
-rw-r--r--kernel/src/arch/x86_64/cpu/idt.cpp (renamed from kernel/src/arch/x86_64/interrupts/idt.cpp)32
-rw-r--r--kernel/src/arch/x86_64/cpu/idt.hpp56
-rw-r--r--kernel/src/arch/x86_64/cpu/smp.cpp88
-rw-r--r--kernel/src/arch/x86_64/cpu/sse.cpp120
-rw-r--r--kernel/src/arch/x86_64/cpu_local.hpp45
-rw-r--r--kernel/src/arch/x86_64/drivers/hpet.cpp58
-rw-r--r--kernel/src/arch/x86_64/drivers/hpet.hpp18
-rw-r--r--kernel/src/arch/x86_64/drivers/io.hpp40
-rw-r--r--kernel/src/arch/x86_64/drivers/pci.hpp42
-rw-r--r--kernel/src/arch/x86_64/drivers/tsc.cpp113
-rw-r--r--kernel/src/arch/x86_64/drivers/tsc.hpp19
-rw-r--r--kernel/src/arch/x86_64/interrupts/irq.cpp94
-rw-r--r--kernel/src/arch/x86_64/interrupts/panic.cpp216
-rw-r--r--kernel/src/arch/x86_64/interrupts/pit.cpp31
-rw-r--r--kernel/src/arch/x86_64/paging.cpp161
-rw-r--r--kernel/src/arch/x86_64/scheduling.cpp1103
-rw-r--r--kernel/src/arch/x86_64/syscalls/file.cpp2737
-rw-r--r--kernel/src/arch/x86_64/syscalls/futex.cpp132
-rw-r--r--kernel/src/arch/x86_64/syscalls/misc.cpp158
-rw-r--r--kernel/src/arch/x86_64/syscalls/process.cpp1081
-rw-r--r--kernel/src/arch/x86_64/syscalls/shm.cpp224
-rw-r--r--kernel/src/arch/x86_64/syscalls/signal.cpp304
-rw-r--r--kernel/src/arch/x86_64/syscalls/sockets.cpp467
-rw-r--r--kernel/src/arch/x86_64/syscalls/syscalls.cpp269
-rw-r--r--kernel/src/arch/x86_64/x86_64.cpp120
-rw-r--r--kernel/src/bg.bmpbin0 -> 6220938 bytes
-rw-r--r--kernel/src/drivers/acpi.cpp569
-rw-r--r--kernel/src/drivers/acpi.hpp7
-rw-r--r--kernel/src/drivers/hpet.cpp52
-rw-r--r--kernel/src/drivers/ioapic.cpp120
-rw-r--r--kernel/src/drivers/kvmtimer.cpp54
-rw-r--r--kernel/src/drivers/pci.cpp137
-rw-r--r--kernel/src/drivers/ps2.cpp326
-rw-r--r--kernel/src/drivers/serial.cpp46
-rw-r--r--kernel/src/drivers/tsc.cpp46
-rw-r--r--kernel/src/drivers/uacpi_kernel_api.cpp397
-rw-r--r--kernel/src/drivers/xhci.cpp1602
-rw-r--r--kernel/src/etc/bootloaderinfo.cpp105
-rw-r--r--kernel/src/etc/libc.cpp4
-rw-r--r--kernel/src/etc/logging.cpp221
-rw-r--r--kernel/src/gaster.txt22
-rw-r--r--kernel/src/generic/arch.hpp35
-rw-r--r--kernel/src/generic/bootloader/bootloader.cpp10
-rw-r--r--kernel/src/generic/bootloader/bootloader.hpp20
-rw-r--r--kernel/src/generic/bootloader/limine.cpp87
-rw-r--r--kernel/src/generic/bootloader/limine.hpp15
-rw-r--r--kernel/src/generic/heap.cpp124
-rw-r--r--kernel/src/generic/heap.hpp20
-rw-r--r--kernel/src/generic/hhdm.hpp8
-rw-r--r--kernel/src/generic/lock/spinlock.hpp29
-rw-r--r--kernel/src/generic/mm/heap.cpp103
-rw-r--r--kernel/src/generic/mm/paging.cpp245
-rw-r--r--kernel/src/generic/mm/pmm.cpp452
-rw-r--r--kernel/src/generic/paging.cpp85
-rw-r--r--kernel/src/generic/paging.hpp20
-rw-r--r--kernel/src/generic/pmm.cpp270
-rw-r--r--kernel/src/generic/pmm.hpp66
-rw-r--r--kernel/src/generic/time.cpp36
-rw-r--r--kernel/src/generic/time.hpp27
-rw-r--r--kernel/src/generic/vfs/devfs.cpp1019
-rw-r--r--kernel/src/generic/vfs/evdev.cpp304
-rw-r--r--kernel/src/generic/vfs/tmpfs.cpp1065
-rw-r--r--kernel/src/generic/vfs/ustar.cpp177
-rw-r--r--kernel/src/generic/vfs/vfs.cpp922
-rw-r--r--kernel/src/klibc/c/assert.h2
-rw-r--r--kernel/src/klibc/c/stdlib.h32
-rw-r--r--kernel/src/klibc/c/string.h3
-rw-r--r--kernel/src/klibc/stdio.cpp34
-rw-r--r--kernel/src/klibc/stdio.hpp18
-rw-r--r--kernel/src/klibc/stdlib.cpp14
-rw-r--r--kernel/src/klibc/stdlib.hpp7
-rw-r--r--kernel/src/klibc/string.cpp62
-rw-r--r--kernel/src/klibc/string.hpp10
-rw-r--r--kernel/src/lib/Flanterm/.gitignore2
-rw-r--r--kernel/src/lib/Flanterm/LICENSE22
-rw-r--r--kernel/src/lib/Flanterm/README.md43
-rw-r--r--kernel/src/lib/Flanterm/src/flanterm.c1424
-rw-r--r--kernel/src/lib/Flanterm/src/flanterm.h80
-rw-r--r--kernel/src/lib/Flanterm/src/flanterm_backends/fb.c1254
-rw-r--r--kernel/src/lib/Flanterm/src/flanterm_backends/fb.h68
-rw-r--r--kernel/src/lib/Flanterm/src/flanterm_backends/fb_private.h121
-rw-r--r--kernel/src/lib/Flanterm/src/flanterm_private.h123
m---------kernel/src/lib/uACPI0
-rw-r--r--kernel/src/main.asm22
-rw-r--r--kernel/src/main.cpp302
-rw-r--r--kernel/src/utils/align.hpp2
-rw-r--r--kernel/src/utils/assembly.hpp0
-rw-r--r--kernel/src/utils/bitmap.hpp37
-rw-r--r--kernel/src/utils/cxx/cxx_constructors.cpp12
-rw-r--r--kernel/src/utils/cxx/cxx_constructors.hpp6
-rw-r--r--kernel/src/utils/cxx/cxx_stuff.cpp (renamed from kernel/src/etc/etc.cpp)51
-rw-r--r--kernel/src/utils/flanterm.cpp638
-rw-r--r--kernel/src/utils/flanterm.hpp11
-rw-r--r--kernel/src/utils/gobject.hpp6
-rw-r--r--kernel/src/utils/hash/hash.hpp8
107 files changed, 3473 insertions, 18304 deletions
diff --git a/kernel/src/arch/aarch64/aarch64.cpp b/kernel/src/arch/aarch64/aarch64.cpp
new file mode 100644
index 0000000..25486dd
--- /dev/null
+++ b/kernel/src/arch/aarch64/aarch64.cpp
@@ -0,0 +1,54 @@
+
+#include <cstdint>
+#include <generic/arch.hpp>
+
+namespace arch {
+ [[gnu::weak]] void disable_interrupts() {
+ asm volatile("msr daifset, #2");
+ }
+
+ [[gnu::weak]] void enable_interrupts() {
+ asm volatile("msr daifclr, #2");
+ }
+
+ [[gnu::weak]] void wait_for_interrupt() {
+ asm volatile("wfi");
+ }
+
+ [[gnu::weak]] void hcf() {
+ disable_interrupts();
+ while(true) {
+ wait_for_interrupt();
+ }
+ }
+
+ [[gnu::weak]] void tlb_flush(std::uintptr_t hint, std::uintptr_t len) {
+ if (len / PAGE_SIZE > 256 || len == 0) {
+ asm volatile("tlbi alle1\n" "dsb ish\n" "isb\n" : : : "memory");
+ } else {
+ for (std::uintptr_t i = 0; i < len; i += PAGE_SIZE) {
+ std::uintptr_t addr = hint + i;
+ asm volatile("tlbi vae1, %0\n" : : "r"(addr) : "memory");
+ }
+
+ asm volatile("dsb ish\n" "isb\n" : : : "memory");
+ }
+ }
+
+ [[gnu::weak]] void pause() {
+ asm volatile("isb");
+ }
+
+ [[gnu::weak]] const char* name() {
+ return "aarch64";
+ }
+
+ [[gnu::weak]] int level_paging() {
+ return 4;
+ }
+
+ [[gnu::weak]] void init(int stage) {
+ (void)stage;
+ }
+
+} \ No newline at end of file
diff --git a/kernel/src/arch/aarch64/paging.cpp b/kernel/src/arch/aarch64/paging.cpp
new file mode 100644
index 0000000..69ecd4b
--- /dev/null
+++ b/kernel/src/arch/aarch64/paging.cpp
@@ -0,0 +1,148 @@
+#include <cstdint>
+#include <generic/arch.hpp>
+#include <generic/bootloader/bootloader.hpp>
+#include <generic/hhdm.hpp>
+#include <generic/pmm.hpp>
+#include <utils/gobject.hpp>
+
+#define PTE_MASK_VALUE 0x0000fffffffff000
+#define PTE_PRESENT (1 << 0)
+#define PTE_RW (0)
+#define PTE_AF (1 << 10)
+#define PTE_4K (1 << 1)
+#define PTE_USER (1 << 6)
+#define PTE_WC (1 << 2)
+#define LVL_PG_MASK PTE_MASK_VALUE
+
+int level_to_index(std::uintptr_t virt, int level) {
+ switch (level) {
+ case 0: return PTE_INDEX(virt, 39);
+ case 1: return PTE_INDEX(virt, 30);
+ case 2: return PTE_INDEX(virt, 21);
+ case 3: return PTE_INDEX(virt, 12);
+ default: return 0;
+ }
+ return 0;
+}
+
+int64_t* __paging_next_level_noalloc(std::uint64_t* table, std::uint16_t idx) {
+ if (!(table[idx] & PTE_PRESENT))
+ return (int64_t*) -1;
+ return (int64_t*) ((table[idx] & LVL_PG_MASK) + etc::hhdm());
+}
+
+std::int64_t __memory_paging_getphys(std::uint64_t* table, std::uint64_t virt, int level) {
+ if (!table && (std::int64_t) table == -1)
+ return -1;
+ int max_level = bootloader::bootloader->is_5_level_paging() ? 4 : 3;
+ if (max_level == level) {
+ return (table[level_to_index(virt, level)] & PTE_PRESENT) ? table[level_to_index(virt, level)] & LVL_PG_MASK : -1;
+ } else
+ return __memory_paging_getphys((std::uint64_t*) __paging_next_level_noalloc(table, level_to_index(virt, level)), virt, level + 1);
+ return -1;
+}
+
+uint64_t* aarch64_paging_next_level(std::uint64_t* table, std::uint16_t idx, std::uint64_t flags) {
+ if (!(table[idx] & PTE_PRESENT))
+ table[idx] = pmm::freelist::alloc_4k() | flags;
+ return (uint64_t*) ((table[idx] & LVL_PG_MASK) + etc::hhdm());
+}
+
+std::uint64_t convert_flags(std::uint64_t flags) {
+ std::uint64_t result = 0;
+ if (flags & PAGING_NC)
+ result |= 0;
+ if (flags & PAGING_PRESENT)
+ result |= PTE_PRESENT | PTE_AF;
+ if (flags & PAGING_RW)
+ result |= PTE_RW;
+ if (flags & PAGING_USER)
+ result |= PTE_USER;
+ if (flags & PAGING_WC)
+ result |= PTE_WC;
+ return result;
+}
+
+void aarch64_map_page(std::uintptr_t root, std::uintptr_t phys, std::uintptr_t virt, std::uint32_t flags) {
+ std::uint64_t* cr30 = (std::uint64_t*) (root + etc::hhdm());
+ std::uint64_t new_flags = PTE_PRESENT | PTE_RW | PTE_4K;
+ if (PTE_INDEX(virt, 39) < 256)
+ new_flags |= PTE_USER;
+ uint64_t* pml3 = aarch64_paging_next_level(cr30, PTE_INDEX(virt, 39), new_flags);
+ uint64_t* pml2 = aarch64_paging_next_level(pml3, PTE_INDEX(virt, 30), new_flags);
+ uint64_t* pml = aarch64_paging_next_level(pml2, PTE_INDEX(virt, 21), new_flags);
+ pml[PTE_INDEX(virt, 12)] = phys | flags | PTE_4K;
+}
+
+
+namespace arch {
+ [[gnu::weak]] void enable_paging(std::uintptr_t root) {
+ asm volatile("msr ttbr0_el1, %0" : : "r"(root) : "memory");
+ if (root == gobject::kernel_root) {
+ asm volatile("msr ttbr1_el1, %0" : : "r"(root) : "memory");
+ asm volatile("dsb ish; tlbi vmalle1; dsb ish; isb" : : : "memory");
+ } else {
+ asm volatile("dsb ish; tlbi vmalle1; dsb ish; isb" : : : "memory");
+ }
+ }
+
+
+ [[gnu::weak]] void map_page(std::uintptr_t root, std::uint64_t phys, std::uintptr_t virt, int flags) {
+ aarch64_map_page(root,phys,virt,convert_flags(flags));
+ }
+
+ [[gnu::weak]] std::uint64_t get_phys_from_page(std::uintptr_t root, std::uintptr_t virt) {
+ return __memory_paging_getphys((std::uint64_t*)(root + etc::hhdm()),virt,0);
+ }
+
+ [[gnu::weak]] void destroy_root(std::uintptr_t root, int level) {
+ std::uint64_t* table = (std::uint64_t*) (root + etc::hhdm());
+ if (bootloader::bootloader->is_5_level_paging()) {
+ if (level != 4) {
+ if (level == 0) {
+ for (int i = 0; i < 256; i++) {
+ if (table[i] & PTE_PRESENT) {
+ destroy_root(table[i] & PTE_MASK_VALUE, level + 1);
+ }
+ }
+ } else {
+ for (int i = 0; i < 512; i++) {
+ if (table[i] & PTE_PRESENT) {
+ destroy_root(table[i] & PTE_MASK_VALUE, level + 1);
+ }
+ }
+ }
+ }
+
+ if (level != 0)
+ pmm::freelist::free(root);
+ } else {
+ if (level != 3) {
+ if (level == 0) {
+ for (int i = 0; i < 256; i++) {
+ if (table[i] & PTE_PRESENT) {
+ destroy_root(table[i] & PTE_MASK_VALUE, level + 1);
+ }
+ }
+ } else {
+ for (int i = 0; i < 512; i++) {
+ if (table[i] & PTE_PRESENT) {
+ destroy_root(table[i] & PTE_MASK_VALUE, level + 1);
+ }
+ }
+ }
+ }
+
+ if (level != 0)
+ pmm::freelist::free(root);
+ }
+ }
+
+ [[gnu::weak]] void copy_higher_half(std::uintptr_t root, std::uintptr_t src_root) {
+ std::uint64_t* virt_rootcr3 = (std::uint64_t*) (root + etc::hhdm());
+ std::uint64_t* virt_srccr3 = (std::uint64_t*) (src_root + etc::hhdm());
+ for (int i = 255; i < 512; i++) {
+ virt_rootcr3[i] = virt_srccr3[i];
+ }
+ }
+}; \ No newline at end of file
diff --git a/kernel/src/arch/riscv64/features.hpp b/kernel/src/arch/riscv64/features.hpp
new file mode 100644
index 0000000..7da036a
--- /dev/null
+++ b/kernel/src/arch/riscv64/features.hpp
@@ -0,0 +1,33 @@
+#pragma once
+
+#include <klibc/stdio.hpp>
+#include <cstdint>
+
+namespace riscv64 {
+
+#define SATP64_MODE 0xF000000000000000
+#define PAGING_3LEVEL 8
+#define PAGING_4LEVEL 9
+#define PAGING_5LEVEL 10
+
+ inline int level_paging = 0;
+ inline int raw_level_paging = 0;
+
+ static inline int get_paging_level() {
+ if (level_paging == 0) {
+ std::uint64_t satp_value = 0;
+ asm volatile("csrr %0, satp" : "=r"(satp_value));
+ std::uint64_t current_mode = (satp_value & SATP64_MODE) >> 60;
+
+ raw_level_paging = current_mode;
+
+ switch (current_mode) {
+ case PAGING_3LEVEL: riscv64::level_paging = 3; break;
+ case PAGING_4LEVEL: riscv64::level_paging = 4; break;
+ case PAGING_5LEVEL: riscv64::level_paging = 5; break;
+ default: klibc::printf("Unsupported level paging for riscv64 ! (%d)\n", current_mode); return 0;
+ };
+ }
+ return riscv64::level_paging;
+ }
+}; // namespace riscv64
diff --git a/kernel/src/arch/riscv64/paging.cpp b/kernel/src/arch/riscv64/paging.cpp
new file mode 100644
index 0000000..bea9c5c
--- /dev/null
+++ b/kernel/src/arch/riscv64/paging.cpp
@@ -0,0 +1,163 @@
+#include <cstdint>
+#include <generic/arch.hpp>
+#include <generic/bootloader/bootloader.hpp>
+#include <generic/hhdm.hpp>
+#include <generic/pmm.hpp>
+#include <arch/riscv64/features.hpp>
+
+#define PTE_MASK_VALUE (0x003ffffffffffc00)
+#define PTE_PRESENT (1 << 0)
+#define PTE_RW ((1 << 1) | (1 << 2) | (1 << 3))
+#define PTE_USER (1 << 4)
+#define PTE_WC (0)
+#define PTE_MMIO (0)
+#define PTE_ACCESSED (1 << 6)
+#define PTE_DIRTY (1 << 7)
+#define LVL_PG_MASK PTE_MASK_VALUE
+
+
+int level_to_index(std::uintptr_t virt, int level) {
+ if (riscv64::get_paging_level() == 5) {
+ switch (level) {
+ case 0: return PTE_INDEX(virt, 48);
+ case 1: return PTE_INDEX(virt, 39);
+ case 2: return PTE_INDEX(virt, 30);
+ case 3: return PTE_INDEX(virt, 21);
+ case 4: return PTE_INDEX(virt, 12);
+ default: return 0;
+ }
+ } else if (riscv64::get_paging_level() == 4) {
+ switch (level) {
+ case 0: return PTE_INDEX(virt, 39);
+ case 1: return PTE_INDEX(virt, 30);
+ case 2: return PTE_INDEX(virt, 21);
+ case 3: return PTE_INDEX(virt, 12);
+ default: return 0;
+ }
+ } else if (riscv64::get_paging_level() == 3) {
+ switch (level) {
+ case 0: return PTE_INDEX(virt, 30);
+ case 1: return PTE_INDEX(virt, 21);
+ case 2: return PTE_INDEX(virt, 12);
+ default: return 0;
+ }
+ }
+ return 0;
+}
+
+std::uint64_t extract_ppn(std::uint64_t masked_table) {
+ return masked_table >> 10;
+}
+
+std::uint64_t make_pte(std::uint64_t ppn) {
+ return ppn << 10;
+}
+
+int64_t* __paging_next_level_noalloc(std::uint64_t* table, std::uint16_t idx) {
+ if (!(table[idx] & PTE_PRESENT))
+ return (int64_t*) -1;
+ return (int64_t*)((extract_ppn(table[idx] & PTE_MASK_VALUE) << 12) + etc::hhdm());
+}
+
+
+std::int64_t __memory_paging_getphys(std::uint64_t* table, std::uint64_t virt, int level) {
+ if (!table && (std::int64_t) table == -1)
+ return -1;
+ int max_level = riscv64::get_paging_level() - 1;
+ if (max_level == level) {
+ return (table[level_to_index(virt, level)] & PTE_PRESENT) ? (extract_ppn(table[level_to_index(virt, level)] & LVL_PG_MASK) << 12) : -1;
+ } else
+ return __memory_paging_getphys((std::uint64_t*) __paging_next_level_noalloc(table, level_to_index(virt, level)), virt, level + 1);
+ return -1;
+}
+
+uint64_t* riscv64_paging_next_level(std::uint64_t* table, std::uint16_t idx) {
+ if (!(table[idx] & PTE_PRESENT))
+ table[idx] = (make_pte(pmm::freelist::alloc_4k() >> 12)) | PTE_PRESENT;
+ return (uint64_t*) ((extract_ppn(table[idx] & PTE_MASK_VALUE) << 12) + etc::hhdm());
+}
+
+std::uint64_t convert_flags(std::uint64_t flags) {
+ std::uint64_t result = 0;
+ if (flags & PAGING_NC)
+ result |= PTE_MMIO;
+ if (flags & PAGING_PRESENT)
+ result |= PTE_PRESENT;
+ if (flags & PAGING_RW)
+ result |= PTE_RW;
+ if (flags & PAGING_USER)
+ result |= PTE_USER;
+ if (flags & PAGING_WC)
+ result |= PTE_WC;
+ result |= PTE_ACCESSED | PTE_DIRTY;
+ return result;
+}
+
+
+void riscv64_map_page(std::uintptr_t root, std::uint64_t phys, std::uintptr_t virt, std::uint32_t flags) {
+ if (riscv64::get_paging_level() == 4) {
+ std::uint64_t* l_root = (std::uint64_t*) (root + etc::hhdm());
+ uint64_t* l1 = riscv64_paging_next_level(l_root, PTE_INDEX(virt, 39));
+ uint64_t* l2 = riscv64_paging_next_level(l1, PTE_INDEX(virt, 30));
+ uint64_t* l3 = riscv64_paging_next_level(l2, PTE_INDEX(virt, 21));
+ l3[PTE_INDEX(virt, 12)] = (make_pte(phys >> 12)) | flags;
+ } else if (riscv64::get_paging_level() == 3) {
+ std::uint64_t* l_root = (std::uint64_t*) (root + etc::hhdm());
+ uint64_t* l2 = riscv64_paging_next_level(l_root, PTE_INDEX(virt, 30));
+ uint64_t* l3 = riscv64_paging_next_level(l2, PTE_INDEX(virt, 21));
+ l3[PTE_INDEX(virt, 12)] = (make_pte(phys >> 12)) | flags;
+ } else if (riscv64::get_paging_level() == 5) {
+ std::uint64_t* l_root = (std::uint64_t*) (root + etc::hhdm());
+ uint64_t* l0 = riscv64_paging_next_level(l_root, PTE_INDEX(virt, 48));
+ uint64_t* l1 = riscv64_paging_next_level(l0, PTE_INDEX(virt, 39));
+ uint64_t* l2 = riscv64_paging_next_level(l1, PTE_INDEX(virt, 30));
+ uint64_t* l3 = riscv64_paging_next_level(l2, PTE_INDEX(virt, 21));
+ l3[PTE_INDEX(virt, 12)] = (make_pte(phys >> 12)) | flags;
+ }
+}
+
+namespace arch {
+ [[gnu::weak]] void enable_paging(std::uintptr_t root) {
+ std::uint64_t mode_root = (root >> 12) | ((std::uint64_t) riscv64::raw_level_paging << 60);
+ asm volatile("csrw satp, %0" : : "r"(mode_root) : "memory");
+ asm volatile("sfence.vma");
+ }
+
+ [[gnu::weak]] void map_page(std::uintptr_t root, std::uint64_t phys, std::uintptr_t virt, int flags) {
+ riscv64_map_page(root,phys,virt,convert_flags(flags));
+ }
+
+ [[gnu::weak]] std::uint64_t get_phys_from_page(std::uintptr_t root, std::uintptr_t virt) {
+ return __memory_paging_getphys((std::uint64_t*)(root + etc::hhdm()),virt,0);
+ }
+
+ [[gnu::weak]] void destroy_root(std::uintptr_t root, int level) {
+ std::uint64_t* table = (std::uint64_t*) (root + etc::hhdm());
+ if (level != riscv64::get_paging_level() - 1) {
+ if (level == 0) {
+ for (int i = 0; i < 256; i++) {
+ if (table[i] & PTE_PRESENT) {
+ destroy_root(table[i] & PTE_MASK_VALUE, level + 1);
+ }
+ }
+ } else {
+ for (int i = 0; i < 512; i++) {
+ if (table[i] & PTE_PRESENT) {
+ destroy_root(table[i] & PTE_MASK_VALUE, level + 1);
+ }
+ }
+ }
+
+ if (level != 0)
+ pmm::freelist::free(root);
+ }
+ }
+
+ [[gnu::weak]] void copy_higher_half(std::uintptr_t root, std::uintptr_t src_root) {
+ std::uint64_t* virt_rootcr3 = (std::uint64_t*) (root + etc::hhdm());
+ std::uint64_t* virt_srccr3 = (std::uint64_t*) (src_root + etc::hhdm());
+ for (int i = 255; i < 512; i++) {
+ virt_rootcr3[i] = virt_srccr3[i];
+ }
+ }
+}; \ No newline at end of file
diff --git a/kernel/src/arch/riscv64/riscv64.cpp b/kernel/src/arch/riscv64/riscv64.cpp
new file mode 100644
index 0000000..2db83bf
--- /dev/null
+++ b/kernel/src/arch/riscv64/riscv64.cpp
@@ -0,0 +1,56 @@
+
+#include <cstdint>
+#include <generic/arch.hpp>
+#include <arch/riscv64/features.hpp>
+
+namespace arch {
+ [[gnu::weak]] void disable_interrupts() {
+ asm volatile("csrc sstatus, %0" : : "r"(1 << 1));
+ }
+
+ [[gnu::weak]] void enable_interrupts() {
+ asm volatile("csrs sstatus, %0" : : "r"(1 << 1));
+ }
+
+ [[gnu::weak]] void wait_for_interrupt() {
+ asm volatile("wfi");
+ }
+
+ [[gnu::weak]] void hcf() {
+ disable_interrupts();
+ while(true) {
+ wait_for_interrupt();
+ }
+ }
+
+ [[gnu::weak]] void pause() {
+#ifdef __riscv_zihintpause
+ asm volatile("pause");
+#else
+ asm volatile("nop");
+#endif
+ }
+
+ [[gnu::weak]] void tlb_flush(std::uintptr_t hint, std::uintptr_t len) {
+ if (len / PAGE_SIZE > 256 || len == 0) {
+ asm volatile("sfence.vma");
+ } else {
+ for (std::uintptr_t i = 0; i < len; i += PAGE_SIZE) {
+ asm volatile("sfence.vma %0" : : "r"(hint + i) : "memory");
+ }
+ }
+ }
+
+ [[gnu::weak]] const char* name() {
+ return "riscv64";
+ }
+
+ [[gnu::weak]] int level_paging() {
+ return riscv64::get_paging_level();
+ }
+
+ [[gnu::weak]] void init(int stage) {
+ (void)stage;
+ }
+
+} \ No newline at end of file
diff --git a/kernel/src/arch/x86_64/asm/scheduling.asm b/kernel/src/arch/x86_64/asm/scheduling.asm
deleted file mode 100644
index 2e67154..0000000
--- a/kernel/src/arch/x86_64/asm/scheduling.asm
+++ /dev/null
@@ -1,121 +0,0 @@
-
-extern schedulingSchedule
-global schedulingEnter
-global schedulingEnd
-global yield
-
-yield:
- pop rax
- mov rdx, rsp
- mov rsp,[gs:16]
- push qword 0
- push rdx
- pushfq
- push qword 0x08
- push qword rax
- jmp schedulingEnter
-
-global yield0
-
-yield0:
- sti
- pause
- cli
- pop rax
- mov rdx, rsp
- mov rsp,[gs:16]
- push qword 0
- push rdx
- pushfq
- push qword 0x08
- push qword rax
- jmp schedulingEnter
-
-
-schedulingEnter:
- cli
- push qword 0
- push qword 0
- push r15
- push r14
- push r13
- push r12
- push r11
- push r10
- push r9
- push r8
- push rbp
- push rdi
- push rsi
- push rdx
- push rcx
- push rbx
- push rax
- mov rax,cr3
- push rax
- mov rdi,rsp
- jmp schedulingSchedule
-
-global schedulingScheduleSaveAndChangeStack
-schedulingScheduleSaveAndChangeStack:
- cli
- mov rsi,rsp
- pop rdx
- mov rsp,rdi
-
- push 0x10
- push rsi
- pushfq
- push 0x08
- push rdx
-
- push qword 0
- push qword 0
- push r15
- push r14
- push r13
- push r12
- push r11
- push r10
- push r9
- push r8
- push rbp
- push rdi
- push rsi
- push rdx
- push rcx
- push rbx
- push rax
- mov rax,cr3
- push rax
- mov rdi,rsp
- jmp schedulingSchedule
-
-
-global schedulingScheduleAndChangeStack
-schedulingScheduleAndChangeStack:
- mov rsp,rdi
- mov rdi,rsi
- jmp schedulingSchedule
-
-schedulingEnd:
- mov rsp,rdi
- pop rax
- mov cr3,rax
- pop rax
- pop rbx
- pop rcx
- pop rdx
- pop rsi
- pop rdi
- pop rbp
- pop r8
- pop r9
- pop r10
- pop r11
- pop r12
- pop r13
- pop r14
- pop r15
- add rsp,16
- iretq \ No newline at end of file
diff --git a/kernel/src/arch/x86_64/asm/syscall.asm b/kernel/src/arch/x86_64/asm/syscall.asm
deleted file mode 100644
index 34b1058..0000000
--- a/kernel/src/arch/x86_64/asm/syscall.asm
+++ /dev/null
@@ -1,56 +0,0 @@
-
-
-global syscall_handler
-extern syscall_handler_c
-syscall_handler:
- swapgs
- mov qword [gs:0],rsp
- mov rsp, qword [gs:8]
- push qword (0x18 | 3)
- push qword [gs:0]
- push qword r11
- push qword (0x20 | 3)
- push qword rcx
- push qword 0
- push qword 0
- push r15
- push r14
- push r13
- push r12
- push r11
- push r10
- push r9
- push r8
- push rbp
- push rdi
- push rsi
- push rdx
- push rcx
- push rbx
- push rax
- mov rax,cr3
- push rax
- mov rdi,rsp
- call syscall_handler_c
- pop rax
- pop rax
- pop rbx
- pop rcx
- pop rdx
- pop rsi
- pop rdi
- pop rbp
- pop r8
- pop r9
- pop r10
- pop r11
- pop r12
- pop r13
- pop r14
- pop r15
- cli
- mov rsp, qword [gs:0]
- swapgs
- o64 sysret
-
-section .rodata
diff --git a/kernel/src/arch/x86_64/assembly.hpp b/kernel/src/arch/x86_64/assembly.hpp
new file mode 100644
index 0000000..4a9bda4
--- /dev/null
+++ b/kernel/src/arch/x86_64/assembly.hpp
@@ -0,0 +1,30 @@
+#include <cstdint>
+
+namespace assembly {
+ inline std::uint64_t rdmsr(std::uint32_t msr) {
+ std::uint32_t lo, hi;
+ __asm__ volatile ("rdmsr" : "=a"(lo), "=d"(hi) : "c"(msr));
+ return ((std::uint64_t)hi << 32) | lo;
+ }
+
+ inline void wrmsr(std::uint32_t msr, std::uint64_t value) {
+ std::uint32_t lo = (uint32_t)(value & 0xFFFFFFFF);
+ std::uint32_t hi = (uint32_t)(value >> 32);
+ __asm__ volatile ("wrmsr" : : "c"(msr), "a"(lo), "d"(hi));
+ }
+
+ inline void cpuid(int code, int code2, std::uint32_t *a, std::uint32_t *b, std::uint32_t *c , std::uint32_t *d) {
+ __asm__ volatile("cpuid":"=a"(*a),"=b"(*b),"=c"(*c),"=d"(*d):"a"(code),"c"(code2));
+ }
+
+ inline int cpuid_string(int code, std::uint32_t where[4]) {
+ __asm__ volatile("cpuid":"=a"(*where),"=b"(*(where+1)),"=c"(*(where+2)),"=d"(*(where+3)):"a"(code));
+ return (int)where[0];
+ }
+
+ inline std::uint64_t rdtsc() {
+ unsigned int hi, lo;
+ __asm__ volatile ("rdtsc" : "=a"(lo), "=d"(hi));
+ return ((uint64_t)hi << 32) | lo;
+ }
+}; \ No newline at end of file
diff --git a/kernel/src/arch/x86_64/cpu/asm/gdt.asm b/kernel/src/arch/x86_64/cpu/gdt.asm
index 312735f..796e892 100644
--- a/kernel/src/arch/x86_64/cpu/asm/gdt.asm
+++ b/kernel/src/arch/x86_64/cpu/gdt.asm
@@ -1,5 +1,5 @@
-global loadgdt
-loadgdt:
+global load_gdt
+load_gdt:
lgdt [rdi]
mov ax,0
mov ds,ax
@@ -13,8 +13,8 @@ loadgdt:
push rdi
retfq
-global loadtss
-loadtss:
+global load_tss
+load_tss:
mov ax,0x28
ltr ax
ret \ No newline at end of file
diff --git a/kernel/src/arch/x86_64/cpu/gdt.cpp b/kernel/src/arch/x86_64/cpu/gdt.cpp
index b83b166..dd406f2 100644
--- a/kernel/src/arch/x86_64/cpu/gdt.cpp
+++ b/kernel/src/arch/x86_64/cpu/gdt.cpp
@@ -1,14 +1,14 @@
-
#include <cstdint>
-#include <generic/mm/pmm.hpp>
-#include <generic/mm/paging.hpp>
-#include <generic/mm/heap.hpp>
-#include <arch/x86_64/cpu/data.hpp>
+#include <generic/heap.hpp>
#include <arch/x86_64/cpu/gdt.hpp>
-#include <etc/libc.hpp>
-#include <config.hpp>
+#include <generic/pmm.hpp>
+#include <generic/hhdm.hpp>
+#include <klibc/stdio.hpp>
+#include <arch/x86_64/cpu_local.hpp>
+
+#define KERNEL_STACK_SIZE 32 * 1024
-gdt_t original_gdt = {
+x86_64::gdt::gdt_t original_gdt = {
{0,0,0,0,0,0}, /* 0x0 Null */
{0,0,0,0x9a,0xa2,0}, /* 0x08 64 bit code */
{0,0,0,0x92,0xa0,0}, /* just align user data and user code */
@@ -17,36 +17,35 @@ gdt_t original_gdt = {
{0x68,0,0,0x89,0x20,0,0,0} /* 0x28 tss */
};
-void arch::x86_64::cpu::gdt::init() {
- arch::x86_64::cpu::gdt* new_gdt = (arch::x86_64::cpu::gdt*)memory::heap::malloc(sizeof(arch::x86_64::cpu::gdt));
+void x86_64::gdt::init() {
+ gdt_t* new_gdt = new gdt_t;
tss_t* tss = new tss_t;
-
- /* For optimizations kheap doesn't zero memory */
- memset(&new_gdt->gdt_obj,0,sizeof(gdt_t));
- memset(tss,0,sizeof(tss_t));
- memcpy(&new_gdt->gdt_obj,&original_gdt,sizeof(gdt_t));
+ gdt_pointer_t* gdtr = new gdt_pointer_t;
+ klibc::memcpy(new_gdt,&original_gdt,sizeof(gdt_t));
- tss->rsp[0] = memory::pmm::helper::alloc_kernel_stack(KERNEL_STACK_SIZE);
- tss->ist[0] = memory::pmm::helper::alloc_kernel_stack(KERNEL_STACK_SIZE); /* Exceptions */
- tss->ist[1] = memory::pmm::helper::alloc_kernel_stack(KERNEL_STACK_SIZE); /* Timer */
- tss->ist[2] = memory::pmm::helper::alloc_kernel_stack(KERNEL_STACK_SIZE); /* IRQ Layout */
- tss->ist[3] = memory::pmm::helper::alloc_kernel_stack(KERNEL_STACK_SIZE); /* For ignorestub */
+ tss->rsp[0] = (std::uint64_t)(pmm::buddy::alloc(KERNEL_STACK_SIZE).phys + etc::hhdm());
+ tss->ist[0] = (std::uint64_t)(pmm::buddy::alloc(KERNEL_STACK_SIZE).phys + etc::hhdm()); /* Exceptions */
+ tss->ist[1] = (std::uint64_t)(pmm::buddy::alloc(KERNEL_STACK_SIZE).phys + etc::hhdm()); /* Timer */
+ tss->ist[2] = (std::uint64_t)(pmm::buddy::alloc(KERNEL_STACK_SIZE).phys + etc::hhdm()); /* IRQ Layout */
+ tss->ist[3] = (std::uint64_t)(pmm::buddy::alloc(KERNEL_STACK_SIZE).phys + etc::hhdm()); /* For ignorestub */
tss->iopb_offsset = sizeof(tss_t);
- new_gdt->gdt_obj.tss.baselow16 = (std::uint64_t)tss & 0xFFFF;
- new_gdt->gdt_obj.tss.basemid8 = ((std::uint64_t)tss >> 16) & 0xFF;
- new_gdt->gdt_obj.tss.basehigh8 = ((std::uint64_t)tss >> 24) & 0xFF;
- new_gdt->gdt_obj.tss.baseup32 = (std::uint64_t)tss >> 32;
+ new_gdt->tss.baselow16 = (std::uint64_t)tss & 0xFFFF;
+ new_gdt->tss.basemid8 = ((std::uint64_t)tss >> 16) & 0xFF;
+ new_gdt->tss.basehigh8 = ((std::uint64_t)tss >> 24) & 0xFF;
+ new_gdt->tss.baseup32 = (std::uint64_t)tss >> 32;
+
+ gdtr->size = sizeof(gdt_t) - 1;
+ gdtr->base = (std::uint64_t)new_gdt;
- new_gdt->gdtr.size = sizeof(gdt_t) - 1;
- new_gdt->gdtr.base = (std::uint64_t)&new_gdt->gdt_obj;
+ load_gdt(gdtr);
+ load_tss();
- new_gdt->LoadGDT();
- new_gdt->LoadTSS();
+ x86_64::restore_cpu_data();
+ auto cpudata = x86_64::cpu_data();
+ cpudata->timer_ist_stack = (std::uint64_t)(pmm::buddy::alloc(KERNEL_STACK_SIZE).phys + etc::hhdm());
- /* Also i want to init cpu data too */
- auto cpudata = arch::x86_64::cpu::data();
- cpudata->timer_ist_stack = memory::pmm::helper::alloc_kernel_stack(KERNEL_STACK_SIZE);
+ klibc::printf("GDT: tss->rsp0 0x%p tss->ist0 0x%p\r\n",tss->rsp[0],tss->ist[0],tss->ist[1],tss->ist[2],tss->ist[3],cpudata->timer_ist_stack);
} \ No newline at end of file
diff --git a/kernel/src/arch/x86_64/cpu/gdt.hpp b/kernel/src/arch/x86_64/cpu/gdt.hpp
new file mode 100644
index 0000000..c71609e
--- /dev/null
+++ b/kernel/src/arch/x86_64/cpu/gdt.hpp
@@ -0,0 +1,56 @@
+#pragma once
+#include <cstdint>
+
+namespace x86_64 {
+ namespace gdt {
+
+ typedef struct __attribute__((packed)) {
+ std::uint16_t size;
+ std::uint64_t base;
+ } gdt_pointer_t;
+
+ typedef struct __attribute__((packed)) {
+ std::uint16_t limit;
+ std::uint16_t baselow16;
+ std::uint8_t basemid8;
+ std::uint8_t access;
+ std::uint8_t granularity;
+ std::uint8_t basehigh8;
+ } gdt_entry_t;
+
+ typedef struct __attribute__((packed)) {
+ std::uint16_t length;
+ std::uint16_t baselow16;
+ std::uint8_t basemid8;
+ std::uint8_t flags0;
+ std::uint8_t flags1;
+ std::uint8_t basehigh8;
+ std::uint32_t baseup32;
+ std::uint32_t reserved;
+ } tss_entry_t;
+
+ typedef struct __attribute__((packed)) {
+ std::uint32_t reserved0;
+ std::uint64_t rsp[3];
+ std::uint64_t reserved1;
+ std::uint64_t ist[7];
+ std::uint32_t reserved2;
+ std::uint32_t reserved3;
+ std::uint16_t reserved4;
+ std::uint16_t iopb_offsset;
+ } tss_t;
+
+ typedef struct __attribute__((packed)) {
+ gdt_entry_t zero;
+ gdt_entry_t _64bitcode;
+ gdt_entry_t _64bitdata;
+ gdt_entry_t usercode;
+ gdt_entry_t userdata;
+ tss_entry_t tss;
+ } gdt_t;
+
+ extern "C" void load_gdt(void* gdtr);
+ extern "C" void load_tss();
+ void init();
+ }
+}; \ No newline at end of file
diff --git a/kernel/src/arch/x86_64/interrupts/asm/idt.asm b/kernel/src/arch/x86_64/cpu/idt.asm
index deb0164..78bed7e 100644
--- a/kernel/src/arch/x86_64/interrupts/asm/idt.asm
+++ b/kernel/src/arch/x86_64/cpu/idt.asm
@@ -194,7 +194,7 @@ irqStub:
push rax
mov rdi,rsp
xor rbp,rbp
- call irqHandler
+ nop
pop rax
mov cr3,rax
pop rax
diff --git a/kernel/src/arch/x86_64/interrupts/idt.cpp b/kernel/src/arch/x86_64/cpu/idt.cpp
index 12fff62..f1765ce 100644
--- a/kernel/src/arch/x86_64/interrupts/idt.cpp
+++ b/kernel/src/arch/x86_64/cpu/idt.cpp
@@ -1,28 +1,22 @@
#include <cstdint>
-#include <arch/x86_64/interrupts/idt.hpp>
-#include <arch/x86_64/cpu/lapic.hpp>
-#include <etc/libc.hpp>
-#include <etc/list.hpp>
+#include <arch/x86_64/cpu/idt.hpp>
+#include <utils/bitmap.hpp>
+#include <klibc/stdio.hpp>
-#include <etc/logging.hpp>
-
-using namespace Lists;
-using namespace arch::x86_64::interrupts;
-
-idt_entry_t idt_entries[255];
-Bitmap* idt_bitmap;
-idtr_t idtr;
+x86_64::idt::idt_entry_t idt_entries[255];
+utils::bitmap* idt_bitmap;
+x86_64::idt::idtr_t idtr;
extern "C" void* isrTable[];
extern "C" void ignoreStubC() {
- arch::x86_64::cpu::lapic::eoi();
+
}
-void arch::x86_64::interrupts::idt::init() {
- memset(idt_entries,0,sizeof(idt_entries));
- idt_bitmap = new Bitmap(255);
+void x86_64::idt::init() {
+ klibc::memset(idt_entries,0,sizeof(idt_entries));
+ idt_bitmap = new utils::bitmap(255);
idtr.base = (std::uint64_t)idt_entries;
idtr.limit = (std::uint16_t)sizeof(idt_entry_t) * 256 - 1;
@@ -40,11 +34,11 @@ void arch::x86_64::interrupts::idt::init() {
load();
}
-void arch::x86_64::interrupts::idt::load() {
+void x86_64::idt::load() {
__asm__ volatile ("lidt %0" : : "m"(idtr));
}
-void arch::x86_64::interrupts::idt::set_entry(std::uint64_t base,std::uint8_t vec,std::uint8_t flags,std::uint8_t ist) {
+void x86_64::idt::set_entry(std::uint64_t base,std::uint8_t vec,std::uint8_t flags,std::uint8_t ist) {
idt_entry_t* descriptor = &idt_entries[vec];
descriptor->low = (std::uint64_t)base & 0xFFFF;
@@ -59,7 +53,7 @@ void arch::x86_64::interrupts::idt::set_entry(std::uint64_t base,std::uint8_t ve
}
-std::uint8_t arch::x86_64::interrupts::idt::alloc() {
+std::uint8_t x86_64::idt::alloc() {
for(int i = 0;i < 255;i++) {
if(!idt_bitmap->test(i)) {
idt_bitmap->set(i);
diff --git a/kernel/src/arch/x86_64/cpu/idt.hpp b/kernel/src/arch/x86_64/cpu/idt.hpp
new file mode 100644
index 0000000..f386e86
--- /dev/null
+++ b/kernel/src/arch/x86_64/cpu/idt.hpp
@@ -0,0 +1,56 @@
+#pragma once
+#include <cstdint>
+
+namespace x86_64 {
+ namespace idt {
+ typedef struct {
+ std::uint16_t low;
+ std::uint16_t cs;
+ std::uint8_t ist;
+ std::uint8_t attr;
+ std::uint16_t mid;
+ std::uint32_t high;
+ std::uint32_t reserved0;
+ } __attribute__((packed)) idt_entry_t;
+
+ typedef struct {
+ std::uint16_t limit;
+ std::uint64_t base;
+ } __attribute__((packed)) idtr_t;
+
+ typedef struct {
+ std::uint64_t cr3;
+ std::uint64_t rax;
+ std::uint64_t rbx;
+ std::uint64_t rcx;
+ std::uint64_t rdx;
+ std::uint64_t rsi;
+ std::uint64_t rdi;
+ std::uint64_t rbp;
+ std::uint64_t r8;
+ std::uint64_t r9;
+ std::uint64_t r10;
+ std::uint64_t r11;
+ std::uint64_t r12;
+ std::uint64_t r13;
+ std::uint64_t r14;
+ std::uint64_t r15;
+ std::uint64_t vec;
+ std::uint64_t err_code;
+ std::uint64_t rip;
+ std::uint64_t cs;
+ std::uint64_t rflags;
+ std::uint64_t rsp;
+ std::uint64_t ss;
+ } int_frame_t;
+
+
+ extern "C" void ignoreStub();
+
+ void init();
+ void set_entry(std::uint64_t base,std::uint8_t vec,std::uint8_t flags,std::uint8_t ist);
+ std::uint8_t alloc();
+ void load();
+
+ };
+}; \ No newline at end of file
diff --git a/kernel/src/arch/x86_64/cpu/smp.cpp b/kernel/src/arch/x86_64/cpu/smp.cpp
deleted file mode 100644
index a06f4c5..0000000
--- a/kernel/src/arch/x86_64/cpu/smp.cpp
+++ /dev/null
@@ -1,88 +0,0 @@
-
-#include <cstdint>
-
-#include <arch/x86_64/cpu/smp.hpp>
-#include <generic/time.hpp>
-
-#include <arch/x86_64/cpu/data.hpp>
-
-#include <arch/x86_64/cpu/gdt.hpp>
-#include <arch/x86_64/cpu/lapic.hpp>
-#include <arch/x86_64/interrupts/idt.hpp>
-#include <generic/mm/paging.hpp>
-
-#include <generic/locks/spinlock.hpp>
-#include <etc/bootloaderinfo.hpp>
-
-#include <drivers/tsc.hpp>
-
-#include <arch/x86_64/syscalls/syscalls.hpp>
-
-#include <arch/x86_64/cpu/sse.hpp>
-
-#include <etc/logging.hpp>
-
-#include <etc/libc.hpp>
-
-#include <limine.h>
-
-#include <drivers/io.hpp>
-
-#include <atomic>
-
-using namespace arch::x86_64::cpu;
-
-int balance_how_much_cpus = 1;
-
-int how_much_cpus = 1;
-std::atomic<int> temp_how_much_cpus[12];
-
-locks::spinlock mp_lock;
-
-void mp::sync(std::uint8_t id) {
- if(how_much_cpus != 1) {
- temp_how_much_cpus[id].fetch_add(1, std::memory_order_acq_rel);
- while (how_much_cpus != temp_how_much_cpus[id].load(std::memory_order_acquire)) {
- asm volatile("nop");
- }
- time::sleep(1000*1000); // perform 1 second sleep
- temp_how_much_cpus[id].store(0, std::memory_order_release);
- }
-}
-
-void __mp_bootstrap(struct LIMINE_MP(info)* smp_info) {
- mp_lock.lock();
- memory::paging::enablekernel();
- arch::x86_64::interrupts::idt::load();
- arch::x86_64::cpu::gdt::init();
- drivers::tsc::init();
-
- arch::x86_64::cpu::data()->smp.cpu_id = balance_how_much_cpus++;
-
- arch::x86_64::cpu::data()->lapic_block = arch::x86_64::cpu::lapic::init(15000);
- arch::x86_64::cpu::sse::init();
- arch::x86_64::syscall::init();
- Log::Display(LEVEL_MESSAGE_OK,"Cpu %d is online \n",arch::x86_64::cpu::data()->smp.cpu_id);
- arch::x86_64::cpu::lapic::tick(arch::x86_64::cpu::data()->lapic_block);
- mp_lock.unlock();
- setwp();
- mp::sync(0);
- mp::sync(1);
- asm volatile("sti");
- while(1) {
- asm volatile("hlt");
- }
-}
-
-void mp::init() {
- struct LIMINE_MP(response)* mp_info = BootloaderInfo::AccessMP();
-
- how_much_cpus = mp_info->cpu_count;
-
- memset(temp_how_much_cpus,0,4*12);
- for(std::uint16_t i = 0;i < mp_info->cpu_count;i++) {
- if(mp_info->bsp_lapic_id != i) {
- mp_info->cpus[i]->goto_address = __mp_bootstrap;
- }
- }
-} \ No newline at end of file
diff --git a/kernel/src/arch/x86_64/cpu/sse.cpp b/kernel/src/arch/x86_64/cpu/sse.cpp
deleted file mode 100644
index d36e245..0000000
--- a/kernel/src/arch/x86_64/cpu/sse.cpp
+++ /dev/null
@@ -1,120 +0,0 @@
-
-#include <cstdint>
-#include <arch/x86_64/cpu/sse.hpp>
-
-#include <etc/assembly.hpp>
-#include <etc/logging.hpp>
-
-std::uint64_t __sse_size = 0;
-char __sse_is_initializied = 0;
-char __sse_legacy_save = 0;
-
-std::uint64_t __sse_cr4_read() {
- uint64_t val;
- asm volatile("mov %%cr4, %0" : "=r"(val));
- return val;
-}
-
-void __sse_cr4_write(std::uint64_t val) {
- asm volatile("mov %0, %%cr4" : : "r"(val) : "memory");
-}
-
-std::uint64_t __sse_cr0_read() {
- uint64_t val;
- asm volatile("mov %%cr0, %0" : "=r"(val));
- return val;
-}
-
-void __sse_cr0_write(std::uint64_t val) {
- asm volatile("mov %0, %%cr0" : : "r"(val) : "memory");
-}
-
-
-void __sse_xsetbv(std::uint64_t val) {
- asm volatile("xsetbv" : : "a"(val), "d"(val >> 32),"c"(0) : "memory");
-}
-
-std::uint64_t __sse_xgetbv() {
- uint32_t a,d;
- asm volatile("xgetbv" : "=a"(a),"=d"(d) : "c"(0) : "memory");
- return ((std::uint64_t)d << 32) | a;
-}
-
-void __sse_xsave(void* buf) {
- std::uint64_t xcr0 = __sse_xgetbv();
- asm volatile("xsave (%0)" :: "r"(buf), "a"(xcr0 & 0xFFFFFFFF), "d"(xcr0 >> 32), "c"(0): "memory");
-}
-
-void __sse_xrstor(void* buf) {
- std::uint64_t xcr0 = __sse_xgetbv();
- asm volatile("xrstor (%0)" :: "r"(buf), "a"(xcr0 & 0xFFFFFFFF), "d"(xcr0 >> 32), "c"(0): "memory");
-}
-
-using namespace arch::x86_64::cpu;
-
-void sse::init() {
- uint32_t a,b,c,d;
- __cpuid(1,0,&a,&b,&c,&d);
- if(!__sse_is_initializied) {
- if(c & SSE_XSAVE_SUPPORT) {
- __cpuid(13,0,&a,&b,&c,&d);
- __sse_legacy_save = 0;
- __sse_size = c;
- } else {
- __sse_legacy_save = 1;
- __sse_size = 512;
- }
- __sse_is_initializied = 1;
- }
- std::uint64_t cr4 = __sse_cr4_read();
-
- cr4 |= DEFAULT_SSE_FLAGS;
-
- std::uint64_t cr0 = __sse_cr0_read();
-
- cr0 &= ~(1 << 2);
- cr0 |= (1 << 1);
-
- __sse_cr0_write(cr0);
-
- std::uint64_t sse_control = 0;
-
- __sse_cr4_write(cr4);
-
- __cpuid(1,0,&a,&b,&c,&d);
- if(c & SSE_XSAVE_SUPPORT)
- cr4 |= SSE_XSAVE_CR4;
- else
- return;
-
- __sse_cr4_write(cr4);
-
- __cpuid(13,0,&a,&b,&c,&d);
-
- sse_control |= SSE_CONTROL_DEFAULT;
- SSE_CHECK_AND_SET((1 << 2));
- SSE_CHECK_AND_SET((1 << 9));
- SSE_CHECK_AND_SET((0b11 < 3));
- SSE_CHECK_AND_SET((0b11 < 17))
- SSE_CHECK_AND_SET((0b111 < 5));
-
- __sse_xsetbv(sse_control);
-}
-
-std::uint64_t sse::size() {
- return __sse_size;
-}
-
-void sse::save(std::uint8_t* buf) {
- if(__sse_legacy_save)
- asm volatile("fxsave (%0)" : : "r"(buf));
- else
- __sse_xsave(buf);
-}
-
-void sse::load(std::uint8_t* buf) {
- if(__sse_legacy_save)
- asm volatile("fxrstor (%0)" : : "r"(buf));
- else
- __sse_xrstor(buf);
-} \ No newline at end of file
diff --git a/kernel/src/arch/x86_64/cpu_local.hpp b/kernel/src/arch/x86_64/cpu_local.hpp
new file mode 100644
index 0000000..13bca71
--- /dev/null
+++ b/kernel/src/arch/x86_64/cpu_local.hpp
@@ -0,0 +1,45 @@
+
+#include <cstdint>
+
+#pragma once
+
+#include <arch/x86_64/cpu_local.hpp>
+#include <arch/x86_64/assembly.hpp>
+#include <klibc/string.hpp>
+#include <klibc/stdio.hpp>
+#include <generic/arch.hpp>
+
+typedef struct {
+ std::uint64_t user_stack;
+ std::uint64_t kernel_stack;
+ std::uint64_t timer_ist_stack;
+ std::uint64_t tsc_freq;
+} cpudata_t;
+
+namespace x86_64 {
+
+ inline std::uint64_t cpu_data_const = 0;
+
+ inline static void init_cpu_data() {
+ std::uint64_t cpudata = assembly::rdmsr(0xC0000101);
+ if(!cpudata) {
+ cpudata = (std::uint64_t)new cpudata_t;
+ cpu_data_const = cpudata;
+ klibc::memset((void*)cpudata,0,sizeof(cpudata_t));
+ assembly::wrmsr(0xC0000101,cpudata);
+ }
+ }
+
+ inline static void restore_cpu_data() {
+ assembly::wrmsr(0xC0000101,cpu_data_const);
+ }
+
+ inline static cpudata_t* cpu_data() {
+ std::uint64_t cpudata = assembly::rdmsr(0xC0000101);
+ if(!cpudata) {
+ klibc::printf("cpudata: fdgkldfglfkdfdjnbdff\r\n");
+ arch::hcf();
+ }
+ return (cpudata_t*)cpudata;
+ }
+};
diff --git a/kernel/src/arch/x86_64/drivers/hpet.cpp b/kernel/src/arch/x86_64/drivers/hpet.cpp
new file mode 100644
index 0000000..152f0d9
--- /dev/null
+++ b/kernel/src/arch/x86_64/drivers/hpet.cpp
@@ -0,0 +1,58 @@
+#include <cstdint>
+#include <drivers/acpi.hpp>
+#include <utils/gobject.hpp>
+#include <generic/time.hpp>
+#include <generic/arch.hpp>
+#include <arch/x86_64/drivers/hpet.hpp>
+#include <klibc/stdio.hpp>
+#include <uacpi/uacpi.h>
+#include <uacpi/tables.h>
+#include <uacpi/status.h>
+#include <uacpi/acpi.h>
+#include <generic/hhdm.hpp>
+#include <generic/paging.hpp>
+
+std::uint64_t hpet_base,hpet_clock_nano;
+std::uint8_t hpet_is_32_bit = 0;
+
+std::uint64_t __hpet_timestamp() {
+ return hpet_is_32_bit ? *(volatile uint32_t*)(hpet_base + 0xf0) : *(volatile uint64_t*)(hpet_base + 0xf0);
+}
+
+void drivers::hpet::init() {
+ uacpi_table hpet;
+ uacpi_status ret = uacpi_table_find_by_signature("HPET",&hpet);
+ if(ret != UACPI_STATUS_OK) {
+ klibc::printf("HPET: hpet is not detected with status %d\r\n",ret);
+ return;
+ }
+
+ struct acpi_hpet* hpet_table = ((struct acpi_hpet*)hpet.virt_addr);
+ hpet_base = (std::uint64_t)(hpet_table->address.address + etc::hhdm());
+ paging::map_range(gobject::kernel_root,hpet_table->address.address,hpet_table->address.address + etc::hhdm(),PAGE_SIZE,PAGING_PRESENT | PAGING_RW);
+
+ *(volatile std::uint64_t*)(hpet_base + 0x10) |= 1;
+ hpet_is_32_bit = (*(volatile uint64_t*)hpet_base & (1 << 13)) ? 0 : 1;
+ hpet_clock_nano = (*(volatile uint32_t*)(hpet_base + 4)) / 1000000;
+ hpet_timer* new_hpet_inst = new hpet_timer;
+ time::setup_timer(new_hpet_inst);
+ klibc::printf("HPET: Detected %s hpet, current timestamp in nano %lli (hpet_base 0x%p)\r\n",hpet_is_32_bit ? "32 bit" : "64 bit", new_hpet_inst->current_nano(),hpet_base);
+}
+
+namespace drivers {
+ void hpet_timer::sleep(std::uint64_t us) {
+ std::uint64_t start = __hpet_timestamp();
+ std::uint64_t conv = us * 1000;
+ while((__hpet_timestamp() - start) * hpet_clock_nano < conv)
+ asm volatile("nop");
+ }
+
+
+ std::uint64_t hpet_timer::current_nano() {
+ return __hpet_timestamp() * hpet_clock_nano;
+ }
+
+ int hpet_timer::get_priority() {
+ return 10;
+ }
+}; \ No newline at end of file
diff --git a/kernel/src/arch/x86_64/drivers/hpet.hpp b/kernel/src/arch/x86_64/drivers/hpet.hpp
new file mode 100644
index 0000000..b8f2b29
--- /dev/null
+++ b/kernel/src/arch/x86_64/drivers/hpet.hpp
@@ -0,0 +1,18 @@
+#pragma once
+#include <cstdint>
+#include <generic/time.hpp>
+
+namespace drivers {
+
+ class hpet_timer final : public time::generic_timer {
+ public:
+ int get_priority() override;
+ std::uint64_t current_nano() override;
+ void sleep(std::uint64_t us) override;
+ };
+
+ class hpet {
+ public:
+ static void init();
+ };
+}; \ No newline at end of file
diff --git a/kernel/src/arch/x86_64/drivers/io.hpp b/kernel/src/arch/x86_64/drivers/io.hpp
new file mode 100644
index 0000000..5314124
--- /dev/null
+++ b/kernel/src/arch/x86_64/drivers/io.hpp
@@ -0,0 +1,40 @@
+#pragma once
+#include <cstdint>
+
+namespace x86_64 {
+ namespace io {
+ inline void outb(std::uint16_t port, std::uint8_t val) {
+ __asm__ volatile("outb %0, %1" : : "a"(val), "Nd"(port) : "memory");
+ }
+
+ inline void outw(std::uint16_t port, std::uint16_t val) {
+ __asm__ volatile("outw %0, %1" : : "a"(val), "Nd"(port) : "memory");
+ }
+
+ inline void outd(std::uint16_t port, std::uint32_t val) {
+ __asm__ volatile("outl %0, %1" : : "a"(val), "Nd"(port) : "memory");
+ }
+
+ inline std::uint8_t inb(std::uint16_t port) {
+ std::uint8_t ret;
+ __asm__ volatile("inb %1, %0" : "=a"(ret) : "Nd"(port) : "memory");
+ return ret;
+ }
+
+ inline std::uint16_t inw(std::uint16_t port) {
+ std::uint16_t ret;
+ __asm__ volatile("inw %1, %0" : "=a"(ret) : "Nd"(port) : "memory");
+ return ret;
+ }
+
+ inline std::uint32_t ind(std::uint16_t port) {
+ std::uint32_t ret;
+ __asm__ volatile("inl %1, %0" : "=a"(ret) : "Nd"(port) : "memory");
+ return ret;
+ }
+
+ inline void wait() {
+ outb(0x80, 0);
+ }
+ };
+} \ No newline at end of file
diff --git a/kernel/src/arch/x86_64/drivers/pci.hpp b/kernel/src/arch/x86_64/drivers/pci.hpp
new file mode 100644
index 0000000..4474997
--- /dev/null
+++ b/kernel/src/arch/x86_64/drivers/pci.hpp
@@ -0,0 +1,42 @@
+#include <arch/x86_64/drivers/io.hpp>
+#include <cstdint>
+
+namespace x86_64 {
+ namespace pci {
+ inline std::uint32_t pci_read_config32(std::uint8_t bus, std::uint8_t num, std::uint8_t function, std::uint8_t offset) {
+ std::uint32_t address = (1 << 31) | (bus << 16) | (num << 11) | (function << 8) | (offset);
+ x86_64::io::outd(0xCF8, address);
+ return x86_64::io::ind(0xCFC);
+ }
+
+ inline std::uint16_t pci_read_config16(std::uint8_t bus, std::uint8_t num, std::uint8_t function, std::uint8_t offset) {
+ std::uint32_t address = (1 << 31) | (bus << 16) | (num << 11) | (function << 8) | (offset & 0xfc);
+ x86_64::io::outd(0xCF8, address);
+ return (std::uint16_t)((x86_64::io::ind(0xCFC) >> ((offset & 2) * 8)) & 0xffff);
+ }
+
+ inline std::uint8_t pci_read_config8(std::uint8_t bus, std::uint8_t num, std::uint8_t function, std::uint8_t offset) {
+ std::uint32_t address = (1 << 31) | (bus << 16) | (num << 11) | (function << 8) | (offset);
+ x86_64::io::outd(0xCF8, address);
+ return (std::uint8_t)((x86_64::io::ind(0xCFC) >> ((offset & 3) * 8)) & 0xff);
+ }
+
+ inline void pci_write_config32(std::uint8_t bus, std::uint8_t num, std::uint8_t function, std::uint8_t offset, std::uint32_t value) {
+ std::uint32_t address = (1 << 31) | (bus << 16) | (num << 11) | (function << 8) | (offset);
+ x86_64::io::outd(0xCF8, address);
+ x86_64::io::outd(0xCFC, value);
+ }
+
+ inline void pci_write_config16(std::uint8_t bus, std::uint8_t num, std::uint8_t function, std::uint8_t offset, std::uint32_t value) {
+ uint32_t address = (1 << 31) | (bus << 16) | (num << 11) | (function << 8) | (offset & 0xfc);
+ x86_64::io::outd(0xCF8, address);
+ x86_64::io::outd(0xCFC,(x86_64::io::ind(0xCFC) & ~(0xffff << ((offset & 2) * 8))) | (value << ((offset & 2) * 8)));
+ }
+
+ inline void pci_write_config8(std::uint8_t bus, std::uint8_t num, std::uint8_t function, std::uint8_t offset, std::uint8_t value) {
+ std::uint32_t address = (1 << 31) | (bus << 16) | (num << 11) | (function << 8) | (offset & 0xfc);
+ x86_64::io::outd(0xCF8, address);
+ x86_64::io::outd(0xCFC, ((x86_64::io::ind(0xCFC) & ~(0xFF << (offset & 3))) | (value << ((offset & 3) * 8))));
+ }
+ };
+}; \ No newline at end of file
diff --git a/kernel/src/arch/x86_64/drivers/tsc.cpp b/kernel/src/arch/x86_64/drivers/tsc.cpp
new file mode 100644
index 0000000..fbb6fad
--- /dev/null
+++ b/kernel/src/arch/x86_64/drivers/tsc.cpp
@@ -0,0 +1,113 @@
+#define BILLION 1000000000UL
+#include <cstdint>
+#include <drivers/acpi.hpp>
+#include <arch/x86_64/drivers/tsc.hpp>
+#include <arch/x86_64/cpu_local.hpp>
+#include <utils/gobject.hpp>
+#include <klibc/stdio.hpp>
+
+#include <generic/arch.hpp>
+
+static inline uint64_t rdtsc() {
+ uint32_t lo, hi;
+ __asm__ volatile ("rdtsc" : "=a"(lo), "=d"(hi));
+ return ((uint64_t)hi << 32) | lo;
+}
+
+void drivers::tsc::init() {
+
+ if(time::timer == nullptr) {
+ klibc::printf("TSC: Can't initialize without timer !\n");
+ }
+
+ uint64_t tsc_start, tsc_end;
+ std::uint64_t time_start,time_end;
+
+ tsc_start = rdtsc();
+ time_start = time::timer->current_nano();
+
+ time::timer->sleep(100000);
+
+ tsc_end = rdtsc();
+ time_end = time::timer->current_nano();
+
+ uint64_t time_ns = time_end - time_start;
+ uint64_t tsc_diff = tsc_end - tsc_start;
+
+ uint64_t tsc_freq;
+
+ if (tsc_diff > UINT64_MAX / BILLION) {
+ uint64_t tsc_high = tsc_diff >> 32;
+ uint64_t tsc_low = tsc_diff & 0xFFFFFFFF;
+
+ uint64_t temp_high = (tsc_high * BILLION) >> 32;
+ uint64_t temp_low = (tsc_high * BILLION) << 32;
+ if (temp_low < (tsc_high * BILLION)) temp_high++;
+
+ uint64_t temp = temp_low + tsc_low * BILLION;
+ if (temp < tsc_low * BILLION) temp_high++;
+
+ tsc_freq = (temp / time_ns + (temp_high / time_ns)) << 32;
+ } else {
+ tsc_freq = (tsc_diff * BILLION) / time_ns;
+ }
+
+ x86_64::cpu_data()->tsc_freq = tsc_freq;
+
+ klibc::printf("TSC: TSC Frequency is %llu\r\n", tsc_freq);
+ drivers::tsc_timer* tsc_timer = new drivers::tsc_timer;
+ time::setup_timer(tsc_timer);
+}
+
+namespace drivers {
+ void tsc_timer::sleep(std::uint64_t us) {
+ std::uint64_t current = this->current_nano();
+ std::uint64_t end_ns = us * 1000;
+ std::uint64_t target = current + end_ns;
+
+ while(this->current_nano() < target) {
+ arch::pause();
+ }
+ }
+
+ std::uint64_t tsc_timer::current_nano() {
+ std::uint64_t freq = x86_64::cpu_data()->tsc_freq;
+
+ if(freq == 0) { // redirect to previous timer
+ if(time::previous_timer) {
+ return time::previous_timer->current_nano();
+ } else {
+ klibc::printf("TSC: Trying to get current nano timestamp without any timer from non calibrated tsc !\n");
+ return 0;
+ }
+ }
+
+ uint32_t lo, hi;
+ asm volatile ("rdtsc" : "=a"(lo), "=d"(hi));
+ std::uint64_t tsc_v = ((uint64_t)hi << 32) | lo;
+
+ if (tsc_v > UINT64_MAX / BILLION) {
+ uint64_t high = tsc_v >> 32;
+ uint64_t low = tsc_v & 0xFFFFFFFF;
+
+ uint64_t high_part = (high * BILLION) / freq;
+ uint64_t high_rem = (high * BILLION) % freq;
+
+ uint64_t low_part = (low * BILLION) / freq;
+ uint64_t low_rem = (low * BILLION) % freq;
+
+ uint64_t result = (high_part << 32) + low_part;
+
+ uint64_t total_rem = (high_rem << 32) + low_rem;
+ result += total_rem / freq;
+
+ return result;
+ } else {
+ return (tsc_v * BILLION) / freq;
+ }
+ }
+
+ int tsc_timer::get_priority() {
+ return 9999999; // undertale reference
+ }
+} \ No newline at end of file
diff --git a/kernel/src/arch/x86_64/drivers/tsc.hpp b/kernel/src/arch/x86_64/drivers/tsc.hpp
new file mode 100644
index 0000000..0ac44bd
--- /dev/null
+++ b/kernel/src/arch/x86_64/drivers/tsc.hpp
@@ -0,0 +1,19 @@
+#pragma once
+#include <cstdint>
+#include <generic/time.hpp>
+
+namespace drivers {
+
+ class tsc_timer final : public time::generic_timer {
+ public:
+ int get_priority() override;
+ std::uint64_t current_nano() override;
+ void sleep(std::uint64_t us) override;
+ };
+
+ class tsc {
+ public:
+ static void init();
+ static void init_bsp();
+ };
+}; \ No newline at end of file
diff --git a/kernel/src/arch/x86_64/interrupts/irq.cpp b/kernel/src/arch/x86_64/interrupts/irq.cpp
deleted file mode 100644
index 7b7c5d4..0000000
--- a/kernel/src/arch/x86_64/interrupts/irq.cpp
+++ /dev/null
@@ -1,94 +0,0 @@
-
-#include <cstdint>
-#include <arch/x86_64/interrupts/irq.hpp>
-#include <arch/x86_64/interrupts/idt.hpp>
-#include <arch/x86_64/interrupts/pic.hpp>
-#include <arch/x86_64/cpu/lapic.hpp>
-#include <generic/mm/paging.hpp>
-#include <drivers/ioapic.hpp>
-#include <etc/libc.hpp>
-
-#include <generic/vfs/vfs.hpp>
-
-#include <etc/logging.hpp>
-
-irq_t irq_table[255];
-std::uint16_t irq_ptr = 0;
-
-std::uint8_t is_legacy_pic = 1;
-
-extern "C" void* irqTable[];
-
-extern "C" void irqHandler(int_frame_t* ctx) {
-
- if(ctx->cs != 0x08)
- asm volatile("swapgs");
-
- memory::paging::enablekernel();
- if(!irq_table[ctx->vec - 1].is_userspace)
- irq_table[ctx->vec - 1].func(irq_table[ctx->vec - 1].arg);
- else {
-
- if(irq_table[ctx->vec - 1].irq == 1) { // irq 12 and irq 1 are connected together
- drivers::ioapic::mask(12);
- } else if(irq_table[ctx->vec - 1].irq == 12) {
- drivers::ioapic::mask(1);
- } else
- drivers::ioapic::mask(irq_table[ctx->vec - 1].irq); /* Mask */
-
- userspace_fd_t fd;
- fd.is_cached_path = 0;
- memset(fd.path,0,sizeof(fd.path));
- __printfbuf(fd.path,sizeof(fd.path),"/dev/masterirq%d",irq_table[ctx->vec - 1].irq);
-
- char i = 1;
- int status = vfs::vfs::write(&fd,&i,1);
- }
-
- arch::x86_64::cpu::lapic::eoi();
-
- if(ctx->cs & 3)
- ctx->ss |= 3;
-
- if(ctx->ss & 3)
- ctx->cs |= 3;
-
- if(ctx->cs == 0x20)
- ctx->cs |= 3;
-
- if(ctx->ss == 0x18)
- ctx->ss |= 3;
-
- if(ctx->cs != 0x08)
- asm volatile("swapgs");
-
-}
-
-void arch::x86_64::interrupts::irq::reset() {
- irq_ptr = 0;
- memset(irq_table,0,sizeof(irq_table));
-}
-
-std::uint8_t arch::x86_64::interrupts::irq::create(std::uint16_t irq,std::uint8_t type,void (*func)(void* arg),void* arg,std::uint64_t flags) {
- uint8_t entry = 0;
-
- if(!is_legacy_pic) {
- entry = arch::x86_64::interrupts::idt::alloc();
- arch::x86_64::interrupts::idt::set_entry((std::uint64_t)irqTable[entry - 0x20],entry,0x8E,3);
- if(type == IRQ_TYPE_LEGACY_USERSPACE)
- irq_table[irq_ptr].is_userspace = 1;
-
- drivers::ioapic::set(entry,irq,0,arch::x86_64::cpu::lapic::id());
- } else {
- arch::x86_64::interrupts::idt::set_entry((std::uint64_t)irqTable[irq],irq + 0x20,0x8E,3);
- irq_table[irq].arg = arg;
-
- irq_table[irq].func = func;
- return irq + 0x20;
- }
-
- irq_table[irq_ptr].arg = arg;
- irq_table[irq_ptr].irq = irq;
- irq_table[irq_ptr++].func = func;
- return entry;
-} \ No newline at end of file
diff --git a/kernel/src/arch/x86_64/interrupts/panic.cpp b/kernel/src/arch/x86_64/interrupts/panic.cpp
deleted file mode 100644
index 237d03a..0000000
--- a/kernel/src/arch/x86_64/interrupts/panic.cpp
+++ /dev/null
@@ -1,216 +0,0 @@
-#include <cstdint>
-#include <arch/x86_64/interrupts/idt.hpp>
-#include <etc/logging.hpp>
-
-#include <arch/x86_64/cpu/data.hpp>
-
-#include <generic/locks/spinlock.hpp>
-
-#include <etc/bootloaderinfo.hpp>
-#include <generic/mm/vmm.hpp>
-
-#include <arch/x86_64/scheduling.hpp>
-
-#include <generic/vfs/fd.hpp>
-
-#include <generic/mm/paging.hpp>
-
-typedef struct stackframe {
- struct stackframe* rbp;
- uint64_t rip;
-} __attribute__((packed)) stackframe_t;
-
-int is_panic = 0;
-int last_sys = 0;
-extern std::int64_t __memory_paging_getphys(std::uint64_t cr3, std::uint64_t virt);
-
-void panic(int_frame_t* ctx, const char* msg) {
-
- memory::paging::enablekernel();
- if(is_panic)
- asm volatile("hlt");
-
- if(ctx) {
- if(ctx->cs != 0x08)
- asm volatile("swapgs");
- }
-
- arch::x86_64::process_t* proc = arch::x86_64::cpu::data()->temp.proc;
- if(proc && 1 && ctx) {
- uint64_t cr2;
- asm volatile("mov %%cr2, %0" : "=r"(cr2) : : "memory");
-
- vmm_obj_t* current1 = (vmm_obj_t*)proc->vmm_start;
- current1->lock.unlock();
-
- vmm_obj_t* obj = memory::vmm::getlen(proc,ctx->rip);
-
-
- if(ctx->vec == 14) {
- vmm_obj_t* obj0 = memory::vmm::getlen(proc,cr2);
-
- if(proc && cr2 == 0 && proc->sigtrace_obj && ctx->err_code == 0x14) {
- arch::x86_64::scheduling::sigreturn(proc);
- }
-
- if(obj0) {
- if(obj0->is_lazy_alloc && !obj0->is_free) {
-
- if(__memory_paging_getphys(proc->original_cr3,cr2) == -1) {
- std::uint64_t new_phys = memory::pmm::_physical::alloc(4096);
- memory::paging::map(proc->original_cr3,new_phys,ALIGNDOWN(cr2,4096),obj0->flags);
- }
-
- if(ctx->cs & 3)
- ctx->ss |= 3;
-
- if(ctx->ss & 3)
- ctx->cs |= 3;
-
- if(ctx->cs == 0x20)
- ctx->cs |= 3;
-
- if(ctx->ss == 0x18)
- ctx->ss |= 3;
-
- if(ctx->cs != 0x08)
- asm volatile("swapgs");
-
- schedulingEnd(ctx);
- } else if(!obj0->is_free && cr2 > 0x1000) {
- Log::SerialDisplay(LEVEL_MESSAGE_WARN,"tlb invalid :( 0x%p is_mapped %d phys 0x%p base 0x%p ",cr2,obj0->is_mapped,obj0->phys,obj0->base);
- memory::paging::maprange(proc->original_cr3,obj0->phys,obj0->base,obj0->len,obj0->flags);
- if(ctx->cs & 3)
- ctx->ss |= 3;
-
- if(ctx->ss & 3)
- ctx->cs |= 3;
-
- if(ctx->cs == 0x20)
- ctx->cs |= 3;
-
- if(ctx->ss == 0x18)
- ctx->ss |= 3;
-
- if(ctx->cs != 0x08)
- asm volatile("swapgs");
-
- schedulingEnd(ctx);
- } else if(1) {
- Log::SerialDisplay(LEVEL_MESSAGE_INFO,"aaa\n");
- }
- }
-
- }
-
- Log::Display(LEVEL_MESSAGE_FAIL,"process %d (%s) fired cpu exception with vec %d, rip 0x%p (offset 0x%p), cr2 0x%p, error code 0x%p, lastsys %d, rdx 0x%p rbp 0x%p\n",proc->id,proc->name,ctx->vec,ctx->rip,ctx->rip - 0x41400000,cr2,ctx->err_code,proc->sys,ctx->rdx,ctx->rbp);
-
- Log::Raw("RAX: 0x%016llX RBX: 0x%016llX RDX: 0x%016llX RCX: 0x%016llX RDI: 0x%016llX\n"
- "RSI: 0x%016llX R8: 0x%016llX R9: 0x%016llX R10: 0x%016llX R11: 0x%016llX\n"
- "R12: 0x%016llX R13: 0x%016llX R14: 0x%016llX R15: 0x%016llX RBP: 0x%016llX\n"
- "RSP: 0x%016llX CR2: 0x%016llX CR3: 0x%016llX\n"
- "CPU: %d Vec: %d Err: %d Last Syscall: %d cs %d\n",
- ctx->rax, ctx->rbx, ctx->rdx, ctx->rcx, ctx->rdi,
- ctx->rsi, ctx->r8, ctx->r9, ctx->r10, ctx->r11,
- ctx->r12, ctx->r13, ctx->r14, ctx->r15, ctx->rbp,
- ctx->rsp, cr2, ctx->cr3,
- arch::x86_64::cpu::data()->smp.cpu_id, ctx->vec, ctx->err_code,arch::x86_64::cpu::data()->last_sys,ctx->cs);
-
- vmm_obj_t* current = (vmm_obj_t*)proc->vmm_start;
-
- while(1) {
-
- Log::SerialDisplay(LEVEL_MESSAGE_INFO,"Memory 0x%p-0x%p (with offset rip 0x%p)\n",current->base,current->base + current->len, ctx->rip - current->base);
-
- if (current->base == (std::uint64_t)Other::toVirt(0) - 4096)
- break;
-
- current = current->next;
-
- }
-
- asm volatile("hlt");
-
- stackframe_t* rbp = (stackframe_t*)ctx->rbp;
-
- memory::paging::enablepaging(ctx->cr3);
- Log::SerialDisplay(LEVEL_MESSAGE_INFO,"[0] - 0x%016llX (current rip)\n",ctx->rip);
- for (int i = 1; i < 10 && rbp; ++i) {
- std::uint64_t ret_addr = rbp->rip;
- Log::SerialDisplay(LEVEL_MESSAGE_INFO,"[%d] - 0x%016llX\n", i, ret_addr);
- rbp = (stackframe_t*)rbp->rbp;
- }
- memory::paging::enablekernel();
-
- arch::x86_64::scheduling::kill(proc);
-
- if(1)
- memory::vmm::free(proc);
-
- vfs::fdmanager* fd = (vfs::fdmanager*)proc->fd;
- fd->free();
-
- memory::pmm::_virtual::free(proc->cwd);
- memory::pmm::_virtual::free(proc->name);
- memory::pmm::_virtual::free(proc->sse_ctx);
-
- arch::x86_64::scheduling::kill(proc);
- schedulingSchedule(0);
- }
-
- int_frame_t test_ctx = {0};
-
- if(!ctx)
- ctx = &test_ctx;
-
- is_panic = 1;
-
- extern locks::spinlock log_lock;
- log_lock.unlock();
-
- uint64_t cr2;
- asm volatile("mov %%cr2, %0" : "=r"(cr2) : : "memory");
-
- Log::Display(LEVEL_MESSAGE_FAIL,R"EOF(
-
- )
- ( /( ( (
- )\()) ( ) ( ( ( ( )\ ) ( ) )\ )
-((_)\ )( ( /( ( )\))( ))\ )\ ( (()/( ))\( /( (()/( __
- ((_)(()\ )(_)) )\ )((_))\ /((_) ((_))\ ((_))((_)(_)) ((_)) _ / /
- / _ \ ((_|(_)_ _(_/( (()(_|_)) (_|(_) _| (_))((_)_ _| | (_) |
-| (_) | '_/ _` | ' \)) _` |/ -_) | (_-< / _` / -_) _` / _` | _| |
- \___/|_| \__,_|_||_|\__, |\___| |_/__/ \__,_\___\__,_\__,_| (_)\_\
- |___/
-
- )EOF");
-
- Log::Raw("Kernel panic\n\nReason: %s\n",msg);
- Log::Raw("RAX: 0x%016llX RBX: 0x%016llX RDX: 0x%016llX RCX: 0x%016llX RDI: 0x%016llX\n"
- "RSI: 0x%016llX R8: 0x%016llX R9: 0x%016llX R10: 0x%016llX R11: 0x%016llX\n"
- "R12: 0x%016llX R13: 0x%016llX R14: 0x%016llX R15: 0x%016llX RBP: 0x%016llX\n"
- "RSP: 0x%016llX CR2: 0x%016llX CR3: 0x%016llX\n"
- "CPU: %d Vec: %d Err: %d Last Syscall: %d cs: %p ss: %p\n",
- ctx->rax, ctx->rbx, ctx->rdx, ctx->rcx, ctx->rdi,
- ctx->rsi, ctx->r8, ctx->r9, ctx->r10, ctx->r11,
- ctx->r12, ctx->r13, ctx->r14, ctx->r15, ctx->rbp,
- ctx->rsp, cr2, ctx->cr3,
- arch::x86_64::cpu::data()->smp.cpu_id, ctx->vec, ctx->err_code,arch::x86_64::cpu::data()->last_sys,ctx->cs,ctx->ss);
- Log::Raw("\n Stacktrace\n\n");
-
- stackframe_t* rbp = (stackframe_t*)ctx->rbp;
-
- Log::Raw("[0] - 0x%016llX (current rip)\n",ctx->rip);
- for (int i = 1; i < 5 && rbp; ++i) {
- std::uint64_t ret_addr = rbp->rip;
- Log::Raw("[%d] - 0x%016llX\n", i, ret_addr);
- rbp = (stackframe_t*)rbp->rbp;
- }
-
-
- asm volatile("hlt");
-}
-
-extern "C" void CPUKernelPanic(int_frame_t* ctx) {
- panic(ctx,"\"cpu exception\"");
-} \ No newline at end of file
diff --git a/kernel/src/arch/x86_64/interrupts/pit.cpp b/kernel/src/arch/x86_64/interrupts/pit.cpp
deleted file mode 100644
index 5154537..0000000
--- a/kernel/src/arch/x86_64/interrupts/pit.cpp
+++ /dev/null
@@ -1,31 +0,0 @@
-
-#include <cstdint>
-#include <arch/x86_64/interrupts/pic.hpp>
-#include <arch/x86_64/interrupts/irq.hpp>
-#include <arch/x86_64/interrupts/pit.hpp>
-#include <drivers/hpet.hpp>
-
-using namespace arch::x86_64::interrupts;
-
-std::uint64_t pit_counter = 0;
-
-void __pit_int_handler(void *arg) {
- pit_counter++;
-}
-
-void arch::x86_64::interrupts::pit::init() {
- drivers::io io;
- std::uint8_t entry = irq::create(0,IRQ_TYPE_LEGACY,__pit_int_handler,0,0);
- std::uint32_t div = PIT_FREQUENCY / 1000;
- io.outb(0x43, 0x36);
- io.outb(0x40,div & 0xFF);
- io.outb(0x40,(div >> 8) & 0xFF);
-
- pic::clear(0);
-
-}
-
-/* idk why but pit sleep is broken on modern hw, redirect to hpet */
-void arch::x86_64::interrupts::pit::sleep(std::uint32_t ms) {
- drivers::hpet::sleep(ms);
-} \ No newline at end of file
diff --git a/kernel/src/arch/x86_64/paging.cpp b/kernel/src/arch/x86_64/paging.cpp
new file mode 100644
index 0000000..3437889
--- /dev/null
+++ b/kernel/src/arch/x86_64/paging.cpp
@@ -0,0 +1,161 @@
+#include <cstdint>
+#include <generic/arch.hpp>
+#include <generic/bootloader/bootloader.hpp>
+#include <generic/hhdm.hpp>
+#include <generic/pmm.hpp>
+
+#define PTE_MASK_VALUE_5 0x000ffffffffffff000
+#define PTE_MASK_VALUE 0x000ffffffffff000
+#define PTE_PRESENT (1 << 0)
+#define PTE_RW (1 << 1)
+#define PTE_USER (1 << 2)
+#define PTE_WC ((1 << 7) | (1 << 3))
+#define PTE_MMIO (1ull << 4)
+#define LVL_PG_MASK (bootloader::bootloader->is_5_level_paging() ? PTE_MASK_VALUE_5 : PTE_MASK_VALUE)
+
+int level_to_index(std::uintptr_t virt, int level) {
+ if(bootloader::bootloader->is_5_level_paging()) {
+ switch (level) {
+ case 0: return PTE_INDEX(virt, 48);
+ case 1: return PTE_INDEX(virt, 39);
+ case 2: return PTE_INDEX(virt, 30);
+ case 3: return PTE_INDEX(virt, 21);
+ case 4: return PTE_INDEX(virt, 12);
+ default: return 0;
+ }
+ } else {
+ switch (level) {
+ case 0: return PTE_INDEX(virt, 39);
+ case 1: return PTE_INDEX(virt, 30);
+ case 2: return PTE_INDEX(virt, 21);
+ case 3: return PTE_INDEX(virt, 12);
+ default: return 0;
+ }
+ }
+ return 0;
+}
+
+int64_t* __paging_next_level_noalloc(std::uint64_t* table, std::uint16_t idx) {
+ if (!(table[idx] & PTE_PRESENT))
+ return (int64_t*) -1;
+ return (int64_t*) ((table[idx] & LVL_PG_MASK) + etc::hhdm());
+}
+
+std::int64_t __memory_paging_getphys(std::uint64_t* table, std::uint64_t virt, int level) {
+ if (!table && (std::int64_t) table == -1)
+ return -1;
+ int max_level = bootloader::bootloader->is_5_level_paging() ? 4 : 3;
+ if (max_level == level) {
+ return (table[level_to_index(virt, level)] & PTE_PRESENT) ? table[level_to_index(virt, level)] & LVL_PG_MASK : -1;
+ } else
+ return __memory_paging_getphys((std::uint64_t*) __paging_next_level_noalloc(table, level_to_index(virt, level)), virt, level + 1);
+ return -1;
+}
+
+uint64_t* x86_64_paging_next_level(std::uint64_t* table, std::uint16_t idx, std::uint64_t flags) {
+ if (!(table[idx] & PTE_PRESENT))
+ table[idx] = pmm::freelist::alloc_4k() | flags;
+ return (uint64_t*) ((table[idx] & LVL_PG_MASK) + etc::hhdm());
+}
+
+std::uint64_t convert_flags(std::uint64_t flags) {
+ std::uint64_t result = 0;
+ if (flags & PAGING_NC)
+ result |= PTE_MMIO;
+ if (flags & PAGING_PRESENT)
+ result |= PTE_PRESENT;
+ if (flags & PAGING_RW)
+ result |= PTE_RW;
+ if (flags & PAGING_USER)
+ result |= PTE_USER;
+ if (flags & PAGING_WC)
+ result |= PTE_WC;
+ return result;
+}
+
+void x86_64_map_page(std::uintptr_t root, std::uintptr_t phys, std::uintptr_t virt, std::uint32_t flags) {
+ std::uint64_t* cr30 = (std::uint64_t*) (root + etc::hhdm());
+ std::uint64_t new_flags = PTE_PRESENT | PTE_RW;
+ if (bootloader::bootloader->is_5_level_paging()) {
+ if (PTE_INDEX(virt, 48) < 256)
+ new_flags |= PTE_USER;
+ uint64_t* pml4 = x86_64_paging_next_level(cr30, PTE_INDEX(virt, 48), new_flags);
+ uint64_t* pml3 = x86_64_paging_next_level(pml4, PTE_INDEX(virt, 39), new_flags);
+ uint64_t* pml2 = x86_64_paging_next_level(pml3, PTE_INDEX(virt, 30), new_flags);
+ uint64_t* pml = x86_64_paging_next_level(pml2, PTE_INDEX(virt, 21), new_flags);
+ pml[PTE_INDEX(virt, 12)] = phys | flags;
+ } else {
+ if (PTE_INDEX(virt, 39) < 256)
+ new_flags |= PTE_USER;
+ uint64_t* pml3 = x86_64_paging_next_level(cr30, PTE_INDEX(virt, 39), new_flags);
+ uint64_t* pml2 = x86_64_paging_next_level(pml3, PTE_INDEX(virt, 30), new_flags);
+ uint64_t* pml = x86_64_paging_next_level(pml2, PTE_INDEX(virt, 21), new_flags);
+ pml[PTE_INDEX(virt, 12)] = phys | flags;
+ }
+}
+
+
+namespace arch {
+ [[gnu::weak]] void enable_paging(std::uintptr_t root) {
+ asm volatile("mov %0, %%cr3" : : "r"(root) : "memory");
+ }
+
+ [[gnu::weak]] void map_page(std::uintptr_t root, std::uint64_t phys, std::uintptr_t virt, int flags) {
+ x86_64_map_page(root,phys,virt,convert_flags(flags));
+ }
+
+ [[gnu::weak]] std::uint64_t get_phys_from_page(std::uintptr_t root, std::uintptr_t virt) {
+ return __memory_paging_getphys((std::uint64_t*)(root + etc::hhdm()),virt,0);
+ }
+
+ [[gnu::weak]] void destroy_root(std::uintptr_t root, int level) {
+ std::uint64_t* table = (std::uint64_t*) (root + etc::hhdm());
+ if (bootloader::bootloader->is_5_level_paging()) {
+ if (level != 4) {
+ if (level == 0) {
+ for (int i = 0; i < 256; i++) {
+ if (table[i] & PTE_PRESENT) {
+ destroy_root(table[i] & PTE_MASK_VALUE, level + 1);
+ }
+ }
+ } else {
+ for (int i = 0; i < 512; i++) {
+ if (table[i] & PTE_PRESENT) {
+ destroy_root(table[i] & PTE_MASK_VALUE, level + 1);
+ }
+ }
+ }
+ }
+
+ if (level != 0)
+ pmm::freelist::free(root);
+ } else {
+ if (level != 3) {
+ if (level == 0) {
+ for (int i = 0; i < 256; i++) {
+ if (table[i] & PTE_PRESENT) {
+ destroy_root(table[i] & PTE_MASK_VALUE, level + 1);
+ }
+ }
+ } else {
+ for (int i = 0; i < 512; i++) {
+ if (table[i] & PTE_PRESENT) {
+ destroy_root(table[i] & PTE_MASK_VALUE, level + 1);
+ }
+ }
+ }
+ }
+
+ if (level != 0)
+ pmm::freelist::free(root);
+ }
+ }
+
+ [[gnu::weak]] void copy_higher_half(std::uintptr_t root, std::uintptr_t src_root) {
+ std::uint64_t* virt_rootcr3 = (std::uint64_t*) (root + etc::hhdm());
+ std::uint64_t* virt_srccr3 = (std::uint64_t*) (src_root + etc::hhdm());
+ for (int i = 255; i < 512; i++) {
+ virt_rootcr3[i] = virt_srccr3[i];
+ }
+ }
+}; \ No newline at end of file
diff --git a/kernel/src/arch/x86_64/scheduling.cpp b/kernel/src/arch/x86_64/scheduling.cpp
deleted file mode 100644
index 13f4300..0000000
--- a/kernel/src/arch/x86_64/scheduling.cpp
+++ /dev/null
@@ -1,1103 +0,0 @@
-
-#include <cstdint>
-#include <arch/x86_64/scheduling.hpp>
-#include <generic/vfs/vfs.hpp>
-
-#include <arch/x86_64/cpu/sse.hpp>
-
-#include <generic/locks/spinlock.hpp>
-
-#include <generic/mm/pmm.hpp>
-#include <generic/mm/vmm.hpp>
-
-#include <arch/x86_64/cpu/data.hpp>
-#include <arch/x86_64/interrupts/idt.hpp>
-#include <arch/x86_64/cpu/lapic.hpp>
-
-#include <generic/vfs/fd.hpp>
-
-#include <etc/libc.hpp>
-#include <etc/list.hpp>
-
-#include <generic/time.hpp>
-
-#include <etc/logging.hpp>
-
-#include <atomic>
-
-#include <etc/errno.hpp>
-
-#include <config.hpp>
-
-arch::x86_64::process_t* head_proc;
-std::uint32_t id_ptr = 0;
-
-locks::spinlock process_lock;
-
-#define PUT_STACK(dest,value) *--dest = value;
-#define PUT_STACK_STRING(dest,string) memcpy(dest,string,strlen(string));
-
-
-uint64_t __elf_get_length(char** arr) {
- uint64_t counter = 0;
-
- while(arr[counter]) {
- counter++;
- char* t = (char*)(arr[counter - 1]);
- if(*t == '\0')
- return counter - 1; // invalid
- }
-
- return counter;
-}
-
-uint64_t __stack_memcpy(std::uint64_t stack, void* src, uint64_t len) {
- std::uint64_t _stack = stack;
- _stack -= 8;
- _stack -= ALIGNUP(len,8);
- memcpy((void*)_stack,src,len);
- return (std::uint64_t)_stack;
-}
-
-uint64_t* __elf_copy_to_stack(char** arr,uint64_t* stack,char** out, uint64_t len) {
-
- uint64_t* temp_stack = stack;
-
- for(uint64_t i = 0;i < len; i++) {
- temp_stack -= ALIGNUP(strlen(arr[i]),8);
- PUT_STACK_STRING(temp_stack,arr[i])
- out[i] = (char*)temp_stack;
- PUT_STACK(temp_stack,0);
- }
-
- return temp_stack;
-
-}
-
-uint64_t* __elf_copy_to_stack_without_out(uint64_t* arr,uint64_t* stack,uint64_t len) {
-
- uint64_t* _stack = stack;
-
- for(uint64_t i = 0;i < len;i++) {
- PUT_STACK(_stack,arr[i]);
- }
-
- return _stack;
-
-}
-
-elfloadresult_t __scheduling_load_elf(arch::x86_64::process_t* proc, std::uint8_t* base) {
- elfheader_t* head = (elfheader_t*)base;
- elfprogramheader_t* current_head;
- std::uint64_t elf_base = UINT64_MAX;
- std::uint64_t size = 0;
- std::uint64_t phdr = 0;
-
- std::uint64_t highest_addr = 0;
- char interp_path[2048];
-
- char ELF[4] = {0x7F,'E','L','F'};
- if(strncmp((const char*)head->e_ident,ELF,4)) {
- return {0,0,0,0,0,ENOENT};
- }
-
- elfloadresult_t elfload;
- elfload.real_entry = head->e_entry;
- elfload.interp_entry = head->e_entry;
- elfload.phnum = head->e_phnum;
- elfload.phentsize = head->e_phentsize;
-
- if(head->e_type != ET_DYN) {
- for(int i = 0; i < head->e_phnum; i++) {
- current_head = (elfprogramheader_t*)((uint64_t)base + head->e_phoff + head->e_phentsize*i);
- if (current_head->p_type == PT_LOAD) {
- elf_base = MIN2(elf_base, ALIGNDOWN(current_head->p_vaddr, PAGE_SIZE));
- highest_addr = MAX2(highest_addr, ALIGNUP(current_head->p_vaddr + current_head->p_memsz, PAGE_SIZE));
- }
- }
- }
-
- for(int i = 0;i < head->e_phnum; i++) {
- uint64_t start = 0, end = 0;
- current_head = (elfprogramheader_t*)((uint64_t)base + head->e_phoff + head->e_phentsize*i);
-
- if(current_head->p_type == PT_PHDR) {
- phdr = current_head->p_vaddr;
- elfload.phdr = phdr;
- }
-
- if (current_head->p_type == PT_LOAD) {
- end = current_head->p_vaddr - elf_base + current_head->p_memsz;
- size = MAX2(size, end);
- }
- }
-
- void* elf_vmm;
-
- DEBUG(1,"proc cr3 0x%p",proc->original_cr3);
-
- size = ALIGNPAGEUP(size);
-
- if(head->e_type != ET_DYN) {
- assert(!(memory::vmm::getlen(proc,elf_base)),"memory 0x%p is not avaiable !",elf_base);
- elf_vmm = memory::vmm::customalloc(proc, elf_base , size, PTE_PRESENT | PTE_RW | PTE_USER, 0,1);
- assert((std::uint64_t)elf_vmm == elf_base,"0x%p is not equal 0x%p",elf_vmm,elf_base);
- elfload.base = (uint64_t)elf_base;
- } else {
- elf_vmm = memory::vmm::alloc(proc, size, PTE_PRESENT | PTE_RW | PTE_USER, 0);
- elfload.base = (uint64_t)elf_vmm;
- }
-
- memory::vmm::invmapping(proc,(std::uint64_t)elf_vmm,size);
-
- uint8_t* allocated_elf = (uint8_t*)elf_vmm;
-
- memory::paging::enablepaging(proc->original_cr3);
-
- for(int i = 0;i < head->e_phnum; i++) {
- uint64_t dest = 0;
- current_head = (elfprogramheader_t*)((uint64_t)base + head->e_phoff + head->e_phentsize*i);
-
- if(current_head->p_type == PT_LOAD) {
- if(head->e_type != ET_DYN) {
- dest = ((current_head->p_vaddr) - elf_base) + (std::uint64_t)allocated_elf;
- DEBUG(1,"load seg 0x%p to 0x%p (0x%p)",current_head->p_vaddr,current_head->p_vaddr + current_head->p_memsz,current_head->p_vaddr + current_head->p_filesz);
- } else {
- dest = (uint64_t)allocated_elf + current_head->p_vaddr;
- }
-
- memset((void*)dest, 0, current_head->p_memsz);
- memcpy((void*)dest, (void*)((uint64_t)base + current_head->p_offset), current_head->p_filesz);
- } else if(current_head->p_type == PT_INTERP) {
- vfs::stat_t stat;
- userspace_fd_t fd;
- zeromem(&fd);
- zeromem(&stat);
-
- memcpy(fd.path, (char*)((uint64_t)base + current_head->p_offset), strlen((char*)((uint64_t)base + current_head->p_offset)));
- int status = vfs::vfs::stat(&fd, &stat);
- if(status) { memory::paging::enablekernel();
- DEBUG(1,"unknown interp path %s (ENOENT)",(char*)((uint64_t)base + current_head->p_offset));
- return {0,0,0,0,0,ENOENT};
- }
-
- char* inter = (char*)memory::pmm::_virtual::alloc(stat.st_size);
- vfs::vfs::read(&fd, inter, stat.st_size);
- memory::paging::enablekernel();
- elfloadresult_t interpload = __scheduling_load_elf(proc, (std::uint8_t*)inter);
- memory::paging::enablepaging(proc->original_cr3);
- memory::pmm::_virtual::free(inter);
-
- elfload.interp_base = interpload.base;
- elfload.interp_entry = interpload.real_entry;
- }
- }
-
- if(head->e_type != ET_DYN) {
- if(phdr) {
- elfload.phdr = phdr;
- DEBUG(1,"phdr 0x%p",phdr);
- }
- } else {
- if(phdr) {
- phdr += (uint64_t)elf_vmm;
- elfload.phdr = phdr;
- }
- elfload.real_entry = (uint64_t)elf_vmm + head->e_entry;
- }
-
- if(proc->is_debug) {
- uint64_t strtab_offset = 0;
- uint64_t strtab_addr = 0;
- uint64_t strtab_size = 0;
-
- elfprogramheader_t* phdrz =0;
-
- if(head->e_type != ET_DYN) {
- phdrz = (elfprogramheader_t*)(phdr);
- } else
- phdrz = (elfprogramheader_t*)((phdr));
- elfprogramheader_t* dynamic_phdr = NULL;
-
- if(phdrz) {
- for (int i = 0; i < head->e_phnum; i++) {
- DEBUG(1,"phdr type %d",phdrz[i].p_type);
- if (phdrz[i].p_type == PT_DYNAMIC) {
- dynamic_phdr = &phdrz[i];
- break;
- }
- }
- }
-
- if (dynamic_phdr == NULL) {
- DEBUG(1, "DYNAMIC segment not found");
- //goto end;
- } else {
- Elf64_Dyn* dyn;
- if(head->e_type != ET_DYN)
- dyn = (Elf64_Dyn *)((char *)allocated_elf + (dynamic_phdr->p_vaddr - elf_base));
- else
- dyn = (Elf64_Dyn *)((char *)allocated_elf + (dynamic_phdr->p_vaddr));
- uint64_t dyn_size = dynamic_phdr->p_filesz / sizeof(Elf64_Dyn);
-
- for (uint64_t i = 0; i < dyn_size; i++) {
- if (dyn[i].d_tag == DT_NULL) {
- break;
- }
-
- if (dyn[i].d_tag == DT_STRTAB) {
- strtab_addr = dyn[i].d_un.d_ptr;
- } else if (dyn[i].d_tag == DT_STRSZ) {
- strtab_size = dyn[i].d_un.d_val;
- }
- }
-
- if (strtab_addr == 0) {
- DEBUG(1, ".dynstr string table not found");
- //goto end;
- }
-
- for (int i = 0; i < head->e_phnum; i++) {
- if (phdrz[i].p_type == PT_LOAD) {
- uint64_t vaddr = phdrz[i].p_vaddr;
- uint64_t memsz = phdrz[i].p_memsz;
- uint64_t offset = phdrz[i].p_offset;
-
- if (strtab_addr >= vaddr && strtab_addr < vaddr + memsz) {
- strtab_offset = offset + (strtab_addr - vaddr);
- break;
- }
- }
- }
-
- if (strtab_offset == 0) {
- DEBUG(1, "Could not find string table offset in file");
- //goto end;
- }
-
- char *strtab = (char *)allocated_elf + strtab_offset;
- int dep_count = 0;
-
- DEBUG(1, "proc %d libraries", proc->id);
-
- // Теперь ищем зависимости
- for (uint64_t i = 0; i < dyn_size; i++) {
- if (dyn[i].d_tag == DT_NULL) {
- break;
- }
-
- if (dyn[i].d_tag == DT_NEEDED) {
- uint64_t str_offset = dyn[i].d_un.d_val;
-
- if (str_offset < strtab_size) {
- DEBUG(1, " %s", strtab + str_offset);
- dep_count++;
- } else {
- DEBUG(1, " [Error: string offset out of bounds]");
- }
- }
- }
-
- if (dep_count == 0) {
- DEBUG(1, " (no dependencies found)");
- }
- }
- }
-
-end:
- elfload.base = (std::uint64_t)elf_vmm;
- elfload.status = 0;
- memory::paging::enablekernel();
- return elfload;
-}
-
-std::atomic<std::uint64_t> znext = 0;
-std::uint64_t __zrand() {
- uint64_t t = __rdtsc();
- return t * (++znext);
-}
-
-int arch::x86_64::scheduling::loadelf(process_t* proc,char* path,char** argv,char** envp, int free_mem) {
- vfs::stat_t stat;
- userspace_fd_t fd;
- zeromem(&fd);
- zeromem(&stat);
-
- memcpy(fd.path,path,strlen(path));
-
- memcpy(proc->name,path,strlen(path) + 1);
-
- int status = vfs::vfs::stat(&fd,&stat);
- if(status) {
- return status;
- }
-
- char* inter = (char*)memory::pmm::_virtual::alloc(stat.st_size);
-
- vfs::vfs::read(&fd,inter,stat.st_size);
- elfloadresult_t elfload = __scheduling_load_elf(proc,(std::uint8_t*)inter);
-
- memory::pmm::_virtual::free(inter);
- if(elfload.status != 0)
- return elfload.status;
-
- proc->ctx.rsp = (std::uint64_t)memory::vmm::alloc(proc,USERSPACE_STACK_SIZE,PTE_PRESENT | PTE_USER | PTE_RW,0) + USERSPACE_STACK_SIZE - 4096;
-
- memory::vmm::invmapping(proc,proc->ctx.rsp - (4096 * 10),4096 * 10);
- std::uint64_t* _stack = (std::uint64_t*)proc->ctx.rsp;
-
- std::uint64_t random_data_aux = (std::uint64_t)memory::vmm::alloc(proc,4096,PTE_PRESENT | PTE_USER | PTE_RW,0);
- memory::vmm::invmapping(proc,random_data_aux,4096);
-
- std::uint64_t auxv_stack[] = {(std::uint64_t)elfload.real_entry,AT_ENTRY,elfload.phdr,AT_PHDR,elfload.phentsize,AT_PHENT,elfload.phnum,AT_PHNUM,4096,AT_PAGESZ,0,AT_SECURE,random_data_aux,AT_RANDOM,4096,51,elfload.interp_base,AT_BASE};
- std::uint64_t argv_length = __elf_get_length(argv);
- std::uint64_t envp_length = __elf_get_length(envp);
-
- memory::paging::enablepaging(proc->ctx.cr3);
-
- std::uint64_t* randaux = (std::uint64_t*)random_data_aux;
- randaux[0] = __zrand();
- randaux[1] = __zrand();
-
- char** stack_argv = (char**)memory::heap::malloc(8 * (argv_length + 1));
- char** stack_envp = (char**)memory::heap::malloc(8 * (envp_length + 1));
-
- memset(stack_argv,0,8 * (argv_length + 1));
- memset(stack_envp,0,8 * (envp_length + 1));
-
- _stack = __elf_copy_to_stack(argv,_stack,stack_argv,argv_length);
-
- for(int i = 0; i < argv_length / 2; ++i) {
- char* tmp = stack_argv[i];
- stack_argv[i] = stack_argv[argv_length - 1 - i];
- stack_argv[argv_length - 1 - i] = tmp;
- }
-
- _stack = __elf_copy_to_stack(envp,_stack,stack_envp,envp_length);
-
- PUT_STACK(_stack,0);
-
- _stack = __elf_copy_to_stack_without_out(auxv_stack,_stack,sizeof(auxv_stack) / 8);
- PUT_STACK(_stack,0);
-
- _stack = __elf_copy_to_stack_without_out((uint64_t*)stack_envp,_stack,envp_length);
- PUT_STACK(_stack,0);
-
- _stack = __elf_copy_to_stack_without_out((uint64_t*)stack_argv,_stack,argv_length);
- PUT_STACK(_stack,argv_length);
-
- memory::paging::enablekernel();
-
- proc->ctx.rsp = (std::uint64_t)_stack;
- proc->ctx.rip = elfload.interp_entry;
-
- memory::heap::free(stack_argv);
- memory::heap::free(stack_envp);
-
- return 0;
-}
-
-void arch::x86_64::scheduling::wakeup(process_t* proc) {
- proc->lock.unlock(); /* Just clear */
-}
-
-arch::x86_64::process_t* arch::x86_64::scheduling::by_pid(int pid) {
- process_t* proc = head_proc_();
- while(proc) {
- if(proc->id == pid) {
- return proc; }
- proc = proc->next;
- }
- return 0;
-}
-
-arch::x86_64::process_t* arch::x86_64::scheduling::clone3(process_t* proc, clone_args* clarg, int_frame_t* ctx) {
- process_t* nproc = create();
-
- memcpy(&nproc->ctx,ctx,sizeof(int_frame_t));
-
- if(clarg->flags & CLONE_VM) {
- memory::vmm::free(nproc);
- nproc->ctx.cr3 = ctx->cr3;
- nproc->original_cr3 = ctx->cr3;
- nproc->vmm_end = proc->vmm_end;
- nproc->vmm_start = proc->vmm_start;
- nproc->reversedforid = *proc->vmm_id;
- nproc->vmm_id = &nproc->reversedforid;
-
- vmm_obj_t* start = (vmm_obj_t*)proc->vmm_start;
- start->lock.lock();
- start->pthread_count++;
- start->lock.unlock();
-
-
- } else {
- memory::vmm::clone(nproc,proc);
- }
-
- nproc->is_cloned = 1;
- nproc->uid = proc->uid;
-
- if(clarg->flags & CLONE_PARENT) {
- nproc->parent_id = proc->parent_id;
- } else {
- nproc->parent_id = proc->id;
- }
-
- if(clarg->flags & CLONE_THREAD) {
- nproc->thread_group = proc->thread_group;
- } else {
- nproc->thread_group = nproc->id;
- }
-
- if(clarg->tls) {
- nproc->fs_base = clarg->tls;
- } else {
- nproc->fs_base = proc->fs_base;
- }
-
- nproc->exit_signal = clarg->exit_signal;
-
- if(clarg->stack) {
- nproc->ctx.rsp = clarg->stack;
- }
-
- memcpy(nproc->sigsets,proc->sigsets,sizeof(proc->sigsets));
-
- memcpy(&nproc->current_sigset,&proc->current_sigset,sizeof(proc->current_sigset));
- memcpy(nproc->ret_handlers,proc->ret_handlers,sizeof(proc->ret_handlers));
- memcpy(nproc->sig_handlers,proc->sig_handlers,sizeof(proc->sig_handlers));
-
- memset(nproc->cwd,0,4096);
- memset(nproc->name,0,4096);
- memcpy(nproc->cwd,proc->cwd,strlen(proc->cwd));
- memcpy(nproc->name,proc->name,strlen(proc->name));
-
- memcpy(nproc->sse_ctx,proc->sse_ctx,arch::x86_64::cpu::sse::size());
-
- if(clarg->flags & CLONE_FILES) {
- nproc->is_shared_fd = 1;
- nproc->fd_ptr = proc->fd_ptr;
- nproc->fd = proc->fd;
-
- vfs::fdmanager* fd = (vfs::fdmanager*)proc->fd;
-
- proc->fd_lock.lock();
- fd->used_counter++;
- proc->fd_lock.unlock();
- } else {
- *nproc->fd_ptr = *proc->fd_ptr;
- nproc->fd_ptr = &nproc->alloc_fd;
-
- vfs::fdmanager* fd = (vfs::fdmanager*)proc->fd;
- fd->duplicate((vfs::fdmanager*)nproc->fd);
- }
- nproc->ctx.cr3 = nproc->original_cr3;
- return nproc;
-}
-
-arch::x86_64::process_t* arch::x86_64::scheduling::clone(process_t* proc,int_frame_t* ctx) {
- process_t* nproc = create();
- memory::vmm::free(nproc);
-
- nproc->is_cloned = 1;
- nproc->ctx.cr3 = ctx->cr3;
- nproc->original_cr3 = ctx->cr3;
- nproc->uid = proc->uid;
-
- nproc->vmm_end = proc->vmm_end;
- nproc->vmm_start = proc->vmm_start;
-
- nproc->parent_id = proc->id;
- nproc->fs_base = proc->fs_base;
- nproc->reversedforid = *proc->vmm_id;
- nproc->vmm_id = &nproc->reversedforid;
-
- memcpy(&nproc->current_sigset,&proc->current_sigset,sizeof(proc->current_sigset));
- memcpy(nproc->ret_handlers,proc->ret_handlers,sizeof(proc->ret_handlers));
- memcpy(nproc->sig_handlers,proc->sig_handlers,sizeof(proc->sig_handlers));
-
- memset(nproc->cwd,0,4096);
- memset(nproc->name,0,4096);
- memcpy(nproc->cwd,proc->cwd,strlen(proc->cwd));
- memcpy(nproc->name,proc->name,strlen(proc->name));
-
- memcpy(nproc->sse_ctx,proc->sse_ctx,arch::x86_64::cpu::sse::size());
-
- nproc->is_shared_fd = 1;
- nproc->fd_ptr = proc->fd_ptr;
- nproc->fd = proc->fd;
-
- vfs::fdmanager* fd = (vfs::fdmanager*)proc->fd;
-
- proc->fd_lock.lock();
- fd->used_counter++;
- proc->fd_lock.unlock();
-
- // userspace_fd_t* fd = proc->fd;
- // while(fd) {
- // userspace_fd_t* newfd = new userspace_fd_t;
- // memcpy(newfd,fd,sizeof(userspace_fd_t));
-
- // if(newfd->state == USERSPACE_FD_STATE_PIPE) {
- // newfd->pipe->create(newfd->pipe_side);
- // } else if(newfd->state == USERSPACE_FD_STATE_EVENTFD)
- // newfd->eventfd->create();
-
- // newfd->next = nproc->fd;
- // nproc->fd = newfd;
- // fd = fd->next;
- // }
-
- memcpy(&nproc->ctx,ctx,sizeof(int_frame_t));
-
- return nproc;
-}
-
-arch::x86_64::process_t* arch::x86_64::scheduling::fork(process_t* proc,int_frame_t* ctx) {
- process_t* nproc = create();
- memory::vmm::clone(nproc,proc);
-
- nproc->parent_id = proc->id;
- nproc->fs_base = proc->fs_base;
- nproc->uid = proc->uid;
-
- memcpy(nproc->sigsets,proc->sigsets,sizeof(proc->sigsets));
-
- memcpy(&nproc->current_sigset,&proc->current_sigset,sizeof(proc->current_sigset));
- memcpy(nproc->ret_handlers,proc->ret_handlers,sizeof(proc->ret_handlers));
- memcpy(nproc->sig_handlers,proc->sig_handlers,sizeof(proc->sig_handlers));
-
- memset(nproc->cwd,0,4096);
- memset(nproc->name,0,4096);
- memcpy(nproc->cwd,proc->cwd,strlen(proc->cwd));
- memcpy(nproc->name,proc->name,strlen(proc->name));
-
- memcpy(nproc->sse_ctx,proc->sse_ctx,arch::x86_64::cpu::sse::size());
-
- *nproc->fd_ptr = *proc->fd_ptr;
- nproc->fd_ptr = &nproc->alloc_fd;
-
- vfs::fdmanager* fd = (vfs::fdmanager*)proc->fd;
- fd->duplicate((vfs::fdmanager*)nproc->fd);
-
- memcpy(&nproc->ctx,ctx,sizeof(int_frame_t));
- nproc->ctx.cr3 = nproc->original_cr3;
-
- return nproc;
-}
-void arch::x86_64::scheduling::kill(process_t* proc) {
- proc->kill_lock.nowaitlock();
- proc->lock.nowaitlock();
- proc->status = PROCESS_STATE_ZOMBIE;
- proc->is_execd = 1;
- proc->exit_timestamp = time::counter();
- free_sigset_from_list(proc);
- delete proc->pass_fd;
-}
-
-void __scheduling_balance_cpus() {
- int cpu_ptr = 0;
- arch::x86_64::process_t* proc = head_proc;
- extern int how_much_cpus;
- while(proc) {
- if(!proc->kill_lock.test()) {
- proc->target_cpu.store(cpu_ptr++,std::memory_order_release);
- //Log::SerialDisplay(LEVEL_MESSAGE_INFO,"cpu %d to proc %s (%d) cpu_count %d\n",cpu_ptr,proc->name,proc->id,how_much_cpus);
- if(cpu_ptr == how_much_cpus)
- cpu_ptr = 0;
- }
- proc = proc->next;
- }
-}
-
-arch::x86_64::process_t* arch::x86_64::scheduling::create() {
- process_t* proc = (process_t*)memory::pmm::_virtual::alloc(4096);
-
- proc->cwd = (char*)memory::pmm::_virtual::alloc(4096);
- proc->name = (char*)memory::pmm::_virtual::alloc(4096);
- proc->sse_ctx = (char*)memory::pmm::_virtual::alloc(arch::x86_64::cpu::sse::size());
-
- proc->syscall_stack = (std::uint64_t)memory::pmm::_virtual::alloc(SYSCALL_STACK_SIZE);
-
- fpu_head_t* head = (fpu_head_t*)proc->sse_ctx;
- head->dumb5 = 0b0001111110000000;
-
- proc->ctx.cs = 0x20 | 3;
- proc->ctx.ss = 0x18 | 3;
- proc->ctx.rflags = (1 << 9);
- proc->status = PROCESS_STATE_RUNNING;
- proc->lock.nowaitlock();
- proc->kill_lock.unlock();
- proc->fd_ptr = &proc->alloc_fd;
-
- proc->thread_group = proc->id;
-
- *proc->fd_ptr = 3;
-
- proc->is_debug = 0;
- proc->next_alarm = -1;
- proc->virt_timer = -1;
- proc->prof_timer = -1;
-
- proc->sig = new signalmanager;
-
- vfs::fdmanager* z = new vfs::fdmanager(proc);
- proc->fd = (void*)z;
-
- proc->next = head_proc;
- head_proc = proc;
-
-
- proc->id = id_ptr++;
- proc->vmm_id = &proc->id;
-
- proc->pass_fd = new vfs::passingfd_manager;
-
- memory::vmm::initproc(proc);
- memory::vmm::reload(proc);
-
- proc->create_timestamp = time::counter();
-
- __scheduling_balance_cpus();
-
- return proc;
-}
-
-locks::spinlock futex_lock;
-
-int arch::x86_64::scheduling::futexwake(process_t* proc, int* lock, int num_to_wake) {
- process_t* proc0 = head_proc;
- futex_lock.lock();
- int nums = 0;
- while(proc0) {
- // if process vmm is same then they are connected
- if(((proc->vmm_start == proc0->vmm_start)) && proc0->futex == (std::uint64_t)lock) {
- proc0->futex = 0;
- proc0->futex_lock.unlock();
- num_to_wake--;
- DEBUG(proc->is_debug,"futex_wakeup proccess %d from proc %d, futex 0x%p",proc0->id,proc->id,lock);
- nums++;
- } else if((proc0->futex == (std::uint64_t)lock || proc->futex == (std::uint64_t)lock)) {
- DEBUG(proc->is_debug,"same futex 0x%p but calling proc %d is not connected to proc %d",lock,proc->id,proc0->id);
- }
- proc0 = proc0->next;
- }
- futex_lock.unlock();
- return nums;
-}
-
-void arch::x86_64::scheduling::futexwait(process_t* proc, int* lock, int val, int* original_lock,std::uint64_t ts) {
- futex_lock.lock();
- int lock_val = *lock;
- proc->futex_lock.lock();
- proc->futex = (std::uint64_t)original_lock;
- proc->ts = ts;
- futex_lock.unlock();
-}
-int l = 0;
-
-
-#define SIG_DFL 0
-#define SIG_IGN 1
-
-extern "C" void schedulingSchedule(int_frame_t* ctx) {
- extern int is_panic;
-
- if(ctx) {
- if(ctx->cs != 0x08)
- asm volatile("swapgs");
- }
-
- if(is_panic == 1)
- asm volatile("hlt");
-
-scheduleagain:
- arch::x86_64::process_t* current = arch::x86_64::cpu::data()->temp.proc;
-
- cpudata_t* data = arch::x86_64::cpu::data();
-
- if(ctx) {
- if(current) {
- if(!current->kill_lock.test() && !current->_3rd_kill_lock.test()) {
- current->ctx = *ctx;
- current->fs_base = __rdmsr(0xC0000100);
- arch::x86_64::cpu::sse::save((std::uint8_t*)current->sse_ctx);
- current->user_stack = data->user_stack; /* Only user stack should be saved */
-
- if(current->time_start) {
- // it wants something
- std::uint64_t delta = drivers::tsc::currentus() - current->time_start;
- if(current->virt_timer > 0) {
- current->virt_timer -= current->virt_timer > delta ? delta : current->virt_timer;
- }
-
- if(current->prof_timer > 0) {
- current->prof_timer -= current->prof_timer > delta ? delta : current->prof_timer;
- }
-
- current->time_start = 0;
-
- }
-
- }
- }
- }
-
- if(current) {
- if(current->_3rd_kill_lock.test() && !current->kill_lock.test()) {
- memory::paging::enablekernel();
- arch::x86_64::scheduling::kill(current);
-
- if(1)
- memory::vmm::free(current);
-
- vfs::fdmanager* fd = (vfs::fdmanager*)current->fd;
- fd->free();
-
- memory::pmm::_virtual::free(current->cwd);
- memory::pmm::_virtual::free(current->name);
- memory::pmm::_virtual::free(current->sse_ctx);
- } else
- current->lock.unlock();
-
- current = current->next;
- }
-
- ctx = 0;
-
- int current_cpu = data->smp.cpu_id;
-
- while (true) {
- while (current) {
-
- if (!current->kill_lock.test() && current->id != 0 && 1) {
-
- if(1) { // signals are only for user mode, or they must be handled by process itself
- if(!current->lock.test_and_set()) {
-
- // real alarm timer
- if(current->next_alarm != -1 && current->sig) {
- if(drivers::tsc::currentus() >= current->next_alarm) {
- // alarm !!!
- pending_signal_t alarm_sig;
- alarm_sig.sig = SIGALRM;
- current->next_alarm = -1;
- if(current->itimer.it_interval.tv_sec != 0 || current->itimer.it_interval.tv_usec != 0) {
- std::uint64_t offs = current->itimer.it_interval.tv_sec * 1000 * 1000;
- offs += current->itimer.it_interval.tv_usec;
- current->next_alarm = drivers::tsc::currentus() + offs;
- }
- current->sig->push(&alarm_sig);
- }
- }
-
- if(current->virt_timer != -1 && current->sig) {
- if(current->virt_timer == 0) {
- // alarm !!!
- pending_signal_t alarm_sig;
- alarm_sig.sig = SIGVTALRM;
- current->virt_timer = -1;
- if(current->vitimer.it_interval.tv_sec != 0 || current->vitimer.it_interval.tv_usec != 0) {
- std::uint64_t offs = current->vitimer.it_interval.tv_sec * 1000 * 1000;
- offs += current->vitimer.it_interval.tv_usec;
- current->virt_timer = offs;
- }
- current->sig->push(&alarm_sig);
- }
- }
-
- if(current->prof_timer != -1 && current->sig) {
- if(current->prof_timer == 0) {
- // alarm !!!
- pending_signal_t alarm_sig;
- alarm_sig.sig = SIGPROF;
- current->prof_timer = -1;
- if(current->proftimer.it_interval.tv_sec != 0 || current->proftimer.it_interval.tv_usec != 0) {
- std::uint64_t offs = current->proftimer.it_interval.tv_sec * 1000 * 1000;
- offs += current->proftimer.it_interval.tv_usec;
- current->prof_timer = offs;
- }
- current->sig->push(&alarm_sig);
- }
- }
-
- if(!ctx) {
- int_frame_t temp_ctx;
- ctx = &temp_ctx;
- }
-
- int is_possible = 1;
- if(current->ctx.cs == 0x08) {
- is_possible = 0;
- }
-
- if(is_possible) {
- pending_signal_t new_sig;
- int status = current->sig->popsigset(&new_sig,&current->current_sigset);
- if(status != -1) {
-
- if((std::uint64_t)current->sig_handlers[new_sig.sig] == SIG_IGN || (std::uint64_t)current->sig_handlers[new_sig.sig] == SIG_DFL || new_sig.sig == SIGKILL) {
- // sig is blocked, push it back
- if(current->sig_handlers[new_sig.sig] == SIG_DFL) {
- switch(new_sig.sig) {
- case SIGCHLD:
- case SIGCONT:
- case SIGURG:
- case SIGWINCH:
- break; //ignore
- case SIGSTOP:
- case SIGTSTP:
- case SIGTTIN:
- case SIGTTOU:
- Log::SerialDisplay(LEVEL_MESSAGE_WARN,"unimplemented process stop to proc %d, sig %d\n",current->id,new_sig.sig);
- break;
-
- default: {
- char* vm_start = current->vmm_start;
- arch::x86_64::process_t* currentz = arch::x86_64::scheduling::head_proc_();
- memory::paging::enablekernel();
- DEBUG(1,"sig kill %d",new_sig.sig);
- while(currentz) {
- if(currentz->vmm_start == vm_start) {
- currentz->exit_code = status;
- arch::x86_64::scheduling::kill(currentz);
-
- if(1)
- memory::vmm::free(currentz);
-
- vfs::fdmanager* fd = (vfs::fdmanager*)currentz->fd;
- fd->free();
-
- memory::pmm::_virtual::free(currentz->cwd);
- memory::pmm::_virtual::free(currentz->name);
- memory::pmm::_virtual::free(currentz->sse_ctx);
- }
- currentz = currentz->next;
- }
- goto scheduleagain;
- }
- };
- }
-
- } else {
-
- if(current->is_restore_sigset) {
- // syscall requested restore sigset
- memcpy(&current->current_sigset,&current->temp_sigset,sizeof(sigset_t));
- current->is_restore_sigset = 0;
- }
-
- sigtrace new_sigtrace;
-
- mcontext_t temp_mctx = {0};
- int_frame_to_mcontext(&current->ctx,&temp_mctx);
-
- memory::paging::enablepaging(current->original_cr3);
-
- std::uint64_t* new_stack = 0;
-
- if(!current->sigtrace_obj) {
- new_stack = (std::uint64_t*)(current->altstack.ss_sp == 0 ? current->ctx.rsp - 8 : (std::uint64_t)current->altstack.ss_sp);
- } else {
- new_stack = (std::uint64_t*)(current->ctx.rsp - 8);
- }
-
- --new_stack;
-
- new_stack = (std::uint64_t*)__stack_memcpy((std::uint64_t)new_stack,&temp_mctx,sizeof(mcontext_t));
-
- new_sigtrace.mctx = (mcontext_t*)new_stack;
- --new_stack;
-
- siginfo_t siginfo;
- memset(&siginfo,0,sizeof(siginfo));
-
- new_stack = (std::uint64_t*)__stack_memcpy((std::uint64_t)new_stack,&siginfo,sizeof(siginfo_t));
- std::uint64_t siginfoz = (std::uint64_t)new_stack;
-
- --new_stack;
-
- new_sigtrace.next = current->sigtrace_obj;
-
- new_sigtrace.sigset = current->current_sigset;
-
- new_stack = (std::uint64_t*)__stack_memcpy((std::uint64_t)new_stack,&new_sigtrace,sizeof(sigtrace));
-
- sigtrace* new_sigstrace_u = (sigtrace*)new_stack;
-
- new_stack = (std::uint64_t*)__stack_memcpy((std::uint64_t)new_stack,current->sse_ctx,arch::x86_64::cpu::sse::size());
-
- new_sigstrace_u->fpu_state = (void*)new_stack;
- current->sigtrace_obj = new_sigstrace_u;
-
- --new_stack;
- *--new_stack = (std::uint64_t)current->ret_handlers[new_sig.sig];
-
- // now setup new registers and stack
-
- current->ctx.rdi = new_sig.sig;
- current->ctx.rsi = 0;
- current->ctx.rdx = 0;
- current->ctx.rsp = (std::uint64_t)new_stack;
- current->ctx.rip = (std::uint64_t)current->sig_handlers[new_sig.sig];
- current->ctx.cs = 0x20 | 3;
- current->ctx.ss = 0x18 | 3;
- current->ctx.rflags = (1 << 9);
-
- memcpy(ctx, &current->ctx, sizeof(int_frame_t));
-
- __wrmsr(0xC0000100, current->fs_base);
- arch::x86_64::cpu::sse::load((std::uint8_t*)current->sse_ctx);
-
- if(ctx->cs & 3)
- ctx->ss |= 3;
-
- if(ctx->ss & 3)
- ctx->cs |= 3;
-
- if(ctx->cs == 0x20)
- ctx->cs |= 3;
-
- if(ctx->ss == 0x18)
- ctx->ss |= 3;
-
- data->kernel_stack = current->syscall_stack + SYSCALL_STACK_SIZE;
- data->user_stack = current->user_stack;
- data->temp.proc = current;
-
- int prio_div = current->prio < 0 ? (current->prio * -1) : 1;
- prio_div++;
-
- if(current->virt_timer != -1 || current->prof_timer != -1) {
- // it will request for time
-
- current->time_start = drivers::tsc::currentus();
- }
-
- arch::x86_64::cpu::lapic::eoi();
-
- if(ctx->cs != 0x08)
- asm volatile("swapgs");
- schedulingEnd(ctx);
- }
-
- }
- }
-
- memcpy(ctx, &current->ctx, sizeof(int_frame_t));
-
- __wrmsr(0xC0000100, current->fs_base);
- arch::x86_64::cpu::sse::load((std::uint8_t*)current->sse_ctx);
-
- if(ctx->cs & 3)
- ctx->ss |= 3;
-
- if(ctx->ss & 3)
- ctx->cs |= 3;
-
- if(ctx->cs == 0x20)
- ctx->cs |= 3;
-
- if(ctx->ss == 0x18)
- ctx->ss |= 3;
-
- data->kernel_stack = current->syscall_stack + SYSCALL_STACK_SIZE;
- data->user_stack = current->user_stack;
- data->temp.proc = current;
-
- int prio_div = current->prio < 0 ? (current->prio * -1) : 1;
- prio_div++;
-
- if(current->virt_timer != -1 || current->prof_timer != -1) {
- // it will request for time
- current->time_start = drivers::tsc::currentus();
- }
-
-
- arch::x86_64::cpu::lapic::eoi();
-
- if(ctx->cs != 0x08)
- asm volatile("swapgs");
-
- schedulingEnd(ctx);
- }
- }
- }
- current = current->next;
- }
- current = head_proc;
- }
-}
-
-void arch::x86_64::scheduling::create_kernel_thread(void (*func)(void*), void* arg) {
- process_t* proc = (process_t*)memory::pmm::_virtual::alloc(4096);
-
- proc->cwd = (char*)memory::pmm::_virtual::alloc(4096);
- proc->name = (char*)memory::pmm::_virtual::alloc(4096);
- proc->sse_ctx = (char*)memory::pmm::_virtual::alloc(arch::x86_64::cpu::sse::size());
-
- proc->syscall_stack = (std::uint64_t)memory::pmm::_virtual::alloc(SYSCALL_STACK_SIZE);
-
- fpu_head_t* head = (fpu_head_t*)proc->sse_ctx;
- head->dumb5 = 0b0001111110000000;
-
- proc->ctx.cs = 0x08;
- proc->ctx.ss = 0;
- proc->ctx.rflags = (1 << 9);
- proc->ctx.rsp = proc->syscall_stack + (SYSCALL_STACK_SIZE - 4096);
- proc->ctx.rip = (std::uint64_t)func;
- proc->ctx.rdi = (std::uint64_t)arg;
- proc->ctx.cr3 = memory::paging::kernelget();
- proc->original_cr3 = memory::paging::kernelget();
- proc->status = PROCESS_STATE_RUNNING;
- proc->lock.nowaitlock();
- proc->kill_lock.unlock();
-
- proc->id = id_ptr++;
-
- proc->next = head_proc;
- head_proc = proc;
-
- proc->create_timestamp = time::counter();
-
- __scheduling_balance_cpus();
-
- wakeup(proc);
-
- return;
-}
-
-arch::x86_64::process_t* arch::x86_64::scheduling::head_proc_() {
- return head_proc;
-}
-
-void arch::x86_64::scheduling::init() {
- process_t* main_proc = create();
- main_proc->kill_lock.nowaitlock();
- arch::x86_64::interrupts::idt::set_entry((std::uint64_t)schedulingEnter,32,0x8E,2);
-}
-
-void arch::x86_64::scheduling::sigreturn(process_t* proc) { // pop values from stack
- sigtrace* st = proc->sigtrace_obj;
- memory::paging::enablepaging(proc->original_cr3);
- if(!st)
- return;
- mcontext_t* mctx = st->mctx;
- proc->current_sigset = st->sigset;
- mcontext_to_int_frame(mctx,&proc->ctx);
- proc->ctx.cr3 = proc->original_cr3;
- proc->ctx.cs = 0x20 | 3;
- proc->ctx.ss = 0x18 | 3;
- proc->ctx.rflags |= (1 << 9);
- memcpy(proc->sse_ctx,st->fpu_state,arch::x86_64::cpu::sse::size());
- proc->sigtrace_obj = st->next;
- //DEBUG(1,"returning from sig to rip 0x%p, proc %d",proc->ctx.rip,proc->id);
- memory::paging::enablekernel();
-
- if(proc->ctx.cs != 0x08)
- asm volatile("swapgs");
-
- schedulingEnd(&proc->ctx);
- __builtin_unreachable();
-} \ No newline at end of file
diff --git a/kernel/src/arch/x86_64/syscalls/file.cpp b/kernel/src/arch/x86_64/syscalls/file.cpp
deleted file mode 100644
index 18e1ab3..0000000
--- a/kernel/src/arch/x86_64/syscalls/file.cpp
+++ /dev/null
@@ -1,2737 +0,0 @@
-
-#include <arch/x86_64/syscalls/syscalls.hpp>
-#include <generic/vfs/vfs.hpp>
-
-#include <generic/mm/vmm.hpp>
-
-#include <arch/x86_64/cpu/data.hpp>
-#include <arch/x86_64/scheduling.hpp>
-
-#include <generic/mm/pmm.hpp>
-
-#include <generic/vfs/fd.hpp>
-
-#include <generic/vfs/devfs.hpp>
-
-#include <drivers/tsc.hpp>
-
-#include <etc/etc.hpp>
-#include <etc/errno.hpp>
-
-#include <etc/logging.hpp>
-
-#include <arch/x86_64/syscalls/sockets.hpp>
-
-#include <cstdint>
-
-long long sys_access(char* path, int mode) {
- SYSCALL_IS_SAFEZ(path,4096);
-
- arch::x86_64::process_t* proc = CURRENT_PROC;
-
- char first_path[2048];
- memset(first_path,0,2048);
- if(0)
- memcpy(first_path,vfs::fdmanager::search(proc,0)->path,strlen(vfs::fdmanager::search(proc,0)->path));
- else if(1 && proc->cwd)
- memcpy(first_path,proc->cwd,strlen(proc->cwd));
-
- char kpath[2048];
- memset(kpath,0,2048);
- copy_in_userspace_string(proc,kpath,(void*)path,2048);
-
- char result[2048];
- memset(result,0,2048);
- vfs::resolve_path(kpath,first_path,result,1,0);
-
- userspace_fd_t fd;
- memset(&fd,0,sizeof(userspace_fd_t));
- memcpy(fd.path,result,strlen(result) + 1);
-
- vfs::stat_t stat;
- int status = vfs::vfs::stat(&fd,&stat);
- return status;
-}
-
-long long sys_faccessat(int dirfd, char* path, int mode, int flags) {
- SYSCALL_IS_SAFEZ(path,4096);
-
- if(!path)
- return -EINVAL;
-
- arch::x86_64::process_t* proc = CURRENT_PROC;
-
- char first_path[2048];
- memset(first_path,0,2048);
- if(dirfd >= 0)
- memcpy(first_path,vfs::fdmanager::search(proc,dirfd)->path,strlen(vfs::fdmanager::search(proc,dirfd)->path));
- else if(dirfd == AT_FDCWD && proc->cwd)
- memcpy(first_path,proc->cwd,strlen(proc->cwd));
-
- char kpath[2048];
- memset(kpath,0,2048);
- copy_in_userspace_string(proc,kpath,(void*)path,2048);
-
- char result[2048];
- memset(result,0,2048);
- vfs::resolve_path(kpath,first_path,result,1,0);
-
- userspace_fd_t fd;
- memset(&fd,0,sizeof(userspace_fd_t));
- memcpy(fd.path,result,strlen(result) + 1);
-
- vfs::stat_t stat;
- int status = 0;
-
- if(flags & AT_SYMLINK_NOFOLLOW)
- status = vfs::vfs::nosym_stat(&fd,&stat);
- else
- status = vfs::vfs::stat(&fd,&stat);
-
- return status;
-}
-
-long long sys_openat(int dirfd, const char* path, int flags, int_frame_t* ctx) {
- SYSCALL_IS_SAFEZ((void*)path,0);
- if(!path)
- return -EFAULT;
-
- arch::x86_64::process_t* proc = CURRENT_PROC;
-
- std::uint32_t mode = ctx->r10;
-
- char first_path[2048];
- memset(first_path,0,2048);
- if(dirfd >= 0)
- memcpy(first_path,vfs::fdmanager::search(proc,dirfd)->path,strlen(vfs::fdmanager::search(proc,dirfd)->path));
- else if(dirfd == AT_FDCWD && proc->cwd)
- memcpy(first_path,proc->cwd,strlen(proc->cwd));
-
- char kpath[2048];
- memset(kpath,0,2048);
- copy_in_userspace_string(proc,kpath,(void*)path,2048);
-
- char result[2048];
- memset(result,0,2048);
- vfs::resolve_path(kpath,first_path,result,1,0);
-
- DEBUG(proc->is_debug,"Trying to open %s, %s + %s from proc %d",result,first_path,path,proc->id);
-
- if(result[0] == '\0') {
- result[0] = '/';
- result[1] = '\0';
- }
-
- int new_fd = vfs::fdmanager::create(proc);
-
- userspace_fd_t* new_fd_s = vfs::fdmanager::search(proc,new_fd);
- memset(new_fd_s->path,0,2048);
- memcpy(new_fd_s->path,result,strlen(result));
-
- new_fd_s->offset = 0;
- new_fd_s->queue = 0;
- new_fd_s->pipe = 0;
- new_fd_s->pipe_side = 0;
- new_fd_s->cycle = 0;
- new_fd_s->is_a_tty = 0;
- new_fd_s->flags = flags; // copy flags
-
- if(flags & O_CREAT)
- vfs::vfs::touch(new_fd_s->path, mode);
-
- new_fd_s->mode = mode;
-
- std::uint64_t start = drivers::tsc::currentnano();
- std::int32_t status = vfs::vfs::open(new_fd_s);
-
- if(status != 0) {
- new_fd_s->state = USERSPACE_FD_STATE_UNUSED;
- DEBUG(proc->is_debug,"Failed to open %s (%d:%s + %s) from proc %d, is_creat %d, is_trunc %d, flags %d (%s)",result,dirfd,first_path,path,proc->id,flags & O_CREAT,flags & O_TRUNC,flags,proc->name);
- return -status;
- }
-
- vfs::stat_t stat;
- std::int32_t stat_status = vfs::vfs::stat(new_fd_s,&stat);
-
- if(stat_status == 0)
- if(flags & __O_DIRECTORY)
- if(!(stat.st_mode & S_IFDIR)) {
- new_fd_s->state = USERSPACE_FD_STATE_UNUSED;
- return -ENOTDIR;
- }
-
- if(flags & O_TRUNC)
- vfs::vfs::write(new_fd_s,(void*)"\0",1);
-
- if(flags & O_APPEND)
- new_fd_s->offset = stat.st_size;
-
- if(status != 0) {
- vfs::fdmanager* fdm = (vfs::fdmanager*)proc->fd;
- fdm->close(new_fd_s->index);
- }
-
- std::uint64_t end = drivers::tsc::currentnano();
- DEBUG(0,"open takes %llu time, status %d, %s",end - start,status,new_fd_s->path);
-
- if(status != 0)
- DEBUG(proc->is_debug,"Failed to open %s (%s + %s) from proc %d",result,first_path,path,proc->id);
-
- new_fd_s->offset = 0;
-
- DEBUG(proc->is_debug,"Open %s (%d) from proc %d",result,new_fd,proc->id);
-
- return status == 0 ? new_fd : -status;
-}
-
-typedef struct stackframe {
- struct stackframe* rbp;
- uint64_t rip;
-} __attribute__((packed)) stackframe_t;
-
-long long sys_pread(int fd, void *buf, size_t count, int_frame_t* ctx) {
-
- std::uint64_t off = ctx->r10;
- SYSCALL_IS_SAFEZ(buf,count);
-
- arch::x86_64::process_t* proc = CURRENT_PROC;
-
- userspace_fd_t* fd_sz = vfs::fdmanager::search(proc,fd);
- if(!fd_sz)
- return -EBADF;
-
- userspace_fd_t fd_ss = *fd_sz;
- fd_ss.offset = off;
-
- userspace_fd_t* fd_s = &fd_ss;
-
- if(fd_s->can_be_closed)
- fd_s->can_be_closed = 0;
-
- DEBUG(proc->is_debug,"Trying to read %s (fd %d) with state %d from proc %d, pipe 0x%p (%s) count %lli",fd_s->path,fd,fd_s->state,proc->id,fd_s->pipe,proc->name,count);
-
- char* temp_buffer = (char*)buf;
- std::int64_t bytes_read;
- if(fd_s->state == USERSPACE_FD_STATE_FILE)
- bytes_read = vfs::vfs::read(fd_s,temp_buffer,count);
- else if(fd_s->state == USERSPACE_FD_STATE_PIPE && fd_s->pipe) {
- if(fd_s->pipe_side != PIPE_SIDE_READ)
- return -EBADF;
-
- proc->debug1 = fd_s->pipe->lock.test();
-
- bytes_read = fd_s->pipe->read(&fd_s->read_counter,temp_buffer,count,(fd_s->flags & O_NONBLOCK) ? 1 : 0);
-
- if(bytes_read == -EAGAIN && (fd_s->pipe->flags & O_NONBLOCK || fd_s->flags & O_NONBLOCK) && !fd_s->pipe->is_closed.test())
- return -EAGAIN;
-
- } else if(fd_s->state == USERSPACE_FD_STATE_SOCKET) {
-
- if(!fd_s->write_socket_pipe || !fd_s->read_socket_pipe)
- return -EFAULT;
-
- if(fd_s->other_state == USERSPACE_FD_OTHERSTATE_MASTER) {
- bytes_read = fd_s->write_socket_pipe->read(&fd_s->read_counter,temp_buffer,count,(fd_s->flags & O_NONBLOCK) ? 1 : 0);
- } else {
- bytes_read = fd_s->read_socket_pipe->read(&fd_s->read_counter,temp_buffer,count,(fd_s->flags & O_NONBLOCK) ? 1 : 0);
- }
-
- if(bytes_read == -EAGAIN)
- return -EAGAIN;
-
- if(bytes_read == 0)
- return 0;
-
- } else if(fd_s->state == USERSPACE_FD_STATE_EVENTFD) {
- if(count != 8)
- return -EINVAL;
- std::uint64_t* _8sizebuf = (std::uint64_t*)buf;
- bytes_read = fd_s->eventfd->read(_8sizebuf);
- } else
- return -EBADF;
-
- return bytes_read;
-}
-
-long long sys_read(int fd, void *buf, size_t count) {
- SYSCALL_IS_SAFEZ(buf,count);
-
- arch::x86_64::process_t* proc = CURRENT_PROC;
-
- userspace_fd_t* fd_s = vfs::fdmanager::search(proc,fd);
- if(!fd_s)
- return -EBADF;
-
- if(fd_s->can_be_closed)
- fd_s->can_be_closed = 0;
-
- DEBUG(proc->is_debug,"Trying to read %s (fd %d) with state %d from proc %d, pipe 0x%p (%s) count %lli",fd_s->path,fd,fd_s->state,proc->id,fd_s->pipe,proc->name,count);
-
- char* temp_buffer = (char*)buf;
- std::int64_t bytes_read;
- if(fd_s->state == USERSPACE_FD_STATE_FILE) {
- bytes_read = vfs::vfs::read(fd_s,temp_buffer,count);
-
- }
- else if(fd_s->state == USERSPACE_FD_STATE_PIPE && fd_s->pipe) {
- if(fd_s->pipe_side != PIPE_SIDE_READ)
- return -EBADF;
-
- proc->debug1 = fd_s->pipe->lock.test();
-
- bytes_read = fd_s->pipe->read(&fd_s->read_counter,temp_buffer,count,(fd_s->flags & O_NONBLOCK) ? 1 : 0);
-
- if(bytes_read == -EAGAIN && (fd_s->pipe->flags & O_NONBLOCK || fd_s->flags & O_NONBLOCK) && !fd_s->pipe->is_closed.test())
- return -EAGAIN;
-
- } else if(fd_s->state == USERSPACE_FD_STATE_SOCKET) {
-
- if(!fd_s->write_socket_pipe || !fd_s->read_socket_pipe)
- return -EFAULT;
-
- if(fd_s->other_state == USERSPACE_FD_OTHERSTATE_MASTER) {
- bytes_read = fd_s->write_socket_pipe->read(&fd_s->read_counter,temp_buffer,count,(fd_s->flags & O_NONBLOCK) ? 1 : 0);
- } else {
- bytes_read = fd_s->read_socket_pipe->read(&fd_s->read_counter,temp_buffer,count,(fd_s->flags & O_NONBLOCK) ? 1 : 0);
- }
-
- if(bytes_read == -EAGAIN)
- return -EAGAIN;
-
- if(bytes_read == 0)
- return 0;
-
- } else if(fd_s->state == USERSPACE_FD_STATE_EVENTFD) {
- if(count != 8)
- return -EINVAL;
- std::uint64_t* _8sizebuf = (std::uint64_t*)buf;
- bytes_read = fd_s->eventfd->read(_8sizebuf);
- } else
- return -EBADF;
-
- return bytes_read;
-}
-
-long long sys_writev(int fd, wiovec* vec, unsigned long vlen) {
- SYSCALL_IS_SAFEZ(vec,vlen * sizeof(wiovec));
- arch::x86_64::process_t* proc = CURRENT_PROC;
- userspace_fd_t* fd_s = vfs::fdmanager::search(proc,fd);
- if(!fd_s) {
- DEBUG(1,"fail write fd %d from proc %d, proc->fd is 0x%p, %s\n",fd,proc->id,proc->fd,vec[0].iov_base);
- return -EBADF;
- }
-
- if(fd_s->can_be_closed)
- fd_s->can_be_closed = 0;
-
- std::uint64_t full_bytes_written = 0;
-
- for(unsigned long i = 0;i < vlen;i++) {
- wiovec cur_vec = vec[i];
- char* temp_buffer = (char*)cur_vec.iov_base;
- std::uint64_t count = cur_vec.iov_len;
- std::int64_t bytes_written;
-
- DEBUG(proc->is_debug,"Writing %s with content %s fd %d state %d from proc %d count %d writ sock 0x%p",fd_s->state == USERSPACE_FD_STATE_FILE ? fd_s->path : "Not file",temp_buffer,fd,fd_s->state,proc->id,count,fd_s->write_socket_pipe);
-
- if(fd_s->state == USERSPACE_FD_STATE_FILE)
- bytes_written = vfs::vfs::write(fd_s,temp_buffer,count);
- else if(fd_s->state == USERSPACE_FD_STATE_PIPE) {
- if(fd_s->pipe_side != PIPE_SIDE_WRITE)
- return -EBADF;
- bytes_written = fd_s->pipe->write(temp_buffer,count,proc->id);
- } else if(fd_s->state == USERSPACE_FD_STATE_SOCKET) {
-
- if(!fd_s->write_socket_pipe || !fd_s->read_socket_pipe)
- return -EFAULT;
-
- if(fd_s->other_state == USERSPACE_FD_OTHERSTATE_MASTER) {
- bytes_written = fd_s->read_socket_pipe->write(temp_buffer,count,proc->id);
- } else {
- bytes_written = fd_s->write_socket_pipe->write(temp_buffer,count,proc->id);
- }
-
- if(bytes_written == 0)
- return 0;
-
- } else if(fd_s->state == USERSPACE_FD_STATE_EVENTFD) {
- if(count != 8)
- return -EINVAL;
- std::uint64_t* _8sizebuf = (std::uint64_t*)temp_buffer;
- bytes_written = fd_s->eventfd->write(*_8sizebuf);
- } else
- return -EBADF;
- full_bytes_written += bytes_written;
- }
-
- return full_bytes_written;
-}
-
-long long sys_write(int fd, const void *buf, size_t count) {
- SYSCALL_IS_SAFEZ((void*)buf,count);
-
- arch::x86_64::process_t* proc = CURRENT_PROC;
- userspace_fd_t* fd_s = vfs::fdmanager::search(proc,fd);
- if(!fd_s) {
- DEBUG(proc->is_debug,"fail write fd %d from proc %d, proc->fd is 0x%p\n",fd,proc->id,proc->fd);
- return -EBADF;
- }
-
- if(fd_s->can_be_closed)
- fd_s->can_be_closed = 0;
-
- char* temp_buffer = (char*)buf;
-
- const char* _0 = "Content view is disabled in files";
- DEBUG(proc->is_debug,"Writing %s with content %s fd %d state %d from proc %d count %d writ sock 0x%p",fd_s->state == USERSPACE_FD_STATE_FILE ? fd_s->path : "Not file",buf,fd,fd_s->state,proc->id,count,fd_s->write_socket_pipe);
-
- if(0) {
- Log::SerialDisplay(LEVEL_MESSAGE_INFO,"%s off %lli, new off %lli\n",buf,fd_s->offset,fd_s->offset + count);
- }
-
- std::int64_t bytes_written;
- if(fd_s->state == USERSPACE_FD_STATE_FILE)
- bytes_written = vfs::vfs::write(fd_s,temp_buffer,count);
- else if(fd_s->state == USERSPACE_FD_STATE_PIPE) {
- if(fd_s->pipe_side != PIPE_SIDE_WRITE)
- return -EBADF;
- bytes_written = fd_s->pipe->write(temp_buffer,count,proc->id);
- } else if(fd_s->state == USERSPACE_FD_STATE_SOCKET) {
-
- if(!fd_s->write_socket_pipe || !fd_s->read_socket_pipe)
- return -EFAULT;
-
- if(fd_s->other_state == USERSPACE_FD_OTHERSTATE_MASTER) {
- bytes_written = fd_s->read_socket_pipe->write(temp_buffer,count,proc->id);
- } else {
- bytes_written = fd_s->write_socket_pipe->write(temp_buffer,count,proc->id);
- }
-
- if(bytes_written == 0)
- return 0;
-
- } else if(fd_s->state == USERSPACE_FD_STATE_EVENTFD) {
- if(count != 8)
- return -EINVAL;
- std::uint64_t* _8sizebuf = (std::uint64_t*)buf;
- bytes_written = fd_s->eventfd->write(*_8sizebuf);
- } else
- return -EBADF;
-
-
- return bytes_written;
-}
-
-#define SEEK_SET 0
-#define SEEK_CUR 1
-#define SEEK_END 2
-
-long long sys_sendto(int s, void* msg, size_t len) {
- return sys_write(s,msg,len);
-}
-
-long long sys_lseek(int fd, long offset, int whence) {
- arch::x86_64::process_t* proc = CURRENT_PROC;
-
- userspace_fd_t* fd_s = vfs::fdmanager::search(proc,fd);
-
- DEBUG(proc->is_debug,"lseek fd %d offset %lli, whence %d",fd,offset,whence);
-
- if(!fd_s)
- return -EBADF;
-
- if(fd_s->state == USERSPACE_FD_STATE_PIPE || fd_s->is_a_tty)
- return 0;
-
- switch (whence)
- {
- case SEEK_SET:
- fd_s->offset = offset;
- break;
-
- case SEEK_CUR:
- fd_s->offset += offset;
- break;
-
- case SEEK_END: {
- vfs::stat_t stat;
- int res = vfs::vfs::stat(fd_s,&stat);
-
- if(res != 0) {
- return -res;
- }
-
- fd_s->offset = stat.st_size + offset;
- break;
- }
-
- default:
- return -EINVAL;
- }
-
- return fd_s->offset;
-
-}
-
-long long sys_close(int fd) {
- arch::x86_64::process_t* proc = CURRENT_PROC;
- userspace_fd_t* fd_s = vfs::fdmanager::search(proc,fd);
-
- if(!fd_s && fd > 2)
- return -EBADF;
- else if(fd < 3 && !fd_s)
- return 0; // ignoring
-
- if(fd_s->state != USERSPACE_FD_STATE_SOCKET) {
- DEBUG(proc->is_debug,"closing %d from proc %d pipe 0x%p",fd,proc->id,fd_s->pipe);
- } else
- DEBUG(proc->is_debug,"closing unix socket %d connected to proc %d from proc %d",fd,fd_s->socket_pid,proc->id);
-
- if(fd_s->can_be_closed)
- return -EBADF;
-
- proc->fd_lock.lock();
-
- if(fd < 3)
- fd_s->can_be_closed = 1;
-
- if(fd_s->state == USERSPACE_FD_STATE_PIPE) {
- fd_s->pipe->close(fd_s->pipe_side);
- } else if(fd_s->state == USERSPACE_FD_STATE_FILE || fd_s->state == USERSPACE_FD_STATE_SOCKET)
- vfs::vfs::close(fd_s);
- else if(fd_s->state == USERSPACE_FD_STATE_EVENTFD)
- fd_s->eventfd->close();
-
- if(!fd_s->is_a_tty && fd_s->index > 2)
- fd_s->state = USERSPACE_FD_STATE_UNUSED;
-
- proc->fd_lock.unlock();
-
- return 0;
-}
-
-long long sys_fstat(int fd, void* out) {
- int flags = 0;
- arch::x86_64::process_t* proc = CURRENT_PROC;
- userspace_fd_t* fd_s = vfs::fdmanager::search(proc,fd);
-
- assert(sizeof(vfs::stat_t) == 144,"omg");
-
- SYSCALL_IS_SAFEZ(out,4096);
- memset(out,0,sizeof(vfs::stat_t));
-
- if(!fd_s)
- return -EBADF;
-
- if(!out)
- return -EBADF;
-
- DEBUG(proc->is_debug,"Trying to fstat %s (fd %d) from proc %d",fd_s->path,fd,proc->id);
-
- if(fd_s->state == USERSPACE_FD_STATE_FILE) {
-
- vfs::stat_t stat;
- int status;
- if(flags & AT_SYMLINK_NOFOLLOW) {
- status = vfs::vfs::nosym_stat(fd_s,&stat);
- }
- else
- status = vfs::vfs::stat(fd_s,&stat);
- if(status != 0)
- return -status;
- copy_in_userspace(proc,out,&stat,sizeof(vfs::stat_t));
- } else {
- vfs::stat_t stat;
- memset(&stat,0,sizeof(vfs::stat_t));
- if(fd_s->state == USERSPACE_FD_STATE_SOCKET)
- stat.st_mode |= S_IFSOCK;
- else if(fd_s->state == USERSPACE_FD_STATE_PIPE)
- stat.st_mode |= S_IFIFO;
- copy_in_userspace(proc,out,&stat,sizeof(vfs::stat_t));
- return 0;
- }
- //DEBUG(1,"ret ino %d",((vfs::stat_t*)out)->st_ino);
- return 0;
-}
-
-
-long long sys_newfstatat(int fd, char* path, void* out, int_frame_t* ctx) {
- arch::x86_64::process_t* proc = CURRENT_PROC;
- userspace_fd_t* fd_sz = vfs::fdmanager::search(proc,fd);
- userspace_fd_t fd_tt;
- userspace_fd_t* fd_s = &fd_tt;
-
- memset(out,0,sizeof(vfs::stat_t));
-
- int flags = ctx->r10;
-
- if(!fd_sz && fd != -100)
- return -EBADF;
-
- if(flags & AT_EMPTY_PATH && !path) {
- if(!fd_sz)
- return -EBADF;
- fd_s = fd_sz;
- } else {
-
- if(!path)
- return -EINVAL;
-
- char first_path[2048];
- memset(first_path,0,2048);
- if(fd >= 0)
- memcpy(first_path,vfs::fdmanager::search(proc,fd)->path,strlen(vfs::fdmanager::search(proc,fd)->path));
- else if(fd == AT_FDCWD && proc->cwd)
- memcpy(first_path,proc->cwd,strlen(proc->cwd));
-
- char kpath[2048];
- memset(kpath,0,2048);
- copy_in_userspace_string(proc,kpath,(void*)path,2048);
-
- char result[2048];
- memset(result,0,2048);
- vfs::resolve_path(kpath,first_path,result,1,0);
- memset(&fd_tt,0,sizeof(userspace_fd_t));
- memcpy(fd_tt.path,result,strlen(result) + 1);
- fd_tt.state = USERSPACE_FD_STATE_FILE;
- }
-
- if(!out)
- return -EINVAL;
-
- DEBUG(proc->is_debug,"Trying to newfstatat %s (fd %d), state %d from proc %d",fd_s->path,fd,proc->id);
-
- if(fd_s->state == USERSPACE_FD_STATE_FILE) {
-
- vfs::stat_t stat;
- int status;
- if(flags & AT_SYMLINK_NOFOLLOW) {
- status = vfs::vfs::nosym_stat(fd_s,&stat);
- }
- else
- status = vfs::vfs::stat(fd_s,&stat);
- //DEBUG(1,"status %d\n",status);
- if(status != 0)
- return -status;
- copy_in_userspace(proc,out,&stat,sizeof(vfs::stat_t));
- } else {
- vfs::stat_t stat;
- memset(&stat,0,sizeof(vfs::stat_t));
- if(fd_s->state == USERSPACE_FD_STATE_SOCKET)
- stat.st_mode |= S_IFSOCK;
- else if(fd_s->state == USERSPACE_FD_STATE_PIPE)
- stat.st_mode |= S_IFIFO;
- copy_in_userspace(proc,out,&stat,sizeof(vfs::stat_t));
- return 0;
- }
- //DEBUG(1,"ret ino %d",((vfs::stat_t*)out)->st_ino);
- return 0;
-}
-
-syscall_ret_t sys_pathstat(char* path, void* out, int flags, int_frame_t* ctx) {
- SYSCALL_IS_SAFEA(path,4096);
- if(!path)
- return {0,EINVAL,0};
-
- if(!out)
- return {0,EINVAL,0};
-
- arch::x86_64::process_t* proc = CURRENT_PROC;
-
- char first_path[2048];
- memset(first_path,0,2048);
- memcpy(first_path,proc->cwd,strlen(proc->cwd));
-
- char kpath[2048];
- memset(kpath,0,2048);
- copy_in_userspace_string(proc,kpath,(void*)path,2048);
-
- char result[2048];
- memset(result,0,2048);
- vfs::resolve_path(kpath,first_path,result,1,0);
-
- if(result[0] == '\0') {
- result[0] = '/';
- result[1] = '\0';
- }
-
- userspace_fd_t fd_s;
- memcpy(fd_s.path,result,strlen(result) + 1);
- fd_s.is_cached_path = 0;
-
- DEBUG(proc->is_debug,"Trying to stat %s from proc %d",result,proc->id);
-
- vfs::stat_t stat;
-
- memset(&stat,0,sizeof(vfs::stat_t));
-
- int status;
- if(flags & AT_SYMLINK_NOFOLLOW) {
- status = vfs::vfs::nosym_stat(&fd_s,&stat);
- }
- else
- status = vfs::vfs::stat(&fd_s,&stat);
- if(status != 0)
- return {0,status,0};
- copy_in_userspace(proc,out,&stat,sizeof(vfs::stat_t));
-
- return {0,0,0};
-}
-
-long long sys_pipe(int* fildes) {
- return sys_pipe2(fildes,0);
-}
-
-long long sys_pipe2(int* fildes, int flags) {
-
- if(!fildes)
- return -EINVAL;
-
- SYSCALL_IS_SAFEZ(fildes,4096);
-
- arch::x86_64::process_t* proc = CURRENT_PROC;
- int read_fd = vfs::fdmanager::create(proc);
- int write_fd = vfs::fdmanager::create(proc);
- userspace_fd_t* fd1 = vfs::fdmanager::search(proc,read_fd);
- userspace_fd_t* fd2 = vfs::fdmanager::search(proc,write_fd);
-
- vfs::pipe* new_pipe = new vfs::pipe(flags);
- fd1->pipe_side = PIPE_SIDE_READ;
- fd2->pipe_side = PIPE_SIDE_WRITE;
-
- fd1->pipe = new_pipe;
- fd2->pipe = new_pipe;
-
- fd1->state = USERSPACE_FD_STATE_PIPE;
- fd2->state = USERSPACE_FD_STATE_PIPE;
-
- fd1->is_cloexec = (flags & __O_CLOEXEC) ? 1 : 0;
- fd2->is_cloexec = (flags & __O_CLOEXEC) ? 1 : 0;
-
- DEBUG(proc->is_debug,"Creating pipe %d-%d from proc %d, cloexec: %d (flags %d)",read_fd,write_fd,proc->id,flags & __O_CLOEXEC,flags);
-
- fildes[0] = read_fd;
- fildes[1] = write_fd;
-
- return 0;
-}
-
-long long sys_dup(int fd) {
- int flags = 0;
- arch::x86_64::process_t* proc = CURRENT_PROC;
- userspace_fd_t* fd_s = vfs::fdmanager::search(proc,fd);
-
- if(!fd_s)
- return -EBADF;
-
- proc->fd_lock.lock();
-
- int i = 0;
- userspace_fd_t* nfd_s = vfs::fdmanager::searchlowest(proc,0);
-
- if(!nfd_s) {
- proc->fd_lock.unlock();
- int new_fd = vfs::fdmanager::create(proc);
- nfd_s = vfs::fdmanager::search(proc,new_fd);
- i = 1;
- }
-
- DEBUG(proc->is_debug,"dup from %d to %d",fd,nfd_s->index);
-
- nfd_s->cycle = fd_s->cycle;
- nfd_s->offset = fd_s->offset;
- nfd_s->state = fd_s->state;
- nfd_s->other_state = fd_s->other_state;
- nfd_s->pipe = fd_s->pipe;
- nfd_s->pipe_side = fd_s->pipe_side;
- nfd_s->queue = fd_s->queue;
- nfd_s->is_a_tty = fd_s->is_a_tty;
- nfd_s->read_counter = fd_s->read_counter;
- nfd_s->write_counter = fd_s->write_counter;
- nfd_s->can_be_closed = 0;
- nfd_s->write_socket_pipe = fd_s->write_socket_pipe;
- nfd_s->read_socket_pipe = fd_s->read_socket_pipe;
- nfd_s->eventfd = fd_s->eventfd;
- nfd_s->flags = fd_s->flags;
-
- memcpy(nfd_s->path,fd_s->path,sizeof(fd_s->path));
-
- if(nfd_s->state == USERSPACE_FD_STATE_PIPE)
- nfd_s->pipe->create(nfd_s->pipe_side);
- else if(nfd_s->state == USERSPACE_FD_STATE_EVENTFD)
- nfd_s->eventfd->create();
-
- if(i == 0)
- proc->fd_lock.unlock();
-
- return nfd_s->index;
-}
-
-long long sys_dup2(int fd, int newfd) {
- int flags = 0;
- arch::x86_64::process_t* proc = CURRENT_PROC;
-
- userspace_fd_t* fd_s = vfs::fdmanager::search(proc,fd);
-
- if(!fd_s)
- return -EBADF;
-
- userspace_fd_t* nfd_s = vfs::fdmanager::search(proc,newfd);
- if(!nfd_s) {
- int t = vfs::fdmanager::create(proc);
- nfd_s = vfs::fdmanager::search(proc,t);
- } else {
- if(nfd_s->state == USERSPACE_FD_STATE_PIPE)
- nfd_s->pipe->close(nfd_s->pipe_side);
- else if(nfd_s->state == USERSPACE_FD_STATE_EVENTFD)
- nfd_s->eventfd->close();
- }
-
- nfd_s->index = newfd;
- nfd_s->cycle = fd_s->cycle;
- nfd_s->offset = fd_s->offset;
- nfd_s->state = fd_s->state;
- nfd_s->other_state = fd_s->other_state;
- nfd_s->pipe = fd_s->pipe;
- nfd_s->pipe_side = fd_s->pipe_side;
- nfd_s->queue = fd_s->queue;
- nfd_s->is_a_tty = fd_s->is_a_tty;
- nfd_s->write_counter = fd_s->write_counter;
- nfd_s->read_counter = fd_s->read_counter;
- nfd_s->can_be_closed = fd_s->can_be_closed;
- nfd_s->read_socket_pipe = fd_s->read_socket_pipe;
- nfd_s->write_socket_pipe = fd_s->write_socket_pipe;
- nfd_s->eventfd = fd_s->eventfd;
- nfd_s->flags = fd_s->flags;
- nfd_s->is_cloexec = (flags & __O_CLOEXEC) ? 1 : 0;
-
- if(nfd_s->state == USERSPACE_FD_STATE_PIPE)
- nfd_s->pipe->create(nfd_s->pipe_side);
- else if(nfd_s->state == USERSPACE_FD_STATE_EVENTFD)
- nfd_s->eventfd->create();
-
- DEBUG(proc->is_debug,"dup2 from %d to %d from proc %d\n",fd,newfd,proc->id);
-
- memcpy(nfd_s->path,fd_s->path,sizeof(fd_s->path));
-
- return nfd_s->index;
-}
-
-syscall_ret_t sys_create_dev(std::uint64_t requestandnum, char* slave_path, char* master_path) {
- char slave[256];
- char master[256];
- memset(slave,0,sizeof(slave));
- memset(master,0,sizeof(master));
-
- arch::x86_64::process_t* proc = CURRENT_PROC;
-
- copy_in_userspace_string(proc,slave,slave_path,256);
- copy_in_userspace_string(proc,master,master_path,256);
-
- vfs::devfs_packet_t packet;
- packet.size = requestandnum & 0xFFFFFFFF;
- packet.request = (uint32_t)(requestandnum >> 32);
- packet.value = (std::uint64_t)&master[0];
-
- vfs::devfs::send_packet(slave,&packet);
- return {0,0,0};
-}
-
-long long sys_ioctl(int fd, unsigned long request, void *arg) {
- arch::x86_64::process_t* proc = CURRENT_PROC;
- userspace_fd_t* fd_s = vfs::fdmanager::search(proc,fd);
-
- if(!fd_s)
- return -EBADF;
-
- DEBUG(proc->is_debug,"ioctl fd %d (%s) req 0x%p arg 0x%p\n",fd,fd_s->path,request,arg);
-
- int res = 0;
-
- SYSCALL_IS_SAFEZ((void*)arg,4096);
-
- std::int64_t ret = vfs::vfs::ioctl(fd_s,request,(void*)arg,&res);
-
- return ret != 0 ? -ret : 0;
-}
-
-syscall_ret_t sys_create_ioctl(char* path, std::uint64_t write_and_read_req, std::uint32_t size) {
-
- std::int32_t read_req = write_and_read_req & 0xFFFFFFFF;
- std::int32_t write_req = (uint32_t)(write_and_read_req >> 32);
-
- char path0[256];
- memset(path0,0,256);
-
- arch::x86_64::process_t* proc = CURRENT_PROC;
- copy_in_userspace_string(proc,path0,path,256);
-
- vfs::devfs_packet_t packet;
- packet.create_ioctl.readreg = read_req;
- packet.create_ioctl.writereg = write_req;
- packet.create_ioctl.request = DEVFS_PACKET_CREATE_IOCTL;
- packet.create_ioctl.size = size;
- packet.create_ioctl.pointer = (std::uint64_t)memory::pmm::_virtual::alloc(size);
- vfs::devfs::send_packet(path0,&packet);
-
- return {0,0,0};
-}
-
-syscall_ret_t sys_setup_tty(char* path) {
-
- char path0[256];
- memset(path0,0,256);
-
- arch::x86_64::process_t* proc = CURRENT_PROC;
- copy_in_userspace_string(proc,path0,path,256);
-
- vfs::devfs_packet_t packet;
- packet.request = DEVFS_PACKET_SETUPTTY;
- vfs::devfs::send_packet(path0,&packet);
-
- return {0,0,0};
-}
-
-syscall_ret_t sys_isatty(int fd) {
-
- arch::x86_64::process_t* proc = CURRENT_PROC;
- userspace_fd_t* fd_s = vfs::fdmanager::search(proc,fd);
- if(!fd_s)
- return {0,EBADF,0};
-
- if(fd_s->state == USERSPACE_FD_STATE_PIPE || fd_s->state == USERSPACE_FD_STATE_SOCKET)
- return {0,ENOTTY,0};
-
- int ret = vfs::vfs::var(fd_s,0,DEVFS_VAR_ISATTY);
-
- DEBUG(proc->is_debug,"sys_isatty %s fd %d ret %d",fd_s->path,fd,ret);
-
- fd_s->is_a_tty = ret == 0 ? 1 : 0;
-
- return {0,ret != 0 ? ENOTTY : 0,0};
-}
-
-syscall_ret_t sys_setupmmap(char* path, std::uint64_t addr, std::uint64_t size, int_frame_t* ctx) {
- std::uint64_t flags = ctx->r8;
-
- char path0[256];
- memset(path0,0,256);
-
- arch::x86_64::process_t* proc = CURRENT_PROC;
- copy_in_userspace_string(proc,path0,path,256);
-
- vfs::devfs_packet_t packet;
- packet.request = DEVFS_SETUP_MMAP;
- packet.setup_mmap.dma_addr = addr;
- packet.setup_mmap.size = size;
- packet.setup_mmap.flags = flags;
-
- vfs::devfs::send_packet(path0,&packet);
-
- return {0,0,0};
-
-}
-
-syscall_ret_t sys_ptsname(int fd, void* out, int max_size) {
- arch::x86_64::process_t* proc = CURRENT_PROC;
- userspace_fd_t* fd_s = vfs::fdmanager::search(proc,fd);
- if(!fd_s)
- return {0,EBADF,0};
-
- char buffer[256];
- memset(buffer,0,256);
-
- vfs::devfs_packet_t packet;
- packet.value = (std::uint64_t)buffer;
- packet.request = DEVFS_GETSLAVE_BY_MASTER;
-
- vfs::devfs::send_packet(fd_s->path + 4,&packet);
-
- if(strlen(buffer) >= max_size)
- return {0,ERANGE,0};
-
- char buffer2[256];
- memset(buffer2,0,256);
-
- __printfbuf(buffer2,256,"/dev%s",buffer);
- zero_in_userspace(proc,out,max_size);
- copy_in_userspace(proc,out,buffer2,strlen(buffer2));
-
- return {0,0,0};
-}
-
-syscall_ret_t sys_setup_ring_bytelen(char* path, int bytelen) {
- char path0[256];
- memset(path0,0,256);
-
- arch::x86_64::process_t* proc = CURRENT_PROC;
- copy_in_userspace_string(proc,path0,path,256);
-
- vfs::devfs_packet_t packet;
- packet.request = DEVFS_PACKET_SETUP_RING_SIZE;
- packet.size = bytelen;
-
- vfs::devfs::send_packet(path0,&packet);
-
- return {0,0,0};
-}
-
-syscall_ret_t sys_read_dir(int fd, void* buffer) {
-
- SYSCALL_IS_SAFEA(buffer,4096);
- arch::x86_64::process_t* proc = CURRENT_PROC;
- userspace_fd_t* fd_s = vfs::fdmanager::search(proc,fd);
- if(!fd_s)
- return {0,EBADF,0};
-
- vfs::dirent_t dirent;
- memset(&dirent,0,sizeof(vfs::dirent_t));
-
- int status = vfs::vfs::ls(fd_s,&dirent);
-
- copy_in_userspace(proc,buffer,&dirent,sizeof(vfs::dirent_t));
- return {1,status,dirent.d_reclen};
-
-}
-
-long long __fcntl_dup_fd(int fd, int is_cloexec, int lowest, int_frame_t* ctx) {
- arch::x86_64::process_t* proc = CURRENT_PROC;
- userspace_fd_t* fd_s = vfs::fdmanager::search(proc,fd);
-
- if(!fd_s)
- return -EBADF;
-
- proc->fd_lock.lock();
-
- int i = 0;
- userspace_fd_t* nfd_s = vfs::fdmanager::searchlowestfrom(proc,lowest);
-
- if(!nfd_s) {
- proc->fd_lock.unlock();
- int new_fd = vfs::fdmanager::create(proc);
- nfd_s = vfs::fdmanager::search(proc,new_fd);
- i = 1;
- }
-
- DEBUG(proc->is_debug,"dup from %d to %d",fd,nfd_s->index);
-
- nfd_s->cycle = fd_s->cycle;
- nfd_s->offset = fd_s->offset;
- nfd_s->state = fd_s->state;
- nfd_s->other_state = fd_s->other_state;
- nfd_s->pipe = fd_s->pipe;
- nfd_s->pipe_side = fd_s->pipe_side;
- nfd_s->queue = fd_s->queue;
- nfd_s->is_a_tty = fd_s->is_a_tty;
- nfd_s->read_counter = fd_s->read_counter;
- nfd_s->write_counter = fd_s->write_counter;
- nfd_s->can_be_closed = 0;
- nfd_s->write_socket_pipe = fd_s->write_socket_pipe;
- nfd_s->read_socket_pipe = fd_s->read_socket_pipe;
- nfd_s->eventfd = fd_s->eventfd;
- nfd_s->flags = fd_s->flags;
-
- memcpy(nfd_s->path,fd_s->path,sizeof(fd_s->path));
-
- if(nfd_s->state == USERSPACE_FD_STATE_PIPE)
- nfd_s->pipe->create(nfd_s->pipe_side);
- else if(nfd_s->state == USERSPACE_FD_STATE_EVENTFD)
- nfd_s->eventfd->create();
-
- if(i == 0)
- proc->fd_lock.unlock();
-
- return nfd_s->index;
-}
-
-#define F_DUPFD_CLOEXEC 1030
-#define F_GETFD 1
-#define F_SETFD 2
-
-long long sys_fcntl(int fd, int request, std::uint64_t arg, int_frame_t* ctx) {
-
- arch::x86_64::process_t* pproc = CURRENT_PROC;
-
- DEBUG(pproc->is_debug,"fcntl fd %d req %d arg 0x%p from proc %d",fd,request,arg,pproc->id);
- int is_cloexec = 0;
- switch(request) {
- case F_DUPFD_CLOEXEC:
- is_cloexec = 1;
- case F_DUPFD: {
- long long r = __fcntl_dup_fd(fd,is_cloexec,arg,ctx);
- DEBUG(pproc->is_debug,"return fd %d from dup fcntl from proc %d",r,pproc->id);
- return r;
- }
-
- case F_GETFD: {
- arch::x86_64::process_t* proc = CURRENT_PROC;
- userspace_fd_t* fd_s = vfs::fdmanager::search(proc,fd);
- if(!fd_s)
- return -EBADF;
- return fd_s->is_cloexec;
- }
-
- case F_SETFD: {
- arch::x86_64::process_t* proc = CURRENT_PROC;
- userspace_fd_t* fd_s = vfs::fdmanager::search(proc,fd);
- if(!fd_s)
- return -EBADF;
-
- fd_s->is_cloexec = arg & 1;
- return 0;
- }
-
- case F_GETFL: {
- arch::x86_64::process_t* proc = CURRENT_PROC;
- userspace_fd_t* fd_s = vfs::fdmanager::search(proc,fd);
- if(!fd_s)
- return -EBADF;
-
- return (fd_s->flags & ~(O_RDONLY | O_WRONLY)) | O_RDWR;
- }
-
- case F_SETFL: {
- arch::x86_64::process_t* proc = CURRENT_PROC;
- userspace_fd_t* fd_s = vfs::fdmanager::search(proc,fd);
-
- if(!fd_s)
- return -EBADF;
-
- fd_s->flags &= ~(O_APPEND | O_ASYNC | O_NONBLOCK | O_RDONLY | O_RDWR | O_WRONLY);
- fd_s->flags |= (arg & (O_APPEND | O_ASYNC | O_NONBLOCK | O_RDONLY | O_RDWR | O_WRONLY));
- if(fd_s->state == USERSPACE_FD_STATE_EVENTFD) {
- fd_s->eventfd->flags &= ~(O_NONBLOCK);
- fd_s->eventfd->flags |= (arg & O_NONBLOCK);
- }
-
- return 0;
- }
-
- default: {
- Log::SerialDisplay(LEVEL_MESSAGE_WARN,"Unsupported fcntl %d arg 0x%p to fd %d from proc %d\n",request,arg,fd,pproc->id);
- return 0;
- }
- }
- return -EINVAL;
-}
-
-long long sys_chdir(char* path) {
- arch::x86_64::process_t* proc = CURRENT_PROC;
- SYSCALL_IS_SAFEZ(path,4096);
-
- if(!path)
- return -EINVAL;
-
- int dirfd = AT_FDCWD;
-
- char first_path[2048];
- memset(first_path,0,2048);
- if(dirfd >= 0)
- memcpy(first_path,vfs::fdmanager::search(proc,dirfd)->path,strlen(vfs::fdmanager::search(proc,dirfd)->path));
- else if(dirfd == AT_FDCWD)
- memcpy(first_path,proc->cwd,strlen(proc->cwd));
-
- char kpath[2048];
- memset(kpath,0,2048);
- copy_in_userspace_string(proc,kpath,(void*)path,2048);
-
- char result[2048];
- memset(result,0,2048);
- vfs::resolve_path(kpath,first_path,result,1,0);
-
- userspace_fd_t fd_s;
- memset(&fd_s,0,sizeof(userspace_fd_t));
- memcpy(fd_s.path,result,strlen(result) + 1);
-
- vfs::stat_t stat;
- int ret = vfs::vfs::stat(&fd_s,&stat);
-
- if(ret != 0)
- return -ret;
-
- if(!(stat.st_mode & S_IFDIR))
- return -ENOTDIR;
-
- memcpy(proc->cwd,result,strlen(result) + 1);
- return 0;
-}
-
-long long sys_fchdir(int fd) {
- arch::x86_64::process_t* proc = CURRENT_PROC;
- userspace_fd_t* fd_s = vfs::fdmanager::search(proc,fd);
- if(!fd_s)
- return -EBADF;
-
- vfs::stat_t stat;
- int ret = vfs::vfs::stat(fd_s,&stat);
-
- if(ret != 0)
- return -ret;
-
- if(!(stat.st_mode & S_IFDIR))
- return -ENOTDIR;
-
- memset(proc->cwd,0,4096);
- memcpy(proc->cwd,fd_s->path,2048);
-
- return 0;
-
-}
-
-syscall_ret_t sys_mkfifoat(int dirfd, const char *path, int mode) {
- SYSCALL_IS_SAFEA((void*)path,0);
-
- arch::x86_64::process_t* proc = CURRENT_PROC;
- char first_path[2048];
- memset(first_path,0,2048);
- if(dirfd >= 0)
- memcpy(first_path,vfs::fdmanager::search(proc,dirfd)->path,strlen(vfs::fdmanager::search(proc,dirfd)->path));
- else if(dirfd == AT_FDCWD)
- memcpy(first_path,proc->cwd,strlen(proc->cwd));
-
- char kpath[2048];
- memset(kpath,0,2048);
- copy_in_userspace_string(proc,kpath,(void*)path,2048);
-
- char result[2048];
- memset(result,0,2048);
- vfs::resolve_path(kpath,first_path,result,1,0);
-
- userspace_fd_t new_fd_s;
- new_fd_s.is_cached_path = 0;
- memset(new_fd_s.path,0,2048);
- memcpy(new_fd_s.path,result,strlen(result));
-
- vfs::stat_t stat;
-
- if(vfs::vfs::stat(&new_fd_s,&stat) == 0)
- return {0,EEXIST,0};
-
- int status = vfs::vfs::create_fifo(result);
-
-
- return {0,status,0};
-}
-
-void poll_to_str(int event, char* out) {
- const char* result = "Undefined";
- if(event & POLLIN && event & POLLOUT) {
- result = "POLLIN and POLLOUT";
- } else if(event & POLLIN) {
- result = "POLLIN";
- } else if(event & POLLOUT) {
- result = "POLLOUT";
- }
- memcpy(out,result,strlen(result) + 1);
-}
-
-long long sys_poll(struct pollfd *fds, int count, int timeout, int_frame_t* ctx) {
- if(ctx->rax != 270) { // ban returning efault from pselect
- SYSCALL_IS_SAFEZ((void*)fds,0);
- }
-
- if(!fds)
- return -EINVAL;
-
- arch::x86_64::process_t* proc = CURRENT_PROC;
- proc->debug0 = count;
- proc->debug1 = timeout;
-
- struct pollfd* fd = fds;
-
- int total_events = 0;
-
- userspace_fd_t* cached_fds[count];
-
- for(int i = 0;i < count; i++) {
- fd[i].revents = 0;
- }
-
- for(int i = 0;i < count; i++) {
- userspace_fd_t* fd0 = vfs::fdmanager::search(proc,fd[i].fd);
-
- cached_fds[i] = fd0;
-
- fd[i].revents = 0;
-
-
- if(!fd0) { return -EBADF;}
-
- if(fd[i].events & POLLIN)
- total_events++;
-
- if(fd[i].events & POLLOUT) {
-
- total_events++;
- }
-
- char out[64];
- if(proc->is_debug) {
- poll_to_str(fd[i].events,out);
-
- DEBUG(1,"Trying to poll %s (%d) timeout %d event %s with state %d is_listen %d from proc %d (%s)",fd0->state == USERSPACE_FD_STATE_FILE ? fd0->path : "Not file",fd0->index,timeout,out,fd0->state,fd0->is_listen,proc->id,proc->name);
-
- }
- }
-
- int num_events = 0;
-
- int success = true;
- int something_bad = 0;
-
- int retry = 0;
-
- int is_first = 1;
-
- if(timeout == -1) {
- while(success) {
-
- for(int i = 0;i < count; i++) {
- userspace_fd_t* fd0 = cached_fds[i];
- if(fd[i].events & POLLIN) {
-
- if(fd0->state == USERSPACE_FD_STATE_SOCKET && !fd0->is_listen && fd0->write_socket_pipe && fd0->read_socket_pipe) {
- int if_pollin = 0;
-
- if(fd0->other_state == USERSPACE_FD_OTHERSTATE_MASTER) {
- if_pollin = fd0->write_socket_pipe->size.load() > 0 ? 1 : 0;
- } else {
- if_pollin = fd0->read_socket_pipe->size.load() > 0 ? 1 : 0;
- }
- if(if_pollin) {
- //DEBUG(fd0->index == 18 || fd0->index == 19 || fd0->index == 20,"polin done fd %d writ sock 0x%p pip 0x%p",fd0->index,fd0->write_socket_pipe,fd0->pipe);
- num_events++;
- fd[i].revents |= POLLIN;
- }
-
- if(fd0->write_socket_pipe->is_closed.test() && !if_pollin) {
- num_events++;
- fd[i].revents |= POLLHUP;
- }
- } else if(fd0->state == USERSPACE_FD_STATE_SOCKET && fd0->is_listen && fd0->binded_socket) {
- if(fd0->read_counter == -1)
- fd0->read_counter = 0;
- socket_node_t* nod = (socket_node_t*)fd0->binded_socket;
- if(nod->socket_counter > (std::uint64_t)fd0->read_counter) {
- fd0->read_counter++;
- num_events++;
- fd[i].revents |= POLLIN;
- }
- } else if(fd0->state == USERSPACE_FD_STATE_PIPE) {
- if(fd0->pipe_side != PIPE_SIDE_READ)
- continue;
- if(fd0->pipe->size.load() > 0) {
- num_events++;
- fd[i].revents |= POLLIN;
- }
- } else if(fd0->state == USERSPACE_FD_STATE_EVENTFD) {
- fd0->eventfd->lock.lock();
- if(fd0->eventfd->buffer > 0) {
- num_events++;
- fd[i].revents |= POLLIN;
- }
- fd0->eventfd->lock.unlock();
- } else {
-
- std::int64_t ret = vfs::vfs::poll(fd0,POLLIN);
- if(ret != 0) {
- num_events++;
- fd[i].revents |= POLLIN;
- }
- }
- }
-
- if(fd[i].events & POLLOUT) {
- if(fd0->state == USERSPACE_FD_STATE_SOCKET && fd0->write_socket_pipe && fd0->read_socket_pipe && !fd0->is_listen) {
- int is_pollout = 0;
- if(fd0->other_state == USERSPACE_FD_OTHERSTATE_MASTER) {
- if(fd0->read_socket_pipe->size.load() < fd0->read_socket_pipe->total_size)
- is_pollout = 1;
- } else {
- if(fd0->write_socket_pipe->size.load() < fd0->write_socket_pipe->total_size)
- is_pollout = 1;
- }
-
- if(is_pollout) {
- num_events++;
- fd[i].revents |= POLLOUT;
- }
- } else if(fd0->state == USERSPACE_FD_STATE_EVENTFD) {
- fd0->eventfd->lock.lock();
- if(fd0->eventfd->buffer <= (0xFFFFFFFFFFFFFFFF - 1)) {
- num_events++;
- fd[i].revents |= POLLOUT;
- }
- fd0->eventfd->lock.unlock();
- } else if(fd0->state == USERSPACE_FD_STATE_PIPE) {
- if(fd0->pipe_side != PIPE_SIDE_READ)
- continue;
- if(fd0->pipe->size.load() < fd0->pipe->total_size) {
- num_events++;
- fd[i].revents |= POLLOUT;
- }
- } else {
- std::int64_t ret = vfs::vfs::poll(fd0,POLLOUT);
-
- if(ret != 0) {
- num_events++;
- fd[i].revents |= POLLOUT;
- }
- }
-
- }
-
-
-
- if(num_events)
- success = false;
- }
-
- if(success)
- yield();
- asm volatile("pause");
- }
- } else {
- int tries = 0;
- std::uint64_t current_timestamp = drivers::tsc::currentus();
- std::uint64_t end_timestamp = (current_timestamp + (timeout * 1000));
- while(drivers::tsc::currentus() < end_timestamp && success) {
- for(int i = 0;i < count; i++) {
- userspace_fd_t* fd0 = cached_fds[i];
- if(fd[i].events & POLLIN) {
- //std::int64_t ret = vfs::vfs::poll(fd0,POLLIN);
- if(fd[i].events & POLLIN) {
-
- if(fd0->state == USERSPACE_FD_STATE_SOCKET && !fd0->is_listen && fd0->write_socket_pipe && fd0->read_socket_pipe) {
- int if_pollin = 0;
-
- if(fd0->other_state == USERSPACE_FD_OTHERSTATE_MASTER) {
- if_pollin = fd0->write_socket_pipe->size.load() > 0 ? 1 : 0;
- } else {
- if_pollin = fd0->read_socket_pipe->size.load() > 0 ? 1 : 0;
- }
- if(if_pollin) {
- //DEBUG(fd0->index == 18 || fd0->index == 19 || fd0->index == 20,"polin done fd %d writ sock 0x%p pip 0x%p",fd0->index,fd0->write_socket_pipe,fd0->pipe);
- num_events++;
- fd[i].revents |= POLLIN;
- }
-
- if(fd0->write_socket_pipe->is_closed.test() && !if_pollin) {
- num_events++;
- fd[i].revents |= POLLHUP;
- }
-
- } else if(fd0->state == USERSPACE_FD_STATE_SOCKET && fd0->is_listen && fd0->binded_socket) {
- if(fd0->read_counter == -1)
- fd0->read_counter = 0;
-
- socket_node_t* nod = (socket_node_t*)fd0->binded_socket;
- if(nod->socket_counter > (std::uint64_t)fd0->read_counter) {
- fd0->read_counter++;
- num_events++;
- fd[i].revents |= POLLIN;
- }
- } else if(fd0->state == USERSPACE_FD_STATE_PIPE) {
- if(fd0->pipe->size.load() > 0) {
- num_events++;
- fd[i].revents |= POLLIN;
- }
- } else if(fd0->state == USERSPACE_FD_STATE_EVENTFD) {
- fd0->eventfd->lock.lock();
- if(fd0->eventfd->buffer > 0) {
- num_events++;
- fd[i].revents |= POLLIN;
- }
- fd0->eventfd->lock.unlock();
- } else {
-
- std::int64_t ret = vfs::vfs::poll(fd0,POLLIN);
-
- if(ret != 0) {
- num_events++;
- fd[i].revents |= POLLIN;
- }
- }
- }
-
- }
-
- if(fd[i].events & POLLOUT) {
- if(fd0->state == USERSPACE_FD_STATE_SOCKET) {
- int is_pollout = 0;
- if(fd0->other_state == USERSPACE_FD_OTHERSTATE_MASTER) {
- if(fd0->read_socket_pipe->size.load() < fd0->read_socket_pipe->total_size)
- is_pollout = 1;
- } else {
- if(fd0->write_socket_pipe->size.load() < fd0->write_socket_pipe->total_size)
- is_pollout = 1;
- }
-
- if(is_pollout) {
- num_events++;
- fd[i].revents |= POLLOUT;
- }
- } else if(fd0->state == USERSPACE_FD_STATE_EVENTFD) {
- fd0->eventfd->lock.lock();
- if(fd0->eventfd->buffer <= (0xFFFFFFFFFFFFFFFF - 1)) {
- num_events++;
- fd[i].revents |= POLLOUT;
- }
- fd0->eventfd->lock.unlock();
- } else if(fd0->state == USERSPACE_FD_STATE_PIPE) {
- if(fd0->pipe->size < fd0->pipe->total_size) {
- num_events++;
- fd[i].revents |= POLLOUT;
- }
- } else {
- std::int64_t ret = vfs::vfs::poll(fd0,POLLOUT);
- if(ret != 0) {
- num_events++;
- fd[i].revents |= POLLOUT;
- }
- }
-
- }
-
- if(num_events)
- success = false;
- // w
- }
-
- if(timeout == 0)
- break;
-
- std::uint64_t start = drivers::tsc::currentus();
- if(drivers::tsc::currentus() < end_timestamp && success) {
- yield();
- std::uint64_t now = drivers::tsc::currentus();
- }
-
- }
- }
-
- DEBUG(proc->is_debug,"%d from proc %d num_ev %d",timeout,proc->id,num_events);
- //copy_in_userspace(proc,fds,fd,count * sizeof(struct pollfd));
- return num_events;
-
-
-}
-
-long long sys_pselect6(int num_fds, fd_set* read_set, fd_set* write_set, int_frame_t* ctx) {
- fd_set* except_set = (fd_set*)ctx->r10;
- timespec* timeout = (timespec*)ctx->r8;
- sigset_t* sigmask = (sigset_t*)ctx->r9;
-
- arch::x86_64::process_t* proc = CURRENT_PROC;
-
- DEBUG(proc->is_debug,"Trying to pselect num_fds %d, read_set 0x%p, write_set 0x%p, except_set 0x%p, timeout 0x%p from proc %d",num_fds,read_set,write_set,except_set,timeout,proc->id);
-
- SYSCALL_IS_SAFEZ(read_set,4096);
- SYSCALL_IS_SAFEZ(write_set,4096);
- SYSCALL_IS_SAFEZ(except_set,4096);
- SYSCALL_IS_SAFEZ(timeout,4096);
-
- pollfd fds[num_fds];
- memset(fds,0,sizeof(fds));
-
- int actual_count = 0;
-
- for(int fd = 0; fd < num_fds; ++fd) {
- short events = 0;
- if(read_set && FD_ISSET(fd, read_set)) {
- events |= POLLIN;
- }
-
- if(write_set && FD_ISSET(fd, write_set)) {
- events |= POLLOUT;
- }
-
- if(except_set && FD_ISSET(fd, except_set)) {
- events |= POLLIN;
- }
-
- if(events) {
- fds[actual_count].fd = fd;
- fds[actual_count].events = events;
- fds[actual_count].revents = 0;
- actual_count++;
- }
- }
-
- long long num;
-
- if(timeout) {
- num = sys_poll(fds, actual_count, (timeout->tv_sec * 1000) + (timeout->tv_nsec / (1000 * 1000)), ctx);
- } else {
- num = sys_poll(fds, actual_count, -1, ctx);
- }
-
- DEBUG(proc->is_debug,"pselect6 to poll status %lli",num);
-
- if(num < 0)
- return num;
-
- #define READ_SET_POLLSTUFF (POLLIN | POLLHUP | POLLERR)
- #define WRITE_SET_POLLSTUFF (POLLOUT | POLLERR)
- #define EXCEPT_SET_POLLSTUFF (POLLPRI)
-
- int return_count = 0;
- for(int fd = 0; fd < actual_count; ++fd) {
- int events = fds[fd].events;
- if((events & POLLIN) && (fds[fd].revents & READ_SET_POLLSTUFF) == 0) {
- FD_CLR(fds[fd].fd, read_set);
- events &= ~POLLIN;
- }
-
- if((events & POLLOUT) && (fds[fd].revents & WRITE_SET_POLLSTUFF) == 0) {
- FD_CLR(fds[fd].fd, write_set);
- events &= ~POLLOUT;
- }
-
- if(events)
- return_count++;
- }
- return return_count;
-}
-
-long long sys_readlinkat(int dirfd, const char* path, void* buffer, int_frame_t* ctx) {
- std::size_t max_size = ctx->r10;
-
- SYSCALL_IS_SAFEZ((void*)path,4096);
- SYSCALL_IS_SAFEZ((void*)buffer,max_size);
-
- if(!path || !buffer || !max_size)
- return -EINVAL;
-
- arch::x86_64::process_t* proc = CURRENT_PROC;
-
- if(!vfs::fdmanager::search(proc,dirfd) && dirfd != AT_FDCWD) { DEBUG(1,"AAA %d\n",dirfd);
- return -EBADF; }
-
-
- char first_path[2048];
- memset(first_path,0,2048);
- if(dirfd >= 0)
- memcpy(first_path,vfs::fdmanager::search(proc,dirfd)->path,strlen(vfs::fdmanager::search(proc,dirfd)->path));
- else if(dirfd == AT_FDCWD)
- memcpy(first_path,proc->cwd,strlen(proc->cwd));
-
- char kpath[2048];
- memset(kpath,0,2048);
- copy_in_userspace_string(proc,kpath,(void*)path,2048);
-
- char result[2048];
- memset(result,0,2048);
- vfs::resolve_path(kpath,first_path,result,1,0);
-
- char readlink_buf[2048];
- memset(readlink_buf,0,2048);
- vfs::vfs::lock();
- int ret = vfs::vfs::extern_readlink(result,readlink_buf,2048);
- vfs::vfs::unlock();
-
- if(ret != 0) {
- return -ret;
- }
-
- copy_in_userspace(proc,buffer,readlink_buf, strlen(readlink_buf) > max_size ? max_size : strlen(readlink_buf));
-
- return (int64_t)(strlen(readlink_buf) > max_size ? max_size : strlen(readlink_buf));
-}
-
-long long sys_readlink(char* path, void* buffer, int max_size) {
-
- int dirfd = AT_FDCWD;
-
- SYSCALL_IS_SAFEZ((void*)path,4096);
- SYSCALL_IS_SAFEZ((void*)buffer,max_size);
-
- if(!path || !buffer || !max_size)
- return -EINVAL;
-
- arch::x86_64::process_t* proc = CURRENT_PROC;
-
- char first_path[2048];
- memset(first_path,0,2048);
- if(dirfd >= 0)
- memcpy(first_path,vfs::fdmanager::search(proc,dirfd)->path,strlen(vfs::fdmanager::search(proc,dirfd)->path));
- else if(dirfd == AT_FDCWD)
- memcpy(first_path,proc->cwd,strlen(proc->cwd));
-
- char kpath[2048];
- memset(kpath,0,2048);
- copy_in_userspace_string(proc,kpath,(void*)path,2048);
-
- char result[2048];
- memset(result,0,2048);
- vfs::resolve_path(kpath,first_path,result,1,0);
-
- char readlink_buf[2048];
- memset(readlink_buf,0,2048);
- vfs::vfs::lock();
- int ret = vfs::vfs::extern_readlink(result,readlink_buf,2048);
- vfs::vfs::unlock();
-
- if(ret != 0) {
- return -ret;
- }
-
- copy_in_userspace(proc,buffer,readlink_buf, strlen(readlink_buf) > max_size ? max_size : strlen(readlink_buf));
-
- return (int64_t)(strlen(readlink_buf) > max_size ? max_size : strlen(readlink_buf));
-}
-
-long long sys_link(char* old_path, char* new_path) {
-
- SYSCALL_IS_SAFEZ((void*)old_path,2048);
- SYSCALL_IS_SAFEZ((void*)new_path,2048);
-
- arch::x86_64::process_t* proc = CURRENT_PROC;
-
- if(!old_path || !new_path)
- return -EINVAL;
-
- char first_path[2048];
- memset(first_path,0,2048);
- if(0)
- memcpy(first_path,vfs::fdmanager::search(proc,0)->path,strlen(vfs::fdmanager::search(proc,0)->path));
- else if(1)
- memcpy(first_path,proc->cwd,strlen(proc->cwd));
-
- char kpath[2048];
- memset(kpath,0,2048);
- copy_in_userspace_string(proc,kpath,(void*)old_path,2048);
-
- char result[2048];
- memset(result,0,2048);
- vfs::resolve_path(kpath,first_path,result,1,0);
-
- char first_path2[2048];
- memset(first_path2,0,2048);
- if(0)
- memcpy(first_path2,vfs::fdmanager::search(proc,0)->path,strlen(vfs::fdmanager::search(proc,0)->path));
- else if(1)
- memcpy(first_path2,proc->cwd,strlen(proc->cwd));
-
- char kpath2[2048];
- memset(kpath2,0,2048);
- copy_in_userspace_string(proc,kpath2,(void*)new_path,2048);
-
- char result2[2048];
- memset(result2,0,2048);
- vfs::resolve_path(kpath2,first_path2,result2,1,0);
-
- int ret = vfs::vfs::create(result2,VFS_TYPE_SYMLINK);
-
- if(ret != 0)
- return ret;
-
- userspace_fd_t fd;
- fd.is_cached_path = 0;
- fd.offset = 0;
- memset(fd.path,0,2048);
- memcpy(fd.path,result2,strlen(result2));
-
- ret = vfs::vfs::write(&fd,result,2047);
-
- return 0;
-
-}
-
-long long sys_linkat(int oldfd, char* old_path, int newfd, int_frame_t* ctx) {
-
- char* new_path = (char*)ctx->r10;
-
- SYSCALL_IS_SAFEZ((void*)old_path,2048);
- SYSCALL_IS_SAFEZ((void*)new_path,2048);
-
- arch::x86_64::process_t* proc = CURRENT_PROC;
-
- if(!old_path || !new_path)
- return -EINVAL;
-
- char first_path[2048];
- memset(first_path,0,2048);
- if(oldfd >= 0)
- memcpy(first_path,vfs::fdmanager::search(proc,oldfd)->path,strlen(vfs::fdmanager::search(proc,oldfd)->path));
- else if(oldfd == AT_FDCWD)
- memcpy(first_path,proc->cwd,strlen(proc->cwd));
-
- char kpath[2048];
- memset(kpath,0,2048);
- copy_in_userspace_string(proc,kpath,(void*)old_path,2048);
-
- char result[2048];
- memset(result,0,2048);
- vfs::resolve_path(kpath,first_path,result,1,0);
-
- char first_path2[2048];
- memset(first_path2,0,2048);
- if(oldfd >= 0)
- memcpy(first_path2,vfs::fdmanager::search(proc,newfd)->path,strlen(vfs::fdmanager::search(proc,newfd)->path));
- else if(oldfd == AT_FDCWD)
- memcpy(first_path2,proc->cwd,strlen(proc->cwd));
-
- char kpath2[2048];
- memset(kpath2,0,2048);
- copy_in_userspace_string(proc,kpath2,(void*)new_path,2048);
-
- char result2[2048];
- memset(result2,0,2048);
- vfs::resolve_path(kpath2,first_path2,result2,1,0);
-
- int ret = vfs::vfs::create(result2,VFS_TYPE_SYMLINK);
-
- if(ret != 0)
- return ret;
-
- userspace_fd_t fd;
- fd.is_cached_path = 0;
- fd.offset = 0;
- memset(fd.path,0,2048);
- memcpy(fd.path,result2,strlen(result2));
-
- ret = vfs::vfs::write(&fd,result,2047);
-
- return 0;
-
-}
-
-long long sys_symlink(char* old, char* path) {
- return sys_symlinkat(old,AT_FDCWD,path);
-}
-
-long long sys_symlinkat(char* old, int dirfd, char* path) {
-
- arch::x86_64::process_t* proc = CURRENT_PROC;
-
- SYSCALL_IS_SAFEZ(old,4096);
- SYSCALL_IS_SAFEZ(path,4096);
-
- if(!old || !path)
- return -EINVAL;
-
- char first_path[2048];
- memset(first_path,0,2048);
- if(dirfd >= 0)
- memcpy(first_path,vfs::fdmanager::search(proc,dirfd)->path,strlen(vfs::fdmanager::search(proc,dirfd)->path));
- else if(dirfd == AT_FDCWD)
- memcpy(first_path,proc->cwd,strlen(proc->cwd));
-
- char kpath[2048];
- memset(kpath,0,2048);
- copy_in_userspace_string(proc,kpath,(void*)path,2048);
-
- char result[2048];
- memset(result,0,2048);
- vfs::resolve_path(kpath,first_path,result,1,0);
-
- if(old[0] == '\0')
- return -EINVAL;
-
- int ret = vfs::vfs::create(result,VFS_TYPE_SYMLINK);
-
- if(ret != 0)
- return ret;
-
- userspace_fd_t fd;
- fd.is_cached_path = 0;
- fd.offset = 0;
- memset(fd.path,0,2048);
- memcpy(fd.path,result,strlen(result));
-
- ret = vfs::vfs::write(&fd,old,strlen(old) + 1);
-
- DEBUG(1,"%s (%s) to %s\n",result,path,old);
-
- return 0;
-
-}
-
-long long sys_mkdir(char* path, int mode) {
- return sys_mkdirat(AT_FDCWD,path,mode);
-}
-
-long long sys_mkdirat(int dirfd, char* path, int mode) {
- SYSCALL_IS_SAFEZ((void*)path,4096);
-
- arch::x86_64::process_t* proc = CURRENT_PROC;
-
- char first_path[2048];
- memset(first_path,0,2048);
- if(dirfd >= 0)
- memcpy(first_path,vfs::fdmanager::search(proc,dirfd)->path,strlen(vfs::fdmanager::search(proc,dirfd)->path));
- else if(dirfd == AT_FDCWD)
- memcpy(first_path,proc->cwd,strlen(proc->cwd));
-
- char kpath[2048];
- memset(kpath,0,2048);
- copy_in_userspace_string(proc,kpath,(void*)path,2048);
-
- char result[2048];
- memset(result,0,2048);
- vfs::resolve_path(kpath,first_path,result,1,0);
-
- int ret = vfs::vfs::create(result,VFS_TYPE_DIRECTORY);
-
- //DEBUG(1,"mkdir %s %d\n",result,ret);
-
- userspace_fd_t fd;
- fd.is_cached_path = 0;
- memcpy(fd.path,result,2048);
-
- vfs::vfs::var(&fd,mode,TMPFS_VAR_CHMOD | (1 << 7));
- return ret;
-}
-
-long long sys_unlink(char* path) {
- return sys_unlinkat(AT_FDCWD,path,0);
-}
-
-long long sys_unlinkat(int dirfd, const char* path, int flags) {
- SYSCALL_IS_SAFEZ((void*)path,4096);
- if(!path)
- return -EINVAL;
-
- arch::x86_64::process_t* proc = CURRENT_PROC;
-
- char first_path[2048];
- memset(first_path,0,2048);
- if(dirfd >= 0)
- memcpy(first_path,vfs::fdmanager::search(proc,dirfd)->path,strlen(vfs::fdmanager::search(proc,dirfd)->path));
- else if(dirfd == AT_FDCWD && proc->cwd)
- memcpy(first_path,proc->cwd,strlen(proc->cwd));
-
- char kpath[2048];
- memset(kpath,0,2048);
- copy_in_userspace_string(proc,kpath,(void*)path,2048);
-
- char result[2048];
- memset(result,0,2048);
- vfs::resolve_path(kpath,first_path,result,1,0);
-
- userspace_fd_t fd;
- fd.is_cached_path = 0;
- memset(&fd,0,sizeof(fd));
- memcpy(fd.path,result,2048);
-
- return vfs::vfs::unlink(&fd);
-}
-
-long long sys_chmod(char* path, int mode) {
- SYSCALL_IS_SAFEZ((void*)path,0);
-
- arch::x86_64::process_t* proc = CURRENT_PROC;
-
- if(!path)
- return -EINVAL;
-
- char first_path[2048];
- memset(first_path,0,2048);
- if(0)
- memcpy(first_path,vfs::fdmanager::search(proc,0)->path,strlen(vfs::fdmanager::search(proc,0)->path));
- else if(1)
- memcpy(first_path,proc->cwd,strlen(proc->cwd));
-
- char kpath[2048];
- memset(kpath,0,2048);
- copy_in_userspace_string(proc,kpath,(void*)path,2048);
-
- char result[2048];
- memset(result,0,2048);
- vfs::resolve_path(kpath,first_path,result,1,0);
-
- userspace_fd_t fd;
- fd.is_cached_path = 0;
- memset(&fd,0,sizeof(fd));
- memcpy(fd.path,result,2048);
-
- uint64_t value;
- int ret = vfs::vfs::var(&fd,(uint64_t)&value,TMPFS_VAR_CHMOD);
-
- if(ret != 0)
- return -ret;
-
- ret = vfs::vfs::var(&fd,value | mode, TMPFS_VAR_CHMOD | (1 << 7));
-
-
-
- return -ret;
-}
-
-long long sys_fchmod(int fd, int mode) {
-
- arch::x86_64::process_t* proc = CURRENT_PROC;
-
- userspace_fd_t* fd_s = vfs::fdmanager::search(proc,fd);
- if(!fd_s)
- return -EBADF;
-
- uint64_t value;
- int ret = vfs::vfs::var(fd_s,(uint64_t)&value,TMPFS_VAR_CHMOD);
-
- if(ret != 0)
- return -ret;
-
- ret = vfs::vfs::var(fd_s,value | mode, TMPFS_VAR_CHMOD | (1 << 7));
-
- return -ret;
-}
-
-long long sys_fchmodat(int dirfd, const char* path, int mode, int_frame_t* ctx) {
- SYSCALL_IS_SAFEZ((void*)path,4096);
- if(!path)
- return -EFAULT;
-
- arch::x86_64::process_t* proc = CURRENT_PROC;
-
- char first_path[2048];
- memset(first_path,0,2048);
- if(dirfd >= 0)
- memcpy(first_path,vfs::fdmanager::search(proc,dirfd)->path,strlen(vfs::fdmanager::search(proc,dirfd)->path));
- else if(dirfd == AT_FDCWD && proc->cwd)
- memcpy(first_path,proc->cwd,strlen(proc->cwd));
-
- char kpath[2048];
- memset(kpath,0,2048);
- copy_in_userspace_string(proc,kpath,(void*)path,2048);
-
- char result[2048];
- memset(result,0,2048);
- vfs::resolve_path(kpath,first_path,result,1,0);
-
- userspace_fd_t fd;
- fd.is_cached_path = 0;
- memset(&fd,0,sizeof(fd));
- memcpy(fd.path,result,2048);
-
- uint64_t value;
- int ret = vfs::vfs::var(&fd,(uint64_t)&value,TMPFS_VAR_CHMOD);
-
- if(ret != 0)
- return -ret;
-
- DEBUG(proc->is_debug,"chmodz %s %d\n",path,mode);
-
- ret = vfs::vfs::var(&fd,value | mode, TMPFS_VAR_CHMOD | (1 << 7));
-
- return -ret;
-
-}
-
-long long sys_fchmodat2(int dirfd, const char* path, int mode, int_frame_t* ctx) {
-
- int flags = ctx->r10 & 0xffffffff;
-
- SYSCALL_IS_SAFEZ((void*)path,4096);
- if(!path)
- return -EFAULT;
-
- arch::x86_64::process_t* proc = CURRENT_PROC;
-
- userspace_fd_t* fd_sz = vfs::fdmanager::search(proc,dirfd);
- userspace_fd_t fd_tt;
- userspace_fd_t* fd_s = &fd_tt;
-
- if(!fd_sz && dirfd != -100)
- return -EBADF;
-
- if(flags & AT_EMPTY_PATH && !path) {
- if(!fd_sz)
- return -EBADF;
- fd_s = fd_sz;
- } else {
-
- if(!path)
- return -EINVAL;
-
- char first_path[2048];
- memset(first_path,0,2048);
- if(dirfd >= 0)
- memcpy(first_path,vfs::fdmanager::search(proc,dirfd)->path,strlen(vfs::fdmanager::search(proc,dirfd)->path));
- else if(dirfd == AT_FDCWD && proc->cwd)
- memcpy(first_path,proc->cwd,strlen(proc->cwd));
-
- char kpath[2048];
- memset(kpath,0,2048);
- copy_in_userspace_string(proc,kpath,(void*)path,2048);
-
- char result[2048];
- memset(result,0,2048);
- vfs::resolve_path(kpath,first_path,result,1,0);
- memset(&fd_tt,0,sizeof(userspace_fd_t));
- memcpy(fd_tt.path,result,strlen(result) + 1);
- fd_tt.state = USERSPACE_FD_STATE_FILE;
- }
-
-
- uint64_t value;
- int ret = vfs::vfs::var(fd_s,(uint64_t)&value,TMPFS_VAR_CHMOD);
-
- if(ret != 0)
- return -ret;
-
- DEBUG(proc->is_debug,"chmodz %s %d\n",path,mode);
-
- ret = vfs::vfs::var(fd_s,value | mode, TMPFS_VAR_CHMOD | (1 << 7));
-
- return -ret;
-
-}
-
-syscall_ret_t sys_ttyname(int fd, char *buf, size_t size) {
- arch::x86_64::process_t* proc = CURRENT_PROC;
- userspace_fd_t* fd_s = vfs::fdmanager::search(proc,fd);
- if(!fd_s)
- return {0,EBADF,0};
-
- if(!buf)
- return {0,EINVAL,0};
-
- SYSCALL_IS_SAFEA(buf,2048);
-
- int ret = vfs::vfs::var(fd_s,0,DEVFS_VAR_ISATTY);
-
- fd_s->is_a_tty = ret == 0 ? 1 : 0;
-
- if(!fd_s->is_a_tty)
- return {0,ENOTTY,0};
-
- zero_in_userspace(proc,buf,size);
- if(strlen(fd_s->path) > size)
- return {0,ERANGE,0};
-
- copy_in_userspace(proc,buf,fd_s->path,strlen(fd_s->path));
- return {0,0,0};
-}
-
-long long sys_renameat(int olddir, char* old, int newdir, int_frame_t* ctx) {
- char* newp = (char*)ctx->r10;
- SYSCALL_IS_SAFEZ((void*)old,0);
- SYSCALL_IS_SAFEZ((void*)newp,0);
-
- arch::x86_64::process_t* proc = CURRENT_PROC;
-
- int dirfd = olddir;
-
- char old_built[2048];
- memset(old_built,0,2048);
- if(dirfd >= 0)
- memcpy(old_built,vfs::fdmanager::search(proc,dirfd)->path,strlen(vfs::fdmanager::search(proc,dirfd)->path));
- else if(dirfd == AT_FDCWD && proc->cwd)
- memcpy(old_built,proc->cwd,strlen(proc->cwd));
-
- char kpath[2048];
- memset(kpath,0,2048);
- copy_in_userspace_string(proc,kpath,(void*)old,2048);
-
- char old_path_resolved[2048];
- memset(old_path_resolved,0,2048);
- vfs::resolve_path(kpath,old_built,old_path_resolved,1,0);
-
- dirfd = newdir;
-
- char new_built[2048];
- memset(new_built,0,2048);
- if(dirfd >= 0)
- memcpy(new_built,vfs::fdmanager::search(proc,dirfd)->path,strlen(vfs::fdmanager::search(proc,dirfd)->path));
- else if(dirfd == AT_FDCWD && proc->cwd)
- memcpy(new_built,proc->cwd,strlen(proc->cwd));
-
- char kzpath[2048];
- memset(kzpath,0,2048);
- copy_in_userspace_string(proc,kzpath,(void*)newp,2048);
-
- char new_path_resolved[2048];
- memset(new_path_resolved,0,2048);
- vfs::resolve_path(kzpath,new_built,new_path_resolved,1,0);
-
- int status = vfs::vfs::rename(old_path_resolved,new_path_resolved);
-
- return status;
-}
-
-long long sys_rename(char* old, char* newp) {
- SYSCALL_IS_SAFEZ((void*)old,4096);
- SYSCALL_IS_SAFEZ((void*)newp,4096);
-
- arch::x86_64::process_t* proc = CURRENT_PROC;
-
- char first_path[2048];
- memset(first_path,0,2048);
- memcpy(first_path,proc->cwd,strlen(proc->cwd));
- char kpath[2048];
- memset(kpath,0,2048);
- copy_in_userspace_string(proc,kpath,(void*)old,2048);
- char old_path[2048];
- memset(old_path,0,2048);
- vfs::resolve_path(kpath,first_path,old_path,1,0);
- if(old_path[0] == '\0') {
- old_path[0] = '/';
- old_path[1] = '\0';
- }
-
- memset(first_path,0,2048);
- memcpy(first_path,proc->cwd,strlen(proc->cwd));
- memset(kpath,0,2048);
- copy_in_userspace_string(proc,kpath,(void*)newp,2048);
- char new_path[2048];
- memset(new_path,0,2048);
- vfs::resolve_path(kpath,first_path,new_path,1,0);
- if(new_path[0] == '\0') {
- new_path[0] = '/';
- new_path[1] = '\0';
- }
-
- int status = vfs::vfs::rename(old_path,new_path);
-
- return status;
-}
-
-typedef __SIZE_TYPE__ __mlibc_size;
-
-struct iovec {
- void *iov_base;
- __mlibc_size iov_len;
-};
-
-typedef unsigned socklen_t;
-
-struct msghdr {
- void *msg_name;
- socklen_t msg_namelen;
- struct iovec *msg_iov;
-#if __INTPTR_WIDTH__ == 64 && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
- int __pad0;
-#endif
- int msg_iovlen;
-#if __INTPTR_WIDTH__ == 64 && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
- int __pad0;
-#endif
- void *msg_control;
-#if __INTPTR_WIDTH__ == 64 && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
- int __pad1;
-#endif
- socklen_t msg_controllen;
-#if __INTPTR_WIDTH__ == 64 && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
- int __pad1;
-#endif
- int msg_flags;
-};
-
-struct cmsghdr {
-#if __INTPTR_WIDTH__ == 64 && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
- int __pad;
-#endif
- socklen_t cmsg_len;
-#if __INTPTR_WIDTH__ == 64 && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
- int __pad;
-#endif
- int cmsg_level;
- int cmsg_type;
-};
-
-#define SOL_SOCKET 1
-
-#define SCM_RIGHTS 1
-#define SCM_CREDENTIALS 2
-
-#define __CMSG_ALIGN(s) (((s) + __alignof__(size_t) - 1) & \
- ~(__alignof__(size_t) - 1))
-
-#if defined(_DEFAULT_SOURCE)
-#define CMSG_ALIGN(s) __CMSG_ALIGN(s)
-#endif /* defined(_DEFAULT_SOURCE) */
-
-/* Basic macros to return content and padding size of a control message. */
-#define CMSG_LEN(s) (__CMSG_ALIGN(sizeof(struct cmsghdr)) + (s))
-#define CMSG_SPACE(s) (__CMSG_ALIGN(sizeof(struct cmsghdr)) + __CMSG_ALIGN(s))
-
-/* Provides access to the data of a control message. */
-#define CMSG_DATA(c) ((unsigned char *)(c) + __CMSG_ALIGN(sizeof(struct cmsghdr)))
-
-#define __MLIBC_CMSG_NEXT(c) ((char *)(c) + __CMSG_ALIGN((c)->cmsg_len))
-#define __MLIBC_MHDR_LIMIT(m) ((char *)(m)->msg_control + (m)->msg_controllen)
-
-/* For parsing control messages only. */
-/* Returns a pointer to the first header or nullptr if there is none. */
-#define CMSG_FIRSTHDR(m) ((size_t)(m)->msg_controllen <= sizeof(struct cmsghdr) \
- ? (struct cmsghdr *)0 : (struct cmsghdr *) (m)->msg_control)
-
-/* For parsing control messages only. */
-/* Returns a pointer to the next header or nullptr if there is none. */
-#define CMSG_NXTHDR(m, c) \
- ((c)->cmsg_len < sizeof(struct cmsghdr) || \
- (std::int64_t)(sizeof(struct cmsghdr) + __CMSG_ALIGN((c)->cmsg_len)) \
- >= __MLIBC_MHDR_LIMIT(m) - (char *)(c) \
- ? (struct cmsghdr *)0 : (struct cmsghdr *)__MLIBC_CMSG_NEXT(c))
-
-syscall_ret_t sys_msg_send(int fd, struct msghdr* hdr, int flags) {
- struct msghdr* msg = hdr;
- SYSCALL_IS_SAFEA(hdr,sizeof(struct msghdr));
-
- arch::x86_64::process_t* proc = CURRENT_PROC;
-
- userspace_fd_t* fd_s = vfs::fdmanager::search(proc,fd);
- if(!fd_s)
- return {1,EBADF,0};
-
- vfs::pipe* target_pipe = fd_s->other_state == USERSPACE_FD_OTHERSTATE_MASTER ? fd_s->read_socket_pipe : fd_s->write_socket_pipe;
- if(!target_pipe)
- return {1,EBADF,0};
-
- std::uint64_t total_size = 0;
- for (int i = 0; i < hdr->msg_iovlen; i++) {
- SYSCALL_IS_SAFEA(hdr->msg_iov[i].iov_base,hdr->msg_iov[i].iov_len);
- total_size += hdr->msg_iov[i].iov_len;
- }
-
- if(total_size > target_pipe->total_size)
- return {1,EMSGSIZE,0};
-
- target_pipe->lock.lock();
- std::uint64_t space_left = target_pipe->total_size - target_pipe->size;
- target_pipe->lock.unlock();
- while(space_left < total_size) {
- yield();
- target_pipe->lock.lock();
- space_left = target_pipe->total_size - target_pipe->size;
- target_pipe->lock.unlock();
- }
-
- target_pipe->lock.lock();
-
- struct cmsghdr *cmsg = 0;
-
- for (cmsg = CMSG_FIRSTHDR(msg);
- cmsg != NULL;
- cmsg = CMSG_NXTHDR(msg, cmsg)) {
- Log::SerialDisplay(LEVEL_MESSAGE_FAIL,"hello %d\n",cmsg->cmsg_type);
-
- if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS) {
- DEBUG(1,"scm\n");
- int new_fd = 0;
- memcpy(&new_fd, CMSG_DATA(cmsg), sizeof(int));
-
- userspace_fd_t* fd_s1 = vfs::fdmanager::search(proc,new_fd);
-
- if(!fd_s1) {
- break;
- }
-
- proc->pass_fd->push(fd_s1);
- target_pipe->fd_pass = (void*)proc->pass_fd; // transfer
-
- } else if(cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_CREDENTIALS) {
- target_pipe->ucred_pass->push((struct ucred*)CMSG_DATA(cmsg));
- }
- }
-
- std::int64_t total_written = 0;
-
- for (int i = 0; i < hdr->msg_iovlen; i++) {
- std::int64_t sent_bytes = target_pipe->nolock_write((const char*)hdr->msg_iov[i].iov_base,hdr->msg_iov[i].iov_len,0);
- if(sent_bytes < 0) {
- target_pipe->lock.unlock();
- return {1,+sent_bytes,0};
- }
- total_written += sent_bytes;
- if (sent_bytes < hdr->msg_iov[i].iov_len) {
- break;
- }
- }
-
- DEBUG(proc->is_debug,"msg_send fd %d total_written %lli flags %d from proc %d\n",fd,total_written,flags,proc->id);
-
- target_pipe->lock.unlock();
- return {1,0,total_written};
-}
-
-long long sys_msg_recv(int fd, struct msghdr *hdr, int flags) {
- struct msghdr* msg = hdr;
- SYSCALL_IS_SAFEZ(hdr,4096);
-
- arch::x86_64::process_t* proc = CURRENT_PROC;
-
- userspace_fd_t* fd_s = vfs::fdmanager::search(proc,fd);
- if(!fd_s)
- return -EBADF;
-
- vfs::pipe* target_pipe = fd_s->other_state == USERSPACE_FD_OTHERSTATE_MASTER ? fd_s->write_socket_pipe : fd_s->read_socket_pipe;
- if(!target_pipe)
- return -EBADF;
-
- std::uint64_t total_size = 0;
- for (int i = 0; i < hdr->msg_iovlen; i++) {
- SYSCALL_IS_SAFEZ(hdr->msg_iov[i].iov_base,hdr->msg_iov[i].iov_len);
- total_size += hdr->msg_iov[i].iov_len;
- }
-
- std::int64_t total_read = 0;
-
- for (int i = 0; i < hdr->msg_iovlen; i++) {
- std::int64_t recv_bytes = 0;
- recv_bytes = target_pipe->read(&fd_s->read_counter,(char*)hdr->msg_iov[i].iov_base,hdr->msg_iov[i].iov_len,((fd_s->flags & O_NONBLOCK) ? 1 : 0));
- if(recv_bytes == -EAGAIN) {
- return -EAGAIN;
- } else if(recv_bytes == -EAGAIN)
- break; // just dont continue
- total_read += recv_bytes;
- }
-
- socklen_t new_msglen = 0;
- socklen_t src_msglen = hdr->msg_controllen;
-
- struct cmsghdr* cmsg = 0;
-
- target_pipe->lock.lock();
- for (cmsg = CMSG_FIRSTHDR(msg);
- cmsg != 0;
- cmsg = CMSG_NXTHDR(msg, cmsg)) {
- if (1) {
- int *fd_ptr = (int *) CMSG_DATA(cmsg);
- userspace_fd_t fd_s1;
- memset(&fd_s1,0,sizeof(userspace_fd_t));
- vfs::passingfd_manager* pasfd = (vfs::passingfd_manager*)target_pipe->fd_pass;
- if(pasfd != 0) {
- if(pasfd->pop(&fd_s1) == 0) {
- cmsg->cmsg_level = SOL_SOCKET;
- cmsg->cmsg_type = SCM_RIGHTS;
- cmsg->cmsg_len = 24;
- new_msglen += 24;
- int new_fd = vfs::fdmanager::create(proc);
- userspace_fd_t* nfd_s = vfs::fdmanager::search(proc,new_fd);
-
- nfd_s->cycle = fd_s1.cycle;
- nfd_s->offset = fd_s1.offset;
- nfd_s->state = fd_s1.state;
- nfd_s->other_state = fd_s1.other_state;
- nfd_s->pipe = fd_s1.pipe;
- nfd_s->pipe_side = fd_s1.pipe_side;
- nfd_s->queue = fd_s1.queue;
- nfd_s->is_a_tty = fd_s1.is_a_tty;
- nfd_s->read_counter = fd_s1.read_counter;
- nfd_s->write_counter = fd_s1.write_counter;
- nfd_s->can_be_closed = 0;
- nfd_s->write_socket_pipe = fd_s1.write_socket_pipe;
- nfd_s->read_socket_pipe = fd_s1.read_socket_pipe;
- nfd_s->eventfd = fd_s1.eventfd;
- nfd_s->flags = fd_s1.flags;
-
- memcpy(nfd_s->path,fd_s1.path,sizeof(fd_s1.path));
-
- memcpy(CMSG_DATA(cmsg), &new_fd, sizeof(int));
- if(nfd_s->state == USERSPACE_FD_STATE_PIPE)
- nfd_s->pipe->create(nfd_s->pipe_side);
- else if(nfd_s->state == USERSPACE_FD_STATE_EVENTFD)
- nfd_s->eventfd->create();
- }
- } else {
- // fd pass is more important than ucred
- if(target_pipe->ucred_pass->pop((struct ucred*)CMSG_DATA(cmsg)) == 0) {
- DEBUG(1,"ucred pass");
- cmsg->cmsg_level = SOL_SOCKET;
- cmsg->cmsg_type = SCM_CREDENTIALS;
- cmsg->cmsg_len = 28;
- new_msglen += 28;
- }
- }
-
- }
- }
-
- if(new_msglen != 0) {
- target_pipe->fd_pass = 0; // clear
- target_pipe->lock.unlock();
- } else
- target_pipe->lock.unlock();
-
- target_pipe->lock.unlock();
- hdr->msg_controllen = new_msglen;
-
- DEBUG(proc->is_debug,"msg_recv fd %d total_read %lli flags %d from proc %d, controllen %d srclen %d\n",fd,total_read,flags,proc->id,hdr->msg_controllen,src_msglen);
- return total_read;
-}
-
-syscall_ret_t sys_eventfd_create(unsigned int initval, int flags) {
- arch::x86_64::process_t* proc = CURRENT_PROC;
-
- int new_fd = vfs::fdmanager::create(proc);
-
- userspace_fd_t* new_fd_s = vfs::fdmanager::search(proc,new_fd);
- memset(new_fd_s->path,0,2048);
-
- new_fd_s->offset = 0;
- new_fd_s->queue = 0;
- new_fd_s->pipe = 0;
- new_fd_s->pipe_side = 0;
- new_fd_s->cycle = 0;
- new_fd_s->is_a_tty = 0;
-
- new_fd_s->state = USERSPACE_FD_STATE_EVENTFD;
- new_fd_s->eventfd = new vfs::eventfd(initval,flags);
-
- new_fd_s->eventfd->create();
-
- DEBUG(proc->is_debug,"Creating eventfd %d from proc %d, proc->fd 0x%p",new_fd,proc->id,proc->fd);
-
- return {1,0,new_fd};
-}
-
-std::uint64_t nextz = 2;
-
-std::uint64_t __rand0() {
- uint64_t t = __rdtsc();
- return t * (++nextz);
-}
-
-syscall_ret_t sys_getentropy(char* buffer, std::uint64_t len) {
- SYSCALL_IS_SAFEA(buffer,256);
- if(!buffer)
- return {0,EFAULT,0};
-
- if(len > 256)
- return {0,EIO,0};
-
- for(std::uint64_t i = 0; i < len; i++) {
- ((char*)buffer)[i] = __rand0() & 0xFF;
- }
-
- return {0,0,0};
-}
-
-long long sys_pwrite(int fd, void* buf, std::uint64_t n, int_frame_t* ctx) {
- std::uint64_t off = ctx->r10;
- SYSCALL_IS_SAFEZ(buf,n);
-
- arch::x86_64::process_t* proc = CURRENT_PROC;
-
- std::uint64_t count = n;
-
- userspace_fd_t* fd_sz = vfs::fdmanager::search(proc,fd);
- if(!fd_sz)
- return -EBADF;
-
- userspace_fd_t fd_ss = *fd_sz;
- fd_ss.offset = off;
-
- userspace_fd_t* fd_s = &fd_ss;
-
- if(fd_s->can_be_closed)
- fd_s->can_be_closed = 0;
-
- char* temp_buffer = (char*)buf;
-
- const char* _0 = "Content view is disabled in files";
- DEBUG(proc->is_debug && fd != 1 && fd != 2,"Writing %s with content %s fd %d state %d from proc %d count %d writ sock 0x%p",fd_s->state == USERSPACE_FD_STATE_FILE ? fd_s->path : "Not file",buf,fd,fd_s->state,proc->id,count,fd_s->write_socket_pipe);
-
- if(fd == 1) {
- //Log::SerialDisplay(LEVEL_MESSAGE_INFO,"%s\n",buf);
- }
-
- std::int64_t bytes_written;
- if(fd_s->state == USERSPACE_FD_STATE_FILE)
- bytes_written = vfs::vfs::write(fd_s,temp_buffer,count);
- else if(fd_s->state == USERSPACE_FD_STATE_PIPE) {
- if(fd_s->pipe_side != PIPE_SIDE_WRITE)
- return -EBADF;
- bytes_written = fd_s->pipe->write(temp_buffer,count,proc->id);
- } else if(fd_s->state == USERSPACE_FD_STATE_SOCKET) {
-
- if(!fd_s->write_socket_pipe || !fd_s->read_socket_pipe)
- return -EFAULT;
-
- if(fd_s->other_state == USERSPACE_FD_OTHERSTATE_MASTER) {
- bytes_written = fd_s->read_socket_pipe->write(temp_buffer,count,proc->id);
- } else {
- bytes_written = fd_s->write_socket_pipe->write(temp_buffer,count,proc->id);
- }
-
- if(bytes_written == 0)
- return 0;
-
- } else if(fd_s->state == USERSPACE_FD_STATE_EVENTFD) {
- if(count != 8)
- return -EINVAL;
- std::uint64_t* _8sizebuf = (std::uint64_t*)buf;
- bytes_written = fd_s->eventfd->write(*_8sizebuf);
- } else
- return -EBADF;
-
-
- return bytes_written;
-
-}
-
-typedef struct __mlibc_fsid {
- int __val[2];
-} fsid_t;
-
-typedef std::uint64_t fsblkcnt_t;
-typedef std::uint64_t fsfilcnt_t;
-
-/* WARNING: keep `statfs` and `statfs64` in sync or bad things will happen! */
-struct statfs {
- unsigned long f_type;
- unsigned long f_bsize;
- fsblkcnt_t f_blocks;
- fsblkcnt_t f_bfree;
- fsblkcnt_t f_bavail;
- fsfilcnt_t f_files;
- fsfilcnt_t f_ffree;
- fsid_t f_fsid;
- unsigned long f_namelen;
- unsigned long f_frsize;
- unsigned long f_flags;
- unsigned long __f_spare[4];
-};
-
-long long sys_statfs(char* path, struct statfs* buf) {
- SYSCALL_IS_SAFEZ(path,4096);
- SYSCALL_IS_SAFEZ(buf,4096);
- arch::x86_64::process_t* proc = CURRENT_PROC;
-
- if(!path || !buf)
- return -EINVAL;
-
- buf->f_type = 0xEF53; // just default to ext2
- buf->f_bsize = 4096;
- buf->f_blocks = 0;
- buf->f_bfree = 0;
- buf->f_bavail = 0;
-
- extern std::uint64_t __tmpfs_ptr_id;
-
- buf->f_files = __tmpfs_ptr_id;
- buf->f_ffree = 0xffffffffffffffff - __tmpfs_ptr_id;
- buf->f_fsid = {0,0};
- buf->f_namelen = 2048;
- buf->f_frsize = 0;
- buf->f_flags = 0;
-
- return 0;
-}
-
-long long sys_fstatfs(int fd, struct statfs *buf) {
- SYSCALL_IS_SAFEZ(buf,4096);
- arch::x86_64::process_t* proc = CURRENT_PROC;
-
- userspace_fd_t* fd_s = vfs::fdmanager::search(proc,fd);
- if(!fd_s)
- return -EBADF;
-
- buf->f_type = 0xEF53; // just default to ext2
- buf->f_bsize = 4096;
- buf->f_blocks = 0;
- buf->f_bfree = 0;
- buf->f_bavail = 0;
-
- extern std::uint64_t __tmpfs_ptr_id;
-
- buf->f_files = __tmpfs_ptr_id;
- buf->f_ffree = 0xffffffffffffffff - __tmpfs_ptr_id;
- buf->f_fsid = {0,0};
- buf->f_namelen = 2048;
- buf->f_frsize = 0;
- buf->f_flags = 0;
-
- return 0;
-
-}
-
-long long sys_statx(int dirfd, const char *path, int flag, int_frame_t* ctx) {
- SYSCALL_IS_SAFEZ((void*)path,4096);
-
- arch::x86_64::process_t* proc = CURRENT_PROC;
-
- std::uint32_t mask = ctx->r10 & 0xFFFFFFFF;
- statx_t* out = (statx_t*)ctx->r8;
-
- userspace_fd_t* fd_sz = vfs::fdmanager::search(proc,dirfd);
- userspace_fd_t fd_tt;
- userspace_fd_t* fd_s = &fd_tt;
-
- int flags = ctx->r10;
-
- if(!fd_sz && dirfd != -100)
- return -EBADF;
-
- if(flags & AT_EMPTY_PATH && !path) {
- if(!fd_sz)
- return -EBADF;
- fd_s = fd_sz;
- } else {
-
- if(!path)
- return -EINVAL;
-
- char first_path[2048];
- memset(first_path,0,2048);
- if(dirfd >= 0)
- memcpy(first_path,vfs::fdmanager::search(proc,dirfd)->path,strlen(vfs::fdmanager::search(proc,dirfd)->path));
- else if(dirfd == AT_FDCWD && proc->cwd)
- memcpy(first_path,proc->cwd,strlen(proc->cwd));
-
- char kpath[2048];
- memset(kpath,0,2048);
- copy_in_userspace_string(proc,kpath,(void*)path,2048);
-
- char result[2048];
- memset(result,0,2048);
- vfs::resolve_path(kpath,first_path,result,1,0);
- memset(&fd_tt,0,sizeof(userspace_fd_t));
- memcpy(fd_tt.path,result,strlen(result) + 1);
- }
-
- DEBUG(proc->is_debug,"trying to statx %s\n",path);
- return vfs::vfs::statx(fd_s,flag,mask,out);
-}
-
-long long sys_getdents64(int fd, char* buf, size_t count) {
- SYSCALL_IS_SAFEZ(buf,count);
-
- arch::x86_64::process_t* proc = CURRENT_PROC;
-
- userspace_fd_t* fd_s = vfs::fdmanager::search(proc,fd);
- if(!fd_s)
- return -EBADF;
-
- if(!buf)
- return -EINVAL;
-
- DEBUG(proc->is_debug,"getdents64 fd %d buf 0x%p, count %lli",fd,buf,count);
-
- memset(buf,0,count);
-
- std::uint64_t off = 0;
- while(1) {
- vfs::dirent_t dirent = {0};
- int status = vfs::vfs::ls(fd_s,&dirent);
- if(status < 0) {
- DEBUG(proc->is_debug,"getdents64 fail status %d",status);
- return -status;
- }
-
- if(dirent.d_reclen == 0) {
- break;
- }
-
- std::uint64_t built_size = strlen(dirent.d_name) + sizeof(linux_dirent64) + 1;
- if(built_size > count - off)
- break;
-
- linux_dirent64* dirent64 = (linux_dirent64*)(buf + off);
- dirent64->d_ino = dirent.d_ino;
- dirent64->d_type = dirent.d_type;
- dirent64->d_off = 0;
- dirent64->d_reclen = strlen(dirent.d_name) + sizeof(linux_dirent64) + 1;
- memcpy(dirent64->d_name,dirent.d_name,strlen(dirent.d_name) + 1);
- off += dirent64->d_reclen;
-
- }
- return off;
-}
-
-long long sys_umask(int mask) {
- return 0;
-} \ No newline at end of file
diff --git a/kernel/src/arch/x86_64/syscalls/futex.cpp b/kernel/src/arch/x86_64/syscalls/futex.cpp
deleted file mode 100644
index 3d3352f..0000000
--- a/kernel/src/arch/x86_64/syscalls/futex.cpp
+++ /dev/null
@@ -1,132 +0,0 @@
-
-#include <cstdint>
-#include <arch/x86_64/syscalls/syscalls.hpp>
-#include <arch/x86_64/syscalls/signal.hpp>
-#include <arch/x86_64/cpu/data.hpp>
-#include <arch/x86_64/scheduling.hpp>
-#include <generic/vfs/vfs.hpp>
-#include <drivers/tsc.hpp>
-
-#include <generic/locks/spinlock.hpp>
-
-locks::spinlock futex_lock2;
-
-long long sys_futex(int* uaddr, int op, uint32_t val, int_frame_t* ctx) {
- int operation = op & FUTEX_CMD_MASK;
- int flags = op & (FUTEX_CLOCK_REALTIME | FUTEX_PRIVATE_FLAG);
-
- arch::x86_64::process_t* proc = arch::x86_64::cpu::data()->temp.proc;
-
- struct timespec* ts = (struct timespec*)ctx->r10;
-
- DEBUG(proc->is_debug,"futex op %d, val %d, uaddr 0x%p, flags %d, raw_op %d",operation,val,uaddr,flags,op);
-
- switch(operation) {
- case FUTEX_WAIT: {
-
- SYSCALL_IS_SAFEZ(uaddr,4096);
-
- int v = 0;
- v = ((std::atomic<int>*)uaddr)->load();
-
- if(v != val)
- return -EAGAIN;
-
- std::uint64_t t = 0;
- if(ts) {
- t = (ts->tv_sec * (1000 * 1000)) + (ts->tv_nsec / 1000);
- t += drivers::tsc::currentus();
- }
-
- DEBUG(proc->is_debug,"Waiting for futex, pointer: 0x%p excepted: %d, pointer_value %d in proc %d, ts->tv_nsec %lli ts->tv_sec %lli",uaddr,val,v,proc->id,ts != nullptr ? ts->tv_nsec : 0, ts != nullptr ? ts->tv_sec : 0);
-
- arch::x86_64::scheduling::futexwait(proc,&v,val,uaddr,t);
-
- futex_lock2.unlock();
- yield();
-
- while(proc->futex_lock.test()) {
- if(ts) {
- if(proc->ts < drivers::tsc::currentus()) {
- proc->futex_lock.unlock();
- return -ETIMEDOUT;
- }
- }
-
- PREPARE_SIGNAL(proc) {
- proc->futex_lock.unlock();
- signal_ret();
- }
-
- yield();
- }
-
- return 0;
- };
- case FUTEX_WAKE: {
- int c = arch::x86_64::scheduling::futexwake(proc,uaddr,val);
- return c;
- }
- default:
- Log::SerialDisplay(LEVEL_MESSAGE_FAIL,"unsupported futex op %d\n",op);
- return 0;
- };
- return 0;
-}
-
-// syscall_ret_t sys_futex_wait(int* pointer, int excepted, struct timespec* ts) {
-
-// futex_lock2.lock();
-// int v = 0;
-// v = ((std::atomic<int>*)pointer)->load();
-
-// if(v != excepted) {
-// futex_lock2.unlock();
-// return {0,EAGAIN,0};
-// }
-
-// arch::x86_64::process_t* proc = arch::x86_64::cpu::data()->temp.proc;
-
-// std::uint64_t t = 0;
-// if(ts) {
-// t = (ts->tv_sec * (1000 * 1000)) + (ts->tv_nsec / 1000);
-// t += drivers::tsc::currentus();
-// }
-
-
-
-// int copied_pointer_val = v;
-// DEBUG(0,"Waiting for futex, pointer: 0x%p excepted: %d, pointer_value %d in proc %d, ts->tv_nsec %lli ts->tv_sec %lli",pointer,excepted,copied_pointer_val,proc->id,ts != nullptr ? ts->tv_nsec : 0, ts != nullptr ? ts->tv_sec : 0);
-
-// arch::x86_64::scheduling::futexwait(proc,&copied_pointer_val,excepted,pointer,t);
-
-// futex_lock2.unlock();
-// yield();
-
-// while(proc->futex_lock.test()) {
-// if(ts) {
-// if(proc->ts < drivers::tsc::currentus()) {
-// proc->futex_lock.unlock();
-// return {0,ETIMEDOUT,0};
-// }
-// }
-
-// PREPARE_SIGNAL(proc) {
-// proc->futex_lock.unlock();
-// signal_ret();
-// }
-
-// yield();
-// }
-
-// return {0,0,0};
-// }
-
-// syscall_ret_t sys_futex_wake(int* pointer) {
-// futex_lock2.lock();
-// arch::x86_64::process_t* proc = arch::x86_64::cpu::data()->temp.proc;
-// DEBUG(0,"Wakeup futex with pointer 0x%p in proc %d",pointer,proc->id);
-// int c = arch::x86_64::scheduling::futexwake(proc,pointer);
-// futex_lock2.unlock();
-// return {0,0,0};
-// }
diff --git a/kernel/src/arch/x86_64/syscalls/misc.cpp b/kernel/src/arch/x86_64/syscalls/misc.cpp
deleted file mode 100644
index d8ca1ac..0000000
--- a/kernel/src/arch/x86_64/syscalls/misc.cpp
+++ /dev/null
@@ -1,158 +0,0 @@
-
-
-#include <arch/x86_64/syscalls/syscalls.hpp>
-#include <generic/vfs/vfs.hpp>
-
-#include <arch/x86_64/cpu/data.hpp>
-#include <arch/x86_64/scheduling.hpp>
-
-#include <generic/mm/pmm.hpp>
-#include <generic/mm/vmm.hpp>
-
-#include <generic/vfs/fd.hpp>
-
-#include <etc/assembly.hpp>
-#include <etc/logging.hpp>
-
-#include <drivers/cmos.hpp>
-
-#include <drivers/tsc.hpp>
-
-#include <etc/errno.hpp>
-
-#include <drivers/hpet.hpp>
-
-#include <drivers/kvmtimer.hpp>
-
-#include <generic/time.hpp>
-
-#include <generic/vfs/vfs.hpp>
-
-#include <etc/bootloaderinfo.hpp>
-
-std::atomic<std::uint64_t> zznext = 0;
-std::uint64_t __zzrand() {
- uint64_t t = __rdtsc();
- return t * (++zznext);
-}
-
-long long sys_getrandom(char *buf, size_t count, unsigned int flags) {
- if(!buf)
- return -EINVAL;
- for(std::uint64_t i = 0;i < count;i++) {
- buf[i] = __zzrand() & 0xFF;
- }
- return 0;
-}
-
-# define CLOCK_REALTIME 0
-/* Monotonic system-wide clock. */
-# define CLOCK_MONOTONIC 1
-/* High-resolution timer from the CPU. */
-# define CLOCK_PROCESS_CPUTIME_ID 2
-/* Thread-specific CPU-time clock. */
-# define CLOCK_THREAD_CPUTIME_ID 3
-/* Monotonic system-wide clock, not adjusted for frequency scaling. */
-# define CLOCK_MONOTONIC_RAW 4
-/* Identifier for system-wide realtime clock, updated only on ticks. */
-# define CLOCK_REALTIME_COARSE 5
-/* Monotonic system-wide clock, updated only on ticks. */
-# define CLOCK_MONOTONIC_COARSE 6
-/* Monotonic system-wide clock that includes time spent in suspension. */
-# define CLOCK_BOOTTIME 7
-/* Like CLOCK_REALTIME but also wakes suspended system. */
-# define CLOCK_REALTIME_ALARM 8
-/* Like CLOCK_BOOTTIME but also wakes suspended system. */
-# define CLOCK_BOOTTIME_ALARM 9
-/* Like CLOCK_REALTIME but in International Atomic Time. */
-# define CLOCK_TAI 11
-
-std::atomic<std::uint64_t> clk_mnt_sync = 0;
-
-long long sys_clock_gettime(clockid_t which_clock, struct __kernel_timespec *tp) {
- switch(which_clock) {
- case CLOCK_TAI:
- case CLOCK_REALTIME_COARSE:
- case CLOCK_REALTIME:
- tp->tv_sec = getUnixTime();
- tp->tv_nsec = 0;
- return 0;
- case CLOCK_THREAD_CPUTIME_ID:
- case CLOCK_PROCESS_CPUTIME_ID:
- case CLOCK_BOOTTIME:
- case CLOCK_MONOTONIC_COARSE:
- case CLOCK_MONOTONIC_RAW:
- case CLOCK_MONOTONIC:
- std::uint64_t ts = drivers::tsc::currentnano();
- tp->tv_sec = ts / 1000000000;
- tp->tv_nsec = ts % 1000000000;
- return 0;
- };
- return -EINVAL;
-}
-
-long long sys_gettimeofday(timeval* tv, void* tz) { // tz unused
- std::uint64_t ts = drivers::tsc::currentnano();
- if(tv) {
- tv->tv_sec = getUnixTime();
- tv->tv_usec = (ts % 1000000000LL) / 1000LL;
- }
- return 0;
-}
-
-long long sys_uname(old_utsname* uname) {
-
- if(!uname)
- return -EINVAL;
-
- memset(uname,0,sizeof(old_utsname));
-
- memcpy(uname->sysname,"Orange",sizeof("Orange"));
- memcpy(uname->nodename,"orange-pc",sizeof("orange-pc"));
- memcpy(uname->machine,"x86_64",sizeof("x86_64"));
-
- return 0;
-
-}
-
-long long sys_time(std::uint64_t* t) {
- SYSCALL_IS_SAFEZ(t,4096);
- std::uint64_t time = getUnixTime();
- if(t)
- *t = time;
- return time;
-}
-
-long long sys_nanosleep(int clock, int flags, timespec* rqtp, int_frame_t* ctx) {
- timespec* rmtp = (timespec*)ctx->r10;
- std::uint64_t us = (rqtp->tv_nsec / 1000) + (rqtp->tv_sec * 1000000);
- arch::x86_64::process_t* proc = CURRENT_PROC;
- if(1) { // tsc sleep
- std::uint64_t current = drivers::tsc::currentnano();
- std::uint64_t end = us * 1000;
- while((drivers::tsc::currentnano() - current) < end) {
- if((drivers::tsc::currentnano() - current) < 15000) {
- asm volatile("pause");
- } else
- yield();
- PREPARE_SIGNAL(proc) {
- std::uint64_t ns = us * 1000;
- rmtp->tv_sec = ns / 1000000000;
- rmtp->tv_nsec = ns % 1000000000;
- signal_ret();
- }
- }
- }
- return 0;
-}
-
-long long sys_sysinfo(sysinfo* info) {
- SYSCALL_IS_SAFEZ(info,4096);
-
- if(!info)
- return -EINVAL;
-
- info->uptime = drivers::tsc::currentus() / (1000 * 1000);
-
- return 0;
-} \ No newline at end of file
diff --git a/kernel/src/arch/x86_64/syscalls/process.cpp b/kernel/src/arch/x86_64/syscalls/process.cpp
deleted file mode 100644
index 473a0bf..0000000
--- a/kernel/src/arch/x86_64/syscalls/process.cpp
+++ /dev/null
@@ -1,1081 +0,0 @@
-
-#include <arch/x86_64/syscalls/syscalls.hpp>
-#include <generic/vfs/vfs.hpp>
-
-#include <arch/x86_64/cpu/data.hpp>
-#include <arch/x86_64/scheduling.hpp>
-
-#include <generic/mm/pmm.hpp>
-#include <generic/mm/vmm.hpp>
-
-#include <generic/vfs/fd.hpp>
-
-#include <etc/assembly.hpp>
-#include <etc/logging.hpp>
-
-#include <drivers/cmos.hpp>
-
-#include <drivers/tsc.hpp>
-
-#include <etc/errno.hpp>
-
-#include <drivers/hpet.hpp>
-
-#include <drivers/kvmtimer.hpp>
-
-#include <generic/time.hpp>
-
-#include <generic/vfs/vfs.hpp>
-
-#include <etc/bootloaderinfo.hpp>
-
-syscall_ret_t sys_tcb_set(std::uint64_t fs) {
- arch::x86_64::process_t* proc = CURRENT_PROC;
- proc->fs_base = fs;
- __wrmsr(0xC0000100,fs);
- DEBUG(proc->is_debug,"Setting tcb %p to proc %d",fs,proc->id);
- return {0,0,0};
-}
-
-syscall_ret_t sys_libc_log(const char* msg) {
- arch::x86_64::process_t* proc = CURRENT_PROC;
- char buffer[2048];
- memset(buffer,0,2048);
- copy_in_userspace_string(proc,buffer,(void*)msg,2048);
- DEBUG(proc->is_debug,"%s from proc %d",buffer,proc->id);
-
- return {0,0,0};
-}
-
-long long sys_exit_group(int status) {
- cpudata_t* cpdata = arch::x86_64::cpu::data();
- arch::x86_64::process_t* proc = CURRENT_PROC;
- DEBUG(1,"Process %d exited with status %d (exit_group)",proc->id,status);
- char* vm_start = proc->vmm_start;
- arch::x86_64::process_t* current = arch::x86_64::scheduling::head_proc_();
- memory::paging::enablekernel();
- DEBUG(proc->is_debug,"a");
- while(current) {
- if(proc->id == current->id) {
- current->exit_code = 0;
- current->is_execd = 1;
-
- DEBUG(proc->is_debug,"sh %d",current->id);
- arch::x86_64::scheduling::kill(current);
-
- if(1)
- memory::vmm::free(current);
-
- vfs::fdmanager* fd = (vfs::fdmanager*)current->fd;
- fd->free();
-
- memory::pmm::_virtual::free(current->cwd);
- memory::pmm::_virtual::free(current->name);
- memory::pmm::_virtual::free(current->sse_ctx);
- cpdata->temp.temp_ctx = 0;
- } else if(proc->vmm_start == current->vmm_start && proc->thread_group == current->thread_group) {
- // send sigkill
- if(current->sig) {
- pending_signal_t sig;
- sig.sig = SIGKILL;
- current->sig->push(&sig);
- }
- }
- current = current->next;
- }
- schedulingScheduleAndChangeStack(arch::x86_64::cpu::data()->timer_ist_stack,0);
- __builtin_unreachable();
-}
-
-long long sys_exit(int status) {
-
- cpudata_t* cpdata = arch::x86_64::cpu::data();
-
- arch::x86_64::process_t* proc = CURRENT_PROC;
- proc->exit_code = status;
-
- if(proc->tidptr) {
- *proc->tidptr = 0;
- arch::x86_64::scheduling::futexwake(proc,proc->tidptr,1);
- }
-
-
- memory::paging::enablekernel();
-
- DEBUG(1,"Process %s (%d) exited with code %d sys %d",proc->name,proc->id,status,proc->sys);
-
- if(proc->is_debug)
- assert(1,"debug: proc exit status is not 0");
-
- if(proc->exit_signal != 0) {
- arch::x86_64::process_t* target_proc = arch::x86_64::scheduling::by_pid(proc->parent_id);
- if(target_proc) {
- pending_signal_t pend_sig;
- pend_sig.sig = proc->exit_signal;
- target_proc->sig->push(&pend_sig);
- }
- }
-
- arch::x86_64::scheduling::kill(proc);
-
- if(1)
- memory::vmm::free(proc);
-
- vfs::fdmanager* fd = (vfs::fdmanager*)proc->fd;
- fd->free();
-
- proc->is_execd = 1;
-
- memory::pmm::_virtual::free(proc->cwd);
- memory::pmm::_virtual::free(proc->name);
- memory::pmm::_virtual::free(proc->sse_ctx);
- cpdata->temp.temp_ctx = 0;
- schedulingScheduleAndChangeStack(arch::x86_64::cpu::data()->timer_ist_stack,0);
- __builtin_unreachable();
-}
-
-locks::spinlock mmap_lock; // memory access should be locked anyway
-
-#define PROT_READ 0x1 /* page can be read */
-#define PROT_WRITE 0x2 /* page can be written */
-#define PROT_EXEC 0x4 /* page can be executed */
-#define PROT_SEM 0x8 /* page may be used for atomic ops */
-/* 0x10 reserved for arch-specific use */
-/* 0x20 reserved for arch-specific use */
-#define PROT_NONE 0x0 /* page can not be accessed */
-#define PROT_GROWSDOWN 0x01000000 /* mprotect flag: extend change to start of growsdown vma */
-#define PROT_GROWSUP 0x02000000 /* mprotect flag: extend change to end of growsup vma */
-
-// unimplemented just return errors if not valid
-long long sys_mprotect(std::uint64_t start, size_t len, std::uint64_t prot) {
- arch::x86_64::process_t* proc = CURRENT_PROC;
- if(!start)
- return -EINVAL;
-
- vmm_obj_t* vmm_ = memory::vmm::getlen(proc,start);
-
- if(!vmm_)
- return -EINVAL;
-
- DEBUG(proc->is_debug,"trying to mprotect 0x%p",start);
-
- std::uint64_t new_flags = PTE_USER | PTE_PRESENT;
- new_flags |= (prot & PROT_WRITE) ? PTE_RW : 0;
-
- return 0;
-}
-
-long long sys_prlimit64(int pid, int res, rlimit64* new_rlimit, int_frame_t* ctx) {
- rlimit64* old_rlimit = (rlimit64*)ctx->r10;
-
- if(new_rlimit || !old_rlimit)
- return 0;
-
- switch(res) {
- case RLIMIT_NOFILE:
- old_rlimit->rlim_cur = 512*1024;
- old_rlimit->rlim_max = 512*1024;
- return 0;
- case RLIMIT_STACK:
- old_rlimit->rlim_cur = USERSPACE_STACK_SIZE;
- old_rlimit->rlim_max = USERSPACE_STACK_SIZE;
- return 0;
- case RLIMIT_NPROC:
- old_rlimit->rlim_cur = 0xffffffff;
- old_rlimit->rlim_max = 0xffffffff;
- return 0;
- case RLIMIT_AS:
- case RLIMIT_LOCKS:
- case RLIMIT_MEMLOCK:
- case RLIMIT_CPU:
- case RLIMIT_RSS:
- case RLIMIT_FSIZE:
- case RLIMIT_DATA:
- old_rlimit->rlim_cur = RLIM_INFINITY;
- old_rlimit->rlim_max = RLIM_INFINITY;
- return 0;
- case RLIMIT_CORE:
- old_rlimit->rlim_cur = 0;
- old_rlimit->rlim_max = 0;
- return 0;
- default:
- return -EINVAL;
- }
- return 0;
-}
-
-long long sys_mmap(std::uint64_t hint, std::uint64_t size, unsigned long prot, int_frame_t* ctx) {
-
- std::uint64_t flags = ctx->r10;
- int fd0 = ctx->r8;
- std::uint64_t off = ctx->r9;
-
- size = ALIGNPAGEUP(size);
-
- arch::x86_64::process_t* proc = CURRENT_PROC;
-
- DEBUG(proc->is_debug,"trying to mmap 0x%p-0x%p sz %lli, prot %lli, flags %lli fd %d off %lli from proc %d, is fixed %d",hint,hint + size,size,prot,flags,fd0,off,proc->id,flags & MAP_FIXED);
-
- if(flags & MAP_ANONYMOUS) {
-
- std::uint64_t new_hint = hint;
- int is_shared = (flags & MAP_SHARED) ? 1 : 0;
-
- if(is_shared) {
- DEBUG(1,"shared mem\n");
- asm volatile("hlt");
- }
-
- if(!new_hint) {
- new_hint = (std::uint64_t)memory::vmm::lazy_alloc(proc,size,PTE_PRESENT | PTE_USER | PTE_RW,0);
- } else
- memory::vmm::customalloc(proc,new_hint,size,PTE_PRESENT | PTE_RW | PTE_USER,0,flags & MAP_FIXED);
-
- memory::vmm::invtlb(proc,new_hint,size);
-
- DEBUG(proc->is_debug,"return 0x%p",new_hint);
- return (std::int64_t)new_hint;
- } else {
-
- std::uint64_t mmap_base = 0;
- std::uint64_t mmap_size = 0;
- std::uint64_t mmap_flags = 0;
- userspace_fd_t* fd = vfs::fdmanager::search(proc,fd0);
- if(!fd) {
- return -EBADF; }
-
- int status = vfs::vfs::mmap(fd,&mmap_base,&mmap_size,&mmap_flags);
-
- if(status == ENOSYS) {
- // try to fix this and read whole file
- std::int64_t old_offset = fd->offset;
- fd->offset = off;
-
- vfs::stat_t stat;
- std::int32_t stat_status = vfs::vfs::stat(fd,&stat);
-
- if(!(stat.st_mode & S_IFREG)) {
- return -EFAULT; }
-
- std::uint64_t new_hint_hint;
-
- if(!hint) {
- new_hint_hint = (std::uint64_t)memory::vmm::lazy_alloc(proc,size,PTE_PRESENT | PTE_USER | PTE_RW,0);
- memory::vmm::invmapping(proc,new_hint_hint,size);
- } else {
- new_hint_hint = (std::uint64_t)memory::vmm::customalloc(proc,hint,size,PTE_PRESENT | PTE_USER | PTE_RW,0,flags & MAP_FIXED);
- memory::vmm::invmapping(proc,new_hint_hint,size);
- }
-
- memory::vmm::invtlb(proc,new_hint_hint,size);
-
- vfs::vfs::read(fd,(void*)new_hint_hint,size <= 0 ? stat.st_size : size);
- fd->offset = old_offset;
-
- DEBUG(proc->is_debug,"returna 0x%p, is_fixed %d",new_hint_hint,flags & 0x100000);
-
- return (std::int64_t)new_hint_hint;
-
- }
-
- if(status != 0) {
- return -status; }
-
- std::uint64_t new_hint_hint = (std::uint64_t)memory::vmm::map(proc,mmap_base,mmap_size,PTE_PRESENT | PTE_USER | PTE_RW | mmap_flags);
- memory::vmm::invtlb(proc,new_hint_hint,mmap_size);
-
- return (std::int64_t)new_hint_hint;
- }
-}
-
-long long sys_free(void *pointer, size_t size) {
- arch::x86_64::process_t* proc = CURRENT_PROC;
- memory::vmm::unmap(proc,(std::uint64_t)pointer,size);
- memory::vmm::invtlb(proc,(std::uint64_t)pointer,size);
-
- return 0;
-}
-
-long long sys_set_tid_address(int* tidptr) {
- SYSCALL_IS_SAFEZ((void*)tidptr,4096);
-
- arch::x86_64::process_t* proc = CURRENT_PROC;
- proc->tidptr = tidptr;
-
- return 0;
-}
-
-typedef struct stackframe {
- struct stackframe* rbp;
- uint64_t rip;
-} __attribute__((packed)) stackframe_t;
-
-syscall_ret_t sys_fork(int D, int S, int d, int_frame_t* ctx) {
-
- arch::x86_64::process_t* proc = CURRENT_PROC;
-
- arch::x86_64::process_t* new_proc = arch::x86_64::scheduling::fork(proc,ctx);
- new_proc->ctx.rax = 0;
- new_proc->ctx.rdx = 0;
-
- arch::x86_64::scheduling::wakeup(new_proc);
-
- DEBUG(proc->is_debug,"Fork from proc %d, new proc %d",proc->id,new_proc->id);
- new_proc->is_debug = proc->is_debug;
- if(proc->is_debug) {
- stackframe_t* rbp = (stackframe_t*)ctx->rbp;
- Log::SerialDisplay(LEVEL_MESSAGE_INFO,"[0] - 0x%016llX (current rip)\n",ctx->rip);
- for (int i = 1; i < 10 && rbp; ++i) {
- std::uint64_t ret_addr = rbp->rip;
- Log::SerialDisplay(LEVEL_MESSAGE_INFO,"[%d] - 0x%016llX (0x%016llX)\n", i, ret_addr,ret_addr - memory::vmm::getlen(proc,ret_addr)->base);
- rbp = (stackframe_t*)rbp->rbp;
- }
- }
-
- return {1,0,new_proc->id};
-}
-
-/* Just give full io access to userspace */
-syscall_ret_t sys_iopl(int a, int b ,int c , int_frame_t* ctx) {
- ctx->r11 |= (1 << 12) | (1 << 13);
- return {0,0,0};
-}
-
-syscall_ret_t sys_access_framebuffer(void* out) {
-
- arch::x86_64::process_t* proc = CURRENT_PROC;
-
- struct limine_framebuffer temp;
- memcpy(&temp,BootloaderInfo::AccessFramebuffer(),sizeof(struct limine_framebuffer));
- temp.address = (void*)((std::uint64_t)temp.address - BootloaderInfo::AccessHHDM());
- copy_in_userspace(proc,out,&temp,sizeof(struct limine_framebuffer));
-
- return {0,0,0};
-}
-
-std::uint64_t __elf_get_length2(char** arr) {
- std::uint64_t counter = 0;
-
- while(arr[counter])
- counter++;
-
- return counter;
-}
-
-long long sys_exec(char* path, char** argv, char** envp, int_frame_t* ctx) {
-
- if(!path || !argv || !envp)
- return -EINVAL;
-
- cpudata_t* cpdata = arch::x86_64::cpu::data();
-
- SYSCALL_IS_SAFEZ(path,4096);
- SYSCALL_IS_SAFEZ(argv,4096);
- SYSCALL_IS_SAFEZ(envp,4096);
-
- std::uint64_t argv_length = 0;
- std::uint64_t envp_length = 0;
-
- arch::x86_64::process_t* proc = arch::x86_64::cpu::data()->temp.proc;
-
- argv_length = __elf_get_length2((char**)argv);
- envp_length = __elf_get_length2((char**)envp);
-
- char** argv0 = (char**)memory::heap::malloc(8 * (argv_length + 3));
- char** envp0 = (char**)memory::heap::malloc(8 * (envp_length + 1));
-
- memset(argv0,0,8 * (envp_length + 2));
- memset(envp0,0,8 * (envp_length + 1));
-
- char stack_path[2048];
-
- memset(stack_path,0,2048);
-
- for(int i = 0;i < argv_length; i++) {
-
- char* str = argv[i];
-
- char* new_str = (char*)memory::heap::malloc(strlen(str) + 1);
-
- memcpy(new_str,str,strlen(str));
-
- argv0[i] = new_str;
-
- }
-
- for(int i = 0;i < envp_length; i++) {
-
- char* str = envp[i];
-
- char* new_str = (char*)memory::heap::malloc(strlen(str) + 1);
-
- memcpy(new_str,str,strlen(str));
-
- envp0[i] = new_str;
-
- }
-
- copy_in_userspace_string(proc,stack_path,path,2048);
-
- char result[2048];
- vfs::resolve_path(stack_path,proc->cwd,result,1,0);
-
- vfs::stat_t stat;
-
- userspace_fd_t fd;
- fd.is_cached_path = 0;
- memset(fd.path,0,2048);
- memcpy(fd.path,result,strlen(result));
-
- int status = vfs::vfs::stat(&fd,&stat);
-
- if(status != 0)
- return -status;
-
- vfs::fdmanager* fd_m = (vfs::fdmanager*)proc->fd;
- fd_m->cloexec();
-
- memset(proc->ret_handlers,0,sizeof(proc->ret_handlers));
- memset(proc->sig_handlers,0,sizeof(proc->sig_handlers));
- arch::x86_64::free_sigset_from_list(proc);
-
- DEBUG(proc->is_debug,"Exec file %s from proc %d",fd.path,proc->id);
- if(1) {
- for(int i = 0;i < argv_length;i++) {
- DEBUG(proc->is_debug,"Argv %d: %s",i,argv0[i]);
- }
- }
-
- if(status == 0) {
- if((stat.st_mode & S_IXUSR) && (stat.st_mode & S_IFREG)) {
-
- proc->fs_base = 0;
-
- memory::paging::enablekernel();
- memory::vmm::free(proc);
-
- memory::vmm::initproc(proc);
-
- memset(&proc->ctx,0,sizeof(int_frame_t));
-
- memory::vmm::reload(proc);
-
- proc->ctx.cs = 0x20 | 3;
- proc->ctx.ss = 0x18 | 3;
-
- proc->ctx.rflags = (1 << 9);
-
- status = arch::x86_64::scheduling::loadelf(proc,result,argv0,envp0,0);
- if(status == 0) {
-
- for(int i = 0;i < argv_length; i++) {
- memory::heap::free(argv0[i]);
- }
-
- for(int i = 0;i < envp_length; i++) {
- memory::heap::free(envp0[i]);
- }
-
- memory::heap::free(argv0);
- memory::heap::free(envp0);
-
- proc->is_execd = 1;
-
- cpdata->temp.temp_ctx = 0;
- schedulingScheduleAndChangeStack(arch::x86_64::cpu::data()->timer_ist_stack,0);
- __builtin_unreachable();
- }
-
- // maybe sh ?
- char interp[2048];
- memset(interp,0,2048);
-
- int i = 0;
- memcpy(interp,"/bin/sh",strlen("/bin/sh"));
-
- userspace_fd_t test;
- test.is_cached_path = 0;
- test.offset = 0;
- memset(test.path,0,2048);
- memcpy(test.path,result,strlen(result));
-
-
-
- char first;
- status = vfs::vfs::read(&test,&first,1);
- if(status > 0) {
- if(first == '!') {
- memset(interp,0,2048);
- while(1) {
- int c = vfs::vfs::read(&test,&first,1);
- if(c && c != '\n')
- interp[i++] = c;
- if(c && c == '\n')
- break;
- }
- }
- argv_length++;
- memcpy(&argv0[2], argv0,sizeof(std::uint64_t) * argv_length);
- char* t1 = (char*)malloc(2048);
- memset(t1,0,2048);
- memcpy(t1,interp,strlen(interp));
- char* t2 = (char*)malloc(2048);
- memset(t2,0,2048);
- memcpy(t2,result,strlen(result));
- argv0[0] = t1;
- argv0[1] = t2;
-
- DEBUG(1,"interp %s to %s",argv0[0],argv0[1]);
-
- status = arch::x86_64::scheduling::loadelf(proc,interp,argv0,envp0,0);
- free((void*)t1);
- free((void*)t2);
-
- if(status == 0) {
-
- for(int i = 0;i < argv_length; i++) {
- memory::heap::free(argv0[i]);
- }
-
- for(int i = 0;i < envp_length; i++) {
- memory::heap::free(envp0[i]);
- }
-
- memory::heap::free(argv0);
- memory::heap::free(envp0);
-
- proc->is_execd = 1;
-
- cpdata->temp.temp_ctx = 0;
- schedulingScheduleAndChangeStack(arch::x86_64::cpu::data()->timer_ist_stack,0);
- __builtin_unreachable();
- }
-
- }
-
- }
- }
-
-
-
- for(int i = 0;i < argv_length; i++) {
- memory::heap::free(argv0[i]);
- }
-
- for(int i = 0;i < envp_length; i++) {
- memory::heap::free(envp0[i]);
- }
-
- memory::heap::free(argv0);
- memory::heap::free(envp0);
-
- proc->exit_code = -1;
- proc->is_execd = 1;
-
- cpdata->temp.temp_ctx = 0;
- arch::x86_64::scheduling::kill(proc);
- schedulingScheduleAndChangeStack(arch::x86_64::cpu::data()->timer_ist_stack,0);
- __builtin_unreachable();
-}
-
-long long sys_getpid() {
- arch::x86_64::process_t* proc = CURRENT_PROC;
- return proc->id;
-}
-
-long long sys_getppid() {
- arch::x86_64::process_t* proc = CURRENT_PROC;
- return proc->parent_id;
-}
-
-syscall_ret_t sys_gethostname(void* buffer, std::uint64_t bufsize) {
-
- if(!buffer)
- return {0,EINVAL,0};
-
- SYSCALL_IS_SAFEA(buffer,bufsize);
-
- const char* default_hostname = "orange-pc";
- arch::x86_64::process_t* proc = CURRENT_PROC;
-
- zero_in_userspace(proc,buffer,bufsize);
- copy_in_userspace(proc,buffer,(void*)default_hostname,strlen(default_hostname));
-
- return {0,0,0};
-}
-
-long long sys_getcwd(void* buffer, std::uint64_t bufsize) {
-
- SYSCALL_IS_SAFEZ(buffer,bufsize);
-
- arch::x86_64::process_t* proc = CURRENT_PROC;
-
- zero_in_userspace(proc,buffer,bufsize);
-
- char buffer0[4096];
- memcpy(buffer0,proc->cwd,4096);
-
- copy_in_userspace(proc,buffer,buffer0,strlen((const char*)buffer0) > bufsize ? bufsize : strlen((const char*)buffer0));
-
- return 0;
-}
-
-long long sys_wait4(int pid,int* status,int flags) {
-
- arch::x86_64::process_t* proc = CURRENT_PROC;
-
- arch::x86_64::process_t* current = arch::x86_64::scheduling::head_proc_();
-
- DEBUG(proc->is_debug,"Trying to waitpid with pid %d from proc %d",pid,proc->id);
-
- if(pid < -1 || pid == 0)
- return -EINVAL;
-
- SYSCALL_IS_SAFEZ(status,4096);
-
- int success = 0;
-
- std::uint64_t current_timestamp = time::counter();
- std::uint64_t ns = 1000 * 1000 * 1000;
-
- if(pid == -1) {
- while (current)
- {
- if(current->parent_id == proc->id && (current->status = PROCESS_STATE_ZOMBIE || current->status == PROCESS_STATE_RUNNING) && current->waitpid_state != 2) {
- current->waitpid_state = 1;
- success = 1;
- }
- current = current->next;
- }
- } else if(pid > 0) {
- while (current)
- {
- if(current->parent_id == proc->id && (current->status = PROCESS_STATE_ZOMBIE || current->status == PROCESS_STATE_RUNNING) && current->id == pid && current->waitpid_state != 2) {
- current->waitpid_state = 1;
- success = 1;
- break;
- }
- current = current->next;
- }
- }
-
- if(!success)
- return -ECHILD;
-
- int parent_id = proc->id;
-
- current = arch::x86_64::scheduling::head_proc_();
- while(1) {
- while (current)
- {
- if(current) {
- if(current->parent_id == parent_id && current->kill_lock.test() && current->waitpid_state == 1 && current->id != 0) {
- current->waitpid_state = 2;
- std::int64_t bro = (std::int64_t)(((std::uint64_t)current->exit_code) << 32) | current->id;
- current->status = PROCESS_STATE_KILLED;
- DEBUG(proc->is_debug,"Waitpid done pid %d from proc %d",pid,proc->id);
- if(status)
- *status = current->exit_code;
- return bro;
- }
- }
- current = current->next;
- }
-
- if(flags & WNOHANG) {
- arch::x86_64::process_t* pro = arch::x86_64::scheduling::head_proc_();
- while(pro) {
- if(pro->parent_id == parent_id && proc->waitpid_state == 1)
- proc->waitpid_state = 0;
- pro = pro->next;
- }
- DEBUG(proc->is_debug,"Waitpid return WNOHAND from proc %d",proc->id);
- return 0;
- }
- signal_ret();
- yield();
- current = arch::x86_64::scheduling::head_proc_();
- }
-
-}
-
-syscall_ret_t sys_sleep(long us) {
-
- std::uint64_t current = drivers::tsc::currentnano();
- std::uint64_t end = us * 1000;
- while((drivers::tsc::currentnano() - current) < end) {
- if((drivers::tsc::currentnano() - current) < 15000) {
- asm volatile("pause");
- } else
- yield();
- signal_ret();
- }
- return {0,0,0};
-}
-
-syscall_ret_t sys_alloc_dma(std::uint64_t size) {
- return {1,0,memory::pmm::_physical::alloc(size)};
-}
-
-syscall_ret_t sys_free_dma(std::uint64_t phys) {
- memory::pmm::_physical::free(phys);
- return {0,0,0};
-}
-
-syscall_ret_t sys_map_phys(std::uint64_t phys, std::uint64_t flags, std::uint64_t size) {
- arch::x86_64::process_t* proc = CURRENT_PROC;
- return {1,0,(std::int64_t)memory::vmm::map(proc,phys,size,PTE_PRESENT | PTE_USER | PTE_RW | flags)};
-}
-
-std::uint64_t timestamp = 0;
-
-syscall_ret_t sys_timestamp() {
- timestamp = drivers::tsc::currentnano() > timestamp ? drivers::tsc::currentnano() : timestamp;
- return {1,0,(std::int64_t)timestamp};
-}
-
-syscall_ret_t sys_enabledebugmode() {
- arch::x86_64::process_t* proc = CURRENT_PROC;
- proc->is_debug = !proc->is_debug;
- DEBUG(proc->is_debug,"Enabling/Disabling debug mode for proc %d",proc->id);
- return {0,0,0};
-}
-
-syscall_ret_t sys_enabledebugmodepid(int pid) {
- arch::x86_64::process_t* proc = arch::x86_64::scheduling::head_proc_();
- while(proc) {
- if(proc->id == pid)
- break;
- proc = proc->next;
- }
- if(!proc)
- return {0,ECHILD};
-
- DEBUG(proc->is_debug,"Enabling/Disabling debug mode for proc %d",proc->id);
- proc->is_debug = !proc->is_debug;
- return {0,0,0};
-}
-
-syscall_ret_t sys_printdebuginfo(int pid) {
- arch::x86_64::process_t* proc = arch::x86_64::scheduling::head_proc_();
- while(proc) {
- if(proc->id == pid)
- break;
- proc = proc->next;
- }
- if(!proc)
- return {0,ECHILD};
-
- DEBUG(1,"Process %d rip is 0x%p debug0 %d debug1 %d, sys %d",proc->id,proc->ctx.rip,proc->debug0,proc->debug1,proc->sys);
- stackframe_t* rbp = (stackframe_t*)proc->ctx.rbp;
- Log::SerialDisplay(LEVEL_MESSAGE_INFO,"[0] - 0x%016llX (current rip)\n",proc->ctx.rip);
- for (int i = 1; i < 10 && rbp; ++i) {
- std::uint64_t ret_addr = rbp->rip;
- Log::SerialDisplay(LEVEL_MESSAGE_INFO,"[%d] - 0x%016llX (0x%016llX)\n", i, ret_addr,0);
- rbp = (stackframe_t*)rbp->rbp;
- }
- return {0,0,0};
-}
-
-
-long long sys_clone3(clone_args* clargs, size_t size, int c, int_frame_t* ctx) {
- // size is ignored
- arch::x86_64::process_t* proc = CURRENT_PROC;
-
- arch::x86_64::process_t* new_proc = arch::x86_64::scheduling::clone3(proc,clargs,ctx);
- new_proc->ctx.rax = 0;
-
- arch::x86_64::scheduling::wakeup(new_proc);
-
- DEBUG(proc->is_debug,"clone3 from proc %d, new proc %d (new syscall_stack: 0x%p) %s, parent tid 0x%p , child tid 0x%p, pidfd 0x%p %s",proc->id,new_proc->id,new_proc->syscall_stack,clargs->flags & CLONE_VM ? "CLONEVM" : "NOCLONEVM",clargs->parent_tid,clargs->child_tid,clargs->pidfd,clargs->flags & CLONE_VFORK ? "VFORK" : "NOVFORK");
- new_proc->is_debug = proc->is_debug;
-
- if(clargs->flags & CLONE_VFORK) {
- while(1) {
- if(new_proc->is_execd == 1)
- break;
- yield();
- }
- }
-
- return new_proc->id;
-}
-
-// convert clone to clone3
-long long sys_clone(unsigned long clone_flags, unsigned long newsp, int *parent_tidptr, int_frame_t* ctx) {
- std::uint64_t child_tidptr = ctx->r10;
- std::uint64_t tls = ctx->r8;
- clone_args arg = {0};
- arg.flags = clone_flags;
- arg.stack = newsp;
- arg.parent_tid = (std::uint64_t)parent_tidptr;
- arg.tls = tls;
- arg.child_tid = child_tidptr;
- return sys_clone3(&arg,sizeof(clone_args),0,ctx);
-}
-
-syscall_ret_t sys_breakpoint(int num, int b, int c, int_frame_t* ctx) {
-
- arch::x86_64::process_t* proc = CURRENT_PROC;
- if(proc->is_debug) {
- Log::SerialDisplay(LEVEL_MESSAGE_INFO,"breakpoint 0x%p\n",num);
- stackframe_t* rbp = (stackframe_t*)ctx->rbp;
- Log::SerialDisplay(LEVEL_MESSAGE_INFO,"[0] - 0x%016llX (current rip)\n",ctx->rip);
- for (int i = 1; i < 10 && rbp; ++i) {
- std::uint64_t ret_addr = rbp->rip;
- Log::SerialDisplay(LEVEL_MESSAGE_INFO,"[%d] - 0x%016llX (0x%016llX)\n", i, ret_addr,ret_addr - memory::vmm::getlen(proc,ret_addr)->base);
- rbp = (stackframe_t*)rbp->rbp;
- }
- }
- return {0,0,0};
-}
-
-syscall_ret_t sys_copymemory(void* src, void* dest, int len) {
- arch::x86_64::process_t* proc = CURRENT_PROC;
- copy_in_userspace(proc,dest,src,len);
- return {0,0,0};
-}
-
-#define PRIO_PROCESS 1
-#define PRIO_PGRP 2
-#define PRIO_USER 3
-
-long long sys_setpriority(int which, int who, int prio) {
- arch::x86_64::process_t* proc = CURRENT_PROC;
- if(which == PRIO_PROCESS) {
-
- arch::x86_64::process_t* need_proc = arch::x86_64::scheduling::head_proc_();
- while(need_proc) {
- if(need_proc->id == who)
- break;
- need_proc = need_proc->next;
- }
-
- if(!need_proc)
- return -ESRCH;
-
- DEBUG(proc->is_debug,"Setpriority %d to proc %d (who %d) which %d from proc %d",prio,need_proc->id,who,which,proc->id);
- need_proc->prio = prio;
-
- } else
- return -ENOSYS;
- return 0;
-}
-
-long long sys_getpriority(int which, int who) {
- int prio = 0;
- if(which == 0) { // PRIO_PROCESS
- arch::x86_64::process_t* proc = CURRENT_PROC;
-
- arch::x86_64::process_t* need_proc = arch::x86_64::scheduling::head_proc_();
- while(need_proc) {
- if(need_proc->id == who)
- break;
- need_proc = need_proc->next;
- }
-
- if(!need_proc)
- return -ESRCH;
- prio = need_proc->prio;
- DEBUG(proc->is_debug,"Getpriority %d to proc %d (who %d) from proc %d",prio,need_proc->id,who,proc->id);
- } else
- return -ENOSYS;
- return prio;
-}
-
-syscall_ret_t sys_yield() {
- yield();
- return {0,0,0};
-}
-
-syscall_ret_t sys_dmesg(char* buf,std::uint64_t count) {
- SYSCALL_IS_SAFEA(buf,count);
- arch::x86_64::process_t* proc = CURRENT_PROC;
-
- if(!buf) {
- return {1,0,(std::int64_t)dmesg_bufsize()};
- }
-
- vmm_obj_t* vmm_object = memory::vmm::getlen(proc,(std::uint64_t)buf);
- uint64_t need_phys = vmm_object->phys + ((std::uint64_t)buf - vmm_object->base);
-
- std::uint64_t offset_start = (std::uint64_t)buf - vmm_object->base;
- std::uint64_t end = vmm_object->base + vmm_object->len;
-
- char* temp_buffer = (char*)Other::toVirt(need_phys);
- memset(temp_buffer,0,count);
-
- dmesg_read(temp_buffer,count);
-
- return {1,0,0};
-}
-
-long long sys_getuid() {
- arch::x86_64::process_t* proc = CURRENT_PROC;
- return proc->uid;
-}
-
-long long sys_getpgrp() {
- arch::x86_64::process_t* proc = CURRENT_PROC;
- return proc->thread_group;
-}
-
-long long sys_setpgid(int pid, int pgid) {
- arch::x86_64::process_t* proc = CURRENT_PROC;
- if(pid > 0) {
- proc = arch::x86_64::scheduling::by_pid(pid);
- if(!proc)
- return -ESRCH;
- }
- proc->thread_group = pgid;
- return 0;
-}
-
-long long sys_getpgid(int pid) {
- arch::x86_64::process_t* proc = CURRENT_PROC;
- if(pid > 0) {
- proc = arch::x86_64::scheduling::by_pid(pid);
- if(!proc)
- return -ESRCH;
- }
- return proc->thread_group;
-}
-
-long long sys_getresuid(int* ruid, int* euid, int *suid) {
-
- SYSCALL_IS_SAFEZ(ruid,4096);
- SYSCALL_IS_SAFEZ(euid,4096);
- SYSCALL_IS_SAFEZ(suid,4096);
-
- if(!ruid || !euid || !suid)
- return -EINVAL;
-
- *ruid = sys_getuid();
- *euid = sys_getuid();
- *suid = sys_getuid();
- return 0;
-}
-
-long long sys_setuid(int uid) {
- arch::x86_64::process_t* proc = CURRENT_PROC;
- if(proc->uid > 1000)
- return -EPERM;
- proc->uid = uid;
- return 0;
-}
-
-// used from mlibc source, why not
-
-#define CHAR_BIT 8
-#define CPU_MASK_BITS (CHAR_BIT * sizeof(__cpu_mask))
-
-std::uint64_t __mlibc_cpu_alloc_size(int num_cpus) {
- /* calculate the (unaligned) remainder that doesn't neatly fit in one __cpu_mask; 0 or 1 */
- std::uint64_t remainder = ((num_cpus % CPU_MASK_BITS) + CPU_MASK_BITS - 1) / CPU_MASK_BITS;
- return sizeof(__cpu_mask) * (num_cpus / CPU_MASK_BITS + remainder);
-}
-
-#define CPU_ALLOC_SIZE(n) __mlibc_cpu_alloc_size((n))
-
-void __mlibc_cpu_zero(const std::uint64_t setsize, cpu_set_t *set) {
- memset(set, 0, CPU_ALLOC_SIZE(setsize));
-}
-
-void __mlibc_cpu_set(const int cpu, const std::uint64_t setsize, cpu_set_t *set) {
- if(cpu >= static_cast<int>(setsize * CHAR_BIT)) {
- return;
- }
-
- unsigned char *ptr = reinterpret_cast<unsigned char *>(set);
- std::uint64_t off = cpu / CHAR_BIT;
- std::uint64_t mask = 1 << (cpu % CHAR_BIT);
-
- ptr[off] |= mask;
-}
-
-#define CPU_ZERO_S(setsize, set) __mlibc_cpu_zero((setsize), (set))
-#define CPU_ZERO(set) CPU_ZERO_S(sizeof(cpu_set_t), set)
-#define CPU_SET_S(cpu, setsize, set) __mlibc_cpu_set((cpu), (setsize), (set))
-#define CPU_SET(cpu, set) CPU_SET_S(cpu, sizeof(cpu_set_t), set)
-
-void __fill_cpu_set(cpu_set_t* cpuset) {
-
- extern int how_much_cpus;
-
- CPU_ZERO(cpuset);
-
- for(int i = 0; i < how_much_cpus; i++) {
- CPU_SET(i, cpuset);
- }
-}
-
-syscall_ret_t sys_getaffinity(pid_t pid, size_t cpusetsize, cpu_set_t *mask) {
-
- arch::x86_64::process_t* proc = 0;
-
- if(cpusetsize > sizeof(cpu_set_t))
- cpusetsize = sizeof(cpu_set_t);
-
- SYSCALL_IS_SAFEA(mask,cpusetsize);
- if(!mask)
- return {0,EINVAL,0};
-
- if(pid == 0) {
- proc = CURRENT_PROC;
- } else if(pid > 0) {
- proc = arch::x86_64::scheduling::by_pid(pid);
- if(!proc)
- return {0,ESRCH,0};
- } else
- return {0,EINVAL,0};
-
- cpu_set_t temp_set;
- memset(&temp_set,0,sizeof(cpu_set_t));
-
- __fill_cpu_set(&temp_set);
-
- memset(mask,0,cpusetsize);
- memcpy(mask,&temp_set,cpusetsize);
-
- return {0,0,0};
-}
-
-syscall_ret_t sys_cpucount() {
- extern int how_much_cpus;
- return {0,how_much_cpus,0};
-}
-
-long long sys_brk() {
- return 0;
-}
-
-#define ARCH_SET_GS 0x1001
-#define ARCH_SET_FS 0x1002
-#define ARCH_GET_FS 0x1003
-#define ARCH_GET_GS 0x1004
-
-#define ARCH_GET_CPUID 0x1011
-#define ARCH_SET_CPUID 0x1012
-
-long long sys_arch_prctl(int option, unsigned long* addr) {
- if(!addr)
- return -EINVAL;
-
- arch::x86_64::process_t* proc = CURRENT_PROC;
-
- switch(option) {
- case ARCH_SET_FS:
- proc->fs_base = (std::uint64_t)addr;
- __wrmsr(0xC0000100,(std::uint64_t)addr);
- return 0;
- case ARCH_GET_FS:
- SYSCALL_IS_SAFEZ(addr,4096);
- *addr = proc->fs_base;
- return 0;
- default:
- Log::SerialDisplay(LEVEL_MESSAGE_FAIL,"unsupported arch_prctl option %p, addr 0x%p, shit %d\n",option,addr,0);
- return -EINVAL;
- };
-
- return 0;
-} \ No newline at end of file
diff --git a/kernel/src/arch/x86_64/syscalls/shm.cpp b/kernel/src/arch/x86_64/syscalls/shm.cpp
deleted file mode 100644
index 7c2a278..0000000
--- a/kernel/src/arch/x86_64/syscalls/shm.cpp
+++ /dev/null
@@ -1,224 +0,0 @@
-
-#include <arch/x86_64/syscalls/syscalls.hpp>
-#include <generic/vfs/vfs.hpp>
-
-#include <arch/x86_64/cpu/data.hpp>
-#include <arch/x86_64/scheduling.hpp>
-
-#include <generic/mm/pmm.hpp>
-#include <generic/mm/vmm.hpp>
-
-#include <generic/vfs/fd.hpp>
-
-#include <etc/assembly.hpp>
-#include <etc/logging.hpp>
-
-#include <drivers/cmos.hpp>
-
-#include <etc/libc.hpp>
-
-#include <drivers/tsc.hpp>
-
-#include <etc/errno.hpp>
-
-#include <drivers/hpet.hpp>
-#include <drivers/kvmtimer.hpp>
-#include <generic/time.hpp>
-#include <generic/vfs/vfs.hpp>
-
-#include <etc/bootloaderinfo.hpp>
-#include <generic/locks/spinlock.hpp>
-
-static_assert(sizeof(shm_seg_t) < 4096, "shm_seg is bigger than page size !");
-
-locks::spinlock shm_lock;
-shm_seg_t* shm_head;
-
-int shm_id_ptr = 0;
-
-shm_seg_t* shm_find_by_key(int key) {
- shm_seg_t* current = shm_head;
- while(current) {
- if(current->key == key)
- return current;
- }
- return 0;
-}
-
-shm_seg_t* shm_find(int id) {
- shm_seg_t* current = shm_head;
- while(current) {
- if(current->id == id)
- return current;
- }
- return 0;
-}
-
-void shm_rm(shm_seg_t* seg) {
- shm_seg_t* prev = shm_head;
- while(prev) {
- if(prev->next == seg)
- break;
- prev = prev->next;
- }
-
- if(shm_head == seg)
- shm_head = seg->next;
- else if(prev)
- prev->next = seg->next;
-
- memory::pmm::_physical::free(seg->phys);
- delete (void*)seg;
-}
-
-shm_seg_t* shm_create(int key, size_t size) {
- shm_seg_t* new_seg = new shm_seg_t;
- memset(new_seg,0,sizeof(shm_seg_t));
- new_seg->next = shm_head;
- shm_head = new_seg;
- new_seg->key = key;
- new_seg->id = shm_id_ptr++;
- new_seg->len = size;
- new_seg->phys = memory::pmm::_physical::alloc(new_seg->len);
- return new_seg;
-}
-
-#define IPC_CREAT 01000
-#define IPC_EXCL 02000
-#define IPC_NOWAIT 04000
-
-syscall_ret_t sys_shmget(int key, size_t size, int shmflg) {
-
- arch::x86_64::process_t* proc = CURRENT_PROC;
- std::uint64_t src_size = size;
-
- if(size < 4096) {
- size = 4096;
- } else {
- size = ALIGNUP(size,4096);
- }
-
- shm_lock.lock();
-
- shm_seg_t* seg = shm_find_by_key(key);
-
- shm_lock.unlock();
-
- if(seg && ((shmflg & IPC_CREAT) && (shmflg & IPC_EXCL)))
- return {1,EEXIST,0};
-
- if(!seg && !(shmflg & IPC_CREAT))
- return {1,ENOENT,0};
-
- shm_lock.lock();
-
- if(shmflg & IPC_CREAT) {
- seg = shm_create(key,size);
- seg->ctl.shm_segsz = src_size;
- seg->ctl.shm_ctime = getUnixTime();
- seg->ctl.shm_cpid = proc->id;
- seg->ctl.shm_perm.cuid = proc->uid;
- seg->ctl.shm_perm.uid = proc->uid;
- seg->ctl.shm_perm.mode = shmflg & 0x1FF;
- }
-
- DEBUG(proc->is_debug,"Creating/getting shm for proc %d, id %d, size %lli, src_size %d, shmflg %d",proc->id,seg->id,size,src_size,shmflg);
-
- shm_lock.unlock();
-
- return {1,0,seg->id};
-}
-
-// inline static void* map(arch::x86_64::process_t* proc, std::uint64_t base, std::uint64_t length, std::uint64_t flags) {
-
-// inline static void* custom_map(arch::x86_64::process_t* proc, std::uint64_t virt, std::uint64_t phys, std::uint64_t length, std::uint64_t flags) {
-
-syscall_ret_t sys_shmat(int shmid, std::uint64_t hint, int shmflg) {
-
- shm_lock.lock();
-
- shm_seg_t* seg = shm_find(shmid);
-
- arch::x86_64::process_t* proc = CURRENT_PROC;
-
- if(!seg) { shm_lock.unlock();
- return {1,EINVAL,0}; }
-
- std::uint64_t new_hint = hint;
-
- new_hint = memory::vmm::shm_map(proc,seg,hint);
-
- memory::paging::enablepaging(proc->original_cr3); // try to reset tlb
-
- DEBUG(proc->is_debug,"Attaching shm %d to 0x%p, shmflg %d from proc %d",shmid,new_hint,shmflg,proc->id);
-
- shm_lock.unlock();
- return {1,0,new_hint};
-}
-
-syscall_ret_t sys_shmdt(std::uint64_t base) {
-
- arch::x86_64::process_t* proc = CURRENT_PROC;
-
- shm_lock.lock();
- vmm_obj_t* vmm_new = memory::vmm::getlen(proc,base);
-
- if(!vmm_new) { shm_lock.unlock();
- return {0,EINVAL,0}; }
-
- if(!vmm_new->shm) {
- shm_lock.unlock();
- return {0,EINVAL,0};
- }
-
- shm_seg_t* seg = vmm_new->shm;
- //memory::vmm::unmap(proc,vmm_new->base);
-
- DEBUG(proc->is_debug,"Removing shm %d, base 0x%p from proc %d",seg->id,base,proc->id);
-
- shm_lock.unlock();
- return {0,0,0};
-}
-
-syscall_ret_t sys_shmctl(int shmid, int cmd, struct shmid_ds *buf) {
-
- arch::x86_64::process_t* proc = CURRENT_PROC;
-
- shm_lock.lock();
-
- shm_seg_t* seg = shm_find(shmid);
-
- if(!seg) { shm_lock.unlock();
- return {0,EINVAL,0}; }
-
- if(!buf) { shm_lock.unlock();
- return {0,EINVAL,0};
- }
-
- switch(cmd) {
- case IPC_RMID: {
- seg->is_pending_rm = 1;
- if(seg->ctl.shm_nattch == 0 && seg->is_pending_rm) {
- shm_rm(seg);
- }
- break;
- }
- case IPC_STAT:
- memcpy(buf,&seg->ctl,sizeof(shmid_ds));
- break;
- case IPC_SET:
- seg->ctl.shm_perm.uid = buf->shm_perm.uid;
- seg->ctl.shm_perm.gid = buf->shm_perm.gid;
- seg->ctl.shm_ctime = getUnixTime();
- seg->ctl.shm_perm.mode = buf->shm_perm.mode;
- break;
- default:
- Log::SerialDisplay(LEVEL_MESSAGE_WARN,"Unknown shmctl cmd %d for id %d from proc %d\n",cmd,shmid,proc->id);
- break;
- }
-
- DEBUG(proc->is_debug,"shmctl id %d cmd %d buf 0x%p from proc %d\n",shmid,cmd,buf,proc->id);
-
- shm_lock.unlock();
- return {0,0,0};
-} \ No newline at end of file
diff --git a/kernel/src/arch/x86_64/syscalls/signal.cpp b/kernel/src/arch/x86_64/syscalls/signal.cpp
deleted file mode 100644
index f156c79..0000000
--- a/kernel/src/arch/x86_64/syscalls/signal.cpp
+++ /dev/null
@@ -1,304 +0,0 @@
-
-#include <arch/x86_64/syscalls/syscalls.hpp>
-#include <generic/vfs/vfs.hpp>
-
-#include <arch/x86_64/cpu/data.hpp>
-#include <arch/x86_64/scheduling.hpp>
-
-#include <generic/mm/pmm.hpp>
-#include <generic/mm/vmm.hpp>
-
-#include <generic/vfs/fd.hpp>
-
-#include <etc/assembly.hpp>
-#include <etc/logging.hpp>
-
-#include <drivers/cmos.hpp>
-
-#include <etc/libc.hpp>
-
-#include <drivers/tsc.hpp>
-
-#include <etc/errno.hpp>
-
-#include <drivers/hpet.hpp>
-#include <drivers/kvmtimer.hpp>
-#include <generic/time.hpp>
-#include <generic/vfs/vfs.hpp>
-
-#include <etc/bootloaderinfo.hpp>
-#include <generic/locks/spinlock.hpp>
-
-syscall_ret_t sys_orangesigreturn(mcontext_t* mctx, int b, int c, int_frame_t* ctx) {
- // is_sig_real
- arch::x86_64::process_t* proc = CURRENT_PROC;
- mcontext_to_int_frame(mctx,&proc->ctx);
- proc->ctx.cs = 0x20 | 3;
- proc->ctx.ss = 0x18 | 3;
- proc->ctx.rflags |= (1 << 9);
- DEBUG(1,"endsig from proc %d rip 0x%p",proc->id,proc->ctx.rip);
- schedulingScheduleAndChangeStack(arch::x86_64::cpu::data()->timer_ist_stack,0);
- __builtin_unreachable();
-}
-
-syscall_ret_t sys_orangedefaulthandler(void* handler) {
- return {0,ENOSYS,0};
- arch::x86_64::process_t* proc = CURRENT_PROC;
-
- DEBUG(proc->is_debug,"Setup default handler 0x%p from proc %d\n",handler,proc->id);
-
- return {0,0,0};
-}
-
-long long sys_pause() {
- arch::x86_64::process_t* proc = CURRENT_PROC;
-
- while(1) {
- signal_ret();
- yield();
- }
-
- return 0;
-}
-
-long long sys_tgkill(int tgid, int tid, int sig) {
- return sys_kill(tid,sig);
-}
-
-long long sys_kill(int pid, int sig) {
- arch::x86_64::process_t* proc = CURRENT_PROC;
- arch::x86_64::process_t* target_proc = arch::x86_64::scheduling::by_pid(pid);
-
- DEBUG(1,"Trying to kill %d with sig %d from proc %d\n",pid,sig,proc->id);
-
- if(!target_proc)
- return -ESRCH;
-
- if(pid == 0 && pid < 0)
- return 0; // not implemented
-
- if(!(proc->uid == 0 || proc->uid == target_proc->uid))
- return -EPERM;
-
- switch(sig) {
- case SIGKILL:
- target_proc->exit_code = 137;
- target_proc->_3rd_kill_lock.nowaitlock();
- break;
- case SIGTSTP:
- case SIGTTIN:
- case SIGTTOU:
- case SIGSTOP:
- if(target_proc->id == proc->id) // shit
- yield();
- return 0;
- default:
- pending_signal_t pend_sig;
- pend_sig.sig = sig;
- target_proc->sig->push(&pend_sig);
-
- DEBUG(1,"%d 0x%p",target_proc->id == proc->id,proc->sig_handlers[sig]);
-
- if(target_proc->id == proc->id) // shit
- signal_ret();
-
- return 0;
- }
-
- if(target_proc->id == proc->id) // shit
- signal_ret();
-
- return 0;
-}
-
-long long sys_sigaction(int signum, struct sigaction* hnd, struct sigaction* old, int_frame_t* ctx) {
- arch::x86_64::process_t* proc = CURRENT_PROC;
- SYSCALL_IS_SAFEZ(hnd,4096);
- SYSCALL_IS_SAFEZ(old,4096);
-
- DEBUG(proc->is_debug,"sigaction signum %d from proc %d with 0x%p",signum,proc->id,0);
-
- if(ctx->r10 != sizeof(sigset_t)) {
- DEBUG(proc->is_debug,"unsupported len %d for sigset sig %d from proc %d (linux dont support this)",ctx->r10,signum,proc->id);
- return -EINVAL;
- }
-
- if(signum >= 36)
- return -EINVAL;
-
- void* old_hnd = proc->sig_handlers[signum];
- void* old_rest = proc->ret_handlers[signum];
- if(old) {
- memset(old,0,sizeof(struct sigaction));
- old->sa_handler = (void (*)(int))old_hnd;
- old->sa_restorer = (void (*)())old_rest;
- old->sa_flags = proc->sig_flags[signum];
- memcpy(&old->sa_mask,&proc->sigsets[signum],sizeof(sigset_t));
- }
-
- if(hnd) {
- DEBUG(proc->is_debug,"sigaction %d, restorer 0x%p, handler 0x%p",signum,hnd->sa_restorer,hnd->sa_handler);
- proc->ret_handlers[signum] = (void*)hnd->sa_restorer;
- proc->sig_handlers[signum] = (void*)hnd->sa_handler;
- proc->sig_flags[signum] = hnd->sa_flags;
- memcpy(&proc->sigsets[signum],&hnd->sa_mask,sizeof(sigset_t));
- }
-
- return 0;
-
-}
-
-#define SIG_BLOCK 0 /* Block signals. sigset_t *unewset size_t sigsetsize */
-#define SIG_UNBLOCK 1 /* Unblock signals. */
-#define SIG_SETMASK 2 /* Set the set of blocked signals. */
-
-long long sys_alarm(int seconds) {
- arch::x86_64::process_t* proc = CURRENT_PROC;
- std::uint64_t t = proc->next_alarm;
- if(seconds != 0) {
- proc->next_alarm = drivers::tsc::currentus() + (seconds * (1000*1000));
- DEBUG(proc->is_debug,"alarm to %lli (%d seconds)",proc->next_alarm,seconds);
- } else {
- proc->next_alarm = 0;
- }
- if(t == 0)
- return 0;
- else {
- t -= drivers::tsc::currentus();
- return (t / (1000 * 1000)) < 0 ? 0 : t / (1000 * 1000);
- }
- return 0;
-}
-
-long long sys_sigprocmask(int how, const sigset_t *set, sigset_t *oldset, int_frame_t* ctx) {
- arch::x86_64::process_t* proc = CURRENT_PROC;
- SYSCALL_IS_SAFEZ((void*)set,4096);
- SYSCALL_IS_SAFEZ(oldset,4096);
-
- if(ctx->r10 != sizeof(sigset_t)) {
- DEBUG(proc->is_debug,"unsupported sigset len %d when normal is %d (even linux dont support this)",ctx->r10,sizeof(sigset_t));
- return 0;
- }
-
- DEBUG(proc->is_debug,"sigprocmask 0x%p old 0x%p, size %lli",set,oldset,ctx->r10);
-
- if(oldset) {
- memcpy(oldset,&proc->current_sigset,sizeof(sigset_t));
- }
-
- if(set) {
- memcpy(&proc->current_sigset,set,sizeof(sigset_t));
- }
-
- return 0;
-}
-
-
-
-long long sys_setitimer(int which, itimerval* val, itimerval* old) {
- arch::x86_64::process_t* proc = CURRENT_PROC;
-
- SYSCALL_IS_SAFEZ(val,4096);
- SYSCALL_IS_SAFEZ(old,4096);
-
- if(!val)
- return -EINVAL;
-
- itimerval oldv = {0};
- std::uint64_t ns = 0;
- switch(which) {
- case ITIMER_REAL:
- oldv = proc->itimer;
- proc->itimer = *val;
- arch::x86_64::update_time(&proc->itimer,&proc->next_alarm,1);
- break;
- case ITIMER_PROF:
- oldv = proc->proftimer;
- proc->proftimer = *val;
- arch::x86_64::update_time(&proc->proftimer,&proc->prof_timer,0);
- break;
- case ITIMER_VIRTUAL:
- oldv = proc->vitimer;
- proc->vitimer = *val;
- arch::x86_64::update_time(&proc->vitimer,&proc->virt_timer,0);
- break;
- default:
- return -EINVAL;
- }
-
- if(old)
- *old = oldv;
-
- return 0;
-}
-
-long long sys_getitimer(int which, itimerval* val) {
- arch::x86_64::process_t* proc = CURRENT_PROC;
-
- SYSCALL_IS_SAFEZ(val,4096);
-
- if(!val)
- return -EINVAL;
-
- std::uint64_t ns = 0;
- switch(which) {
- case ITIMER_REAL:
- *val = proc->itimer;
- ns = (proc->next_alarm - drivers::tsc::currentus()) * 1000;
- val->it_value.tv_sec = ns / 1000000000;
- val->it_value.tv_usec = (ns % 1000000000) / 1000;
- return 0;
- case ITIMER_PROF:
- *val = proc->proftimer;
- ns = (proc->prof_timer) * 1000;
- val->it_value.tv_sec = ns / 1000000000;
- val->it_value.tv_usec = (ns % 1000000000) / 1000;
- return 0;
- case ITIMER_VIRTUAL:
- *val = proc->vitimer;
- ns = (proc->virt_timer) * 1000;
- val->it_value.tv_sec = ns / 1000000000;
- val->it_value.tv_usec = (ns % 1000000000) / 1000;
- return 0;
- default:
- return -EINVAL;
- }
- return -EINVAL;
-}
-
-// same as sys_pause but wait for signals
-long long sys_sigsuspend(sigset_t* sigset, size_t size) {
-
- if(size != sizeof(sigset_t))
- return -EINVAL;
-
- if(!sigset)
- return -EINVAL;
-
- SYSCALL_IS_SAFEZ(sigset,4096);
-
- arch::x86_64::process_t* proc = CURRENT_PROC;
-
- while(1) {
- signal_ret_sigmask(sigset);
- yield();
- }
-
- return 0;
-}
-
-long long sys_sigaltstack(stack_t* new_stack, stack_t* old) {
- arch::x86_64::process_t* proc = CURRENT_PROC;
- SYSCALL_IS_SAFEZ(new_stack,4096);
- SYSCALL_IS_SAFEZ(old,4096);
-
- if(old) {
- *old = proc->altstack;
- }
-
- if(new_stack) {
- proc->altstack = *new_stack;
- }
-
- return 0;
-} \ No newline at end of file
diff --git a/kernel/src/arch/x86_64/syscalls/sockets.cpp b/kernel/src/arch/x86_64/syscalls/sockets.cpp
deleted file mode 100644
index f5c28af..0000000
--- a/kernel/src/arch/x86_64/syscalls/sockets.cpp
+++ /dev/null
@@ -1,467 +0,0 @@
-
-#include <arch/x86_64/syscalls/syscalls.hpp>
-#include <arch/x86_64/syscalls/sockets.hpp>
-
-#include <generic/vfs/vfs.hpp>
-
-#include <generic/vfs/fd.hpp>
-
-#include <generic/locks/spinlock.hpp>
-
-#include <etc/errno.hpp>
-
-#include <cstdint>
-
-locks::spinlock socket_spinlock;
-socket_node_t* head = 0;
-
-char is_socket_init = 0;
-
-socket_node_t* find_node(struct sockaddr_un* path) {
- socket_node_t* current = head;
- while(current) {
- if(!memcmp(current->path,path->sun_path,sizeof(path->sun_path))) {
- return current;
- }
- current = current->next;
- }
- return 0;
-}
-
-socket_node_t* sockets::find(char* path) {
- socket_node_t* current = head;
- int is_abstract = 0;
- if(path[0] == '\0') {// abstract path
- path += 1;
- is_abstract = 1;
- }
- while(current) {
- if(!strcmp(is_abstract == 1 ? current->path + 1 : current->path,path)) {
- return current;
- }
- current = current->next;
- }
- return 0;
-}
-
-socket_node_t* find_node_str(char* path) {
- return sockets::find(path);
-}
-
-char sockets::is_exists(char* path) {
-
- if(!is_socket_init)
- return 0;
-
- socket_node_t* node = find_node_str(path);
- if(!node)
- return 0;
- return 1;
-}
-
-int sockets::bind(userspace_fd_t* fd, struct sockaddr_un* path) {
-
- if(!fd || !path)
- return -EINVAL;
-
- if(path->sun_family != AF_UNIX)
- return -ENOSYS;
-
- memset(fd->path,0,2048);
- memcpy(fd->path,path->sun_path,sizeof(path->sun_path));
-
- vfs::stat_t stat;
- if(vfs::vfs::stat(fd,&stat) == 0) /* Check is there vfs object with some name */
- return -EEXIST;
-
- socket_spinlock.lock();
-
- if(find_node(path)) { socket_spinlock.unlock();
- return -EEXIST; }
-
- socket_node_t* new_node = new socket_node_t;
- memset(new_node->path,0,128);
- memcpy(new_node->path,path->sun_path,108);
- new_node->is_used = 1;
- new_node->socket_counter = 0;
- new_node->next = head;
-
- fd->binded_socket = (void*)new_node;
- head = new_node;
- socket_spinlock.unlock();
-
- return 0;
-
-}
-
-int sockets::connect(userspace_fd_t* fd, struct sockaddr_un* path) {
-
- if(!fd || !path)
- return -EINVAL;
-
- if(path->sun_family != AF_UNIX)
- return -ENOSYS;
-
- //socket_spinlock.lock();
-
- socket_node_t* node = find_node(path);
- if(!node) { //socket_spinlock.unlock();
- return -ENOENT; }
-
- socket_pending_obj_t* pending = new socket_pending_obj_t;
- pending->son = fd;
- pending->next = node->pending_list;
- pending->is_accepted.unlock();
- node->pending_list = pending;
-
- memcpy(fd->path,node->path,sizeof(node->path));
-
- node->socket_counter++;
-
- while(!pending->is_accepted.test()) { yield(); }
-
- //socket_spinlock.unlock();
- return 0;
-}
-
-int sockets::accept(userspace_fd_t* fd, struct sockaddr_un* path) {
- if(!fd)
- return -EINVAL;
-
- arch::x86_64::process_t* proc = CURRENT_PROC;
-
- socket_spinlock.lock();
-
- socket_node_t* node = find_node_str(fd->path);
- if(!node) { socket_spinlock.unlock();
- return -ENOENT; }
-
- socket_pending_obj_t* pending_connections = node->pending_list;
- while(1) {
- while(pending_connections) {
- if(!pending_connections->is_accepted.test()) {
- int new_fd = vfs::fdmanager::create(proc);
-
- userspace_fd_t* new_fd_s = vfs::fdmanager::search(proc,new_fd);
- memset(new_fd_s->path,0,2048);
- memcpy(new_fd_s->path,fd->path,strlen(fd->path));
-
- new_fd_s->offset = 0;
- new_fd_s->queue = 0;
- new_fd_s->pipe = 0;
- new_fd_s->pipe_side = 0;
- new_fd_s->cycle = 0;
- new_fd_s->is_a_tty = 0;
- new_fd_s->is_cached_path = 0;
-
- new_fd_s->state = USERSPACE_FD_STATE_SOCKET;
- new_fd_s->other_state = USERSPACE_FD_OTHERSTATE_MASTER; // master - writes to read pipe and reads from write pipe
-
- pending_connections->son->other_state = USERSPACE_FD_OTHERSTATE_SLAVE;
-
- new_fd_s->read_socket_pipe = new vfs::pipe(0);
- new_fd_s->write_socket_pipe = new vfs::pipe(0);
-
- new_fd_s->read_socket_pipe->create(PIPE_SIDE_READ);
- new_fd_s->read_socket_pipe->create(PIPE_SIDE_WRITE);
- new_fd_s->write_socket_pipe->create(PIPE_SIDE_READ);
- new_fd_s->write_socket_pipe->create(PIPE_SIDE_WRITE);
-
- new_fd_s->read_socket_pipe->ucred_pass = new vfs::ucred_manager;
- new_fd_s->write_socket_pipe->ucred_pass = new vfs::ucred_manager;
-
- new_fd_s->socket_pid = pending_connections->son->pid;
- new_fd_s->socket_uid = pending_connections->son->uid;
-
- pending_connections->son->read_socket_pipe = new_fd_s->read_socket_pipe;
- pending_connections->son->write_socket_pipe = new_fd_s->write_socket_pipe;
-
- //Log::SerialDisplay(LEVEL_MESSAGE_INFO,"together fd %d fd2 %d\n",pending_connections->son->index,new_fd_s->index);
-
- if(path)
- memcpy(path->sun_path,node->path,sizeof(path->sun_path));
-
- pending_connections->is_accepted.test_and_set();
-
- socket_spinlock.unlock();
- return new_fd_s->index;
-
- }
- pending_connections = pending_connections->next;
- }
- socket_spinlock.unlock();
- yield();
- socket_spinlock.lock();
- pending_connections = node->pending_list;
- }
-
- return -EFAULT;
-}
-
-void sockets::init() {
- is_socket_init = 1;
- socket_spinlock.unlock();
-}
-
-long long sys_connect(int fd, struct sockaddr_un* path, int len) {
-
- arch::x86_64::process_t* proc = CURRENT_PROC;
- userspace_fd_t* fd_s = vfs::fdmanager::search(proc,fd);
-
- if(!fd_s)
- return -EBADF;
-
- if(!path)
- return -EINVAL;
-
- DEBUG(1,"Trying to connect to socket %s (fd %d) from proc %d",path->sun_path,fd,proc->id);
-
- int status = sockets::connect(fd_s,path);
-
- DEBUG(proc->is_debug,"Socket is connected %s from proc %d, status %d",path->sun_path,proc->id,status);
-
- return status;
-}
-
-long long sys_bind(int fd, struct sockaddr_un* path, int len) {
-
- arch::x86_64::process_t* proc = CURRENT_PROC;
- userspace_fd_t* fd_s = vfs::fdmanager::search(proc,fd);
-
- if(!path)
- return -EINVAL;
-
- if(!fd_s)
- return -EBADF;
-
- struct sockaddr_un spath = *path;
-
- DEBUG(proc->is_debug,"Binding socket from fd %d to %s from proc %d",fd,spath.sun_path + 1,proc->id);
-
- int status = sockets::bind(fd_s,&spath);
-
- memcpy(fd_s->path,spath.sun_path,sizeof(spath.sun_path));
-
- return status;
-}
-
-long long sys_accept(int fd, struct sockaddr_un* path, int* zlen) {
-
- arch::x86_64::process_t* proc = CURRENT_PROC;
- userspace_fd_t* fd_s = vfs::fdmanager::search(proc,fd);
-
- if(!zlen)
- return -EINVAL;
-
- SYSCALL_IS_SAFEZ(zlen,4096);
-
- int len = sizeof(sockaddr_un);
-
- struct sockaddr_un spath;
-
- if(path) {
- memset(&spath,0,sizeof(spath));
- copy_in_userspace(proc,&spath,path,len > sizeof(spath) ? sizeof(spath) : len);
- }
-
- if(!fd_s)
- return -EBADF;
-
-
- DEBUG(proc->is_debug,"Accepting socket %s on fd %d from proc %d, path %s",fd_s->path + 1,fd,proc->id,spath.sun_path);
-
- int status = sockets::accept(fd_s,path != 0 ? &spath : 0);
-
- if(path)
- copy_in_userspace(proc,path,&spath,len > sizeof(spath) ? sizeof(spath) : len);
-
- return status;
-}
-
-#define SOCK_NONBLOCK 04000
-#define SOCK_CLOEXEC 02000000
-#define SOCK_STREAM 1
-#define SOCK_DGRAM 2
-
-long long sys_socket(int family, int type, int protocol) {
- arch::x86_64::process_t* proc = CURRENT_PROC;
-
- if(family != AF_UNIX)
- return -EINVAL; // only unix socekts fo rnow
-
- std::uint8_t socket_type = type & 0xFF;
-
- if(socket_type != SOCK_STREAM) {
- Log::SerialDisplay(LEVEL_MESSAGE_WARN,"Tried to open non SOCK_STREAM socket which not implemented (socket type %d)\n",socket_type);
- //return {1,ENOSYS,0};
- }
-
- int new_fd = vfs::fdmanager::create(proc);
-
- userspace_fd_t* new_fd_s = vfs::fdmanager::search(proc,new_fd);
- memset(new_fd_s->path,0,2048);
-
- new_fd_s->offset = 0;
- new_fd_s->queue = 0;
- new_fd_s->pipe = 0;
- new_fd_s->pipe_side = 0;
- new_fd_s->cycle = 0;
- new_fd_s->is_a_tty = 0;
- new_fd_s->is_listen = 0;
- new_fd_s->flags = (type & SOCK_NONBLOCK) ? O_NONBLOCK : 0;
-
- new_fd_s->state = USERSPACE_FD_STATE_SOCKET;
-
- DEBUG(proc->is_debug,"Creating socket on fd %d from proc %d",new_fd,proc->id);
-
- return new_fd;
-}
-
-long long sys_listen(int fd, int backlog) {
- arch::x86_64::process_t* proc = CURRENT_PROC;
- userspace_fd_t* fd_s = vfs::fdmanager::search(proc,fd);
-
- if(!fd_s)
- return -EBADF;
-
- if(fd_s->state == USERSPACE_FD_STATE_SOCKET) {
- if(!fd_s->read_socket_pipe) { // not connected
- fd_s->is_listen = 1;
- }
- } else
- return -ENOTSOCK;
-
- return 0;
-}
-
-syscall_ret_t sys_socketpair(int domain, int type_and_flags, int proto) {
-
- arch::x86_64::process_t* proc = CURRENT_PROC;
- int read_fd = vfs::fdmanager::create(proc);
- int write_fd = vfs::fdmanager::create(proc);
- userspace_fd_t* fd1 = vfs::fdmanager::search(proc,read_fd);
- userspace_fd_t* fd2 = vfs::fdmanager::search(proc,write_fd);
-
- vfs::pipe* first = new vfs::pipe(0);
- vfs::pipe* second = new vfs::pipe(0);
-
- fd1->read_socket_pipe = first;
- fd2->write_socket_pipe = first;
- fd1->write_socket_pipe = second;
- fd2->read_socket_pipe = second;
-
- fd1->other_state = USERSPACE_FD_OTHERSTATE_MASTER;
- fd2->other_state = USERSPACE_FD_OTHERSTATE_MASTER;
-
- fd1->read_socket_pipe->create(PIPE_SIDE_READ);
- fd1->read_socket_pipe->create(PIPE_SIDE_WRITE);
- fd1->write_socket_pipe->create(PIPE_SIDE_READ);
- fd1->write_socket_pipe->create(PIPE_SIDE_WRITE);
-
- fd1->state = USERSPACE_FD_STATE_SOCKET;
- fd2->state = USERSPACE_FD_STATE_SOCKET;
-
- DEBUG(proc->is_debug,"Creating socketpair %d:%d from proc %d",read_fd,write_fd,proc->id);
-
- return {1,read_fd,write_fd};
-}
-
-long long sys_getsockname(int fd, struct sockaddr_un* path, int* len) {
- arch::x86_64::process_t* proc = CURRENT_PROC;
- userspace_fd_t* fd_s = vfs::fdmanager::search(proc,fd);
-
- if(!fd_s)
- return -EBADF;
-
- if(path) {
- path->sun_family = AF_UNIX;
- memcpy(path->sun_path,fd_s->path,strlen(fd_s->path) + 1);
- *len = strlen(fd_s->path);
- return 0;
- } else
- return -EINVAL;
- return 0;
-}
-
-#define SO_PEERCRED 17
-
-long long sys_getsockopt(int fd, int layer, int number, int_frame_t* ctx) {
- arch::x86_64::process_t* proc = CURRENT_PROC;
- userspace_fd_t* fd_s = vfs::fdmanager::search(proc,fd);
-
- if(!fd_s)
- return -EBADF;
-
- void* buffer = (void*)ctx->r10;
-
- int* optlen = (int*)ctx->r8;
-
- SYSCALL_IS_SAFEZ(buffer,4096);
- SYSCALL_IS_SAFEZ(optlen,4096);
-
- if(!buffer)
- return -EINVAL;
-
- if(fd_s->state != USERSPACE_FD_STATE_SOCKET || !fd_s->read_socket_pipe)
- return -EBADF;
-
- switch(number) {
-
- case SO_PEERCRED: {
- struct ucred* cred = (struct ucred*)buffer;
- cred->pid = fd_s->socket_pid;
- cred->uid = fd_s->socket_uid;
- cred->gid = 0; // not implemented
-
- if(optlen)
- *optlen = sizeof(struct ucred);
-
- return 0;
- };
-
- default: {
- return -ENOSYS;
- };
-
- }
-
- return 0;
-
-}
-
-#define SHUT_RD 0
-#define SHUT_WR 1
-#define SHUT_RDWR 2
-
-long long sys_shutdown(int sockfd, int how) {
- arch::x86_64::process_t* proc = CURRENT_PROC;
- userspace_fd_t* fd_s = vfs::fdmanager::search(proc,sockfd);
-
- if(!fd_s)
- return -EBADF;
-
- if(fd_s->state != USERSPACE_FD_STATE_SOCKET)
- return -ENOTSOCK;
-
- if(fd_s->is_listen || fd_s->read_socket_pipe == 0)
- return -ENOTCONN;
-
- switch(how) {
- case SHUT_RD:
- case SHUT_RDWR:
- fd_s->read_socket_pipe->lock.lock();
- fd_s->write_socket_pipe->lock.lock();
- fd_s->read_socket_pipe->is_closed.test_and_set();
- fd_s->write_socket_pipe->is_closed.test_and_set();
- fd_s->read_socket_pipe->lock.unlock();
- fd_s->write_socket_pipe->lock.unlock();
- DEBUG(proc->is_debug,"shutdown %d from proc %d",sockfd,proc->id);
- break;
- case SHUT_WR:
- return -ENOSYS;
- default:
- return -EINVAL;
- }
-
- return 0;
-}
diff --git a/kernel/src/arch/x86_64/syscalls/syscalls.cpp b/kernel/src/arch/x86_64/syscalls/syscalls.cpp
deleted file mode 100644
index 927297a..0000000
--- a/kernel/src/arch/x86_64/syscalls/syscalls.cpp
+++ /dev/null
@@ -1,269 +0,0 @@
-
-#include <cstdint>
-#include <arch/x86_64/syscalls/syscalls.hpp>
-
-#include <etc/assembly.hpp>
-#include <etc/logging.hpp>
-
-#include <generic/locks/spinlock.hpp>
-
-#include <generic/vfs/fd.hpp>
-
-#include <arch/x86_64/scheduling.hpp>
-#include <arch/x86_64/cpu/data.hpp>
-
-#include <arch/x86_64/syscalls/signal.hpp>
-
-#include <etc/errno.hpp>
-
-extern "C" syscall_ret_t sys_hello(int a, int b ,int c) {
- DEBUG(1,"hello");
- return {0,0,0};
-}
-
-void signal_ret_sigmask(sigset_t* sigmask) {
- // it can be only called from syscall
- cpudata_t* cpdata = arch::x86_64::cpu::data();
-
- if(!cpdata)
- return;
-
- arch::x86_64::process_t* proc = cpdata->temp.proc;
- if(!proc)
- return;
-
- if(proc->sig->is_not_empty_sigset(sigmask) && 1) {
-
- memcpy(&proc->temp_sigset,&proc->current_sigset,sizeof(sigset_t));
- memcpy(&proc->current_sigset,sigmask,sizeof(sigset_t));
- proc->is_restore_sigset = 1;
-
- proc->ctx = *proc->sys_ctx;
- proc->ctx.rax = -EINTR;
- schedulingScheduleAndChangeStack(arch::x86_64::cpu::data()->timer_ist_stack,0);
- __builtin_unreachable();
-
- }
-
- return;
-
-}
-
-void signal_ret() {
- // it can be only called from syscall
- cpudata_t* cpdata = arch::x86_64::cpu::data();
-
- if(!cpdata)
- return;
-
- arch::x86_64::process_t* proc = cpdata->temp.proc;
- if(!proc)
- return;
-
- PREPARE_SIGNAL(proc) {
-
-
-
- proc->ctx = *proc->sys_ctx;
- proc->ctx.rax = -EINTR;
- schedulingScheduleAndChangeStack(arch::x86_64::cpu::data()->timer_ist_stack,0);
- __builtin_unreachable();
-
- }
-
- return;
-
-}
-
-long long sys_stub() {
- return -ENOSYS;
-}
-
-long long sys_zero_stub() {
- return 0;
-}
-
-arch::x86_64::syscall_item_t sys_table[] = {
- {12,(void*)sys_zero_stub}, // brk
- {21,(void*)sys_access},
- {257,(void*)sys_openat},
- {5,(void*)sys_fstat},
- {3,(void*)sys_close},
- {0,(void*)sys_read},
- {20,(void*)sys_writev},
- {231,(void*)sys_exit_group},
- {262,(void*)sys_newfstatat},
- {9,(void*)sys_mmap},
- {17,(void*)sys_pread},
- {158,(void*)sys_arch_prctl},
- {202,(void*)sys_futex},
- {218,(void*)sys_set_tid_address},
- {273,(void*)sys_stub},
- {334,(void*)sys_stub},
- {10,(void*)sys_mprotect},
- {302,(void*)sys_prlimit64},
- {318,(void*)sys_getrandom},
- {228,(void*)sys_clock_gettime},
- {16,(void*)sys_ioctl},
- {11,(void*)sys_free},
- {8,(void*)sys_lseek},
- {33,(void*)sys_dup2},
- {13,(void*)sys_sigaction},
- {14,(void*)sys_sigprocmask},
- {28,(void*)sys_zero_stub},
- {435,(void*)sys_clone3},
- {203,(void*)sys_zero_stub},
- {1,(void*)sys_write},
- {59,(void*)sys_exec},
- {18,(void*)sys_pwrite},
- {27,(void*)sys_stub},
- {7,(void*)sys_poll},
- {72,(void*)sys_fcntl},
- {102,(void*)sys_getuid},
- {104,(void*)sys_zero_stub}, // get_gid
- {107,(void*)sys_getuid}, // get_euid,
- {108,(void*)sys_zero_stub}, // get_egid
- {96,(void*)sys_gettimeofday},
- {63,(void*)sys_uname},
- {79,(void*)sys_getcwd},
- {39,(void*)sys_getpid},
- {110,(void*)sys_getppid},
- {62,(void*)sys_kill},
- {34,(void*)sys_pause},
- {105,(void*)sys_setuid},
- {60,(void*)sys_exit},
- {111,(void*)sys_getpgrp},
- {56,(void*)sys_clone},
- {61,(void*)sys_wait4},
- {41,(void*)sys_socket},
- {42,(void*)sys_connect},
- {50,(void*)sys_listen},
- {44,(void*)sys_sendto},
- {32,(void*)sys_dup2},
- {109,(void*)sys_setpgid}, // set pgid todo
- {201,(void*)sys_time},
- {217,(void*)sys_getdents64},
- {80,(void*)sys_chdir},
- {81,(void*)sys_fchdir},
- {332,(void*)sys_statx},
- {267,(void*)sys_readlinkat},
- {89,(void*)sys_readlink},
- {258,(void*)sys_mkdirat},
- {83,(void*)sys_mkdir},
- {293,(void*)sys_pipe2},
- {86,(void*)sys_link},
- {265,(void*)sys_linkat},
- {22,(void*)sys_pipe},
- {88,(void*)sys_symlink},
- {266,(void*)sys_symlinkat},
- {82,(void*)sys_rename},
- {264,(void*)sys_renameat},
- {316,(void*)sys_renameat},
- {221,(void*)sys_stub},
- {90,(void*)sys_chmod},
- {91,(void*)sys_fchmod},
- {268,(void*)sys_fchmodat},
- {452,(void*)sys_fchmodat2},
- {326,(void*)sys_stub},
- {285,(void*)sys_stub},
- {77,(void*)sys_stub}, // todo implement ftrunc
- {95,(void*)sys_umask},
- {230,(void*)sys_nanosleep},
- {55,(void*)sys_getsockopt},
- {49,(void*)sys_bind},
- {229,(void*)sys_stub}, //clock_getres
- {48,(void*)sys_shutdown},
- {106,(void*)sys_zero_stub}, // set_gid
- {157,(void*)sys_stub}, // prctl
- {141,(void*)sys_setpriority},
- {140,(void*)sys_getpriority},
- {98,(void*)sys_stub}, // getrusage
- {37,(void*)sys_alarm},
- {38,(void*)sys_setitimer},
- {36,(void*)sys_getitimer},
- {130,(void*)sys_sigsuspend},
- {52,(void*)sys_stub}, // get peername
- {51,(void*)sys_getsockname},
- {47,(void*)sys_msg_recv},
- {43,(void*)sys_accept},
- {186,(void*)sys_getpid},
- {234,(void*)sys_tgkill}, // tgkill
- {99,(void*)sys_sysinfo},
- {439,(void*)sys_faccessat},
- {334,(void*)sys_faccessat},
- {118,(void*)sys_getresuid},
- {120,(void*)sys_zero_stub}, // getgid
- {122,(void*)sys_zero_stub}, // setfsuid
- {123,(void*)sys_zero_stub}, // setfsgid
- {121,(void*)sys_getpgid},
- {270,(void*)sys_pselect6},
- {137,(void*)sys_statfs},
- {138,(void*)sys_fstatfs},
- {74,(void*)sys_zero_stub}, // fsync
- {144,(void*)sys_zero_stub}, // setscheduler
- {131,(void*)sys_sigaltstack},
- {25,(void*)sys_stub}, // mremap
- {87,(void*)sys_unlink},
- {263,(void*)sys_unlinkat}
-};
-
-arch::x86_64::syscall_item_t* __syscall_find(int rax) {
- for(int i = 0; i < sizeof(sys_table) / sizeof(arch::x86_64::syscall_item_t);i++) {
- if(sys_table[i].syscall_num == rax)
- return &sys_table[i];
- }
- Log::SerialDisplay(LEVEL_MESSAGE_WARN,"unknown syscall %d",rax);
- return 0; // without it there will be ub
-}
-
-extern "C" void syscall_handler_c(int_frame_t* ctx) {
-
- arch::x86_64::syscall_item_t* item = __syscall_find(ctx->rax);
-
- if(!item) {
- assert(0,"unimplemented syscall %d !\n",ctx->rax);
- ctx->rax = -ENOSYS;
- return;
- }
-
-
-
- cpudata_t* cpdata = arch::x86_64::cpu::data();
- arch::x86_64::process_t* proc = cpdata->temp.proc;
- proc->old_stack = ctx->rsp;
-
- if(1)
- proc->sys = ctx->rax;
-
- extern int last_sys;
- last_sys = ctx->rax;
-
- DEBUG(0,"sys %d from %d rdi 0x%p, rsi %lli",ctx->rax,proc->id,ctx->rdi,ctx->rsi);
-
- //DEBUG(1,"sys %d from %d rip 0x%p, min_free_fd %d",ctx->rax,proc->id,ctx->rip,vfs::fdmanager::min_free(proc));
-
- proc->sys_ctx = ctx;
-
- long long (*sys)(std::uint64_t D, std::uint64_t S, std::uint64_t d, int_frame_t* frame) = (long long (*)(std::uint64_t, std::uint64_t, std::uint64_t, int_frame_t*))item->syscall_func;
- long long ret = sys(ctx->rdi,ctx->rsi,ctx->rdx,ctx);
- ctx->rax = ret;
-
- if(proc->is_debug)
- DEBUG(ret < 0,"sys %d failed with code %lli",item->syscall_num,ctx->rax);
-
- //DEBUG(1,"sys %d ret %d",item->syscall_num,ctx->rax);
-
- cpdata->temp.temp_ctx = 0;
-
- proc->sys_ctx = 0;
-
- return;
-}
-
-void arch::x86_64::syscall::init() {
- __wrmsr(STAR_MSR,(0x08ull << 32) | (0x10ull << 48));
- __wrmsr(LSTAR,(uint64_t)syscall_handler);
- __wrmsr(STAR_MASK,(1 << 9)); // syscalls will enable interrupts when gs is swapped + stack is saved
- __wrmsr(EFER,__rdmsr(EFER) | 1);
-}
-
diff --git a/kernel/src/arch/x86_64/x86_64.cpp b/kernel/src/arch/x86_64/x86_64.cpp
new file mode 100644
index 0000000..e45d336
--- /dev/null
+++ b/kernel/src/arch/x86_64/x86_64.cpp
@@ -0,0 +1,120 @@
+
+#include <cstdint>
+#include <generic/arch.hpp>
+#include <generic/bootloader/bootloader.hpp>
+#include <arch/x86_64/drivers/hpet.hpp>
+#include <arch/x86_64/cpu_local.hpp>
+#include <arch/x86_64/drivers/tsc.hpp>
+#include <arch/x86_64/cpu/gdt.hpp>
+#include <arch/x86_64/cpu/idt.hpp>
+#include <klibc/stdio.hpp>
+
+typedef struct stackframe {
+ struct stackframe* rbp;
+ uint64_t rip;
+} __attribute__((packed)) stackframe_t;
+
+void print_regs(x86_64::idt::int_frame_t* ctx) {
+ uint64_t cr2;
+ asm volatile("mov %%cr2, %0" : "=r"(cr2) : : "memory");
+ klibc::printf("Kernel panic\n\nReason: %s\n\r","cpu exception");
+ klibc::printf("RAX: 0x%016llX RBX: 0x%016llX RDX: 0x%016llX RCX: 0x%016llX RDI: 0x%016llX\n\r"
+ "RSI: 0x%016llX R8: 0x%016llX R9: 0x%016llX R10: 0x%016llX R11: 0x%016llX\n\r"
+ "R12: 0x%016llX R13: 0x%016llX R14: 0x%016llX R15: 0x%016llX RBP: 0x%016llX\n\r"
+ "RSP: 0x%016llX CR2: 0x%016llX CR3: 0x%016llX\n\r"
+ "Vec: %d Err: %d cs: %p ss: %p\n\r",
+ ctx->rax, ctx->rbx, ctx->rdx, ctx->rcx, ctx->rdi,
+ ctx->rsi, ctx->r8, ctx->r9, ctx->r10, ctx->r11,
+ ctx->r12, ctx->r13, ctx->r14, ctx->r15, ctx->rbp,
+ ctx->rsp, cr2, ctx->cr3, ctx->vec, ctx->err_code, ctx->cs,ctx->ss);
+ klibc::printf("\n\r Stacktrace\n\r\n\r");
+
+ stackframe_t* rbp = (stackframe_t*)ctx->rbp;
+
+ klibc::printf("[0] - 0x%016llX (current rip)\n\r",ctx->rip);
+ for (int i = 1; i < 5 && rbp; ++i) {
+ std::uint64_t ret_addr = rbp->rip;
+ klibc::printf("[%d] - 0x%016llX\n\r", i, ret_addr);
+ rbp = (stackframe_t*)rbp->rbp;
+ }
+
+}
+
+std::uint8_t gaster[] = {
+#embed "src/gaster.txt"
+};
+
+void print_ascii_art() {
+ klibc::printf("%s\n",gaster);
+}
+
+extern "C" void CPUKernelPanic(x86_64::idt::int_frame_t* frame) {
+ print_ascii_art();
+ print_regs(frame);
+ arch::hcf();
+}
+
+namespace arch {
+ [[gnu::weak]] void disable_interrupts() {
+ asm volatile("cli");
+ }
+
+ [[gnu::weak]] void enable_interrupts() {
+ asm volatile("sti");
+ }
+
+ [[gnu::weak]] void wait_for_interrupt() {
+ asm volatile("hlt");
+ }
+
+ [[gnu::weak]] void hcf() {
+ disable_interrupts();
+ while(true) {
+ wait_for_interrupt();
+ }
+ }
+
+ [[gnu::weak]] void pause() {
+ asm volatile("pause");
+ }
+
+ [[gnu::weak]] void tlb_flush(std::uintptr_t hint, std::uintptr_t len) {
+ if (len / PAGE_SIZE > 256 || len == 0) {
+ std::uint64_t cr3 = 0;
+ asm volatile("mov %%cr3, %0" : "=r"(cr3) : : "memory");
+ asm volatile("mov %0, %%cr3" : : "r"(cr3) : "memory");
+ } else {
+ for (std::uintptr_t i = 0; i < len; i += PAGE_SIZE) {
+ asm volatile("invlpg (%0)" : : "b"(hint + i) : "memory");
+ }
+ }
+ }
+
+ [[gnu::weak]] const char* name() {
+ return "x86_64";
+ }
+
+ [[gnu::weak]] int level_paging() {
+ return bootloader::bootloader->is_5_level_paging() ? 5 : 4;
+ }
+
+ [[gnu::weak]] void init(int stage) {
+ switch(stage) {
+ case ARCH_INIT_EARLY:
+ x86_64::init_cpu_data();
+ drivers::hpet::init();
+ drivers::tsc::init();
+ return;
+ case ARCH_INIT_COMMON:
+ x86_64::gdt::init();
+ x86_64::idt::init();
+ return;
+ }
+ }
+
+ [[gnu::weak]] void panic(char* msg) {
+ print_ascii_art();
+ klibc::printf("Panic with message \"%s\"",msg);
+ }
+
+} \ No newline at end of file
diff --git a/kernel/src/bg.bmp b/kernel/src/bg.bmp
new file mode 100644
index 0000000..4709edd
--- /dev/null
+++ b/kernel/src/bg.bmp
Binary files differ
diff --git a/kernel/src/drivers/acpi.cpp b/kernel/src/drivers/acpi.cpp
index 61a4366..e0ab5ee 100644
--- a/kernel/src/drivers/acpi.cpp
+++ b/kernel/src/drivers/acpi.cpp
@@ -1,570 +1,29 @@
-
#include <cstdint>
#include <drivers/acpi.hpp>
-
-#include <etc/bootloaderinfo.hpp>
+#include <uacpi/uacpi.h>
+#include <uacpi/acpi.h>
#include <uacpi/types.h>
#include <uacpi/platform/arch_helpers.h>
-#include <generic/mm/paging.hpp>
-#include <generic/mm/heap.hpp>
-#include <generic/mm/pmm.hpp>
#include <uacpi/kernel_api.h>
#include <uacpi/uacpi.h>
-
-#include <arch/x86_64/cpu/data.hpp>
-
-#include <drivers/io.hpp>
-
-#include <generic/locks/spinlock.hpp>
-
-#include <arch/x86_64/interrupts/irq.hpp>
-
-#include <drivers/ioapic.hpp>
-
-#include <drivers/pci.hpp>
-#include <drivers/io.hpp>
-
-#include <drivers/tsc.hpp>
-#include <drivers/hpet.hpp>
-
-#include <arch/x86_64/cpu/lapic.hpp>
-
-#include <etc/logging.hpp>
-
-#include <etc/etc.hpp>
-
#include <uacpi/utilities.h>
#include <uacpi/event.h>
+#include <uacpi/uacpi.h>
+#include <uacpi/event.h>
-#include <generic/time.hpp>
-
-extern std::uint64_t __hpet_counter();
-
-extern int how_much_cpus;
-
-void drivers::acpi::init() {
+void acpi::init_tables() {
+#if defined(__x86_64__)
uacpi_status ret = uacpi_initialize(0);
-
- drivers::hpet::init();
- Log::Display(LEVEL_MESSAGE_OK,"HPET initializied\n");
-
- drivers::tsc::init();
- Log::Display(LEVEL_MESSAGE_OK,"TSC initializied\n");
-
- drivers::ioapic::init();
- Log::Display(LEVEL_MESSAGE_OK,"IOAPIC initializied\n");
-
- arch::x86_64::cpu::data()->lapic_block = arch::x86_64::cpu::lapic::init(15000);
-
- ret = uacpi_namespace_load();
-
- ret = uacpi_set_interrupt_model(UACPI_INTERRUPT_MODEL_IOAPIC);
-
- ret = uacpi_namespace_initialize();
- ret = uacpi_finalize_gpe_initialization();
-
-}
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-// Returns the PHYSICAL address of the RSDP structure via *out_rsdp_address.
-uacpi_status uacpi_kernel_get_rsdp(uacpi_phys_addr *out_rsdp_address) {
- *out_rsdp_address = BootloaderInfo::AccessRSDP();
- return UACPI_STATUS_OK;
-}
-
-/*
- * Map a physical memory range starting at 'addr' with length 'len', and return
- * a virtual address that can be used to access it.
- *
- * NOTE: 'addr' may be misaligned, in this case the host is expected to round it
- * down to the nearest page-aligned boundary and map that, while making
- * sure that at least 'len' bytes are still mapped starting at 'addr'. The
- * return value preserves the misaligned offset.
- *
- * Example for uacpi_kernel_map(0x1ABC, 0xF00):
- * 1. Round down the 'addr' we got to the nearest page boundary.
- * Considering a PAGE_SIZE of 4096 (or 0x1000), 0x1ABC rounded down
- * is 0x1000, offset within the page is 0x1ABC - 0x1000 => 0xABC
- * 2. Requested 'len' is 0xF00 bytes, but we just rounded the address
- * down by 0xABC bytes, so add those on top. 0xF00 + 0xABC => 0x19BC
- * 3. Round up the final 'len' to the nearest PAGE_SIZE boundary, in
- * this case 0x19BC is 0x2000 bytes (2 pages if PAGE_SIZE is 4096)
- * 4. Call the VMM to map the aligned address 0x1000 (from step 1)
- * with length 0x2000 (from step 3). Let's assume the returned
- * virtual address for the mapping is 0xF000.
- * 5. Add the original offset within page 0xABC (from step 1) to the
- * resulting virtual address 0xF000 + 0xABC => 0xFABC. Return it
- * to uACPI.
- */
-void *uacpi_kernel_map(uacpi_phys_addr addr, uacpi_size len) {
- extern std::uint64_t kernel_cr3;
- memory::paging::maprange(kernel_cr3,addr,(std::uint64_t)Other::toVirt(addr),len,PTE_PRESENT | PTE_RW);
- return Other::toVirt(addr);
-}
-
-/*
- * Unmap a virtual memory range at 'addr' with a length of 'len' bytes.
- *
- * NOTE: 'addr' may be misaligned, see the comment above 'uacpi_kernel_map'.
- * Similar steps to uacpi_kernel_map can be taken to retrieve the
- * virtual address originally returned by the VMM for this mapping
- * as well as its true length.
- */
-void uacpi_kernel_unmap(void *addr, uacpi_size len) {
- asm volatile("nop");
-}
-
-#ifndef UACPI_FORMATTED_LOGGING
-void uacpi_kernel_log(uacpi_log_level lvl, const uacpi_char* msg) {
- Log::Display(LEVEL_MESSAGE_INFO,"UACPI: %s",msg);
-}
-#else
-UACPI_PRINTF_DECL(2, 3)
-void uacpi_kernel_log(uacpi_log_level, const uacpi_char*, ...);
-void uacpi_kernel_vlog(uacpi_log_level, const uacpi_char*, uacpi_va_list);
+ (void)ret;
#endif
-
-/*
- * Only the above ^^^ API may be used by early table access and
- * UACPI_BAREBONES_MODE.
- */
-#ifndef UACPI_BAREBONES_MODE
-
-/*
- * Convenience initialization/deinitialization hooks that will be called by
- * uACPI automatically when appropriate if compiled-in.
- */
-#ifdef UACPI_KERNEL_INITIALIZATION
-/*
- * This API is invoked for each initialization level so that appropriate parts
- * of the host kernel and/or glue code can be initialized at different stages.
- *
- * uACPI API that triggers calls to uacpi_kernel_initialize and the respective
- * 'current_init_lvl' passed to the hook at that stage:
- * 1. uacpi_initialize() -> UACPI_INIT_LEVEL_EARLY
- * 2. uacpi_namespace_load() -> UACPI_INIT_LEVEL_SUBSYSTEM_INITIALIZED
- * 3. (start of) uacpi_namespace_initialize() -> UACPI_INIT_LEVEL_NAMESPACE_LOADED
- * 4. (end of) uacpi_namespace_initialize() -> UACPI_INIT_LEVEL_NAMESPACE_INITIALIZED
- */
-uacpi_status uacpi_kernel_initialize(uacpi_init_level current_init_lvl);
-void uacpi_kernel_deinitialize(void);
-#endif
-
-/*
- * Open a PCI device at 'address' for reading & writing.
- *
- * Note that this must be able to open any arbitrary PCI device, not just those
- * detected during kernel PCI enumeration, since the following pattern is
- * relatively common in AML firmware:
- * Device (THC0)
- * {
- * // Device at 00:10.06
- * Name (_ADR, 0x00100006) // _ADR: Address
- *
- * OperationRegion (THCR, PCI_Config, Zero, 0x0100)
- * Field (THCR, ByteAcc, NoLock, Preserve)
- * {
- * // Vendor ID field in the PCI configuration space
- * VDID, 32
- * }
- *
- * // Check if the device at 00:10.06 actually exists, that is reading
- * // from its configuration space returns something other than 0xFFs.
- * If ((VDID != 0xFFFFFFFF))
- * {
- * // Actually create the rest of the device's body if it's present
- * // in the system, otherwise skip it.
- * }
- * }
- *
- * The handle returned via 'out_handle' is used to perform IO on the
- * configuration space of the device.
- */
-uacpi_status uacpi_kernel_pci_device_open(
- uacpi_pci_address address, uacpi_handle *out_handle
-) {
- uacpi_pci_address* pci = new uacpi_pci_address;
- *pci = address;
- *out_handle = (uacpi_handle)pci;
- return UACPI_STATUS_OK;
-}
-
-void uacpi_kernel_pci_device_close(uacpi_handle hnd) {
- delete (void*)hnd;
-}
-
-/*
- * Read & write the configuration space of a previously open PCI device.
- */
-uacpi_status uacpi_kernel_pci_read8(
- uacpi_handle device, uacpi_size offset, uacpi_u8 *value
-) {
- uacpi_pci_address* pci = (uacpi_pci_address*)device;
- *value = drivers::pci::in(pci->bus,pci->device,pci->function,offset,1);
- return UACPI_STATUS_OK;
}
-uacpi_status uacpi_kernel_pci_read16(
- uacpi_handle device, uacpi_size offset, uacpi_u16 *value
-) {
- uacpi_pci_address* pci = (uacpi_pci_address*)device;
- *value = drivers::pci::in(pci->bus,pci->device,pci->function,offset,2);
- return UACPI_STATUS_OK;
-}
-
-uacpi_status uacpi_kernel_pci_read32(
- uacpi_handle device, uacpi_size offset, uacpi_u32 *value
-) {
- uacpi_pci_address* pci = (uacpi_pci_address*)device;
- *value = drivers::pci::in(pci->bus,pci->device,pci->function,offset,4);
- return UACPI_STATUS_OK;
-}
-
-uacpi_status uacpi_kernel_pci_write8(
- uacpi_handle device, uacpi_size offset, uacpi_u8 value
-) {
- uacpi_pci_address* pci = (uacpi_pci_address*)device;
- drivers::pci::out(pci->bus,pci->device,pci->function,offset,value,1);
- return UACPI_STATUS_OK;
-}
-uacpi_status uacpi_kernel_pci_write16(
- uacpi_handle device, uacpi_size offset, uacpi_u16 value
-) {
- uacpi_pci_address* pci = (uacpi_pci_address*)device;
- drivers::pci::out(pci->bus,pci->device,pci->function,offset,value,2);
- return UACPI_STATUS_OK;
-}
-uacpi_status uacpi_kernel_pci_write32(
- uacpi_handle device, uacpi_size offset, uacpi_u32 value
-) {
- uacpi_pci_address* pci = (uacpi_pci_address*)device;
- drivers::pci::out(pci->bus,pci->device,pci->function,offset,value,4);
- return UACPI_STATUS_OK;
-}
-
-/*
- * Map a SystemIO address at [base, base + len) and return a kernel-implemented
- * handle that can be used for reading and writing the IO range.
- *
- * NOTE: The x86 architecture uses the in/out family of instructions
- * to access the SystemIO address space.
- */
-typedef struct {
- uint64_t base;
- uint64_t len;
-} __attribute__((packed)) uacpi_io_struct_t;
-
-uacpi_status uacpi_kernel_io_map(
- uacpi_io_addr base, uacpi_size len, uacpi_handle *out_handle
-) {
- uacpi_io_struct_t* iomap = new uacpi_io_struct_t;
- iomap->base = base;
- iomap->len = len;
- *out_handle = (uacpi_handle*)iomap;
- return UACPI_STATUS_OK;
-}
-void uacpi_kernel_io_unmap(uacpi_handle handle) {
- delete (void*)handle;
-}
-
-/*
- * Read/Write the IO range mapped via uacpi_kernel_io_map
- * at a 0-based 'offset' within the range.
- *
- * NOTE:
- * The x86 architecture uses the in/out family of instructions
- * to access the SystemIO address space.
- *
- * You are NOT allowed to break e.g. a 4-byte access into four 1-byte accesses.
- * Hardware ALWAYS expects accesses to be of the exact width.
- */
-uacpi_status uacpi_kernel_io_read8(
- uacpi_handle hnd, uacpi_size offset, uacpi_u8 *out_value
-) {
- drivers::io io;
- *out_value = io.inb(*(std::uint16_t*)hnd + offset);
- return UACPI_STATUS_OK;
-}
-uacpi_status uacpi_kernel_io_read16(
- uacpi_handle hnd, uacpi_size offset, uacpi_u16 *out_value
-) {
- drivers::io io;
- *out_value = io.inw(*(std::uint16_t*)hnd + offset);
- return UACPI_STATUS_OK;
-}
-uacpi_status uacpi_kernel_io_read32(
- uacpi_handle hnd, uacpi_size offset, uacpi_u32 *out_value
-) {
- drivers::io io;
- *out_value = io.ind(*(std::uint16_t*)hnd + offset);
- return UACPI_STATUS_OK;
-}
-
-uacpi_status uacpi_kernel_io_write8(
- uacpi_handle hnd, uacpi_size offset, uacpi_u8 in_value
-) {
- drivers::io io;
- io.outb(*(std::uint16_t*)hnd + offset,in_value);
- return UACPI_STATUS_OK;
-}
-uacpi_status uacpi_kernel_io_write16(
- uacpi_handle hnd, uacpi_size offset, uacpi_u16 in_value
-) {
- drivers::io io;
- io.outw(*(std::uint16_t*)hnd + offset,in_value);
- return UACPI_STATUS_OK;
-}
-uacpi_status uacpi_kernel_io_write32(
- uacpi_handle hnd, uacpi_size offset, uacpi_u32 in_value
-) {
- drivers::io io;
- io.outd(*(std::uint16_t*)hnd + offset,in_value);
- return UACPI_STATUS_OK;
-}
-
-/*
- * Allocate a block of memory of 'size' bytes.
- * The contents of the allocated memory are unspecified.
- */
-void *uacpi_kernel_alloc(uacpi_size size) {
- return memory::heap::malloc(size);
-}
-
-#ifdef UACPI_NATIVE_ALLOC_ZEROED
-/*
- * Allocate a block of memory of 'size' bytes.
- * The returned memory block is expected to be zero-filled.
- */
-void *uacpi_kernel_alloc_zeroed(uacpi_size size);
-#endif
-
-/*
- * Free a previously allocated memory block.
- *
- * 'mem' might be a NULL pointer. In this case, the call is assumed to be a
- * no-op.
- *
- * An optionally enabled 'size_hint' parameter contains the size of the original
- * allocation. Note that in some scenarios this incurs additional cost to
- * calculate the object size.
- */
-#ifndef UACPI_SIZED_FREES
-void uacpi_kernel_free(void *mem) {
- memory::heap::free(mem);
-}
-#else
-void uacpi_kernel_free(void *mem, uacpi_size size_hint);
-#endif
-
-/*
- * Returns the number of nanosecond ticks elapsed since boot,
- * strictly monotonic.
- */
-uacpi_u64 uacpi_kernel_get_nanoseconds_since_boot(void) {
- return drivers::tsc::currentnano();
-}
-
-/*
- * Spin for N microseconds.
- */
-void uacpi_kernel_stall(uacpi_u8 usec) {
- drivers::tsc::sleep(usec);
-}
-
-/*
- * Sleep for N milliseconds.
- */
-void uacpi_kernel_sleep(uacpi_u64 msec) {
- drivers::tsc::sleep(msec * 1000);
-}
-
-/*
- * Create/free an opaque non-recursive kernel mutex object.
- */
-uacpi_handle uacpi_kernel_create_mutex(void) {
- locks::spinlock* lock = new locks::spinlock;
- return (uacpi_handle)lock;
-}
-
-void uacpi_kernel_free_mutex(uacpi_handle hnd) {
- delete (void*)hnd;
-}
-
-/*
- * Create/free an opaque kernel (semaphore-like) event object.
- */
-uacpi_handle uacpi_kernel_create_event(void) {
- return (uacpi_handle)1;
-}
-
-void uacpi_kernel_free_event(uacpi_handle) {
- asm volatile("nop");
-}
-
-/*
- * Returns a unique identifier of the currently executing thread.
- *
- * The returned thread id cannot be UACPI_THREAD_ID_NONE.
- */
-uacpi_thread_id uacpi_kernel_get_thread_id(void) {
- return 0;
-}
-
-/*
- * Try to acquire the mutex with a millisecond timeout.
- *
- * The timeout value has the following meanings:
- * 0x0000 - Attempt to acquire the mutex once, in a non-blocking manner
- * 0x0001...0xFFFE - Attempt to acquire the mutex for at least 'timeout'
- * milliseconds
- * 0xFFFF - Infinite wait, block until the mutex is acquired
- *
- * The following are possible return values:
- * 1. UACPI_STATUS_OK - successful acquire operation
- * 2. UACPI_STATUS_TIMEOUT - timeout reached while attempting to acquire (or the
- * single attempt to acquire was not successful for
- * calls with timeout=0)
- * 3. Any other value - signifies a host internal error and is treated as such
- */
-uacpi_status uacpi_kernel_acquire_mutex(uacpi_handle lock, uacpi_u16) {
- locks::spinlock* slock = (locks::spinlock*)lock;
- slock->lock();
- return UACPI_STATUS_OK;
-}
-
-void uacpi_kernel_release_mutex(uacpi_handle lock) {
- locks::spinlock* slock = (locks::spinlock*)lock;
- slock->unlock();
-}
-
-/*
- * Try to wait for an event (counter > 0) with a millisecond timeout.
- * A timeout value of 0xFFFF implies infinite wait.
- *
- * The internal counter is decremented by 1 if wait was successful.
- *
- * A successful wait is indicated by returning UACPI_TRUE.
- */
-uacpi_bool uacpi_kernel_wait_for_event(uacpi_handle, uacpi_u16) {
- return 1;
-}
-
-/*
- * Signal the event object by incrementing its internal counter by 1.
- *
- * This function may be used in interrupt contexts.
- */
-void uacpi_kernel_signal_event(uacpi_handle) {
- asm volatile("nop");
-}
-
-/*
- * Reset the event counter to 0.
- */
-void uacpi_kernel_reset_event(uacpi_handle) {
- asm volatile("nop");
-}
-
-/*
- * Handle a firmware request.
- *
- * Currently either a Breakpoint or Fatal operators.
- */
-uacpi_status uacpi_kernel_handle_firmware_request(uacpi_firmware_request*) {
- return UACPI_STATUS_OK;
-}
-
-/*
- * Install an interrupt handler at 'irq', 'ctx' is passed to the provided
- * handler for every invocation.
- *
- * 'out_irq_handle' is set to a kernel-implemented value that can be used to
- * refer to this handler from other API.
- */
-
-uacpi_status uacpi_kernel_install_interrupt_handler(
- uacpi_u32 irq, uacpi_interrupt_handler base, uacpi_handle ctx,
- uacpi_handle *out_irq_handle
-) {
- std::uint8_t vec = arch::x86_64::interrupts::irq::create(irq,IRQ_TYPE_LEGACY,(void (*)(void*))base,0,0);
- *out_irq_handle = (uacpi_handle)vec;
- return UACPI_STATUS_OK;
-}
-
-/*
- * Uninstall an interrupt handler. 'irq_handle' is the value returned via
- * 'out_irq_handle' during installation.
- */
-uacpi_status uacpi_kernel_uninstall_interrupt_handler(
- uacpi_interrupt_handler, uacpi_handle irq_handle
-) {
- asm volatile("nop");
- return UACPI_STATUS_OK;
-}
-
-/*
- * Create/free a kernel spinlock object.
- *
- * Unlike other types of locks, spinlocks may be used in interrupt contexts.
- */
-uacpi_handle uacpi_kernel_create_spinlock(void) {
- locks::spinlock* lock = new locks::spinlock;
- return (uacpi_handle)lock;
-}
-
-void uacpi_kernel_free_spinlock(uacpi_handle hnd) {
- delete (void*)hnd;
-}
-
-/*
- * Lock/unlock helpers for spinlocks.
- *
- * These are expected to disable interrupts, returning the previous state of cpu
- * flags, that can be used to possibly re-enable interrupts if they were enabled
- * before.
- *
- * Note that lock is infalliable.
- */
-uacpi_cpu_flags uacpi_kernel_lock_spinlock(uacpi_handle hnd) {
- locks::spinlock* lock = (locks::spinlock*)hnd;
- lock->lock();
- return UACPI_STATUS_OK;
-}
-
-void uacpi_kernel_unlock_spinlock(uacpi_handle hnd, uacpi_cpu_flags) {
- locks::spinlock* lock = (locks::spinlock*)hnd;
- lock->unlock();
-}
-
-/*
- * Schedules deferred work for execution.
- * Might be invoked from an interrupt context.
- */
-uacpi_status uacpi_kernel_schedule_work(
- uacpi_work_type, uacpi_work_handler, uacpi_handle ctx
-) {
- asm volatile("nop");
- return UACPI_STATUS_OK;
-}
-
-/*
- * Waits for two types of work to finish:
- * 1. All in-flight interrupts installed via uacpi_kernel_install_interrupt_handler
- * 2. All work scheduled via uacpi_kernel_schedule_work
- *
- * Note that the waits must be done in this order specifically.
- */
-uacpi_status uacpi_kernel_wait_for_work_completion(void) {
- asm volatile("nop");
- return UACPI_STATUS_OK;
-}
-
-#endif // !UACPI_BAREBONES_MODE
-
-#ifdef __cplusplus
-}
+void acpi::full_init() {
+#if defined(__x86_64__)
+ uacpi_namespace_load();
+ uacpi_namespace_initialize();
+ uacpi_finalize_gpe_initialization();
+ uacpi_set_interrupt_model(UACPI_INTERRUPT_MODEL_IOAPIC);
#endif
+} \ No newline at end of file
diff --git a/kernel/src/drivers/acpi.hpp b/kernel/src/drivers/acpi.hpp
new file mode 100644
index 0000000..db53e7f
--- /dev/null
+++ b/kernel/src/drivers/acpi.hpp
@@ -0,0 +1,7 @@
+#pragma once
+#include <cstdint>
+
+namespace acpi {
+ void init_tables();
+ void full_init();
+} \ No newline at end of file
diff --git a/kernel/src/drivers/hpet.cpp b/kernel/src/drivers/hpet.cpp
deleted file mode 100644
index 20e92b8..0000000
--- a/kernel/src/drivers/hpet.cpp
+++ /dev/null
@@ -1,52 +0,0 @@
-
-#include <cstdint>
-#include <drivers/hpet.hpp>
-
-#include <arch/x86_64/interrupts/pit.hpp>
-
-std::uint64_t hpet_base,hpet_clock_nano;
-std::uint8_t hpet_is_32_bit = 0;
-
-#include <uacpi/uacpi.h>
-#include <uacpi/tables.h>
-#include <uacpi/status.h>
-#include <uacpi/acpi.h>
-
-#include <etc/logging.hpp>
-
-#include <generic/mm/paging.hpp>
-
-#include <generic/time.hpp>
-
-#include <etc/etc.hpp>
-
-std::uint64_t __hpet_timestamp() {
- return hpet_is_32_bit ? *(volatile uint32_t*)(hpet_base + 0xf0) : *(volatile uint64_t*)(hpet_base + 0xf0);
-}
-
-std::uint64_t drivers::hpet::nanocurrent() {
- return __hpet_timestamp() * hpet_clock_nano;
-}
-
-extern std::uint16_t KERNEL_GOOD_TIMER;
-
-void drivers::hpet::init() {
- uacpi_table hpet;
- uacpi_status ret = uacpi_table_find_by_signature("HPET",&hpet);
- assert(ret == UACPI_STATUS_OK,"HPET required to get working orange");
- struct acpi_hpet* hpet_table = ((struct acpi_hpet*)hpet.virt_addr);
- hpet_base = (std::uint64_t)Other::toVirt(hpet_table->address.address);
- memory::paging::kernelmap(0,hpet_table->address.address);
-
- *(volatile std::uint64_t*)(hpet_base + 0x10) |= 1;
- hpet_is_32_bit = (*(volatile uint64_t*)hpet_base & (1 << 13)) ? 0 : 1;
- hpet_clock_nano = (*(volatile uint32_t*)(hpet_base + 4)) / 1000000;
-
-}
-
-void drivers::hpet::sleep(std::uint64_t us) {
- std::uint64_t start = __hpet_timestamp();
- std::uint64_t conv = us * 1000;
- while((__hpet_timestamp() - start) * hpet_clock_nano < conv)
- asm volatile("nop");
-}
diff --git a/kernel/src/drivers/ioapic.cpp b/kernel/src/drivers/ioapic.cpp
deleted file mode 100644
index 8f73cf9..0000000
--- a/kernel/src/drivers/ioapic.cpp
+++ /dev/null
@@ -1,120 +0,0 @@
-
-#include <cstdint>
-#include <generic/mm/paging.hpp>
-#include <drivers/ioapic.hpp>
-
-#include <arch/x86_64/interrupts/pic.hpp>
-#include <etc/logging.hpp>
-
-#include <uacpi/acpi.h>
-#include <uacpi/uacpi.h>
-#include <uacpi/status.h>
-#include <uacpi/tables.h>
-
-struct acpi_madt_ioapic apics[24];
-struct acpi_madt_interrupt_source_override iso[24];
-std::uint8_t apic_ent, iso_ent;
-extern std::uint8_t is_legacy_pic;
-
-void drivers::ioapic::init() {
- apic_ent = 0; iso_ent = 0;
- struct uacpi_table apic_table;
- uacpi_status ret = uacpi_table_find_by_signature(ACPI_MADT_SIGNATURE,&apic_table);
- if(ret != UACPI_STATUS_OK)
- return; // ignore just use pic later
- else {
- arch::x86_64::interrupts::pic::disable();
-
- is_legacy_pic = 0;
- }
-
- struct acpi_madt* apic = (struct acpi_madt*)apic_table.virt_addr;
- struct acpi_entry_hdr* current = (struct acpi_entry_hdr*)apic->entries;
- while(1) {
-
- if((std::uint64_t)current >= (std::uint64_t)apic->entries + apic->hdr.length - sizeof(acpi_madt))
- break;
-
- switch (current->type)
- {
- case ACPI_MADT_ENTRY_TYPE_IOAPIC: {
- struct acpi_madt_ioapic* cur_ioapic = (acpi_madt_ioapic*)current;
- memory::paging::kernelmap(0,cur_ioapic->address);
- apics[apic_ent++] = *cur_ioapic;
- break;
- }
- case ACPI_MADT_ENTRY_TYPE_INTERRUPT_SOURCE_OVERRIDE: {
- struct acpi_madt_interrupt_source_override* cur_iso = (struct acpi_madt_interrupt_source_override*)current;
- iso[iso_ent++] = *cur_iso;
- break;
- }
- }
- current = (acpi_entry_hdr*)((std::uint64_t)current + current->length);
-
- }
-}
-
-void drivers::ioapic::set(std::uint8_t vec,std::uint8_t irq,std::uint64_t flags,std::uint64_t lapic) {
- struct acpi_madt_ioapic* apic;
- struct acpi_madt_interrupt_source_override* ciso;
- std::uint8_t is_found_iso = 0;
- for(std::uint8_t i = 0;i < iso_ent;i++) {
- ciso = &iso[i];
- if(ciso->source == irq) {
- is_found_iso = 1;
- break;
- }
- }
-
- std::uint64_t calc_flags = (lapic << 56) | flags | (vec & 0xFF);
- if(is_found_iso) {
- char pol = (ciso->flags & 0b11) == 0b11 ? 1 : 0;
- char mode = ((ciso->flags >> 2) & 0b11) == 0b11 ? 1 : 0;
- calc_flags = (lapic << 56) | (mode << 15) | (pol << 13) | (vec & 0xff) | flags;
- }
-
- for(std::uint8_t i = 0;i < apic_ent; i++) {
- apic = &apics[i];
- std::uint32_t ver = read(apic->address,1);
- std::uint32_t max = ver >> 16;
- if(apic->gsi_base <= irq && apic->gsi_base + max > irq)
- break;
- }
-
- std::uint32_t irqreg = ((irq - apic->gsi_base) * 2) + 0x10;
- write(apic->address,irqreg,(std::uint32_t)calc_flags);
- write(apic->address,irqreg + 1,(std::uint32_t)((std::uint64_t)calc_flags >> 32));
-
-}
-
-void drivers::ioapic::mask(std::uint8_t irq) {
- struct acpi_madt_ioapic* apic;
- struct acpi_madt_interrupt_source_override* ciso;
-
- for(std::uint8_t i = 0;i < apic_ent; i++) {
- apic = &apics[i];
- std::uint32_t ver = read(apic->address,1);
- std::uint32_t max = ver >> 16;
- if(apic->gsi_base <= irq && apic->gsi_base + max > irq)
- break;
- }
-
- std::uint32_t irqreg = ((irq - apic->gsi_base) * 2) + 0x10;
- write(apic->address,irqreg,(std::uint32_t)read(apic->address,irqreg) | (1 << 16));
-}
-
-void drivers::ioapic::unmask(std::uint8_t irq) {
- struct acpi_madt_ioapic* apic;
- struct acpi_madt_interrupt_source_override* ciso;
-
- for(std::uint8_t i = 0;i < apic_ent; i++) {
- apic = &apics[i];
- std::uint32_t ver = read(apic->address,1);
- std::uint32_t max = ver >> 16;
- if(apic->gsi_base <= irq && apic->gsi_base + max > irq)
- break;
- }
-
- std::uint32_t irqreg = ((irq - apic->gsi_base) * 2) + 0x10;
- write(apic->address,irqreg,(std::uint32_t)read(apic->address,irqreg) & ~(1 << 16));
-} \ No newline at end of file
diff --git a/kernel/src/drivers/kvmtimer.cpp b/kernel/src/drivers/kvmtimer.cpp
deleted file mode 100644
index 302e03d..0000000
--- a/kernel/src/drivers/kvmtimer.cpp
+++ /dev/null
@@ -1,54 +0,0 @@
-
-#include <cstdint>
-
-#include <drivers/kvmtimer.hpp>
-#include <generic/time.hpp>
-#include <etc/assembly.hpp>
-#include <etc/etc.hpp>
-
-#include <etc/logging.hpp>
-
-#include <generic/mm/pmm.hpp>
-
-struct pvclock_vcpu_time_info* kvmclock_info;
-
-extern std::uint16_t KERNEL_GOOD_TIMER;
-
-void drivers::kvmclock::init() {
-
- std::uint32_t a,b,c,d;
-
- __cpuid(0x40000000,0,&a,&b,&c,&d);
- if(b != 0x4b4d564b || d != 0x4d || c != 0x564b4d56)
- return;
-
- __cpuid(0x40000001,0,&a,&b,&c,&d);
- if(!(a & (1 << 3)))
- return;
-
- KERNEL_GOOD_TIMER = KVM_TIMER;
-
- kvmclock_info = (struct pvclock_vcpu_time_info*)memory::pmm::_virtual::alloc(4096);
-
- __wrmsr(0x4b564d01,(std::uint64_t)Other::toPhys(kvmclock_info) | 1);
- Log::Display(LEVEL_MESSAGE_OK,"KVMClock initializied\n");
-
-}
-
-void drivers::kvmclock::sleep(std::uint64_t us) {
- std::uint64_t start = currentnano();
- std::uint64_t conv = us * 1000;
- while((currentnano() - start) < conv)
- asm volatile("nop");
-}
-
-std::uint64_t drivers::kvmclock::currentnano() {
- std::uint64_t time0 = __rdtsc() - kvmclock_info->tsc_timestamp;
- if(kvmclock_info->tsc_shift >= 0)
- time0 <<= kvmclock_info->tsc_shift;
- else
- time0 >>= -kvmclock_info->tsc_shift;
- time0 = (time0 * kvmclock_info->tsc_to_system_mul) >> 32;
- time0 = time0 + kvmclock_info->system_time;
- return time0;
-} \ No newline at end of file
diff --git a/kernel/src/drivers/pci.cpp b/kernel/src/drivers/pci.cpp
deleted file mode 100644
index 8167b07..0000000
--- a/kernel/src/drivers/pci.cpp
+++ /dev/null
@@ -1,137 +0,0 @@
-
-#include <cstdint>
-#include <drivers/io.hpp>
-
-#include <drivers/pci.hpp>
-
-char pci_spinlock = 0;
-
-pci_driver_t pci_drivers[256];
-
-std::uint32_t pci_read_config32(std::uint8_t bus, std::uint8_t num, std::uint8_t function, std::uint8_t offset) {
- drivers::io io;
- std::uint32_t address = (1 << 31) | (bus << 16) | (num << 11) | (function << 8) | (offset);
- io.outd(0xCF8, address);
- return io.ind(0xCFC);
-}
-
-std::uint16_t pci_read_config16(std::uint8_t bus, std::uint8_t num, std::uint8_t function, std::uint8_t offset) {
- drivers::io io;
- std::uint32_t address = (1 << 31) | (bus << 16) | (num << 11) | (function << 8) | (offset & 0xfc);
- io.outd(0xCF8, address);
- return (std::uint16_t)((io.ind(0xCFC) >> ((offset & 2) * 8)) & 0xffff);
-}
-
-std::uint8_t pci_read_config8(std::uint8_t bus, std::uint8_t num, std::uint8_t function, std::uint8_t offset) {
- drivers::io io;
- std::uint32_t address = (1 << 31) | (bus << 16) | (num << 11) | (function << 8) | (offset);
- io.outd(0xCF8, address);
- return (std::uint8_t)((io.ind(0xCFC) >> ((offset & 3) * 8)) & 0xff);
-}
-
-void pci_write_config32(std::uint8_t bus, std::uint8_t num, std::uint8_t function, std::uint8_t offset, std::uint32_t value) {
- drivers::io io;
- std::uint32_t address = (1 << 31) | (bus << 16) | (num << 11) | (function << 8) | (offset);
- io.outd(0xCF8, address);
- io.outd(0xCFC, value);
-}
-
-void pci_write_config16(std::uint8_t bus, std::uint8_t num, std::uint8_t function, std::uint8_t offset, std::uint32_t value) {
- drivers::io io;
- uint32_t address = (1 << 31) | (bus << 16) | (num << 11) | (function << 8) | (offset & 0xfc);
- io.outd(0xCF8, address);
- io.outd(0xCFC,(io.ind(0xCFC) & ~(0xffff << ((offset & 2) * 8))) | (value << ((offset & 2) * 8)));
-}
-
-void pci_write_config8(std::uint8_t bus, std::uint8_t num, std::uint8_t function, std::uint8_t offset, std::uint8_t value) {
- drivers::io io;
- std::uint32_t address = (1 << 31) | (bus << 16) | (num << 11) | (function << 8) | (offset & 0xfc);
- io.outd(0xCF8, address);
- io.outd(0xCFC, ((io.ind(0xCFC) & ~(0xFF << (offset & 3))) | (value << ((offset & 3) * 8))));
-}
-
-std::uint32_t drivers::pci::in(std::int8_t bus, std::uint8_t num, std::uint8_t function, std::uint8_t offset, std::uint8_t bytewidth) {
- uint32_t value = 0;
- switch(bytewidth) {
- case 1:
- value = pci_read_config8(bus,num,function,offset);
- break;
- case 2:
- value = pci_read_config16(bus,num,function,offset);
- break;
- case 4:
- value = pci_read_config32(bus,num,function,offset);
- break;
- default:
- break;
- }
-
- return value;
-
-}
-
-void drivers::pci::out(std::uint8_t bus, std::uint8_t num, std::uint8_t function, std::uint8_t offset, std::uint32_t value, std::uint8_t bytewidth) {
- switch(bytewidth) {
- case 1:
- pci_write_config8(bus,num,function,offset,(std::uint8_t)value);
- break;
- case 2:
- pci_write_config16(bus,num,function,offset,(std::uint16_t)value);
- break;
- case 4:
- pci_write_config32(bus,num,function,offset,(std::uint32_t)value);
- break;
- default:
- break;
- }
-}
-
-pci_t __pci_load(std::uint8_t bus, std::uint8_t num, std::uint8_t function) {
- pci_t pciData;
- std::uint16_t *p = (std::uint16_t *)&pciData;
- for (std::uint8_t i = 0; i < 32; i++) {
- p[i] = pci_read_config16(bus, num, function, i * 2);
- }
- return pciData;
-}
-
-void drivers::pci::reg(void (*pcidrv)(pci_t, std::uint8_t, std::uint8_t, std::uint8_t), std::uint8_t _class, std::uint8_t subclass) {
- for (std::uint16_t i = 0; i < 256; i++) {
- if (!pci_drivers[i].used) {
- pci_drivers[i].used = true;
- pci_drivers[i]._class = _class;
- pci_drivers[i].subclass = subclass;
- pci_drivers[i].pcidrv = pcidrv;
- }
- }
-}
-
-void __pci_launch(pci_t pci, std::uint8_t bus, std::uint8_t device, std::uint8_t function) {
- for (std::uint16_t i = 0; i < 256; i++) {
- if (pci_drivers[i].used && pci_drivers[i]._class == pci._class && pci_drivers[i].subclass == pci.subclass) {
- pci_drivers[i].pcidrv(pci, bus, device, function);
- return;
- }
- }
-}
-
-void drivers::pci::initworkspace() {
- pci_t c_pci;
- for (std::uint16_t bus = 0; bus < 256; bus++) {
- c_pci = __pci_load(bus, 0, 0);
- if (c_pci.vendorID != 0xFFFF) {
- for (std::uint8_t device = 0; device < 32; device++) {
- c_pci = __pci_load(bus, device, 0);
- if (c_pci.vendorID != 0xFFFF) {
- __pci_launch(c_pci, bus, device, 0);
- for (std::uint8_t function = 1; function < 8; function++) {
- pci_t pci = __pci_load(bus, device, function);
- if (pci.vendorID != 0xFFFF) {
- __pci_launch(pci, bus, device, function);
- }
- }
- }
- }
- }
- }
-} \ No newline at end of file
diff --git a/kernel/src/drivers/ps2.cpp b/kernel/src/drivers/ps2.cpp
deleted file mode 100644
index a0f5dbf..0000000
--- a/kernel/src/drivers/ps2.cpp
+++ /dev/null
@@ -1,326 +0,0 @@
-#include <drivers/tsc.hpp>
-#include <generic/mm/paging.hpp>
-#include <generic/mm/pmm.hpp>
-#include <generic/mm/heap.hpp>
-#include <generic/vfs/vfs.hpp>
-#include <etc/etc.hpp>
-#include <etc/logging.hpp>
-
-#include <drivers/pci.hpp>
-#include <generic/vfs/evdev.hpp>
-
-#include <arch/x86_64/scheduling.hpp>
-#include <drivers/ps2.hpp>
-
-#include <etc/assembly.hpp>
-#include <drivers/io.hpp>
-
-void ps2_wait_write() {
- drivers::io io;
- while (io.inb(PS2_STATUS) & (1 << 1));
-}
-
-void ps2_wait_read() {
- drivers::io io;
- while (!(io.inb(PS2_STATUS) & (1 << 0)));
-}
-
-void ps2_writecmddata(char cmd, char data) {
- drivers::io io;
- ps2_wait_write();
- io.wait();
- io.outb(PS2_STATUS, cmd);
- io.wait();
- io.outb(PS2_DATA, data);
-}
-
-void ps2_writecmd(char cmd) {
- drivers::io io;
- ps2_wait_write();
- io.outb(PS2_STATUS, cmd);
-}
-
-void ps2_writedata(char cmd) {
- drivers::io io;
- ps2_wait_write();
- io.outb(PS2_DATA, cmd);
-}
-
-char ps2_not_empty() {
- drivers::io io;
- return (io.inb(PS2_STATUS) & 1) == 0;
-}
-
-int ps2_is_timeout = 0;
-
-char ps2_read_data() {
- drivers::io io;
- int timeout = 0;
- while(ps2_not_empty()) {
- if(timeout++ == 100) {
- ps2_is_timeout = 1;
- return 0;
- }
- drivers::tsc::sleep(100);
- }
- return io.inb(PS2_DATA);
-}
-
-void ps2_flush() {
- drivers::io io;
- while(io.inb(PS2_STATUS) & (1 << 0)) {
- io.inb(PS2_DATA);
- }
-}
-
-#define STATUS 0x64
-#define COMMAND 0x64
-#define DATA 0x60
-#define RESEND 0xFE
-#define ACK 0xFA
-#define ECHO 0xEE
-
-void ps2_writeport(uint8_t port, uint8_t cmd) {
- if(port == 2)
- ps2_writecmd(0xD4);
-
- ps2_writedata(cmd);
-}
-
-static inline char ps2_wait() {
- drivers::io io;
- return (io.inb(0x64) & 1) == 0;
-}
-
-uint8_t ps2_readtimeout() {
- drivers::io io;
- int timeout = 100;
- while(ps2_wait() && --timeout > 0) drivers::tsc::sleep(100);
- if(timeout <= 0)
- return 0;
- return io.inb(0x60);
-}
-
-void ps2_enableport(uint8_t port) {
- ps2_writeport(port,0xF4);
- int retry = 0;
- while(1) {
- uint8_t response = ps2_readtimeout();
- if(!response)
- break;
- else if(response == ACK)
- break;
- else if(response == RESEND) {
- if(++retry == 10)
- break;
- ps2_writeport(port,0xF4);
- }
- }
- ps2_flush();
-}
-
-#define MOUSE_LB (1 << 0)
-#define MOUSE_RB (1 << 1)
-#define MOUSE_MB (1 << 2)
-#define MOUSE_B4 (1 << 3)
-#define MOUSE_B5 (1 << 4)
-
-/*
-input0_fd = open("/dev/masterps2keyboard",O_RDWR);
- mouse_fd = open("/dev/mastermouse",O_RDWR);
-*/
-
-#define REL_X 0x00
-#define REL_Y 0x01
-#define REL_Z 0x02
-#define REL_RX 0x03
-#define REL_RY 0x04
-#define REL_RZ 0x05
-#define REL_HWHEEL 0x06
-#define REL_DIAL 0x07
-#define REL_WHEEL 0x08
-#define REL_MISC 0x09
-
-typedef struct {
- unsigned char buttons;
- unsigned char x;
- unsigned char y;
- unsigned char z;
-} __attribute__((packed)) mouse_packet_t;
-
-int mouse_evdev = 0;
-int kbd_evdev = 0;
-
-mouse_packet_t last_pack = {0};
-
-void ps2_process(void* arg) {
- int mouse_seq = 0;
- drivers::io io;
- if(1) {
-
- uint8_t mouse_buffer[4] = {0,0,0,0};
-
- while(1) {
-
- if(1) {
-
- int val = 1;
-
- uint8_t status = io.inb(0x64);
- while(status & 1) {
- int data = io.inb(DATA);
-
- if(status & (1 << 5)) {
- mouse_buffer[mouse_seq++] = data;
-
- if(mouse_seq == 3) {
- mouse_packet_t packet = {0,0,0,0};
-
- packet.x = mouse_buffer[1] - (mouse_buffer[0] & 0x10 ? 0x100 : 0);
- packet.y = mouse_buffer[2] - (mouse_buffer[0] & 0x20 ? 0x100 : 0);
- packet.z = (mouse_buffer[3] & 0x7) * (mouse_buffer[3] & 0x8 ? -1 : 1);
-
- packet.buttons |= (mouse_buffer[0] & 1) ? MOUSE_LB : 0;
- packet.buttons |= (mouse_buffer[0] & 2) ? MOUSE_RB : 0;
- packet.buttons |= (mouse_buffer[0] & 4) ? MOUSE_MB : 0;
-
- packet.buttons |= (mouse_buffer[0] & 0x10) ? MOUSE_B4 : 0;
- packet.buttons |= (mouse_buffer[0] & 0x20) ? MOUSE_B5 : 0;
-
- userspace_fd_t fd;
- memset(&fd,0,sizeof(userspace_fd_t));
- memcpy(fd.path,"/dev/mastermouse",strlen("/dev/mastermouse"));
- fd.is_cached_path = 1;
-
- asm volatile("cli");
- std::uint64_t current_nano = drivers::tsc::currentnano();
- input_event ev;
- ev.time.tv_sec = current_nano / 1000000000;
- ev.time.tv_usec = (current_nano & 1000000000) / 1000;
- if(packet.x) {
- ev.code = REL_X;
- ev.type = 2;
- ev.value = (packet.x & 0x80) ? (packet.x | 0xFFFFFF00) : packet.x;
- vfs::evdev::submit(mouse_evdev,ev);
- }
-
- if(packet.y) {
- ev.code = REL_Y;
- ev.type = 2;
- ev.value = (packet.y & 0x80) ? (packet.y | 0xFFFFFF00) : packet.y;
- vfs::evdev::submit(mouse_evdev,ev);
- }
-
- if(packet.z) {
- ev.code = REL_Z;
- ev.type = 2;
- ev.value = (packet.z & 0x80) ? (packet.z | 0xFFFFFF00) : packet.z;
- vfs::evdev::submit(mouse_evdev,ev);
- }
-
- if((packet.buttons & MOUSE_LB) && !(last_pack.buttons & MOUSE_LB)) {
- ev.code = 272;
- ev.type = 1;
- ev.value = 1;
- vfs::evdev::submit(mouse_evdev,ev);
- } else if(!(packet.buttons & MOUSE_LB) && (last_pack.buttons & MOUSE_LB)) {
- ev.code = 272;
- ev.type = 1;
- ev.value = 0;
- vfs::evdev::submit(mouse_evdev,ev);
- }
-
- if((packet.buttons & MOUSE_RB) && !(last_pack.buttons & MOUSE_RB)) {
- ev.code = 273;
- ev.type = 1;
- ev.value = 1;
- vfs::evdev::submit(mouse_evdev,ev);
- } else if(!(packet.buttons & MOUSE_RB) && (last_pack.buttons & MOUSE_RB)) {
- ev.code = 273;
- ev.type = 1;
- ev.value = 0;
- vfs::evdev::submit(mouse_evdev,ev);
- }
-
- if((packet.buttons & MOUSE_MB) && !(last_pack.buttons & MOUSE_MB)) {
- ev.code = 274;
- ev.type = 1;
- ev.value = 1;
- vfs::evdev::submit(mouse_evdev,ev);
- } else if(!(packet.buttons & MOUSE_MB) && (last_pack.buttons & MOUSE_MB)) {
- ev.code = 274;
- ev.type = 1;
- ev.value = 0;
- vfs::evdev::submit(mouse_evdev,ev);
- }
-
- asm volatile("sti");
-
- last_pack = packet;
-
- mouse_seq = 0;
-
- }
-
- } else {
- userspace_fd_t fd;
- memset(&fd,0,sizeof(userspace_fd_t));
- memcpy(fd.path,"/dev/masterps2keyboard",strlen("/dev/masterps2keyboard"));
- fd.is_cached_path = 1;
-
- std::uint64_t current_nano = drivers::tsc::currentnano();
-
- asm volatile("cli");
- input_event ev;
- ev.time.tv_sec = current_nano / 1000000000;
- ev.time.tv_usec = (current_nano & 1000000000) / 1000;
- ev.type = 1;
- ev.code = data & ~(1 << 7);
- ev.value = (data & (1 << 7)) ? 0 : 1;
- vfs::evdev::submit(kbd_evdev,ev);
- vfs::vfs::write(&fd,&data,1);
- asm volatile("sti");
- }
-
- status = io.inb(0x64);
- }
- asm volatile("cli");
- yield();
- asm volatile("sti");
- }
- }
- }
-}
-
-void drivers::ps2::init() {
- ps2_flush();
- ps2_writecmd(CMD_READ_CONFIG);
- std::uint8_t ctrl = (std::uint8_t)ps2_read_data();
- if(ps2_is_timeout) {
- Log::Display(LEVEL_MESSAGE_FAIL,"ps2: there's no ps2 controller !\n");
- return;
- }
-
- ps2_writecmd(0xAD);
- ps2_writecmd(0xA7);
-
- ps2_writecmd(0x20);
- uint8_t config = ps2_read_data();
- config |= (1 << 0) | (1 << 1) | (1 << 6);
- ps2_writecmd(0x60);
- ps2_writedata(config);
-
- ps2_enableport(1);
- ps2_enableport(2);
-
- ps2_writecmd(0xAE);
- ps2_writecmd(0xA8);
-
- ps2_flush();
-
- mouse_evdev = vfs::evdev::create("Generic PS/2 Mouse",EVDEV_TYPE_MOUSE);
- kbd_evdev = vfs::evdev::create("Generic PS/2 Keyboard",EVDEV_TYPE_KEYBOARD);
-
- arch::x86_64::scheduling::create_kernel_thread(ps2_process,0);
- Log::Display(LEVEL_MESSAGE_INFO,"PS/2 Initializied\n");
-} \ No newline at end of file
diff --git a/kernel/src/drivers/serial.cpp b/kernel/src/drivers/serial.cpp
deleted file mode 100644
index 626aa0d..0000000
--- a/kernel/src/drivers/serial.cpp
+++ /dev/null
@@ -1,46 +0,0 @@
-
-#include <cstdint>
-#include <cstddef>
-
-#include <drivers/serial.hpp>
-#include <drivers/io.hpp>
-
-#include <etc/libc.hpp>
-
-serial_mapping_t __serial_map[32];
-int __serial_map_ptr = 0;
-
-void drivers::serial::init(uint16_t port) {
-
- if(__serial_map_ptr == 0)
- memset(__serial_map,0,sizeof(serial_mapping_t));
-
- drivers::io io;
- io.outb(DEFAULT_SERIAL_PORT + 1, 0x00);
- io.outb(DEFAULT_SERIAL_PORT + 3, 0x80);
- io.outb(DEFAULT_SERIAL_PORT + 0, 0x03);
- io.outb(DEFAULT_SERIAL_PORT + 1, 0x00);
- io.outb(DEFAULT_SERIAL_PORT + 3, 0x03);
- io.outb(DEFAULT_SERIAL_PORT + 2, 0xC7);
- io.outb(DEFAULT_SERIAL_PORT + 4, 0x0B);
- io.outb(DEFAULT_SERIAL_PORT + 4, 0x1E);
- io.outb(DEFAULT_SERIAL_PORT + 0, 0xAE);
-
- if(io.inb(DEFAULT_SERIAL_PORT + 0) != 0xAE) {
- __serial_map[__serial_map_ptr].port = port;
- __serial_map[__serial_map_ptr++].is_init = 0;
- }
-
- io.outb(DEFAULT_SERIAL_PORT + 4, 0x0F);
- __serial_map[__serial_map_ptr].port = port;
- __serial_map[__serial_map_ptr++].is_init = 1;
-}
-
-std::uint8_t drivers::serial::is_init(uint16_t port) {
-
- for(int i = 0;i < __serial_map_ptr;i++) {
- if(__serial_map[i].port == port && __serial_map[i].is_init == 1)
- return 1;
- }
- return 0;
-} \ No newline at end of file
diff --git a/kernel/src/drivers/tsc.cpp b/kernel/src/drivers/tsc.cpp
deleted file mode 100644
index 0490ccd..0000000
--- a/kernel/src/drivers/tsc.cpp
+++ /dev/null
@@ -1,46 +0,0 @@
-
-#include <drivers/tsc.hpp>
-#include <drivers/hpet.hpp>
-#include <cstdint>
-
-#include <generic/time.hpp>
-
-#include <arch/x86_64/cpu/data.hpp>
-
-#include <etc/logging.hpp>
-
-#include <etc/assembly.hpp>
-
-using namespace drivers;
-
-std::uint64_t freq;
-
-void tsc::init() {
- std::uint64_t start = __rdtsc();
- time::sleep(100);
- std::uint64_t end = __rdtsc();
- std::uint64_t d = end - start;
- arch::x86_64::cpu::data()->tsc.freq = (d * 1000000ULL) / (100 * 1000ULL);
-}
-
-
-void tsc::sleep(std::uint64_t us) {
-
- if(arch::x86_64::cpu::data()->tsc.freq == 0) {
- drivers::hpet::sleep(us);
- return;
- }
-
- std::uint64_t current = currentnano();
- std::uint64_t end = us * 1000;
- while((currentnano() - current) < end);
- __nop();
-}
-
-std::uint64_t tsc::currentnano() {
- return (__rdtsc() * 1000000ULL) / arch::x86_64::cpu::data()->tsc.freq;
-}
-
-std::uint64_t tsc::currentus() {
- return currentnano() / 1000;
-} \ No newline at end of file
diff --git a/kernel/src/drivers/uacpi_kernel_api.cpp b/kernel/src/drivers/uacpi_kernel_api.cpp
new file mode 100644
index 0000000..532fe63
--- /dev/null
+++ b/kernel/src/drivers/uacpi_kernel_api.cpp
@@ -0,0 +1,397 @@
+
+#include <uacpi/types.h>
+#include <uacpi/kernel_api.h>
+#include <uacpi/platform/arch_helpers.h>
+#if defined(__x86_64__)
+#include <arch/x86_64/drivers/io.hpp>
+#include <arch/x86_64/drivers/pci.hpp>
+#endif
+#include <generic/bootloader/bootloader.hpp>
+#include <generic/hhdm.hpp>
+#include <generic/paging.hpp>
+#include <utils/gobject.hpp>
+#include <klibc/stdio.hpp>
+#include <generic/heap.hpp>
+#include <generic/lock/spinlock.hpp>
+#include <generic/time.hpp>
+
+uacpi_status uacpi_kernel_get_rsdp(uacpi_phys_addr *out_rsdp_address) {
+
+ if(bootloader::bootloader->get_rsdp() == nullptr)
+ return UACPI_STATUS_NOT_FOUND;
+
+ *out_rsdp_address = ((std::uint64_t)bootloader::bootloader->get_rsdp() - etc::hhdm());
+ return UACPI_STATUS_OK;
+}
+
+void *uacpi_kernel_map(uacpi_phys_addr addr, uacpi_size len) {
+ paging::map_range(gobject::kernel_root,addr,addr + etc::hhdm(),ALIGNUP(len, PAGE_SIZE),PAGING_PRESENT | PAGING_RW);
+ return (void*)(addr + etc::hhdm());
+}
+
+void uacpi_kernel_unmap(void *addr, uacpi_size len) {
+ (void)addr;
+ (void)len;
+}
+
+void uacpi_kernel_log(uacpi_log_level, const uacpi_char* msg) {
+ klibc::printf("uACPI: %s\r", msg);
+}
+
+uacpi_status uacpi_kernel_pci_device_open(
+ uacpi_pci_address address, uacpi_handle *out_handle
+) {
+ uacpi_pci_address* pci = (uacpi_pci_address*)kheap::opt_malloc(sizeof(uacpi_pci_address));
+ *pci = address;
+ *out_handle = (uacpi_handle)pci;
+ return UACPI_STATUS_OK;
+}
+
+void uacpi_kernel_pci_device_close(uacpi_handle hnd) {
+ kheap::opt_free((void*)hnd);
+}
+
+typedef struct {
+ uint64_t base;
+ uint64_t len;
+} __attribute__((packed)) uacpi_io_struct_t;
+
+uacpi_status uacpi_kernel_io_map(
+ uacpi_io_addr base, uacpi_size len, uacpi_handle *out_handle
+) {
+ uacpi_io_struct_t* iomap = (uacpi_io_struct_t*)kheap::opt_malloc(sizeof(uacpi_io_struct_t));
+ iomap->base = base;
+ iomap->len = len;
+ *out_handle = (uacpi_handle*)iomap;
+ return UACPI_STATUS_OK;
+}
+
+void uacpi_kernel_io_unmap(uacpi_handle handle) {
+ kheap::opt_free((void*)handle);
+}
+
+#if defined(__x86_64__)
+
+uacpi_status uacpi_kernel_pci_read8(
+ uacpi_handle device, uacpi_size offset, uacpi_u8 *value
+) {
+ uacpi_pci_address* pci = (uacpi_pci_address*)device;
+ *value = x86_64::pci::pci_read_config8(pci->bus,pci->device,pci->function,offset);
+ return UACPI_STATUS_OK;
+}
+uacpi_status uacpi_kernel_pci_read16(
+ uacpi_handle device, uacpi_size offset, uacpi_u16 *value
+) {
+ uacpi_pci_address* pci = (uacpi_pci_address*)device;
+ *value = x86_64::pci::pci_read_config16(pci->bus,pci->device,pci->function,offset);
+ return UACPI_STATUS_OK;
+}
+
+uacpi_status uacpi_kernel_pci_read32(
+ uacpi_handle device, uacpi_size offset, uacpi_u32 *value
+) {
+ uacpi_pci_address* pci = (uacpi_pci_address*)device;
+ *value = x86_64::pci::pci_read_config32(pci->bus,pci->device,pci->function,offset);
+ return UACPI_STATUS_OK;
+}
+
+uacpi_status uacpi_kernel_pci_write8(
+ uacpi_handle device, uacpi_size offset, uacpi_u8 value
+) {
+ uacpi_pci_address* pci = (uacpi_pci_address*)device;
+ x86_64::pci::pci_write_config8(pci->bus,pci->device,pci->function,offset,value);
+ return UACPI_STATUS_OK;
+}
+uacpi_status uacpi_kernel_pci_write16(
+ uacpi_handle device, uacpi_size offset, uacpi_u16 value
+) {
+ uacpi_pci_address* pci = (uacpi_pci_address*)device;
+ x86_64::pci::pci_write_config16(pci->bus,pci->device,pci->function,offset,value);
+ return UACPI_STATUS_OK;
+}
+uacpi_status uacpi_kernel_pci_write32(
+ uacpi_handle device, uacpi_size offset, uacpi_u32 value
+) {
+ uacpi_pci_address* pci = (uacpi_pci_address*)device;
+ x86_64::pci::pci_write_config32(pci->bus,pci->device,pci->function,offset,value);
+ return UACPI_STATUS_OK;
+}
+
+uacpi_status uacpi_kernel_io_read8(
+ uacpi_handle hnd, uacpi_size offset, uacpi_u8 *out_value
+) {
+ *out_value = x86_64::io::inb(*(std::uint16_t*)hnd + offset);
+ return UACPI_STATUS_OK;
+}
+uacpi_status uacpi_kernel_io_read16(
+ uacpi_handle hnd, uacpi_size offset, uacpi_u16 *out_value
+) {
+ *out_value = x86_64::io::inw(*(std::uint16_t*)hnd + offset);
+ return UACPI_STATUS_OK;
+}
+uacpi_status uacpi_kernel_io_read32(
+ uacpi_handle hnd, uacpi_size offset, uacpi_u32 *out_value
+) {
+ *out_value = x86_64::io::ind(*(std::uint16_t*)hnd + offset);
+ return UACPI_STATUS_OK;
+}
+
+uacpi_status uacpi_kernel_io_write8(
+ uacpi_handle hnd, uacpi_size offset, uacpi_u8 in_value
+) {
+ x86_64::io::outb(*(std::uint16_t*)hnd + offset,in_value);
+ return UACPI_STATUS_OK;
+}
+uacpi_status uacpi_kernel_io_write16(
+ uacpi_handle hnd, uacpi_size offset, uacpi_u16 in_value
+) {
+ x86_64::io::outw(*(std::uint16_t*)hnd + offset,in_value);
+ return UACPI_STATUS_OK;
+}
+uacpi_status uacpi_kernel_io_write32(
+ uacpi_handle hnd, uacpi_size offset, uacpi_u32 in_value
+) {
+ x86_64::io::outd(*(std::uint16_t*)hnd + offset,in_value);
+ return UACPI_STATUS_OK;
+}
+
+#else
+
+uacpi_status uacpi_kernel_pci_read8(
+ uacpi_handle device, uacpi_size offset, uacpi_u8 *value
+) {
+ (void)device;
+ (void)offset;
+ (void)value;
+ return UACPI_STATUS_UNIMPLEMENTED;
+}
+uacpi_status uacpi_kernel_pci_read16(
+ uacpi_handle device, uacpi_size offset, uacpi_u16 *value
+) {
+ (void)device;
+ (void)offset;
+ (void)value;
+ return UACPI_STATUS_UNIMPLEMENTED;
+}
+
+uacpi_status uacpi_kernel_pci_read32(
+ uacpi_handle device, uacpi_size offset, uacpi_u32 *value
+) {
+ (void)device;
+ (void)offset;
+ (void)value;
+ return UACPI_STATUS_UNIMPLEMENTED;
+}
+
+uacpi_status uacpi_kernel_pci_write8(
+ uacpi_handle device, uacpi_size offset, uacpi_u8 value
+) {
+ (void)device;
+ (void)offset;
+ (void)value;
+ return UACPI_STATUS_UNIMPLEMENTED;
+}
+uacpi_status uacpi_kernel_pci_write16(
+ uacpi_handle device, uacpi_size offset, uacpi_u16 value
+) {
+ (void)device;
+ (void)offset;
+ (void)value;
+ return UACPI_STATUS_UNIMPLEMENTED;
+}
+uacpi_status uacpi_kernel_pci_write32(
+ uacpi_handle device, uacpi_size offset, uacpi_u32 value
+) {
+ (void)device;
+ (void)offset;
+ (void)value;
+ return UACPI_STATUS_UNIMPLEMENTED;
+}
+
+uacpi_status uacpi_kernel_io_read8(
+ uacpi_handle hnd, uacpi_size offset, uacpi_u8 *out_value
+) {
+ (void)hnd;
+ (void)offset;
+ (void)out_value;
+ return UACPI_STATUS_UNIMPLEMENTED;
+}
+uacpi_status uacpi_kernel_io_read16(
+ uacpi_handle hnd, uacpi_size offset, uacpi_u16 *out_value
+) {
+ (void)hnd;
+ (void)offset;
+ (void)out_value;
+ return UACPI_STATUS_UNIMPLEMENTED;
+}
+uacpi_status uacpi_kernel_io_read32(
+ uacpi_handle hnd, uacpi_size offset, uacpi_u32 *out_value
+) {
+ (void)hnd;
+ (void)offset;
+ (void)out_value;
+ return UACPI_STATUS_UNIMPLEMENTED;
+}
+
+uacpi_status uacpi_kernel_io_write8(
+ uacpi_handle hnd, uacpi_size offset, uacpi_u8 in_value
+) {
+ (void)hnd;
+ (void)offset;
+ (void)in_value;
+ return UACPI_STATUS_UNIMPLEMENTED;
+}
+uacpi_status uacpi_kernel_io_write16(
+ uacpi_handle hnd, uacpi_size offset, uacpi_u16 in_value
+) {
+ (void)hnd;
+ (void)offset;
+ (void)in_value;
+ return UACPI_STATUS_UNIMPLEMENTED;
+}
+uacpi_status uacpi_kernel_io_write32(
+ uacpi_handle hnd, uacpi_size offset, uacpi_u32 in_value
+) {
+ (void)hnd;
+ (void)offset;
+ (void)in_value;
+ return UACPI_STATUS_UNIMPLEMENTED;
+}
+
+
+#endif
+
+void *uacpi_kernel_alloc(uacpi_size size) {
+ return kheap::opt_malloc(size);
+}
+
+void uacpi_kernel_free(void *mem) {
+ kheap::opt_free(mem);
+}
+
+/*
+ * Returns the number of nanosecond ticks elapsed since boot,
+ * strictly monotonic.
+ */
+uacpi_u64 uacpi_kernel_get_nanoseconds_since_boot(void) {
+ if(!time::timer) {
+ klibc::printf("uACPI: generic timer is missing !\r\n");
+ return 0;
+ }
+
+ return time::timer->current_nano();
+}
+
+/*
+ * Spin for N microseconds.
+ */
+void uacpi_kernel_stall(uacpi_u8 usec) {
+ if(!time::timer) {
+ klibc::printf("uACPI: generic timer is missing !\r\n");
+ return;
+ }
+
+ time::timer->sleep(usec);
+}
+
+void uacpi_kernel_sleep(uacpi_u64 msec) {
+ if(!time::timer) {
+ klibc::printf("uACPI: generic timer is missing !\r\n");
+ return;
+ }
+
+ time::timer->sleep(msec * 1000);
+}
+
+uacpi_handle uacpi_kernel_create_mutex(void) {
+ locks::spinlock* lock = (locks::spinlock*)kheap::opt_malloc(sizeof(locks::spinlock));
+ return (uacpi_handle)lock;
+}
+
+void uacpi_kernel_free_mutex(uacpi_handle hnd) {
+ kheap::opt_free((void*)hnd);
+}
+
+uacpi_handle uacpi_kernel_create_event(void) {
+ return (uacpi_handle)1;
+}
+
+void uacpi_kernel_free_event(uacpi_handle) {
+ asm volatile("nop");
+}
+
+uacpi_thread_id uacpi_kernel_get_thread_id(void) {
+ return 0;
+}
+
+uacpi_status uacpi_kernel_acquire_mutex(uacpi_handle lock, uacpi_u16) {
+ (void)lock;
+ return UACPI_STATUS_OK;
+}
+
+void uacpi_kernel_release_mutex(uacpi_handle lock) {
+ (void)lock;
+}
+
+uacpi_bool uacpi_kernel_wait_for_event(uacpi_handle, uacpi_u16) {
+ return 1;
+}
+
+void uacpi_kernel_signal_event(uacpi_handle) {
+ asm volatile("nop");
+}
+
+void uacpi_kernel_reset_event(uacpi_handle) {
+ asm volatile("nop");
+}
+
+uacpi_status uacpi_kernel_handle_firmware_request(uacpi_firmware_request*) {
+ return UACPI_STATUS_OK;
+}
+
+uacpi_status uacpi_kernel_install_interrupt_handler(
+ uacpi_u32 irq, uacpi_interrupt_handler base, uacpi_handle ctx,
+ uacpi_handle *out_irq_handle
+) {
+ (void)irq;
+ (void)base;
+ (void)ctx;
+ (void)out_irq_handle;
+ return UACPI_STATUS_OK;
+}
+
+uacpi_status uacpi_kernel_uninstall_interrupt_handler(
+ uacpi_interrupt_handler, uacpi_handle irq_handle
+) {
+ (void)irq_handle;
+ return UACPI_STATUS_OK;
+}
+
+uacpi_handle uacpi_kernel_create_spinlock(void) {
+ locks::spinlock* lock = (locks::spinlock*)kheap::opt_malloc(sizeof(locks::spinlock));
+ return (uacpi_handle)lock;
+}
+
+void uacpi_kernel_free_spinlock(uacpi_handle hnd) {
+ kheap::opt_free((void*)hnd);
+}
+
+uacpi_cpu_flags uacpi_kernel_lock_spinlock(uacpi_handle hnd) {
+ (void)hnd;
+ return UACPI_STATUS_OK;
+}
+
+void uacpi_kernel_unlock_spinlock(uacpi_handle hnd, uacpi_cpu_flags) {
+ (void)hnd;
+}
+
+uacpi_status uacpi_kernel_schedule_work(
+ uacpi_work_type, uacpi_work_handler, uacpi_handle ctx
+) {
+ (void)ctx;
+ return UACPI_STATUS_UNIMPLEMENTED;
+}
+
+uacpi_status uacpi_kernel_wait_for_work_completion(void) {
+ return UACPI_STATUS_OK;
+}
diff --git a/kernel/src/drivers/xhci.cpp b/kernel/src/drivers/xhci.cpp
deleted file mode 100644
index 816a049..0000000
--- a/kernel/src/drivers/xhci.cpp
+++ /dev/null
@@ -1,1602 +0,0 @@
-
-#include <drivers/xhci.hpp>
-#include <etc/libc.hpp>
-#include <drivers/tsc.hpp>
-#include <generic/mm/paging.hpp>
-#include <generic/mm/pmm.hpp>
-#include <generic/mm/heap.hpp>
-#include <generic/vfs/vfs.hpp>
-#include <etc/etc.hpp>
-#include <etc/logging.hpp>
-
-#include <drivers/pci.hpp>
-#include <generic/vfs/evdev.hpp>
-
-#include <arch/x86_64/scheduling.hpp>
-
-xhci_device_t* xhci_list;
-
-void __xhci_put_new_device(xhci_device_t* dev) {
- if(!dev) {
- return;
- }
-
- if(!xhci_list) {
- xhci_list = dev;
- } else {
- dev->next = xhci_list;
- xhci_list = dev;
- }
-
-}
-
-void __xhci_doorbell(xhci_device_t* dev,uint32_t value) {
- *dev->doorbell = value;
-}
-
-void __xhci_doorbell_id(xhci_device_t* dev,uint32_t idx,uint32_t val) {
- dev->doorbell[idx] = val;
-}
-
-void __xhci_reset(xhci_device_t* dev) {
-
- drivers::tsc::sleep(50*1000); // wait some time
-
- dev->op->usbcmd |= (1 << 1);
- uint16_t timeout = XHCI_RESET_TIMEOUT;
- while(dev->op->usbsts & (1 << 11)) {
- if(!timeout) {
- Log::Display(LEVEL_MESSAGE_FAIL,"Can't reset XHCI Controller, ignoring\n");
- break;
- }
- drivers::tsc::sleep(5 * 1000);
- timeout = timeout - 1;
- }
-
- drivers::tsc::sleep(5000);
-
-}
-
-void __xhci_enable(xhci_device_t* dev) {
- drivers::tsc::sleep(50*1000);
- dev->op->usbcmd |= (1 << 0) | (1 << 2);
- uint16_t timeout = XHCI_RESET_TIMEOUT;
- while(dev->op->usbsts & (1 << 0)) {
- if(!timeout) {
- Log::Display(LEVEL_MESSAGE_FAIL,"Can't start XHCI Controller, crying\n");
- break;
- }
- drivers::tsc::sleep(5 * 1000);
- timeout = timeout - 1;
- }
-
- drivers::tsc::sleep(5000);
-
-}
-
-void __xhci_reset_intr(xhci_device_t* dev, uint16_t intr) {
-
- if(intr > dev->cap->hcsparams1.maxintrs) {
- Log::Display(LEVEL_MESSAGE_FAIL,"Intr is higher than maxintrs! Skipping");
- return;
- }
-
- dev->op->usbsts = (1 << 3);
- dev->runtime->int_regs[intr].iman |= (1 << 0);
-}
-
-void __xhci_punch_intr(xhci_device_t* dev,uint16_t intr) {
- dev->runtime->int_regs[intr].erdp.event_busy = 1;
-}
-
-void __xhci_update_stepfather(xhci_device_t* dev,xhci_event_ring_ctx_t* grandpa) {
- grandpa->father->erdp_val = grandpa->table[0].base + (grandpa->queue * sizeof(xhci_trb_t));
-}
-
-xhci_trb_t* __xhci_move_father(xhci_device_t* dev,xhci_event_ring_ctx_t* ctx) {
- xhci_trb_t* trb = &ctx->trb[ctx->queue++];
- if(ctx->queue == ctx->trb_limit) {
- ctx->cycle = !ctx->cycle;
- ctx->queue = 0;
- }
- return trb;
-}
-
-xhci_event_ring_ctx_t* __xhci_create_event_ring(xhci_device_t* dev,uint16_t trb_size,volatile IR_t* stepfather,uint16_t sons) {
- xhci_event_ring_ctx_t* ring_info = new xhci_event_ring_ctx_t;
- ring_info->cycle = 1;
- ring_info->queue = 0;
- ring_info->father = stepfather; // :pensive:
- ring_info->trb_limit = trb_size;
- ring_info->trb = 0;
-
- uint64_t new_table = memory::pmm::_physical::alloc(ALIGNPAGEUP(sons * sizeof(xhci_erst_t)));
- void* virt_table = Other::toVirt(new_table);
-
- ring_info->table = (xhci_erst_t*)virt_table;
-
- uint64_t phys_trb = memory::pmm::_physical::alloc(16 * PAGE_SIZE);
- ring_info->table[0].base = phys_trb;
- ring_info->table[0].size = trb_size;
-
- ring_info->trb = (xhci_trb_t*)Other::toVirt(phys_trb);
-
- stepfather->erstsz = sons;
- __xhci_update_stepfather(dev,ring_info);
- stepfather->erstba = new_table;
-
- return ring_info;
-
-}
-
-xhci_trb_t get_trb(xhci_event_ring_ctx_t* father,uint16_t idx) {
- return father->trb[idx];
-}
-
-int __xhci_event_receive(xhci_device_t* dev,xhci_event_ring_ctx_t* father,xhci_trb_t** out) { // it will return trb virtual addresses
- int len = 0;
- while(get_trb(father,father->queue).info_s.cycle == father->cycle)
- out[len++] = __xhci_move_father(dev,father);
- __xhci_punch_intr(dev,0);
- __xhci_update_stepfather(dev,father);
- return len;
-}
-
-xhci_command_ring_ctx_t* __xhci_create_command_ring(xhci_device_t* dev,uint16_t trb_size) {
- xhci_command_ring_ctx_t* ring_info = new xhci_command_ring_ctx_t;
- ring_info->cycle = 1;
- ring_info->queue = 0;
- ring_info->trb_limit = trb_size;
-
- uint64_t phys_trb = memory::pmm::_physical::alloc(ALIGNPAGEUP(trb_size * sizeof(xhci_trb_t)));
-
- ring_info->phys = phys_trb;
-
- ring_info->trb = (xhci_trb_t*)Other::toVirt(phys_trb);
- ring_info->trb[trb_size - 1].base = phys_trb;
- ring_info->trb[trb_size - 1].info = (6 << 10) | (1 << 1) | (1 << 0);
- return ring_info;
-}
-
-
-void __xhci_command_ring_queue(xhci_device_t* dev,xhci_command_ring_ctx_t* ctx,xhci_trb_t* trb) {
- trb->info |= ctx->cycle;
- memcpy(&ctx->trb[ctx->queue],trb,sizeof(xhci_trb_t));
- if(++ctx->queue == ctx->trb_limit - 1) {
- ctx->queue = 0;
- ctx->trb[ctx->trb_limit - 1].info = (6 << 10) | (1 << 1) | (ctx->cycle << 0);
- ctx->cycle = !ctx->cycle;
- }
-}
-
-void __xhci_setup_run(xhci_device_t* dev) {
- volatile IR_t* head = (volatile IR_t*)&dev->runtime->int_regs[0];
- head->iman |= (1 << 1);
-
- dev->event_ring = __xhci_create_event_ring(dev,256,head,1);
-
- __xhci_reset_intr(dev,0);
-}
-
-void __xhci_fill_dcbaa(xhci_device_t* dev) {
-
- uint64_t phys_dcbaa = memory::pmm::_physical::alloc(ALIGNPAGEUP(8*dev->cap->hcsparams1.maxslots));
-
- uint64_t* dcbaa = (uint64_t*)Other::toVirt(phys_dcbaa);
-
- if(dev->calculated_scratchpad_count) {
-
- uint64_t phys_list = memory::pmm::_physical::alloc(ALIGNPAGEUP(8*dev->calculated_scratchpad_count));
-
- uint64_t* list = (uint64_t*)Other::toVirt(phys_list);
- for(uint16_t i = 0;i < dev->calculated_scratchpad_count;i++) {
- uint64_t hi = memory::pmm::_physical::alloc(4096);
- list[i] = hi;
- }
- dcbaa[0] = phys_list;
- }
-
- dev->dcbaa = (uint64_t*)dcbaa;
- dev->op->dcbaap = phys_dcbaa;
- drivers::tsc::sleep(5000);
-}
-
-void __xhci_setup_op(xhci_device_t* dev) {
- __xhci_fill_dcbaa(dev);
- dev->com_ring = __xhci_create_command_ring(dev,128); // i dont think what command ring will be fat
- dev->op->crcr = dev->com_ring->phys | dev->com_ring->cycle;
- dev->op->config = dev->cap->hcsparams1.maxslots;
- dev->op->dnctrl = 0xFFFF;
-}
-
-volatile uint32_t* __xhci_portsc(xhci_device_t* dev,uint32_t portnum) {
- return ((volatile uint32_t*)(dev->xhci_virt_base + 0x400 + dev->cap->caplength + (0x10 * portnum)));
-}
-
-void* __xhci_helper_map(uint64_t start,uint64_t pagelen) {
- return memory::paging::maprangeret(start,pagelen,PTE_MMIO);
-}
-
-const char* trb_type_to_str(int type) {
- switch(type) {
- case TRB_COMMANDCOMPLETIONEVENT_TYPE:
- return "TRB_COMMAND_COMPLETION_EVENT";
- case TRB_TRANSFEREVENT_TYPE:
- return "TRB_TRANSFER_EVENT";
- default:
- return "Unknown";
- }
-}
-
-xhci_trb_t __xhci_event_wait(xhci_device_t* dev,int type) {
- xhci_event_ring_ctx_t* father = dev->event_ring;
- xhci_trb_t* buffer[1024];
- int timeout = 100;
- while(1) {
- int count = 0;
- memset(buffer,0,sizeof(xhci_trb_t*) * 1024);
- if(get_trb(father,father->queue).info_s.cycle == father->cycle)
- count = __xhci_event_receive(dev,father,buffer);
-
- if(count) {
- xhci_trb_t* current = 0;
- for(int i = 0;i < count;i++) {
- current = buffer[i];
- if(current->info_s.type == type) {
- return *current;
- } else {
- Log::Display(LEVEL_MESSAGE_WARN,"Wait for wrong type %d\n",current->info_s.type);
- }
- }
- }
-
- if(--timeout == 0) {
- xhci_trb_t t;
- t.base = 0xDEAD;
- t.ret_code = 0;
- return t;
- }
-
- drivers::tsc::sleep(5000);
-
- }
-}
-
-void __xhci_clear_event(xhci_device_t* dev) {
- int count = 0;
- xhci_trb_t* buffer[1024];
- if(get_trb(dev->event_ring,dev->event_ring->queue).info_s.cycle == dev->event_ring->cycle)
- count = __xhci_event_receive(dev,dev->event_ring,buffer);
-}
-
-xhci_port_ring_ctx_t* __xhci_setup_port_ring(uint16_t trb_count,uint16_t slot) {
- xhci_port_ring_ctx_t* ring_info = new xhci_port_ring_ctx_t;
- ring_info->cycle = 1;
- ring_info->queue = 0;
- ring_info->slot = slot;
- ring_info->trb_limit = trb_count;
-
- uint64_t phys_trb = memory::pmm::_physical::alloc(16 * 4096);
- ring_info->trb = (xhci_trb_t*)Other::toVirt(phys_trb);
-
- ring_info->phys = phys_trb;
- ring_info->trb[trb_count - 1].base = phys_trb;
- ring_info->trb[trb_count - 1].info = (6 << 10) | (1 << 1) | (1 << 0);
- return ring_info;
-}
-
-// its same as command ring
-void __xhci_port_ring_queue(xhci_port_ring_ctx_t* ctx,xhci_trb_t* trb) {
- trb->info |= ctx->cycle;
- memcpy(&ctx->trb[ctx->queue],trb,sizeof(xhci_trb_t));
- if(++ctx->queue == ctx->trb_limit - 1) {
- ctx->queue = 0;
- ctx->trb[ctx->trb_limit - 1].info = (6 << 10) | (1 << 1) | (ctx->cycle << 0);
- ctx->cycle = !ctx->cycle;
- }
-}
-
-void __xhci_create_dcbaa(xhci_device_t* dev,uint32_t slotid,uint64_t addr) {
- dev->dcbaa[slotid] = addr;
-}
-
-xhci_usb_device_t* usbdevs = 0;
-
-xhci_usb_device_t* __xhci_alloc_dev(uint32_t portnum,uint32_t slotid) {
- xhci_usb_device_t* dev = new xhci_usb_device_t;
- dev->next = 0;
- dev->portnum = portnum;
- dev->slotid = slotid;
- dev->transfer_ring = __xhci_setup_port_ring(256,slotid);
- dev->phys_input_ctx = memory::pmm::_physical::alloc(4096);
- if(!usbdevs) {
- usbdevs = dev;
- } else {
- dev->next = usbdevs;
- usbdevs = dev;
- }
- return dev;
-}
-
-int __xhci_enable_slot(xhci_device_t* dev, int portnum) {
- xhci_trb_t trb;
-
- memset(&trb,0,sizeof(xhci_trb_t));
-
- trb.info_s.intoncompletion = 1;
- trb.info_s.type = TRB_ENABLESLOTCOMMAND_TYPE;
-
- __xhci_clear_event(dev);
-
- __xhci_command_ring_queue(dev,dev->com_ring,&trb);
- __xhci_doorbell(dev,0);
- drivers::tsc::sleep(25000);
-
- xhci_trb_t ret = __xhci_event_wait(dev,TRB_COMMANDCOMPLETIONEVENT_TYPE);
-
- if(ret.base == 0xDEAD) {
- Log::Display(LEVEL_MESSAGE_FAIL,"Timeout for port %d in slot enabling\n",portnum);
- return 0;
- }
-
- xhci_slot_trb_t* slot_ret = (xhci_slot_trb_t*)&ret;
-
- if(ret.ret_code != 1)
- Log::Display(LEVEL_MESSAGE_FAIL,"Can't allocate slot for port %d (ret %d)\n",portnum,ret.ret_code);
-
- return slot_ret->info_s.slotid;
-
-}
-
-int __xhci_set_addr(xhci_device_t* dev,uint64_t addr,uint32_t id,char bsr) {
- xhci_set_addr_trb_t trb;
- memset(&trb,0,sizeof(trb));
- trb.base = addr;
- trb.info_s.bsr = 0;
- trb.info_s.type = TRB_ADDRESSDEVICECOMMAND_TYPE;
- trb.info_s.slotid = id;
- __xhci_clear_event(dev);
-
- drivers::tsc::sleep(5000);
-
- __xhci_clear_event(dev);
-
- __xhci_command_ring_queue(dev,dev->com_ring,(xhci_trb_t*)&trb);
- __xhci_doorbell(dev,0);
- drivers::tsc::sleep(5000);
-
- xhci_trb_t ret = __xhci_event_wait(dev,TRB_COMMANDCOMPLETIONEVENT_TYPE);
-
- if(ret.ret_code != 1 && ret.ret_code != 0)
- Log::Display(LEVEL_MESSAGE_FAIL,"Can't set XHCI port address (ret %d)\n",ret.ret_code);
-
- return ret.ret_code;
-
-}
-
-xhci_trb_t __xhci_send_usb_request_packet(xhci_device_t* dev,xhci_usb_device_t* usbdev,xhci_usb_command_t usbcommand,void* out,uint64_t len) {
-
- uint64_t phys_status_buf = memory::pmm::_physical::alloc(4096);
- uint64_t phys_desc_buf = memory::pmm::_physical::alloc(4096);
-
- void* status_buf = Other::toVirt(phys_status_buf);
- void* desc_buf = Other::toVirt(phys_desc_buf);
-
- memset(out,0,len);
-
- xhci_setupstage_trb_t setup;
- xhci_datastage_trb_t data;
- xhci_eventdata_trb_t event0;
- xhci_statusstage_trb_t status;
- xhci_eventdata_trb_t event1;
-
- memset(&setup,0,sizeof(xhci_trb_t));
- memset(&data,0, sizeof(xhci_trb_t));
- memset(&event0,0,sizeof(xhci_trb_t));
- memset(&status,0,sizeof(xhci_trb_t));
- memset(&event1,0,sizeof(xhci_trb_t));
-
- memcpy(&setup.command,&usbcommand,sizeof(xhci_usb_command_t));
-
- setup.type = TRB_SETUPSTAGE_TYPE;
- setup.trt = 3;
- setup.imdata = 1;
- setup.len = 8;
-
- data.type = TRB_DATASTAGE_TYPE;
- data.data = phys_desc_buf;
- data.len = len;
- data.chain = 1;
- data.direction = 1;
-
- event0.type = TRB_EVENTDATA_TYPE;
- event0.base = phys_status_buf;
- event0.intoncomp = 1;
-
- status.type = TRB_STATUSSTAGE_TYPE;
- status.chain = 1;
-
- event1.type = TRB_EVENTDATA_TYPE;
- event1.intoncomp = 1;
-
- __xhci_port_ring_queue(usbdev->transfer_ring,(xhci_trb_t*)&setup);
- __xhci_port_ring_queue(usbdev->transfer_ring,(xhci_trb_t*)&data);
- __xhci_port_ring_queue(usbdev->transfer_ring,(xhci_trb_t*)&event0);
- __xhci_port_ring_queue(usbdev->transfer_ring,(xhci_trb_t*)&status);
- __xhci_port_ring_queue(usbdev->transfer_ring,(xhci_trb_t*)&event1);
-
- __xhci_clear_event(dev);
-
- __xhci_doorbell_id(dev,usbdev->slotid,1);
- drivers::tsc::sleep(5000);
-
- xhci_trb_t ret = __xhci_event_wait(dev,TRB_TRANSFEREVENT_TYPE);
-
- if(ret.base == 0xDEAD) {
- ret.ret_code = 0;
- return ret;
- }
-
- if(ret.ret_code != 1) {
- Log::Display(LEVEL_MESSAGE_FAIL,"Failed to request xhci device, idx: %p, val: %p, type: %p, len: %p, request: %d ret_code %d\n",usbcommand.index,usbcommand.value,usbcommand.type,usbcommand.len,usbcommand.request,ret.ret_code);
- ret.ret_code = 0;
- return ret;
- }
-
- drivers::tsc::sleep(5000);
-
- memcpy(out,desc_buf,len);
-
- memory::pmm::_physical::free(phys_desc_buf);
- memory::pmm::_physical::free(phys_status_buf);
-
- return ret;
-
-}
-
-xhci_trb_t __xhci_send_usb_packet(xhci_device_t* dev,xhci_usb_device_t* usbdev,xhci_usb_command_t com) {
-
- xhci_setupstage_trb_t setup;
- xhci_statusstage_trb_t status;
-
- memset(&setup,0,sizeof(xhci_setupstage_trb_t));
- memset(&status,0,sizeof(xhci_statusstage_trb_t));
-
- memcpy(&setup.command,&com,sizeof(xhci_usb_command_t));
-
- setup.imdata = 1;
- setup.len = 8;
- setup.type = TRB_SETUPSTAGE_TYPE;
-
- status.direction = 1;
- status.intoncomp = 1;
- status.type = TRB_STATUSSTAGE_TYPE;
-
- __xhci_port_ring_queue(usbdev->transfer_ring,(xhci_trb_t*)&setup);
- __xhci_port_ring_queue(usbdev->transfer_ring,(xhci_trb_t*)&status);
-
- __xhci_clear_event(dev);
-
- __xhci_doorbell_id(dev,usbdev->slotid,1);
- drivers::tsc::sleep(5000);
-
- xhci_trb_t ret = __xhci_event_wait(dev,TRB_TRANSFEREVENT_TYPE);
-
- return ret;
-
-}
-
-int __xhci_get_usb_descriptor(xhci_device_t* dev,xhci_usb_device_t* usbdev,void* out,uint64_t len) {
- xhci_usb_command_t usbcommand;
- usbcommand.type = 0x80;
- usbcommand.request = 6;
- usbcommand.value = 1 << 8;
- usbcommand.index = 0;
- usbcommand.len = len;
-
- xhci_trb_t ret = __xhci_send_usb_request_packet(dev,usbdev,usbcommand,out,len);
- if(ret.ret_code != 1)
- return 0;
-
- return 1;
-
-}
-
-uint16_t __xhci_get_speed(xhci_device_t* dev,uint32_t portsc) {
- uint8_t extracted_speed = (portsc & 0x3C00) >> 10;
- switch (extracted_speed) {
- case XHCI_USB_SPEED_LOW_SPEED:
- return 8;
-
- case XHCI_USB_SPEED_FULL_SPEED:
- return 64;
-
- case XHCI_USB_SPEED_HIGH_SPEED:
- return 64;
-
- case XHCI_USB_SPEED_SUPER_SPEED:
- return 512;
-
- case XHCI_USB_SPEED_SUPER_SPEED_PLUS:
- return 512;
-
- default:
- return 0;
- }
-}
-
-int __xhci_reset_dev(xhci_device_t* dev,uint32_t portnum) {
- volatile uint32_t* portsc = (volatile uint32_t*)__xhci_portsc(dev,portnum);
- uint32_t load_portsc = *portsc;
-
- if(!(*portsc & (1 << 9))) {
- load_portsc |= (1 << 9);
- *portsc = load_portsc;
- drivers::tsc::sleep(5000);
- if(!(*portsc & (1 << 9))) {
- return 0;
- }
- }
-
- uint8_t old_bit = load_portsc & (1 << 1);
-
- if(dev->usb3ports[portnum]) {
- load_portsc |= (1 << 31);
- *portsc = load_portsc;
- } else {
- load_portsc |= 0x10;
- *portsc = load_portsc;
- }
-
- uint16_t time = 50;
-
- if(dev->usb3ports[portnum]) {
- while(*portsc & (1 << 19)) {
- if(time-- == 0) {
- Log::Display(LEVEL_MESSAGE_FAIL,"Can't reset USB 3.0 device with port %d, ignoring\n",portnum);
- return 0;
- }
- drivers::tsc::sleep(5000);
- }
- } else {
- while((*portsc & (1 << 1)) == old_bit) {
- if(time-- == 0) {
- Log::Display(LEVEL_MESSAGE_FAIL,"Can't reset USB 2.0 device with port %d, ignoring\n",portnum);
- return 1;
- }
- drivers::tsc::sleep(5000);
- }
- }
-
- drivers::tsc::sleep(5000);
- return 1;
-
-}
-
-void __xhci_unicode_to_ascii(uint16_t* src,char* dest) {
- uint16_t src_ptr = 0;
- uint16_t dest_ptr = 0;
-
- uint16_t* ptr = (uint16_t*)src;
- while(ptr[src_ptr]) {
-
- if(ptr[src_ptr] < 128)
- dest[dest_ptr++] = ptr[src_ptr++];
- else
- dest[dest_ptr++] = '?';
- }
- dest[dest_ptr] = '\0';
-}
-
-int __xhci_read_usb_string(xhci_device_t* dev,xhci_usb_device_t* usbdev,xhci_string_descriptor_t* out,uint8_t index,uint8_t lang) {
- xhci_usb_command_t usbcommand;
- usbcommand.type = 0x80;
- usbcommand.request = 6;
- usbcommand.value = (3 << 8) | index;
- usbcommand.index = lang;
- usbcommand.len = sizeof(xhci_usb_descriptor_header);
-
- xhci_trb_t ret = __xhci_send_usb_request_packet(dev,usbdev,usbcommand,out,usbcommand.len);
- if(ret.ret_code != 1)
- return 0;
-
- usbcommand.len = out->head.len;
-
- if(usbcommand.len < 8) {
- return 1;
- }
-
- ret = __xhci_send_usb_request_packet(dev,usbdev,usbcommand,out,usbcommand.len);
- if(ret.ret_code != 1)
- return 0;
-
- return 1;
-
-}
-
-
-
-int __xhci_read_usb_lang_string(xhci_device_t* dev,xhci_usb_device_t* usbdev,xhci_lang_descriptor_t* out) {
- xhci_usb_command_t usbcommand;
- usbcommand.type = 0x80;
- usbcommand.request = 6;
- usbcommand.value = (3 << 8);
- usbcommand.index = 0;
- usbcommand.len = sizeof(xhci_usb_descriptor_header);
-
- xhci_trb_t ret = __xhci_send_usb_request_packet(dev,usbdev,usbcommand,out,usbcommand.len);
- if(ret.ret_code != 1)
- return 0;
-
- usbcommand.len = out->head.len;
-
- ret = __xhci_send_usb_request_packet(dev,usbdev,usbcommand,out,usbcommand.len);
- if(ret.ret_code != 1)
- return 0;
-
- return 1;
-
-}
-
-int __xhci_print_device_info(xhci_device_t* dev,xhci_usb_device_t* usb_dev,char* product0,char* manufacter0) {
- xhci_lang_descriptor_t lang;
-
- int status = __xhci_read_usb_lang_string(dev,usb_dev,&lang);
-
- if(!status)
- return 0;
-
- uint16_t lang0 = lang.lang[0];
-
- xhci_string_descriptor_t product;
- xhci_string_descriptor_t manufacter;
-
- memset(&product,0,sizeof(product));
- memset(&manufacter,0,sizeof(manufacter));
-
- status = __xhci_read_usb_string(dev,usb_dev,&product,usb_dev->desc->product1,lang0);
-
- if(!status)
- return 0;
-
- status = __xhci_read_usb_string(dev,usb_dev,&manufacter,usb_dev->desc->manufacter,lang0);
-
- if(!status)
- return 0;
-
- memset(product0,0,256);
- memset(manufacter0,0,256);
-
- __xhci_unicode_to_ascii(product.str,product0);
- __xhci_unicode_to_ascii(manufacter.str,manufacter0);
-
- return 1;
-
-}
-
-void __xhci_setup_config(xhci_device_t* dev,xhci_usb_device_t* usbdev,uint16_t value) {
- xhci_usb_command_t command;
- command.type = 0;
- command.index = 0;
- command.len = 0;
- command.request = 9;
- command.value = value;
-
- int ret = __xhci_send_usb_packet(dev,usbdev,command).ret_code;
-
- if(ret != 1)
- Log::Display(LEVEL_MESSAGE_FAIL,"Can't set configuration on port %d with val %d (ret %d)\n",usbdev->portnum,value,ret);
-}
-
-void __xhci_get_config_descriptor(xhci_device_t* dev,xhci_usb_device_t* usbdev, xhci_config_descriptor_t* out) {
- xhci_usb_command_t com;
- com.type = 0x80;
- com.value = 2 << 8;
- com.index = 0;
- com.len = sizeof(xhci_usb_descriptor_header);
- com.request = 6;
-
- __xhci_send_usb_request_packet(dev,usbdev,com,out,sizeof(xhci_usb_descriptor_header));
- com.len = out->head.len;
- __xhci_send_usb_request_packet(dev,usbdev,com,out,out->head.len);
- com.len = out->len;
- __xhci_send_usb_request_packet(dev,usbdev,com,out,out->len);
-
-}
-
-void __xhci_get_hid_report(xhci_device_t* dev,xhci_usb_device_t* usbdev,uint8_t idx,uint8_t internum,void* data,uint32_t len) {
- xhci_usb_command_t cmd;
- cmd.index = internum;
- cmd.request = 6;
- cmd.type = 0x81;
- cmd.len = len;
- cmd.value = (0x22 << 8) | idx;
- __xhci_send_usb_request_packet(dev,usbdev,cmd,data,len);
-}
-
-void __xhci_set_boot_protocol(xhci_device_t* dev, xhci_usb_device_t* usbdev, int internum) {
- xhci_usb_command_t cmd;
- cmd.index = internum;
- cmd.request = 0x0B;
- cmd.type = 0x21;
- cmd.len = 0;
- cmd.value = 0;
-
- char data[4096];
- __xhci_send_usb_request_packet(dev,usbdev,cmd,data,0);
-}
-
-int __xhci_ep_to_type(xhci_endpoint_descriptor_t* desc) {
- uint8_t direction = (desc->endpointaddr & 0x80) ? 1 : 0;
- uint8_t type = desc->attributes & 3;
-
- switch (type) {
- case 1:
- return direction == 1 ? XHCI_ENDPOINTTYPE_ISOCHRONOUS_IN : XHCI_ENDPOINTTYPE_ISOCHRONOUS_OUT;
-
- case 2:
- return direction == 1 ? XHCI_ENDPOINTTYPE_BULK_IN : XHCI_ENDPOINTTYPE_BULK_OUT;
-
- case 3:
- return direction == 1 ? XHCI_ENDPOINTTYPE_INTERRUPT_IN : XHCI_ENDPOINTTYPE_INTERRUPT_OUT;
- }
-
- return 0; // without it i will got UB
-}
-
-void __xhci_ask_for_help_hid(xhci_device_t* dev,xhci_usb_device_t* usbdev) {
-
- for(int i = 0;i < 30;i++) {
-
- if(!usbdev->doorbell_values[i])
- continue;
-
- xhci_port_ring_ctx_t* transfer_ring = usbdev->ep_ctx[i];
- xhci_normal_trb_t trb;
- memset(&trb,0,sizeof(xhci_normal_trb_t));
- trb.info_s.type = 1;
- trb.info_s.ioc = 1;
- trb.base = (uint64_t)usbdev->phys_buffers[i];
- trb.trbtransferlen = usbdev->buffers_need_size[i];
-
- __xhci_port_ring_queue(transfer_ring,(xhci_trb_t*)&trb);
- __xhci_doorbell_id(dev,usbdev->slotid,usbdev->doorbell_values[i]);
- }
-
-}
-
-const char* __xhci_usb_type_to_str(int type) {
- switch(type) {
- case USB_TYPE_KEYBOARD:
- return "USB Keyboard";
- case USB_TYPE_MOUSE:
- return "USB Mouse";
- default:
- return "Unsupported";
- };
-}
-
-int log2(unsigned int x) {
- int result = -1;
- while (x) {
- x >>= 1;
- result++;
- }
- return result;
-}
-
-void __xhci_init_dev(xhci_device_t* dev,int portnum) {
-
- volatile uint32_t* portsc = __xhci_portsc(dev,portnum);
- uint32_t load_portsc = *portsc;
- if(!(load_portsc & 1))
- return;
-
- int status = __xhci_reset_dev(dev,portnum);
- if(!status)
- return;
-
- int id = __xhci_enable_slot(dev,portnum);
-
- xhci_usb_device_t* usb_dev = __xhci_alloc_dev(portnum,id);
- //String::memset(usb_dev,0,sizeof(xhci_usb_device_t));
-
- memset(usb_dev->doorbell_values,0,30);
-
- usb_dev->interface = 0;
-
- uint64_t addr = memory::pmm::_physical::alloc(4096);
- __xhci_create_dcbaa(dev,usb_dev->slotid,addr);
-
- uint32_t* hccparams = (uint32_t*)(&dev->cap->hccparams1);
- char context_size = ((hccparams1_t*)hccparams)->contextsize;
-
- if(!context_size)
- dev->dcbaa[id] += 64;
- else
- dev->dcbaa[id] += 128;
-
- if(!context_size)
- usb_dev->_is64byte = 0;
- else
- usb_dev->_is64byte = 1;
-
- usb_dev->dev = dev;
-
- load_portsc = *portsc; // load it again
-
- uint16_t speed = __xhci_get_speed(dev,load_portsc);
-
- const char* speed_to_str[7] = {
- "(0 MB/s - USB ?)",
- "(12 MB/s - USB 2.0)",
- "(1.5 Mb/s - USB 2.0)",
- "(480 Mb/s - USB 2.0)",
- "(5 Gb/s - USB3.0)",
- "(10 Gb/s - USB 3.1)"
- };
-
- if(!context_size) {
- xhci_input_ctx_t* input_ctx = (xhci_input_ctx_t*)Other::toVirt(addr);
-
- memset(input_ctx,0,4096);
- input_ctx->input_ctx.A = (1 << 0) | (1 << 1);
- input_ctx->slot.contextentries = 1;
- input_ctx->slot.speed = (load_portsc & 0x3C00) >> 10;
- input_ctx->slot.porthubnum = portnum + 1;
- input_ctx->ep0.endpointtype = 4;
- input_ctx->ep0.cerr = 3;
- input_ctx->ep0.maxpacketsize = speed;
- input_ctx->ep0.base = usb_dev->transfer_ring->phys | usb_dev->transfer_ring->cycle;
- input_ctx->ep0.averagetrblen = 0x8;
- usb_dev->input_ctx = (xhci_input_ctx_t*)input_ctx;
-
- } else {
- xhci_input_ctx64_t* input_ctx = (xhci_input_ctx64_t*)Other::toVirt(addr);
-
- memset(input_ctx,0,4096);
- input_ctx->input_ctx.A = (1 << 0) | (1 << 1);
- input_ctx->slot.contextentries = 1;
- input_ctx->slot.speed = (load_portsc & 0x3C00) >> 10;
- input_ctx->slot.porthubnum = portnum + 1;
- input_ctx->ep0.endpointtype = 4;
- input_ctx->ep0.cerr = 3;
- input_ctx->ep0.maxpacketsize = speed;
- input_ctx->ep0.base = usb_dev->transfer_ring->phys | usb_dev->transfer_ring->cycle;
- input_ctx->ep0.averagetrblen = 8;
-
- usb_dev->input_ctx = (xhci_input_ctx_t*)input_ctx;
-
- }
-
- int status_addr = __xhci_set_addr(dev,addr,id,0);
-
- if(status_addr == 0) {
- Log::Display(LEVEL_MESSAGE_WARN,"zero ret from xhci_set_addr (broken xhci ?)\n");
- } else if(status_addr != 1)
- return;
-
- xhci_usb_descriptor_t* descriptor = (xhci_usb_descriptor_t*)malloc(4096);
- int status2 = __xhci_get_usb_descriptor(dev,usb_dev,(void*)descriptor,8);
-
- if(!status2)
- return;
-
- ((xhci_input_ctx_t*)Other::toVirt(dev->dcbaa[id]))->ep0.maxpacketsize = descriptor->maxpacketsize;
-
- status2 = __xhci_get_usb_descriptor(dev,usb_dev,(void*)descriptor,descriptor->head.len);
- if(!status2)
- return;
- usb_dev->desc = descriptor;
-
- usb_dev->type = 0;
-
- if(!speed) {
- Log::Display(LEVEL_MESSAGE_FAIL,"Broken USB Device/Firmware, can't continue work. skipping\n");
- return;
- }
-
- char product[1024];
- char manufacter[1024];
-
- memset(product,0,1024);
- memset(manufacter,0,1024);
-
- int status4 = __xhci_print_device_info(dev,usb_dev,product,manufacter);
- if(!status4)
- return;
-
- xhci_config_descriptor_t* cfg = (xhci_config_descriptor_t*)malloc(4096);
- usb_dev->config = cfg;
-
- __xhci_get_config_descriptor(dev,usb_dev,cfg);
-
- __xhci_setup_config(dev,usb_dev,cfg->configval);
-
- if(!context_size) {
- usb_dev->input_ctx->input_ctx.A = (1 << 0);
- } else {
- xhci_input_ctx64_t* input = (xhci_input_ctx64_t*)Other::toVirt(addr);
- input->input_ctx.A = (1 << 0);
- }
-
- uint16_t i = 0;
- while(i < (cfg->len - cfg->head.len)) {
- xhci_usb_descriptor_header* current = (xhci_usb_descriptor_header*)(&cfg->data[i]);
- //INFO("Found descriptor with type %d (0x%p) and len %d (i %d)!\n",current->type,current->type,current->len,i);
-
- xhci_interface_t* inter = new xhci_interface_t;
- inter->type = current->type;
- inter->data = current;
- memset(inter,0,sizeof(xhci_interface_t));
- if(!usb_dev->interface)
- usb_dev->interface = inter;
- else {
- inter->next = usb_dev->interface;
- usb_dev->interface = inter;
- }
-
- switch(current->type) {
-
- case 0x04: {
- xhci_interface_descriptor_t* interface = (xhci_interface_descriptor_t*)current;
- //INFO("interface interclass %d, interface intersubclass %d, protocol %d\n",interface->interclass,interface->intersubclass,interface->protocol);
- if(interface->interclass == 3 && interface->intersubclass == 1 && !usb_dev->type) {
- switch(interface->protocol) {
- case 2: {
- usb_dev->type = USB_TYPE_MOUSE;
- break;
- }
-
- case 1: {
- usb_dev->type = USB_TYPE_KEYBOARD;
- break;
- }
- }
- }
- break;
- }
-
- case 0x21: {
- xhci_hid_descriptor_t* hid = (xhci_hid_descriptor_t*)current;
- for(int i = 0; i < hid->numdesc;i++) {
- xhci_hid_sub_desc* desc = &hid->desc[i];
- if(desc->desctype == 0x22) {
-
- xhci_interface_t* need_interface = usb_dev->interface;
- while(need_interface) {
- if(need_interface->type = 0x04)
- break;
- need_interface = need_interface->next;
- }
-
- if(!need_interface)
- continue;
-
- need_interface->buffer = malloc(desc->desclen + 1);
- memset(need_interface->buffer,0,desc->desclen + 1);
- need_interface->len = desc->desclen;
-
- xhci_interface_descriptor_t* interface = (xhci_interface_descriptor_t*)need_interface;
-
- __xhci_set_boot_protocol(dev,usb_dev,interface->num);
- __xhci_get_hid_report(dev,usb_dev,0,interface->num,need_interface->buffer,need_interface->len);
-
- }
- }
- break;
- }
- // __xhci_setup_port_ring(256,slotid);
- case 0x05: {
- xhci_endpoint_descriptor_t* ep = (xhci_endpoint_descriptor_t*)current;
-
- int idx = ((ep->endpointaddr >> 7) & 1) + ((ep->endpointaddr & 0x0F) << 1);
- usb_dev->main_ep = idx;
- idx -= 2;
- usb_dev->ep_ctx[idx] = __xhci_setup_port_ring(256,usb_dev->slotid);
-
- usb_dev->buffers_need_size[idx] = ep->maxpacketsize;
-
- usb_dev->phys_buffers[idx] = memory::pmm::_physical::alloc(4096);
- usb_dev->buffers[idx] = (uint8_t*)Other::toVirt(usb_dev->phys_buffers[idx]);
- usb_dev->doorbell_values[idx] = idx + 2;
-
- if(!context_size) {
- xhci_input_ctx_t* input = (xhci_input_ctx_t*)Other::toVirt(addr);
- xhci_endpoint_ctx_t* ep1 = &input->ep[idx];
- memset(ep1,0,sizeof(xhci_endpoint_ctx_t));
- usb_dev->input_ctx->input_ctx.A |= (1 << (idx + 2));
-
- input->slot.contextentries += 2;
- ep1->state = 0;
- ep1->endpointtype = __xhci_ep_to_type(ep);
- ep1->maxpacketsize = ep->maxpacketsize;
- ep1->some_shit_with_long_name_lo = ep->maxpacketsize;
- ep1->cerr = 3;
- ep1->maxburstsize = 0;
- ep1->averagetrblen = ep->maxpacketsize;
- ep1->base = usb_dev->ep_ctx[idx]->phys | usb_dev->ep_ctx[idx]->cycle;
- uint8_t port_speed = (load_portsc & 0x3C00) >> 10;
- uint8_t interval = ep->interval;
- uint8_t epty = ep1->endpointtype;
-
- /* thanks n00byedge for tips */
-
- if(port_speed == XHCI_USB_SPEED_HIGH_SPEED || port_speed == XHCI_USB_SPEED_SUPER_SPEED || port_speed == XHCI_USB_SPEED_SUPER_SPEED_PLUS)
- ep1->interval = interval - 1;
- else if(port_speed == XHCI_USB_SPEED_FULL_SPEED && (epty == XHCI_ENDPOINTTYPE_ISOCHRONOUS_IN || epty == XHCI_ENDPOINTTYPE_ISOCHRONOUS_OUT))
- ep1->interval = interval + 2;
- else if((port_speed == XHCI_USB_SPEED_FULL_SPEED || port_speed == XHCI_USB_SPEED_LOW_SPEED) && (epty == XHCI_ENDPOINTTYPE_INTERRUPT_IN || epty == XHCI_ENDPOINTTYPE_INTERRUPT_OUT)) {
- ep1->interval = log2(interval) + 4;
- }
-
-
- } else {
- xhci_input_ctx64_t* input = (xhci_input_ctx64_t*)Other::toVirt(addr);
- xhci_endpoint_ctx_t* ep1 = (xhci_endpoint_ctx_t*)(&input->ep[idx]);
- memset(ep1,0,sizeof(xhci_endpoint_ctx_t));
-
- input->slot.contextentries += 2;
- input->input_ctx.A |= (1 << (idx + 2));
- ep1->state = 0;
- ep1->endpointtype = __xhci_ep_to_type(ep);
- ep1->maxpacketsize = ep->maxpacketsize;
- ep1->some_shit_with_long_name_lo = ep->maxpacketsize;
- ep1->cerr = 3;
- ep1->maxburstsize = 0;
- ep1->averagetrblen = ep->maxpacketsize;
- ep1->base = (uint64_t)usb_dev->ep_ctx[idx]->phys | usb_dev->ep_ctx[idx]->cycle;
- uint8_t port_speed = (load_portsc & 0x3C00) >> 10;
- uint8_t interval = ep->interval;
- uint8_t epty = ep1->endpointtype;
-
- if(port_speed == XHCI_USB_SPEED_HIGH_SPEED || port_speed == XHCI_USB_SPEED_SUPER_SPEED || port_speed == XHCI_USB_SPEED_SUPER_SPEED_PLUS)
- ep1->interval = interval - 1;
- else if(port_speed == XHCI_USB_SPEED_FULL_SPEED && (epty == XHCI_ENDPOINTTYPE_ISOCHRONOUS_IN || epty == XHCI_ENDPOINTTYPE_ISOCHRONOUS_OUT))
- ep1->interval = interval + 2;
- else if((port_speed == XHCI_USB_SPEED_FULL_SPEED || port_speed == XHCI_USB_SPEED_LOW_SPEED) && (epty == XHCI_ENDPOINTTYPE_INTERRUPT_IN || epty == XHCI_ENDPOINTTYPE_INTERRUPT_OUT)) {
- ep1->interval = log2(interval) + 4;
- }
- }
-
- break;
- }
- }
-
- i += current->len;
- }
-
- xhci_configure_endpoints_trb_t ep_trb;
- memset(&ep_trb,0,sizeof(xhci_trb_t));
-
- ep_trb.info_s.type = 12;
- ep_trb.base = addr;
- ep_trb.info_s.slot = usb_dev->slotid;
-
- __xhci_clear_event(dev);
-
- __xhci_command_ring_queue(dev,dev->com_ring,(xhci_trb_t*)&ep_trb);
- __xhci_doorbell(dev,0);
- drivers::tsc::sleep(5000);
-
- xhci_trb_t ret = __xhci_event_wait(dev,TRB_COMMANDCOMPLETIONEVENT_TYPE);
-
- if(ret.ret_code > 1) {
- Log::Display(LEVEL_MESSAGE_FAIL,"Can't configure endpoints for port %d (ret %d base %p), context_size: %d, given addr %p\n",portnum,ret.ret_code,ret.base,usb_dev->_is64byte,ep_trb.base);
- return;
- } else if(ret.ret_code == 0) {
- Log::Display(LEVEL_MESSAGE_WARN,"Endpoint configure TRB ret_code is 0 (it shouldn't)\n");
- }
-
- __xhci_ask_for_help_hid(dev,usb_dev);
-
- drivers::tsc::sleep(1000);
-
- Log::Display(LEVEL_MESSAGE_INFO,"Found USB%s Device %s (%d, %d, %d) %s %s on port %d and slot %d\n",dev->usb3ports[portnum] == 1 ? "3.0" : "2.0",((load_portsc & 0x3C00) >> 10) < 7 ? speed_to_str[(load_portsc & 0x3C00) >> 10] : "Broken (0 MB/S - USB ?)",(load_portsc & 0x3C00) >> 10,speed,descriptor->maxpacketsize,manufacter,product,portnum,usb_dev->slotid);
-
- char buffer[2048];
- memset(buffer,0,2048);
- __printfbuf(buffer,2048,"%s %s",manufacter, product);
-
- usb_dev->evdev_num = vfs::evdev::create(buffer,usb_dev->type == USB_TYPE_KEYBOARD ? EVDEV_TYPE_KEYBOARD : EVDEV_TYPE_MOUSE);
-
-}
-
-void __xhci_init_ports(xhci_device_t* dev) {
- for(int i = 0;i <= dev->max_ports;i++) {
- __xhci_init_dev(dev,i);
- }
-}
-
-void __xhci_iterate_usb_ports(xhci_device_t* dev) {
-
- volatile uint32_t* cap = (volatile uint32_t*)(dev->xhci_virt_base + dev->cap->hccparams1.xECP * 4);
-
- xhci_ext_cap_t load_cap;
- load_cap.full = *cap;
- //INFO("0x%p\n",cap);
- while(1) {
- //INFO("Found cap with id %d\n",load_cap.id);
-
- if(load_cap.id == 2) {
-
- xhci_usb_cap_t usb_cap;
-
- usb_cap.firsthalf = cap[0];
- usb_cap.name = cap[1];
- usb_cap.thirdhalf = cap[2];
- usb_cap.fourhalf = cap[3];
-
- if(usb_cap.major == 3) {
- for(uint8_t i = usb_cap.portoffset - 1;i <= (usb_cap.portoffset - 1) + usb_cap.portcount - 1;i++) {
- dev->usb3ports[i] = 1;
- //Log::Display(LEVEL_MESSAGE_INFO,"Found USB 3.0 Port %d !\n",i);
- }
- } else {
- for(uint8_t i = usb_cap.portoffset - 1;i <= (usb_cap.portoffset - 1) + usb_cap.portcount - 1;i++) {
- dev->usb3ports[i] = 0;
- //Log::Display(LEVEL_MESSAGE_INFO,"Found USB 2.0 Port %d !\n",i);
- }
- }
-
- } else if(load_cap.id == 1) {
- *((uint32_t*)((uint64_t)cap + 4)) &= ~((1 << 0) | (1 << 13) | (1 << 4) | (1 << 14) | (1 << 15));
- *cap |= (1 << 24);
-
- drivers::tsc::sleep(500 * 1000);
-
- }
-
-
-
- if(!load_cap.nextcap)
- break;
-
-
- cap = (uint32_t*)((uint64_t)cap + (load_cap.nextcap * 4));
- load_cap.full = *cap;
-
- }
-}
-
-xhci_hid_driver_t* hid_drv = 0;
-
-void xhci_hid_register(void (*func)(xhci_usb_device_t* usbdev,xhci_done_trb_t* trb),int type) {
- xhci_hid_driver_t* drv = new xhci_hid_driver_t;
- drv->func = func;
- drv->type = type;
-
- if(!hid_drv)
- hid_drv = drv;
- else {
- drv->next = hid_drv;
- hid_drv = drv;
- }
-}
-
-void __xhci_process_fetch(xhci_device_t* dev) {
- xhci_event_ring_ctx_t* father = dev->event_ring;
- xhci_trb_t* buffer[1024];
-
- xhci_usb_device_t* usbdev = usbdevs;
-
- while(1) {
- //Paging::EnableKernel();
- int count = 0;
- memset(buffer,0,sizeof(xhci_trb_t*) * 1024);
- if(get_trb(father,father->queue).info_s.cycle == father->cycle)
- count = __xhci_event_receive(dev,father,buffer);
-
- if(!count) {
- asm volatile("cli");
- yield();
- asm volatile("sti");
- }
-
- if(count) {
- xhci_trb_t* current = 0;
- for(int i = 0;i < count;i++) {
- current = buffer[i];
- switch(current->info_s.type) {
- case TRB_TRANSFEREVENT_TYPE: {
- xhci_usb_device_t* usbdev = usbdevs;
- xhci_done_trb_t* trb = (xhci_done_trb_t*)current;
- while(usbdev) {
- if(usbdev->dev == dev) {
- if(usbdev->slotid == trb->info_s.slot) {
- xhci_hid_driver_t* drv = hid_drv;
- while(drv) {
- if(drv->type == usbdev->type)
- drv->func(usbdev,trb);
- drv = drv->next;
- }
- __xhci_ask_for_help_hid(dev,usbdev);
- }
- }
- usbdev = usbdev->next;
- }
- break;
- }
- default: {
- Log::Display(LEVEL_MESSAGE_WARN,"xhci unsupported trb: %d\n",current->info_s.type);
- }
- }
- }
- }
-
- }
-}
-
-void __xhci_device(pci_t pci_dev,uint8_t a, uint8_t b,uint8_t c) {
- if(pci_dev.progIF != 0x30) {
- //INFO("Current USB device with progIF 0x%p is not XHCI !\n",pci_dev.progIF);
- return;
- }
-
- xhci_device_t* dev = (xhci_device_t*)malloc(4096);
- memset(dev,0,4096);
-
- uint32_t usb3_ports = drivers::pci::in(a,b,c,0xDC,4);
- drivers::pci::out(a,b,c,0xD8,usb3_ports,4);
-
- auto usb2_ports = drivers::pci::in(a,b,c,0xD4,4);
- drivers::pci::out(a,b,c,0xD0,usb2_ports,4);
-
- uint64_t addr = pci_dev.bar0 & ~4; // clear upper 2 bits
- addr |= ((uint64_t)pci_dev.bar1 << 32);
-
- dev->xhci_phys_base = addr;
- dev->xhci_virt_base = (uint64_t)memory::paging::maprangeret(addr,8 * PAGE_SIZE,PTE_RW | PTE_PRESENT); // map everything
-
- dev->cap = (xhci_cap_regs_t*)dev->xhci_virt_base;
- dev->op = (xhci_op_regs_t*)(dev->xhci_virt_base + dev->cap->caplength);
- dev->runtime = (xhci_runtime_regs_t*)(dev->xhci_virt_base + dev->cap->rtsoff);
- dev->doorbell = (uint32_t*)(dev->xhci_virt_base + dev->cap->dboff);
-
- __xhci_put_new_device(dev);
- if(dev->op->usbcmd & XHCI_USBCMD_RS) { // wtf how does it running
- uint16_t timeout = XHCI_RESET_TIMEOUT;
- //INFO("XHCI is already running, stopping it.\n");
- dev->op->usbcmd &= ~(XHCI_USBCMD_RS);
- drivers::tsc::sleep(20 * 1000);
- while(!(dev->op->usbsts & (1 << 0))) {
- if(!timeout) {
- Log::Raw("Can't disable XHCI. Ignoring\n");
- return;
- }
- drivers::tsc::sleep(20 * 1000);
- timeout = timeout - 1;
- }
- }
- //DEBUG("Resetting XHCI device\n");
- __xhci_reset(dev);
-
- dev->calculated_scratchpad_count = (uint16_t)((dev->cap->hcsparams2.max_scratchpad_hi << 5) | dev->cap->hcsparams2.max_scratchpad_lo);
-
- uint32_t hcsparams1 = *(uint32_t*)(&dev->cap->hcsparams1);
-
- dev->max_ports = ((volatile hcsparams1_t*)&hcsparams1)->maxports;
-
- //INFO("Configuring XHCI OPER\n");
- __xhci_setup_op(dev);
- //INFO("Configuring XHCI Runtime\n");
- __xhci_setup_run(dev);
- //INFO("Starting XHCI Device\n");
- __xhci_enable(dev);
- //INFO("Iterating USB Ports\n");
- __xhci_iterate_usb_ports(dev);
- //INFO("Configuring XHCI Ports\n");
- __xhci_init_ports(dev);
-
- // int pid = fork();
- // if(pid == 0)
- // __xhci_process_fetch(dev);
-
- arch::x86_64::scheduling::create_kernel_thread((void (*)(void*))__xhci_process_fetch,(void*)dev);
- Log::Display(LEVEL_MESSAGE_OK,"XHCI initializied\n");
-
-
-}
-
-char hid_to_ps2_layout[0x48];
-
-int input0_fd = 0;
-int mouse_fd = 0;
-
-void hid_layout_init() {
- hid_to_ps2_layout[0x04] = 0x1E;
- hid_to_ps2_layout[0x05] = 0x30;
- hid_to_ps2_layout[0x06] = 0x2E;
- hid_to_ps2_layout[0x07] = 0x20;
- hid_to_ps2_layout[0x08] = 0x12;
- hid_to_ps2_layout[0x09] = 0x21;
- hid_to_ps2_layout[0x0A] = 0x22;
- hid_to_ps2_layout[0x0B] = 0x23;
- hid_to_ps2_layout[0x0C] = 0x17;
- hid_to_ps2_layout[0x0D] = 0x24;
- hid_to_ps2_layout[0x0E] = 0x25;
- hid_to_ps2_layout[0x0F] = 0x26;
- hid_to_ps2_layout[0x10] = 0x32;
- hid_to_ps2_layout[0x11] = 0x31;
- hid_to_ps2_layout[0x12] = 0x18;
- hid_to_ps2_layout[0x13] = 0x19;
- hid_to_ps2_layout[0x14] = 0x10;
- hid_to_ps2_layout[0x15] = 0x13;
- hid_to_ps2_layout[0x16] = 0x1F;
- hid_to_ps2_layout[0x17] = 0x14;
- hid_to_ps2_layout[0x18] = 0x16;
- hid_to_ps2_layout[0x19] = 0x2F;
- hid_to_ps2_layout[0x1A] = 0x11;
- hid_to_ps2_layout[0x1B] = 0x2D;
- hid_to_ps2_layout[0x1C] = 0x15;
- hid_to_ps2_layout[0x1D] = 0x2C;
- hid_to_ps2_layout[0x1E] = 0x02;
- hid_to_ps2_layout[0x1F] = 0x03;
- hid_to_ps2_layout[0x20] = 0x04;
- hid_to_ps2_layout[0x21] = 0x05;
- hid_to_ps2_layout[0x22] = 0x06;
- hid_to_ps2_layout[0x23] = 0x07;
- hid_to_ps2_layout[0x24] = 0x08;
- hid_to_ps2_layout[0x25] = 0x09;
- hid_to_ps2_layout[0x26] = 0x0A;
- hid_to_ps2_layout[0x27] = 0x0B;
- hid_to_ps2_layout[0x28] = 0x1C;
- hid_to_ps2_layout[0x29] = 0x01;
- hid_to_ps2_layout[0x2A] = 0x0E;
- hid_to_ps2_layout[0x2B] = 0x0F;
- hid_to_ps2_layout[0x2C] = 0x39;
- hid_to_ps2_layout[0x2D] = 0x0C;
- hid_to_ps2_layout[0x2E] = 0x0D;
- hid_to_ps2_layout[0x2F] = 0x1A;
- hid_to_ps2_layout[0x30] = 0x1B;
- hid_to_ps2_layout[0x31] = 0x2B;
- hid_to_ps2_layout[0x32] = 0x2B;
- hid_to_ps2_layout[0x33] = 0x27;
- hid_to_ps2_layout[0x34] = 0x28;
- hid_to_ps2_layout[0x35] = 0x29;
- hid_to_ps2_layout[0x36] = 0x33;
- hid_to_ps2_layout[0x37] = 0x34;
- hid_to_ps2_layout[0x38] = 0x35;
- hid_to_ps2_layout[0x39] = 0x3A;
- hid_to_ps2_layout[0x3B] = 0x3C;
- hid_to_ps2_layout[0x3C] = 0x3D;
- hid_to_ps2_layout[0x3D] = 0x3E;
- hid_to_ps2_layout[0x3E] = 0x3F;
- hid_to_ps2_layout[0x3F] = 0x40;
- hid_to_ps2_layout[0x40] = 0x41;
- hid_to_ps2_layout[0x41] = 0x42;
- hid_to_ps2_layout[0x42] = 0x43;
- hid_to_ps2_layout[0x43] = 0x44;
- hid_to_ps2_layout[0x44] = 0x57;
- hid_to_ps2_layout[0x45] = 0x58;
- hid_to_ps2_layout[0x46] = 0x00;
- hid_to_ps2_layout[0x47] = 0x46;
-}
-
-void input_send(int num, uint8_t key) {
- userspace_fd_t fd;
- memset(&fd,0,sizeof(userspace_fd_t));
- memcpy(fd.path,"/dev/masterps2keyboard",strlen("/dev/masterps2keyboard"));
- fd.is_cached_path = 1;
-
- std::uint64_t current_nano = drivers::tsc::currentnano();
-
- asm volatile("cli");
- input_event ev;
- ev.time.tv_sec = current_nano / 1000000000;
- ev.time.tv_usec = (current_nano & 1000000000) / 1000;
- ev.type = 1;
- ev.code = key & ~(1 << 7);
- ev.value = (key & (1 << 7)) ? 0 : 1;
- vfs::evdev::submit(num,ev);
- vfs::vfs::write(&fd,&key,1);
- asm volatile("sti");
-}
-
-uint8_t hid_mods_to_ps2[8] = {
- 0x1D,
- 0x2A,
- 0x38,
- 0x5B,
- 0x1D,
- 0x36,
- 0x38,
- 0x5C
-};
-
-void __usbkeyboard_handler(xhci_usb_device_t* usbdev, xhci_done_trb_t* trb) {
- uint8_t* data = usbdev->buffers[trb->info_s.ep_id - 2];
- uint8_t mods = data[0];
- uint8_t prev_mods = usbdev->add_buffer[0];
-
- for (int i = 0; i < 8; i++) {
- uint8_t mask = 1 << i;
- if ((mods & mask) && !(prev_mods & mask)) {
- if (i >= 4) input_send(usbdev->evdev_num, 0xE0);
- input_send(usbdev->evdev_num, hid_mods_to_ps2[i]);
- } else if (!(mods & mask) && (prev_mods & mask)) {
- if (i >= 4) input_send(usbdev->evdev_num, 0xE0);
- input_send(usbdev->evdev_num, hid_mods_to_ps2[i] | 0x80);
- }
- }
-
- for (int i = 2; i < 8; i++) {
- int isPressed = 0;
- for (int j = 2; j < 8; j++) {
- if (usbdev->add_buffer[j] == data[i]) {
- isPressed = 1;
- break;
- }
- }
- if (!isPressed && data[i] != 0) {
- if (data[i] < 0x47) {
- input_send(usbdev->evdev_num, hid_to_ps2_layout[data[i]]);
- } else if(data[i] == 0x4F) {
- input_send(usbdev->evdev_num, 0xE0);
- input_send(usbdev->evdev_num, 0x4D);
- } else if(data[i] == 0x50) {
- input_send(usbdev->evdev_num, 0xE0);
- input_send(usbdev->evdev_num, 0x4B);
- } else if(data[i] == 0x51) {
- input_send(usbdev->evdev_num, 0xE0);
- input_send(usbdev->evdev_num, 0x50);
- } else if(data[i] == 0x52) {
- input_send(usbdev->evdev_num, 0xE0);
- input_send(usbdev->evdev_num, 0x48);
- }
- }
- }
-
- for (int i = 2; i < 8; i++) {
- int isStillPressed = 0;
- for (int j = 2; j < 8; j++) {
- if (usbdev->add_buffer[i] == data[j]) {
- isStillPressed = 1;
- break;
- }
- }
- if (!isStillPressed && usbdev->add_buffer[i] != 0) {
- input_send(usbdev->evdev_num, hid_to_ps2_layout[usbdev->add_buffer[i]] | 0x80);
- } else if(usbdev->add_buffer[i] == 0x4F) {
- input_send(usbdev->evdev_num, 0xE0 | 0x80);
- input_send(usbdev->evdev_num, 0x4D | 0x80);
- } else if(usbdev->add_buffer[i] == 0x50) {
- input_send(usbdev->evdev_num, 0xE0 | 0x80);
- input_send(usbdev->evdev_num, 0x4B | 0x80);
- } else if(usbdev->add_buffer[i] == 0x51) {
- input_send(usbdev->evdev_num, 0xE0 | 0x80);
- input_send(usbdev->evdev_num, 0x50 | 0x80);
- } else if(usbdev->add_buffer[i] == 0x52) {
- input_send(usbdev->evdev_num, 0xE0 | 0x80);
- input_send(usbdev->evdev_num, 0x48 | 0x80);
- }
- }
-
- memcpy(usbdev->add_buffer, data, 8);
-}
-
-
-#define MOUSE_LB (1 << 0)
-#define MOUSE_RB (1 << 1)
-#define MOUSE_MB (1 << 2)
-#define MOUSE_B4 (1 << 3)
-#define MOUSE_B5 (1 << 4)
-
-/*
-input0_fd = open("/dev/masterps2keyboard",O_RDWR);
- mouse_fd = open("/dev/mastermouse",O_RDWR);
-*/
-
-#define REL_X 0x00
-#define REL_Y 0x01
-#define REL_Z 0x02
-#define REL_RX 0x03
-#define REL_RY 0x04
-#define REL_RZ 0x05
-#define REL_HWHEEL 0x06
-#define REL_DIAL 0x07
-#define REL_WHEEL 0x08
-#define REL_MISC 0x09
-
-void __usbmouse_handler(xhci_usb_device_t* usbdev, xhci_done_trb_t* trb) {
- uint8_t* data = usbdev->buffers[trb->info_s.ep_id - 2];
-
- mouse_packet_t packet;
-
- packet.buttons = 0;
-
- packet.buttons |= (data[0] & (1 << 0)) ? MOUSE_LB : 0;
- packet.buttons |= (data[0] & (1 << 1)) ? MOUSE_RB : 0;
- packet.buttons |= (data[0] & (1 << 2)) ? MOUSE_MB : 0;
-
- packet.x = data[1];
- packet.y = -data[2];
- packet.z = 0; // todo: figure out how to get mouse scroll wheel data
-
- userspace_fd_t fd;
- memset(&fd,0,sizeof(userspace_fd_t));
- memcpy(fd.path,"/dev/mastermouse",strlen("/dev/mastermouse"));
- fd.is_cached_path = 1;
-
- asm volatile("cli");
- std::uint64_t current_nano = drivers::tsc::currentnano();
- input_event ev;
- ev.time.tv_sec = current_nano / 1000000000;
- ev.time.tv_usec = (current_nano & 1000000000) / 1000;
- if(packet.x) {
- ev.code = REL_X;
- ev.type = 2;
- ev.value = (packet.x & 0x80) ? (packet.x | 0xFFFFFF00) : packet.x;
- vfs::evdev::submit(usbdev->evdev_num,ev);
- }
-
- if(packet.y) {
- ev.code = REL_Y;
- ev.type = 2;
- ev.value = (packet.y & 0x80) ? (packet.y | 0xFFFFFF00) : packet.y;
- vfs::evdev::submit(usbdev->evdev_num,ev);
- }
-
- if(packet.z) {
- ev.code = REL_Z;
- ev.type = 2;
- ev.value = (packet.z & 0x80) ? (packet.z | 0xFFFFFF00) : packet.z;
- vfs::evdev::submit(usbdev->evdev_num,ev);
- }
-
- if((packet.buttons & MOUSE_LB) && !(usbdev->last_pack.buttons & MOUSE_LB)) {
- ev.code = 272;
- ev.type = 1;
- ev.value = 1;
- vfs::evdev::submit(usbdev->evdev_num,ev);
- } else if(!(packet.buttons & MOUSE_LB) && (usbdev->last_pack.buttons & MOUSE_LB)) {
- ev.code = 272;
- ev.type = 1;
- ev.value = 0;
- vfs::evdev::submit(usbdev->evdev_num,ev);
- }
-
- if((packet.buttons & MOUSE_RB) && !(usbdev->last_pack.buttons & MOUSE_RB)) {
- ev.code = 273;
- ev.type = 1;
- ev.value = 1;
- vfs::evdev::submit(usbdev->evdev_num,ev);
- } else if(!(packet.buttons & MOUSE_RB) && (usbdev->last_pack.buttons & MOUSE_RB)) {
- ev.code = 273;
- ev.type = 1;
- ev.value = 0;
- vfs::evdev::submit(usbdev->evdev_num,ev);
- }
-
- if((packet.buttons & MOUSE_MB) && !(usbdev->last_pack.buttons & MOUSE_MB)) {
- ev.code = 274;
- ev.type = 1;
- ev.value = 1;
- vfs::evdev::submit(usbdev->evdev_num,ev);
- } else if(!(packet.buttons & MOUSE_MB) && (usbdev->last_pack.buttons & MOUSE_MB)) {
- ev.code = 274;
- ev.type = 1;
- ev.value = 0;
- vfs::evdev::submit(usbdev->evdev_num,ev);
- }
-
- asm volatile("sti");
-
- usbdev->last_pack = packet;
-
- drivers::tsc::sleep(1000); // actually hid wants this only after 1 ms
-
-}
-
-#include <drivers/pci.hpp>
-
-int xhci_init() {
-
- xhci_hid_register(__usbkeyboard_handler,USB_TYPE_KEYBOARD);
- xhci_hid_register(__usbmouse_handler,USB_TYPE_MOUSE);
-
- hid_layout_init();
-
- drivers::pci::reg(__xhci_device,0x0C,0x03);
- return 0;
-} \ No newline at end of file
diff --git a/kernel/src/etc/bootloaderinfo.cpp b/kernel/src/etc/bootloaderinfo.cpp
deleted file mode 100644
index 50fb856..0000000
--- a/kernel/src/etc/bootloaderinfo.cpp
+++ /dev/null
@@ -1,105 +0,0 @@
-
-#include <etc/bootloaderinfo.hpp>
-
-#include <etc/logging.hpp>
-
-#include <limine.h>
-#include <cstdint>
-
-namespace {
-
-__attribute__((used, section(".limine_requests")))
-volatile LIMINE_BASE_REVISION(3);
-
-}
-
-namespace {
-
-__attribute__((used, section(".limine_requests")))
-volatile limine_framebuffer_request framebuffer_request = {
- .id = LIMINE_FRAMEBUFFER_REQUEST,
- .revision = 0,
- .response = nullptr
-};
-
-__attribute__((used, section(".limine_requests")))
-volatile limine_hhdm_request hhdm_request = {
- .id = LIMINE_HHDM_REQUEST,
- .revision = 0,
- .response = nullptr
-};
-
-__attribute__((used, section(".limine_requests")))
-volatile limine_memmap_request memmap_request = {
- .id = LIMINE_MEMMAP_REQUEST,
- .revision = 0,
- .response = nullptr
-};
-
-__attribute__((used, section(".limine_requests")))
-volatile limine_rsdp_request rsdp_request = {
- .id = LIMINE_RSDP_REQUEST,
- .revision = 0,
- .response = nullptr
-};
-
-__attribute__((used, section(".limine_requests")))
-volatile limine_executable_address_request keraddr_request = {
- .id = LIMINE_EXECUTABLE_ADDRESS_REQUEST,
- .revision = 0,
- .response = nullptr
-};
-
-__attribute__((used, section(".limine_requests")))
-volatile limine_module_request initrd_request = {
- .id = LIMINE_MODULE_REQUEST,
- .revision = 0,
- .response = nullptr
-};
-
-__attribute__((used, section(".limine_requests")))
-volatile LIMINE_MP(request) smp_request = {
- .id = LIMINE_MP_REQUEST,
- .revision = 0,
- .response = nullptr
-};
-
-}
-
-namespace {
-
-__attribute__((used, section(".limine_requests_start")))
-volatile LIMINE_REQUESTS_START_MARKER;
-
-__attribute__((used, section(".limine_requests_end")))
-volatile LIMINE_REQUESTS_END_MARKER;
-
-}
-
-std::uint64_t BootloaderInfo::AccessRSDP() {
- return rsdp_request.response->address;
-}
-
-struct limine_framebuffer* BootloaderInfo::AccessFramebuffer() {
- return framebuffer_request.response->framebuffers[0];
-}
-
-std::uint64_t BootloaderInfo::AccessHHDM() {
- return hhdm_request.response->offset;
-}
-
-struct limine_memmap_response* BootloaderInfo::AccessMemoryMap() {
- return memmap_request.response;
-}
-
-struct limine_executable_address_response* BootloaderInfo::AccessKernel() {
- return keraddr_request.response;
-}
-
-struct LIMINE_MP(response)* BootloaderInfo::AccessMP() {
- return smp_request.response;
-}
-
-struct limine_module_response* BootloaderInfo::AccessInitrd() {
- return initrd_request.response;
-} \ No newline at end of file
diff --git a/kernel/src/etc/libc.cpp b/kernel/src/etc/libc.cpp
deleted file mode 100644
index 60f87ca..0000000
--- a/kernel/src/etc/libc.cpp
+++ /dev/null
@@ -1,4 +0,0 @@
-
-#include <cstdint>
-
-#include <etc/libc.hpp>
diff --git a/kernel/src/etc/logging.cpp b/kernel/src/etc/logging.cpp
deleted file mode 100644
index ee5e7cf..0000000
--- a/kernel/src/etc/logging.cpp
+++ /dev/null
@@ -1,221 +0,0 @@
-
-#include <etc/bootloaderinfo.hpp>
-#include <etc/logging.hpp>
-
-#define NANOPRINTF_USE_FIELD_WIDTH_FORMAT_SPECIFIERS 1
-#define NANOPRINTF_USE_PRECISION_FORMAT_SPECIFIERS 1
-#define NANOPRINTF_USE_LARGE_FORMAT_SPECIFIERS 1
-#define NANOPRINTF_USE_SMALL_FORMAT_SPECIFIERS 1
-#define NANOPRINTF_USE_FLOAT_FORMAT_SPECIFIERS 0
-#define NANOPRINTF_USE_BINARY_FORMAT_SPECIFIERS 1
-#define NANOPRINTF_USE_WRITEBACK_FORMAT_SPECIFIERS 0
-#define NANOPRINTF_IMPLEMENTATION
-#include <lib/nanoprintf.h>
-
-#include <etc/libc.hpp>
-
-#include <drivers/serial.hpp>
-
-#include <generic/locks/spinlock.hpp>
-
-#include <stddef.h>
-#include <stdarg.h>
-
-int __snprintf(char *buffer, size_t bufsz, char const *fmt, va_list vlist) {
- int const rv = npf_vsnprintf(buffer, bufsz, fmt, vlist);
- return rv;
-}
-
-Log LogObject;
-uint32_t default_fg = 0xFFFFFFFF;
-uint32_t default_fg_bright = 0xFFFFFFFF;
-
-locks::spinlock log_lock;
-#include <etc/font.hpp>
-
-extern "C" void* __flanterm_malloc(size_t size) {
- return malloc(size);
-}
-
-extern "C" void __flanterm_free(void* ptr,size_t size) {
- free(ptr);
-}
-
-
-void Log::Init() {
- struct limine_framebuffer* fb0 = BootloaderInfo::AccessFramebuffer();
- struct flanterm_context *ft_ctx = flanterm_fb_init(
- __flanterm_malloc,
- __flanterm_free,
- (uint32_t*)fb0->address, fb0->width, fb0->height, fb0->pitch,
- fb0->red_mask_size, fb0->red_mask_shift,
- fb0->green_mask_size, fb0->green_mask_shift,
- fb0->blue_mask_size, fb0->blue_mask_shift,
- NULL,
- NULL, NULL,
- NULL, &default_fg,
- NULL, &default_fg_bright,
- (void*)unifont_arr, FONT_WIDTH, FONT_HEIGHT, 0,
- 1, 1, 0
- );
- LogObject.Setup(ft_ctx);
-
-}
-
-const char* level_messages[] = {
- [LEVEL_MESSAGE_OK] = "[ \x1b[38;2;0;255;0mOK\033[0m ] ",
- [LEVEL_MESSAGE_FAIL] = "[ \x1b[38;2;255;0;0mFAILED\033[0m ] ",
- [LEVEL_MESSAGE_WARN] = "[ \x1b[38;2;255;165;0mWARN\033[0m ] ",
- [LEVEL_MESSAGE_INFO] = "[ \x1b[38;2;0;191;255mINFO\033[0m ] "
-};
-
-int __printfbuf(char* buffer, size_t bufsf, char const* fmt, ...) {
- va_list val;
- va_start(val, fmt);
- return __snprintf(buffer,bufsf,fmt,val);
- va_end(val);
-}
-
-void Log::RawDisp(char* buffer, int len) {
- LogObject.Write(buffer,len);
-}
-
-void Log::SerialDisplay(int level,char* msg,...) {
- log_lock.lock();
- va_list val;
- va_start(val, msg);
- char buffer[512];
- memset(buffer,0,512);
-
- drivers::serial serial(DEFAULT_SERIAL_PORT);
-
- serial.write((uint8_t*)level_messages[level],strlen(level_messages[level]));
- int len = __snprintf(buffer,512,msg,val);
- serial.write((uint8_t*)buffer,len);
- va_end(val);
- log_lock.unlock();
-}
-
-void Log::Display(int level,char* msg,...) {
- va_list val;
- va_start(val, msg);
- char buffer[4096];
- memset(buffer,0,4096);
- log_lock.lock();
- LogObject.Write((char*)level_messages[level],strlen(level_messages[level]));
- int len = __snprintf(buffer,4096,msg,val);
- LogObject.Write(buffer,len);
-
- drivers::serial serial(DEFAULT_SERIAL_PORT);
-
- serial.write((uint8_t*)level_messages[level],strlen(level_messages[level]));
- serial.write((uint8_t*)buffer,len);
-
- log_lock.unlock();
- va_end(val);
-}
-
-winsizez Log::GetDimensions() {
- struct winsizez buf;
-
- size_t cols = 0;
- size_t rows = 0;
- flanterm_get_dimensions(LogObject.ft_ctx0,&cols,&rows);
- buf.ws_col = cols;
- buf.ws_row = rows;
- return buf;
-}
-
-void Log::Raw(char* msg,...) {
- va_list val;
- va_start(val, msg);
- char buffer[4096];
- memset(buffer,0,4096);
- log_lock.lock();
- int len = __snprintf(buffer,4096,msg,val);
- LogObject.Write(buffer,len);
-
- drivers::serial serial(DEFAULT_SERIAL_PORT);
-
- serial.write((uint8_t*)buffer,len);
-
- log_lock.unlock();
- va_end(val);
-}
-
-#include <generic/mm/pmm.hpp>
-
-char* dmesg_buf = 0;
-std::uint64_t dmesg_size = 0;
-std::uint64_t dmesg_real_size = 0;
-
-std::uint64_t dmesg_bufsize() {
- return dmesg_size;
-}
-
-void dmesg_read(char* buffer,std::uint64_t count) {
- memset(buffer,0,count);
- memcpy(buffer,dmesg_buf,dmesg_size > count ? count : dmesg_size);
-}
-
-void dmesg0(char* msg,...) {
-
- if(!dmesg_buf) {
- dmesg_buf = (char*)memory::pmm::_virtual::alloc(4096);
- dmesg_real_size = 4096;
- }
-
- log_lock.lock();
-
- va_list val;
- va_start(val, msg);
- char buffer[4096];
- memset(buffer,0,4096);
- int len = __snprintf(buffer,4096,msg,val);
-
- drivers::serial serial(DEFAULT_SERIAL_PORT);
- serial.write((uint8_t*)buffer,len);
-
- uint64_t size = len;
-
- std::uint64_t offset = dmesg_size;
- std::uint64_t new_size = offset + size;
-
- if (new_size > dmesg_real_size) {
- alloc_t new_content0 = memory::pmm::_physical::alloc_ext(new_size);
- std::uint8_t* new_content = (std::uint8_t*)new_content0.virt;
- memcpy(new_content, dmesg_buf, dmesg_size);
- memory::pmm::_physical::free((std::uint64_t)dmesg_buf);
- dmesg_buf = (char*)new_content;
- dmesg_real_size = new_content0.real_size;
- }
-
- dmesg_size = new_size;
-
- memcpy(dmesg_buf + offset, buffer, size);
-
- dmesg_size += size;
-
- log_lock.unlock();
-
- va_end(val);
-}
-
-#include <arch/x86_64/interrupts/idt.hpp>
-
-extern void panic(int_frame_t* ctx, const char* msg);
-
-void panic_wrap(const char* msg,...) {
-
- va_list val;
- va_start(val, msg);
- char buffer[4096];
- memset(buffer,0,4096);
- log_lock.lock();
- int len = __snprintf(buffer,4096,msg,val);
-
- panic(0,buffer);
-
- log_lock.unlock();
- va_end(val);
-} \ No newline at end of file
diff --git a/kernel/src/gaster.txt b/kernel/src/gaster.txt
new file mode 100644
index 0000000..294ea7c
--- /dev/null
+++ b/kernel/src/gaster.txt
@@ -0,0 +1,22 @@
+
+ ++++++++ ++
+ +&&&&&&&&&&&&&&&&&+
+ +&&&&&&&&&&&&&&&&&&&+
+ +&x. .;&&&x++
+ &&&&.&&&&&. &&&&+
+ &::::&:::::&&&&+
+ &&&&.&&&&& .&
+ ++ ... . :&X .&+&&+
+ +++........ +&& .&&&&++
+ + & +$ &&&+
+ +&.&. Xx .&+
+ +&&&... . .&&&+
+ +$&&&&x;;;+x&&&&&+
+ +&&&&&&&+.;X&&&+&&&+
+ ++ +&+ +&&&&&&&&&&+ +&&+
+ +++ +&&&&&&&&+ +& +
+ ;&&&&&&;
+ +&... .+
+ +.&;:+
+
+ \ No newline at end of file
diff --git a/kernel/src/generic/arch.hpp b/kernel/src/generic/arch.hpp
new file mode 100644
index 0000000..7649b5b
--- /dev/null
+++ b/kernel/src/generic/arch.hpp
@@ -0,0 +1,35 @@
+#include <cstdint>
+
+#define PAGE_SIZE 4096
+#define PAGING_PRESENT (1 << 0)
+#define PAGING_RW (1 << 1)
+#define PAGING_USER (1 << 2)
+#define PAGING_NC (1 << 3)
+#define PAGING_WC (1 << 4)
+#define PTE_INDEX(address, bit) ((address & (uint64_t) 0x1FF << bit) >> bit)
+
+#define ARCH_INIT_EARLY 0
+#define ARCH_INIT_COMMON 1
+
+namespace arch {
+
+ extern void init(int stage);
+
+ extern void disable_interrupts();
+ extern void enable_interrupts();
+ extern void wait_for_interrupt();
+ extern void hcf();
+ extern void pause();
+ extern void tlb_flush(std::uintptr_t hint, std::uintptr_t len);
+ extern const char* name();
+
+ extern void enable_paging(std::uintptr_t root);
+ extern void map_page(std::uintptr_t root, std::uint64_t phys, std::uintptr_t virt, int flags);
+ extern std::uint64_t get_phys_from_page(std::uintptr_t root, std::uintptr_t virt);
+ extern void destroy_root(std::uintptr_t root, int level);
+ extern void copy_higher_half(std::uintptr_t root, std::uintptr_t src_root);
+ extern int level_paging();
+
+ extern void panic(char* msg);
+
+}; \ No newline at end of file
diff --git a/kernel/src/generic/bootloader/bootloader.cpp b/kernel/src/generic/bootloader/bootloader.cpp
new file mode 100644
index 0000000..a51035d
--- /dev/null
+++ b/kernel/src/generic/bootloader/bootloader.cpp
@@ -0,0 +1,10 @@
+
+#include <cstdint>
+#include <generic/bootloader/limine.hpp>
+#include <generic/bootloader/bootloader.hpp>
+
+bootloader::limine limine_bootloader;
+
+void bootloader::init() {
+ bootloader::bootloader = &limine_bootloader;
+} \ No newline at end of file
diff --git a/kernel/src/generic/bootloader/bootloader.hpp b/kernel/src/generic/bootloader/bootloader.hpp
new file mode 100644
index 0000000..21aa650
--- /dev/null
+++ b/kernel/src/generic/bootloader/bootloader.hpp
@@ -0,0 +1,20 @@
+#pragma once
+#include <cstdint>
+#include <limine.h>
+
+namespace bootloader {
+
+ class bootloader_generic {
+ public:
+ virtual limine_framebuffer* get_framebuffer() = 0;
+ virtual std::uintptr_t get_hhdm() = 0;
+ virtual void* get_rsdp() = 0;
+ virtual std::uint64_t get_kernel_phys() = 0;
+ virtual std::uintptr_t get_kernel_virt() = 0;
+ virtual limine_memmap_response* get_memory_map() = 0;
+ virtual bool is_5_level_paging() = 0;
+ };
+
+ void init();
+ inline bootloader_generic* bootloader = nullptr;
+} \ No newline at end of file
diff --git a/kernel/src/generic/bootloader/limine.cpp b/kernel/src/generic/bootloader/limine.cpp
new file mode 100644
index 0000000..e7175a4
--- /dev/null
+++ b/kernel/src/generic/bootloader/limine.cpp
@@ -0,0 +1,87 @@
+
+#include <generic/bootloader/bootloader.hpp>
+#include <generic/bootloader/limine.hpp>
+#include <limine.h>
+
+namespace {
+
+__attribute__((used, section(".limine_requests")))
+volatile std::uint64_t limine_base_revision[] = LIMINE_BASE_REVISION(5);
+
+}
+
+namespace {
+
+__attribute__((used, section(".limine_requests")))
+volatile limine_framebuffer_request framebuffer_request = {
+ .id = LIMINE_FRAMEBUFFER_REQUEST_ID,
+ .revision = 0,
+ .response = nullptr
+};
+
+__attribute__((used, section(".limine_requests"))) volatile limine_memmap_request memmap_request = { .id = LIMINE_MEMMAP_REQUEST_ID, .revision = 0, .response = nullptr };
+
+
+__attribute__((used, section(".limine_requests"))) volatile limine_hhdm_request hhdm_request = { .id = LIMINE_HHDM_REQUEST_ID, .revision = 0, .response = nullptr };
+
+
+__attribute__((used, section(".limine_requests"))) volatile limine_executable_address_request kaddr_request = { .id = LIMINE_EXECUTABLE_ADDRESS_REQUEST_ID, .revision = 0, .response = nullptr };
+
+
+__attribute__((used, section(".limine_requests"))) volatile limine_rsdp_request rsdp_request = { .id = LIMINE_RSDP_REQUEST_ID, .revision = 0, .response = nullptr };
+
+#if defined(__x86_64__)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wmissing-field-initializers"
+ [[gnu::used]] [[gnu::section(".limine_requests")]] volatile limine_paging_mode_request _5lvl_paging = { .id = LIMINE_PAGING_MODE_REQUEST_ID,.revision = 0,.response = nullptr,.mode = LIMINE_PAGING_MODE_X86_64_5LVL,.max_mode = LIMINE_PAGING_MODE_AARCH64_5LVL,.min_mode = LIMINE_PAGING_MODE_AARCH64_4LVL };
+#pragma GCC diagnostic pop
+#endif
+}
+
+namespace {
+
+__attribute__((used, section(".limine_requests_start")))
+volatile std::uint64_t limine_requests_start_marker[] = LIMINE_REQUESTS_START_MARKER;
+
+__attribute__((used, section(".limine_requests_end")))
+volatile std::uint64_t limine_requests_end_marker[] = LIMINE_REQUESTS_END_MARKER;
+
+}
+
+namespace bootloader {
+
+ std::uintptr_t limine::get_hhdm() {
+ return hhdm_request.response->offset;
+ }
+
+ limine_framebuffer* limine::get_framebuffer() {
+ return framebuffer_request.response->framebuffers[0];
+ }
+
+ void* limine::get_rsdp() {
+ return rsdp_request.response->address;
+ }
+
+ std::uint64_t limine::get_kernel_phys() {
+ return kaddr_request.response->physical_base;
+ }
+
+ std::uint64_t limine::get_kernel_virt() {
+ return kaddr_request.response->virtual_base;
+ }
+
+ limine_memmap_response* limine::get_memory_map() {
+ return memmap_request.response;
+ }
+
+#if defined(__x86_64__)
+ bool limine::is_5_level_paging() {
+ return _5lvl_paging.response->mode == LIMINE_PAGING_MODE_X86_64_5LVL ? true : false;
+ }
+#else
+ bool limine::is_5_level_paging() {
+ return false;
+ }
+#endif
+
+}; \ No newline at end of file
diff --git a/kernel/src/generic/bootloader/limine.hpp b/kernel/src/generic/bootloader/limine.hpp
new file mode 100644
index 0000000..c0fd78b
--- /dev/null
+++ b/kernel/src/generic/bootloader/limine.hpp
@@ -0,0 +1,15 @@
+
+#include <generic/bootloader/bootloader.hpp>
+
+namespace bootloader {
+ class limine final : public bootloader_generic {
+public:
+ limine_framebuffer* get_framebuffer() override;
+ std::uintptr_t get_hhdm() override;
+ void* get_rsdp() override;
+ std::uint64_t get_kernel_phys() override;
+ std::uint64_t get_kernel_virt() override;
+ limine_memmap_response* get_memory_map() override;
+ bool is_5_level_paging() override;
+ };
+}; \ No newline at end of file
diff --git a/kernel/src/generic/heap.cpp b/kernel/src/generic/heap.cpp
new file mode 100644
index 0000000..e096a68
--- /dev/null
+++ b/kernel/src/generic/heap.cpp
@@ -0,0 +1,124 @@
+#include <cstdint>
+#include <generic/pmm.hpp>
+#include <generic/heap.hpp>
+#include <generic/lock/spinlock.hpp>
+#include <generic/hhdm.hpp>
+#include <klibc/stdio.hpp>
+
+std::uint8_t* heap_pool;
+heap_block* heap_end;
+heap_block* current;
+
+locks::spinlock heap_lock;
+
+void kheap::init() {
+ heap_pool = (std::uint8_t*)(pmm::buddy::alloc(KHEAP_SIZE).phys + etc::hhdm());
+ heap_block* block = (heap_block*)heap_pool;
+ block->size = KHEAP_SIZE;
+ block->is_free = 1;
+ block->next = 0;
+ current = (heap_block*)heap_pool;
+ heap_end = block;
+ klibc::printf("KHeap: Available memory %lli bytes\r\n",KHEAP_SIZE);
+
+}
+
+int is_early = 1;
+
+void kheap::opt_free(void* ptr) {
+ if(!is_early) {
+ kheap::free(ptr);
+ return;
+ }
+
+ if(!ptr) return;
+ heap_block* block = (heap_block*)((std::uint64_t)ptr - sizeof(heap_block));
+ block->is_free = 1;
+ if (block->next && block->next->is_free) {
+ block->size += block->next->size;
+ block->next = block->next->next;
+ }
+}
+
+void* kheap::opt_malloc(std::size_t size) {
+
+ if(!is_early) {
+ return kheap::malloc(size);
+ }
+
+ size = (size + sizeof(heap_block) + 7) & ~7;
+
+ if (1) {
+ heap_block* block = heap_end;
+ block->size = size;
+ block->is_free = 0;
+ block->next = nullptr;
+
+ heap_end = (heap_block*)((std::uint64_t)heap_end + size);
+
+ return (void*)((std::uint64_t)block + sizeof(heap_block));
+ }
+ return 0;
+}
+
+void kheap::free(void* ptr) {
+ if(ptr == 0)
+ return;
+
+ heap_lock.lock();
+
+ heap_block* block = (heap_block*)((std::uint64_t)ptr - sizeof(heap_block));
+ block->is_free = 1;
+ if (block->next && block->next->is_free) {
+ block->size += block->next->size;
+ block->next = block->next->next;
+ }
+
+ heap_lock.unlock();
+
+}
+
+void* kheap::malloc(std::size_t size) {
+
+ heap_lock.lock();
+
+ size = (size + sizeof(heap_block) + 7) & ~7;
+
+ if ((std::uint64_t)heap_end + size <= (std::uint64_t)heap_pool + KHEAP_SIZE) {
+ heap_block* block = heap_end;
+ block->size = size;
+ block->is_free = 0;
+ block->next = nullptr;
+
+ heap_end = (heap_block*)((std::uint64_t)heap_end + size);
+
+ heap_lock.unlock();
+ return (void*)((std::uint64_t)block + sizeof(heap_block));
+ }
+
+ heap_block* start = current;
+ do {
+ if (current->is_free && current->size >= size) {
+ if (current->size > size + sizeof(heap_block)) {
+ heap_block* new_block = (heap_block*)((char*)current + size);
+ new_block->size = current->size - size;
+ new_block->is_free = 1;
+ new_block->next = current->next;
+
+ current->size = size;
+ current->next = new_block;
+ }
+
+ current->is_free = 0;
+ void* allocated = (void*)((char*)current + sizeof(heap_block));
+ current = current->next ? current->next : (heap_block*)heap_pool;
+ heap_lock.unlock();
+ return allocated;
+ }
+
+ current = current->next ? current->next : (heap_block*)heap_pool;
+ } while (current != start);
+
+ heap_lock.unlock();
+ return 0;
+} \ No newline at end of file
diff --git a/kernel/src/generic/heap.hpp b/kernel/src/generic/heap.hpp
new file mode 100644
index 0000000..960087b
--- /dev/null
+++ b/kernel/src/generic/heap.hpp
@@ -0,0 +1,20 @@
+#pragma once
+#include <cstdint>
+
+#define KHEAP_SIZE (16 * 1024 * 1024)
+#define HEAP_SIZE KHEAP_SIZE
+struct heap_block {
+ std::uint32_t size;
+ std::uint16_t is_free;
+ heap_block* next;
+};
+
+namespace kheap {
+
+ void* opt_malloc(std::size_t size);
+ void opt_free(void* ptr);
+
+ void init();
+ void* malloc(std::size_t size);
+ void free(void* ptr);
+} \ No newline at end of file
diff --git a/kernel/src/generic/hhdm.hpp b/kernel/src/generic/hhdm.hpp
new file mode 100644
index 0000000..edfab3c
--- /dev/null
+++ b/kernel/src/generic/hhdm.hpp
@@ -0,0 +1,8 @@
+#pragma once
+#include <generic/bootloader/bootloader.hpp>
+
+namespace etc {
+ inline static std::uintptr_t hhdm() {
+ return bootloader::bootloader->get_hhdm();
+ }
+} \ No newline at end of file
diff --git a/kernel/src/generic/lock/spinlock.hpp b/kernel/src/generic/lock/spinlock.hpp
new file mode 100644
index 0000000..12bbe16
--- /dev/null
+++ b/kernel/src/generic/lock/spinlock.hpp
@@ -0,0 +1,29 @@
+#include <atomic>
+#include <cstdint>
+
+#include <generic/arch.hpp>
+
+namespace locks {
+ class spinlock {
+ private:
+ std::atomic_flag flag = ATOMIC_FLAG_INIT;
+ public:
+ void lock() {
+ while (flag.test_and_set(std::memory_order_acquire)) {
+ arch::pause();
+ }
+ }
+
+ void unlock() {
+ flag.clear(std::memory_order_release);
+ }
+
+ bool test() {
+ return flag.test();
+ }
+
+ bool try_lock() {
+ return !flag.test_and_set(std::memory_order_acquire);
+ }
+ };
+}; \ No newline at end of file
diff --git a/kernel/src/generic/mm/heap.cpp b/kernel/src/generic/mm/heap.cpp
deleted file mode 100644
index e85bb54..0000000
--- a/kernel/src/generic/mm/heap.cpp
+++ /dev/null
@@ -1,103 +0,0 @@
-
-#include <cstdint>
-#include <cstddef>
-
-#include <generic/mm/heap.hpp>
-#include <generic/mm/pmm.hpp>
-#include <generic/mm/paging.hpp>
-
-#include <etc/logging.hpp>
-
-#include <config.hpp>
-
-#include <generic/locks/spinlock.hpp>
-
-#include <etc/etc.hpp>
-
-std::uint8_t* heap_pool;
-heap_block_t* heap_end;
-heap_block_t* current;
-
-locks::spinlock heap_lock;
-
-void memory::heap::init() {
- heap_pool = (std::uint8_t*)memory::pmm::_virtual::alloc(KHEAP_SIZE);
- heap_block_t* block = (heap_block_t*)heap_pool;
- block->size = KHEAP_SIZE;
- block->is_free = 1;
- block->next = 0;
- current = (heap_block_t*)heap_pool;
- heap_end = block;
-
- memory::paging::alwaysmappedadd(Other::toPhys(heap_pool),KHEAP_SIZE);
-}
-
-void memory::heap::lock() {
- heap_lock.lock();
-}
-
-void memory::heap::unlock() {
- heap_lock.unlock();
-}
-
-void memory::heap::free(void* ptr) {
- if(ptr == 0)
- return;
-
- heap_lock.lock();
-
- heap_block_t* block = (heap_block_t*)((std::uint64_t)ptr - sizeof(heap_block_t));
- block->is_free = 1;
- if (block->next && block->next->is_free) {
- block->size += block->next->size;
- block->next = block->next->next;
- }
-
- heap_lock.unlock();
-
-}
-
-void* memory::heap::malloc(std::uint32_t size) {
-
- heap_lock.lock();
-
- size = (size + sizeof(heap_block_t) + 7) & ~7;
-
- if ((std::uint64_t)heap_end + size <= (std::uint64_t)heap_pool + KHEAP_SIZE) {
- heap_block_t* block = heap_end;
- block->size = size;
- block->is_free = 0;
- block->next = nullptr;
-
- heap_end = (heap_block_t*)((std::uint64_t)heap_end + size);
-
- heap_lock.unlock();
- return (void*)((std::uint64_t)block + sizeof(heap_block_t));
- }
-
- heap_block_t* start = current;
- do {
- if (current->is_free && current->size >= size) {
- if (current->size > size + sizeof(heap_block_t)) {
- heap_block_t* new_block = (heap_block_t*)((char*)current + size);
- new_block->size = current->size - size;
- new_block->is_free = 1;
- new_block->next = current->next;
-
- current->size = size;
- current->next = new_block;
- }
-
- current->is_free = 0;
- void* allocated = (void*)((char*)current + sizeof(heap_block_t));
- current = current->next ? current->next : (heap_block_t*)heap_pool;
- heap_lock.unlock();
- return allocated;
- }
-
- current = current->next ? current->next : (heap_block_t*)heap_pool;
- } while (current != start);
-
- heap_lock.unlock();
- return 0;
-}
diff --git a/kernel/src/generic/mm/paging.cpp b/kernel/src/generic/mm/paging.cpp
deleted file mode 100644
index 5f2f9fe..0000000
--- a/kernel/src/generic/mm/paging.cpp
+++ /dev/null
@@ -1,245 +0,0 @@
-
-#include <cstdint>
-#include <generic/mm/pmm.hpp>
-#include <generic/mm/heap.hpp>
-#include <generic/mm/paging.hpp>
-#include <etc/bootloaderinfo.hpp>
-#include <etc/logging.hpp>
-#include <limine.h>
-#include <etc/etc.hpp>
-
-#include <etc/libc.hpp>
-
-static void init();
-std::uint64_t kernel_cr3;
-alwaysmapped_t* alwmap = 0;
-
-uint64_t* __paging_next_level(std::uint64_t* table,std::uint16_t idx,std::uint64_t flags,std::uint32_t id) {
- if(!(table[idx] & PTE_PRESENT))
- table[idx] = memory::pmm::_physical::allocid(4096,id) | flags;
- return (uint64_t*)Other::toVirt(table[idx] & PTE_MASK_VALUE);
-}
-
-uint64_t* __paging_next_level_noalloc(std::uint64_t* table,std::uint16_t idx,std::uint64_t flags,std::uint32_t id) {
- if(!(table[idx] & PTE_PRESENT))
- return 0;
- return (uint64_t*)Other::toVirt(table[idx] & PTE_MASK_VALUE);
-}
-
-void memory::paging::map(std::uint64_t cr3,std::uint64_t phys,std::uint64_t virt,std::uint64_t flags) {
- std::uint64_t align_phys = ALIGNDOWN(phys,4096);
- std::uint64_t align_virt = ALIGNDOWN(virt,4096);
- std::uint64_t* cr30 = (std::uint64_t*)Other::toVirt(cr3);
- std::uint64_t new_flags = PTE_PRESENT | PTE_RW;
- if(PTE_INDEX(align_virt,39) < 256)
- new_flags |= PTE_USER;
- uint64_t* pml3 = __paging_next_level(cr30,PTE_INDEX(align_virt,39),new_flags,0);
- uint64_t* pml2 = __paging_next_level(pml3,PTE_INDEX(align_virt,30),new_flags,0);
- uint64_t* pml = __paging_next_level(pml2,PTE_INDEX(align_virt,21),new_flags,0);
- pml[PTE_INDEX(align_virt,12)] = align_phys | flags;
-}
-
-void memory::paging::mapid(std::uint64_t cr3,std::uint64_t phys,std::uint64_t virt,std::uint64_t flags,std::uint32_t id) {
- std::uint64_t align_phys = ALIGNDOWN(phys,4096);
- std::uint64_t align_virt = ALIGNDOWN(virt,4096);
- std::uint64_t* cr30 = (std::uint64_t*)Other::toVirt(cr3);
- std::uint64_t new_flags = PTE_PRESENT | PTE_RW;
- if(PTE_INDEX(align_virt,39) < 256)
- new_flags |= PTE_USER;
- uint64_t* pml3 = __paging_next_level(cr30,PTE_INDEX(align_virt,39),new_flags,id);
- uint64_t* pml2 = __paging_next_level(pml3,PTE_INDEX(align_virt,30),new_flags,id);
- uint64_t* pml = __paging_next_level(pml2,PTE_INDEX(align_virt,21),new_flags,id);
- pml[PTE_INDEX(align_virt,12)] = align_phys | flags;
-}
-
-void memory::paging::change(std::uint64_t cr3, std::uint64_t virt, std::uint64_t flags) {
- std::uint64_t align_virt = ALIGNDOWN(virt,4096);
- std::uint64_t* cr30 = (std::uint64_t*)Other::toVirt(cr3);
- std::uint64_t new_flags = PTE_PRESENT | PTE_RW;
- if(PTE_INDEX(align_virt,39) < 256)
- new_flags |= PTE_USER;
- uint64_t* pml3 = __paging_next_level(cr30,PTE_INDEX(align_virt,39),new_flags,0);//1
- uint64_t* pml2 = __paging_next_level(pml3,PTE_INDEX(align_virt,30),new_flags,0); // 2
- uint64_t* pml = __paging_next_level(pml2,PTE_INDEX(align_virt,21),new_flags,0); // 3
- pml[PTE_INDEX(align_virt,12)] = (pml[PTE_INDEX(align_virt,12)] & PTE_MASK_VALUE) | flags;
-}
-
-std::int64_t __memory_paging_getphys(std::uint64_t cr3, std::uint64_t virt) {
- std::uint64_t align_virt = ALIGNDOWN(virt,4096);
- std::uint64_t* cr30 = (std::uint64_t*)Other::toVirt(cr3);
- if(cr30[PTE_INDEX(virt,39)] & PTE_PRESENT) {
- std::uint64_t* pml3 = __paging_next_level_noalloc(cr30,PTE_INDEX(align_virt,39),0,0);//1
- if(pml3[PTE_INDEX(virt,30)] & PTE_PRESENT) {
- std::uint64_t* pml2 = __paging_next_level_noalloc(pml3,PTE_INDEX(align_virt,30),0,0); // 2
- if(pml2[PTE_INDEX(virt,21)] & PTE_PRESENT) {
- uint64_t* pml = __paging_next_level_noalloc(pml2,PTE_INDEX(align_virt,21),0,0); // 3
- if(pml[PTE_INDEX(align_virt,12)] & PTE_PRESENT) {
- return pml[PTE_INDEX(virt,12)] & PTE_MASK_VALUE;
- } else {
- return -1;
- }
- } else {
- return -1;
- }
- } else {
- return -1;
- }
- } else {
- return -1;
- }
-}
-
-void memory::paging::destroyrange(std::uint64_t cr3, std::uint64_t virt, std::uint64_t len) {
- for(std::uint64_t i = 0;i < len; i += 4096) {
- std::int64_t phys = __memory_paging_getphys(cr3,virt + i);
- if(phys != -1 && phys != 0) {
- memory::pmm::_physical::free((std::uint64_t)phys);
- map(cr3,0,virt + i,0);
- }
- }
-}
-
-void memory::paging::duplicaterangeifexists(std::uint64_t src_cr3, std::uint64_t dest_cr3, std::uint64_t virt, std::uint64_t len, std::uint64_t flags) {
- zerorange(dest_cr3,virt,len);
- for(std::uint64_t i = 0;i < len; i += 4096) {
- std::int64_t phys = __memory_paging_getphys(src_cr3,virt + i);
- if(phys != -1) {
- std::uint64_t new_phys = memory::pmm::_physical::alloc(4096);
- memcpy(Other::toVirt(new_phys),Other::toVirt(phys),4096);
- map(dest_cr3,new_phys,virt + i,flags);
- }
- }
-}
-
-void memory::paging::changerange(std::uint64_t cr3, std::uint64_t virt, std::uint64_t len , std::uint64_t flags) {
- for(std::uint64_t i = 0;i < len; i += 4096) {
- change(cr3,virt + i, flags);
- }
-}
-
-void memory::paging::maprange(std::uint64_t cr3,std::uint64_t phys,std::uint64_t virt,std::uint64_t len,std::uint64_t flags) {
- for(std::uint64_t i = 0; i < len; i += 4096) {
- map(cr3,phys + i,virt + i,flags);
- }
-}
-
-void* memory::paging::maprangeret(std::uint64_t phys,std::uint64_t len,std::uint64_t flags) {
- std::uint64_t virt = (std::uint64_t)Other::toVirt(phys);
- for(std::uint64_t i = 0; i < len; i += 4096) {
- map(kernel_cr3,phys + i,virt + i,flags);
- }
- return (void*)Other::toVirt(phys);
-}
-
-void memory::paging::zerorange(std::uint64_t cr3,std::uint64_t virt,std::uint64_t len) {
- for(std::uint64_t i = 0; i < len; i += 4096) {
- map(cr3,0,virt + i,0);
- }
-}
-
-void memory::paging::maprangeid(std::uint64_t cr3,std::uint64_t phys,std::uint64_t virt,std::uint64_t len,std::uint64_t flags, std::uint32_t id) {
- for(std::uint64_t i = 0; i < len; i += 4096) {
- mapid(cr3,phys + i,virt + i,flags,id);
- }
-}
-
-void memory::paging::mapentry(std::uint64_t cr3,std::uint8_t type,std::uint64_t add_flags) {
- limine_memmap_response* mmap = BootloaderInfo::AccessMemoryMap();
- limine_memmap_entry* current = mmap->entries[0];
- for(int i = 0;i < mmap->entry_count;i++) {
- current = mmap->entries[i];
- if(current->type == type)
- maprange(cr3,current->base,(std::uint64_t)Other::toVirt(current->base),current->length,PTE_PRESENT | PTE_RW | add_flags);
- }
-}
-
-void* memory::paging::kernelmap(std::uint64_t cr3,std::uint64_t phys) {
- map(kernel_cr3,phys,(std::uint64_t)Other::toVirt(phys),PTE_PRESENT | PTE_RW);
- return Other::toVirt(phys);
-}
-
-void __paging_map_kernel(std::uint64_t cr3,std::uint32_t id) {
- extern std::uint64_t kernel_start;
- extern std::uint64_t kernel_end;
- limine_executable_address_response* ker = BootloaderInfo::AccessKernel();
-
- for(std::uint64_t i = ALIGNDOWN((std::uint64_t)&kernel_start,4096);i < ALIGNUP((std::uint64_t)&kernel_end,4096);i += 4096) {
- memory::paging::mapid(cr3,i - ker->virtual_base + ker->physical_base,i,PTE_PRESENT | PTE_RW,0);
- }
-}
-
-void memory::paging::mapkernel(std::uint64_t cr3,std::uint32_t id) {
- __paging_map_kernel(cr3,id);
-}
-
-void memory::paging::enablekernel() {
- asm volatile("mov %0, %%cr3" : : "r"(kernel_cr3) : "memory");
-}
-
-void memory::paging::enablepaging(std::uint64_t cr3) {
- asm volatile("mov %0, %%cr3" : : "r"(cr3) : "memory");
-}
-
-std::uint64_t memory::paging::kernelget() {
- return kernel_cr3;
-}
-
-void __map_range_id(std::uint64_t cr3,std::uint64_t phys,std::uint64_t virt,std::uint64_t len,std::uint64_t flags,std::uint32_t id) {
- for(std::uint64_t i = 0; i < len; i += 4096) {
- memory::paging::map(cr3,phys + i,virt + i,flags);
- }
-}
-
-void memory::paging::alwaysmappedadd(std::uint64_t phys, std::uint64_t len) {
- alwaysmapped_t* alw = new alwaysmapped_t;
- alw->next = alwmap;
- alw->phys = phys;
- alw->len = len;
- alwmap = alw;
-}
-
-void memory::paging::alwaysmappedmap(std::uint64_t cr3,std::uint32_t id) {
- alwaysmapped_t* current = alwmap;
- while(current) {
- __map_range_id(cr3,current->phys,(std::uint64_t)Other::toVirt(current->phys),current->len,PTE_RW | PTE_PRESENT,id);
- current = current->next;
- }
-}
-
-void __paging_destroy_table(std::uint64_t phys_table, int level) {
- std::uint64_t* table = (std::uint64_t*)Other::toVirt(phys_table);
- if(level != 3) {
- if(level == 0) {
- for(int i = 0; i < 256; i++) {
- if(table[i] & PTE_PRESENT) {
- __paging_destroy_table(table[i] & PTE_MASK_VALUE,level + 1);
- }
- }
- } else {
- for(int i = 0;i < 512; i++) {
- if(table[i] & PTE_PRESENT) {
- __paging_destroy_table(table[i] & PTE_MASK_VALUE,level + 1);
- }
- }
- }
- }
-
- if(level != 0)
- memory::pmm::_physical::free(phys_table);
-}
-
-void memory::paging::destroy(std::uint64_t cr3) {
- if(cr3 == kernel_cr3)
- return;
- __paging_destroy_table(cr3,0);
-}
-
-void memory::paging::init() {
- kernel_cr3 = memory::pmm::_physical::alloc(4096);
- mapentry(kernel_cr3,LIMINE_MEMMAP_USABLE,0);
- mapentry(kernel_cr3,LIMINE_MEMMAP_FRAMEBUFFER,PTE_WC);
- mapentry(kernel_cr3,LIMINE_MEMMAP_BOOTLOADER_RECLAIMABLE,0);
- mapentry(kernel_cr3,LIMINE_MEMMAP_EXECUTABLE_AND_MODULES,0);
- mapkernel(kernel_cr3,0);
- enablekernel();
-} \ No newline at end of file
diff --git a/kernel/src/generic/mm/pmm.cpp b/kernel/src/generic/mm/pmm.cpp
deleted file mode 100644
index 3225854..0000000
--- a/kernel/src/generic/mm/pmm.cpp
+++ /dev/null
@@ -1,452 +0,0 @@
-
-#include <generic/locks/spinlock.hpp>
-#include <etc/bootloaderinfo.hpp>
-#include <generic/mm/pmm.hpp>
-#include <etc/logging.hpp>
-#include <etc/libc.hpp>
-#include <etc/etc.hpp>
-#include <limine.h>
-#include <cstddef>
-#include <cstdint>
-
-/* buddy allocator */
-
-locks::spinlock pmm_lock;
-buddy_t mem;
-
-buddy_info_t* buddy_find_by_parent(buddy_info_t* blud,char split_x) {
- if(split_x) {
- for(std::uint64_t i = 0;i < mem.buddy_queue;i++) {
- if(mem.mem[i].parent == blud && mem.mem[i].split_x)
- return &mem.mem[i];
- }
- } else {
- for(std::uint64_t i = 0;i < mem.buddy_queue;i++) {
- if(mem.mem[i].parent == blud && !mem.mem[i].split_x)
- return &mem.mem[i];
- }
- }
-}
-
-buddy_info_t* buddy_find_by_phys(std::uint64_t phys) {
- for(std::uint64_t i = 0;i < mem.buddy_queue;i++) {
- if(mem.mem[i].phys == phys)
- return &mem.mem[i];
- }
- return 0;
-}
-
-buddy_info_t* buddy_find_by_phys_without_split(std::uint64_t phys) {
- for(std::uint64_t i = 0;i < mem.buddy_queue;i++) {
- if(mem.mem[i].phys == phys && !mem.mem[i].is_splitted)
- return &mem.mem[i];
- }
- return 0;
-}
-
-buddy_info_t* memory::buddy::put(std::uint64_t phys, std::uint8_t level) {
- buddy_info_t* blud = &mem.mem[mem.buddy_queue++];
- blud->level = level;
- blud->phys = phys;
- blud->is_free = 1;
- blud->is_splitted = 0;
- blud->is_was_splitted = 0;
- blud->parent = 0;
- blud->split_x = 0;
- return blud;
-}
-
-buddy_info_t* memory::buddy::split_maximum(buddy_info_t* blud, std::uint64_t size) {
- if((size <= LEVEL_TO_SIZE(blud->level) && LEVEL_TO_SIZE(blud->level - 1) < size) || LEVEL_TO_SIZE(blud->level) == 4096)
- return blud;
- return split_maximum(split(blud).first,size);
-}
-
-void memory::buddy::merge(buddy_info_t* budy) {
- buddy_info_t* bl = budy;
- buddy_info_t* ud = budy->twin;
- if(!bl || !ud || !bl->is_free || !ud->is_free)
- return;
-
- buddy_info_t* blud = budy->parent;
- bl->is_free = 0;
- ud->is_free = 0;
- blud->is_splitted = 0;
- blud->is_was_splitted = 1;
- blud->is_free = 1;
- blud->id = 0;
- bl->id = 0;
- ud->id = 0;
- if(blud->parent)
- merge(blud);
- return;
-}
-
-buddy_split_t memory::buddy::split(buddy_info_t* info) {
- if(!info || LEVEL_TO_SIZE(info->level) == 4096 || !info->is_free)
- return {info,info};
- buddy_info_t* bl = 0;
- buddy_info_t* ud = 0;
- if(!info->is_was_splitted) {
- bl = put(info->phys,info->level - 1);
- ud = put(info->phys + LEVEL_TO_SIZE(info->level - 1), info->level - 1);
- bl->split_x = 0;
- bl->is_free = 1;
- ud->split_x = 1;
- ud->is_free = 1;
- bl->parent = info;
- ud->parent = info;
- bl->twin = ud;
- ud->twin = bl;
- } else {
- bl = buddy_find_by_parent(info,0);
- ud = bl->twin;
- bl->is_free = 1;
- ud->is_free = 1;
- }
- info->is_splitted = 1;
- info->is_free = 0;
- info->is_was_splitted = 1;
- return {bl,ud};
-}
-
-int __buddy_align_power(uint64_t number) {
- if (number == 0) return 0;
-
- uint64_t power = 12;
-
- while (LEVEL_TO_SIZE(power) <= number && power < MAX_LEVEL) {
- power++;
- }
-
- return power - 1;
-}
-
-void memory::buddy::init() {
- limine_memmap_response* mmap = BootloaderInfo::AccessMemoryMap();
- limine_memmap_entry* current = mmap->entries[0];
- std::uint64_t top,top_size,total_pages;
- top = 0;
- top_size = 0;
- total_pages = 0;
- total_pages = 0;
- for(int i = 0;i < mmap->entry_count; i++) {
- current = mmap->entries[i];
- if(current->type == LIMINE_MEMMAP_USABLE) {
- total_pages += current->length / 4096;
- if(current->length > top_size) {
- top = current->base;
- top_size = current->length;
- }
- }
- }
-
- std::uint64_t buddy_size = (total_pages * sizeof(buddy_info_t));
-
- memset(&mem,0,sizeof(buddy_t));
- mem.mem = (buddy_info_t*)Other::toVirt(top);
- memset(mem.mem,0,buddy_size);
-
- mem.buddy_queue = 0;
-
- for(int i = 0;i < mmap->entry_count; i++) {
- current = mmap->entries[i];
- if(current->type == LIMINE_MEMMAP_USABLE) {
- std::int64_t new_len = 0;
- std::uint64_t new_base = 0;
- new_len = current->length;
- new_base = current->base;
- if(new_base == top) {
- new_len = top_size - buddy_size;
- new_base = ALIGNUP(top + buddy_size,4096);
- }
- while(new_len > 4096) {
- auto blud = put(new_base,__buddy_align_power(new_len));
- new_base += LEVEL_TO_SIZE(__buddy_align_power(new_len));
- new_len -= LEVEL_TO_SIZE(__buddy_align_power(new_len));
- }
- }
- }
-
-}
-
-int memory::buddy::free(std::uint64_t phys) {
- auto blud = buddy_find_by_phys_without_split(phys);
- if(!blud || blud->is_splitted)
- return -1;
- blud->is_free = 1;
- blud->id = 0;
- if(blud->parent)
- merge(blud);
- return 0;
-}
-
-int last_i = 0;
-
-std::int64_t memory::buddy::alloc(std::size_t size) {
- std::uint64_t top_size = UINT64_MAX;
- buddy_info_t* nearest_buddy = 0;
-
- if(size < 4096)
- size = 4096;
-
- for(std::uint64_t i = 0;i < mem.buddy_queue; i++) {
- if(LEVEL_TO_SIZE(mem.mem[i].level) >= size && LEVEL_TO_SIZE(mem.mem[i].level) < top_size && mem.mem[i].is_free) {
- top_size = LEVEL_TO_SIZE(mem.mem[i].level);
- nearest_buddy = &mem.mem[i];
- if(top_size == size) {
- last_i = i; break; }
- }
- }
-
-found:
- if(nearest_buddy) {
- auto blud = split_maximum(nearest_buddy,size);
- blud->is_free = 0;
- memset(Other::toVirt(blud->phys),0,LEVEL_TO_SIZE(blud->level));
- return blud->phys;
- }
-
- assert(0,"There's no memory !");
- return 0;
-
-}
-
-alloc_t memory::buddy::alloc_ext(std::size_t size) {
- std::uint64_t top_size = UINT64_MAX;
- buddy_info_t* nearest_buddy = 0;
-
- if(size < 4096)
- size = 4096;
-
- for(std::uint64_t i = 0;i < mem.buddy_queue; i++) {
- if(LEVEL_TO_SIZE(mem.mem[i].level) >= size && LEVEL_TO_SIZE(mem.mem[i].level) < top_size && mem.mem[i].is_free) {
- top_size = LEVEL_TO_SIZE(mem.mem[i].level);
- nearest_buddy = &mem.mem[i];
- if(top_size == size)
- break;
- }
- }
-
- if(nearest_buddy) {
- auto blud = split_maximum(nearest_buddy,size);
- blud->is_free = 0;
- memset(Other::toVirt(blud->phys),0,LEVEL_TO_SIZE(blud->level));
-
- alloc_t result;
- result.real_size = LEVEL_TO_SIZE(blud->level);
- result.virt = blud->phys;
-
- return result;
- }
-
- assert(0,"There's no memory !");
- return {0,0};
-}
-
-std::int64_t memory::buddy::allocid(std::size_t size,std::uint32_t id0) {
- std::uint64_t top_size = UINT64_MAX;
- buddy_info_t* nearest_buddy = 0;
-
- if(size < 4096)
- size = 4096;
-
- for(std::uint64_t i = 0;i < mem.buddy_queue; i++) {
- if(LEVEL_TO_SIZE(mem.mem[i].level) >= size && LEVEL_TO_SIZE(mem.mem[i].level) < top_size && mem.mem[i].is_free) {
- top_size = LEVEL_TO_SIZE(mem.mem[i].level);
- nearest_buddy = &mem.mem[i];
- if(top_size == size)
- break;
- }
- }
-
- if(nearest_buddy) {
- auto blud = split_maximum(nearest_buddy,size);
- blud->is_free = 0;
- blud->id = id0;
- memset(Other::toVirt(blud->phys),0,LEVEL_TO_SIZE(blud->level));
- return blud->phys;
- }
-
- assert(0,"There's no memory !");
- return 0;
-}
-
-void memory::buddy::fullfree(std::uint32_t id) {
- for(std::uint64_t i = 0;i < mem.buddy_queue; i++) {
- if(mem.mem[i].id == id) {
- //free(mem.mem[i].phys);
- }
- }
-}
-
-/* freelist allocator */
-
-template <int N>
-struct freelist_allocated_memory {
- std::uint64_t arr[131072];
-};
-
-template <int N>
-struct memory_id_block {
- std::uint64_t phys_block[N];
- struct memory_id_block* next;
-};
-
-typedef struct memory_id_block<4> memory_id_t;
-
-typedef struct freelist_allocated_memory<1048576> freelist_allocated_memory_t;
-
-std::uint64_t freelist_page = 0;
-
-freelist_allocated_memory_t freelist_aloc_mem;
-int freelist_aloc_mem_ptr = 0;
-
-int memory::freelist::free(std::uint64_t phys) {
- if(phys == 0)
- return -1;
- // sorry but my freelist free is O(n) :(
-
- int success = 0;
-
- //Log::SerialDisplay(LEVEL_MESSAGE_INFO,"freelist: free 0x%p\n",phys);
-
- for(int i = 0; i < freelist_aloc_mem_ptr; i++) {
- if(phys >= freelist_aloc_mem.arr[i] && phys < freelist_aloc_mem.arr[i] + (1024 * 1024)) {
- success = 1;
- break;
- }
- }
-
- if(!success) {
- return -1; // not free list memory, ignore
- }
-
- memset(Other::toVirt(phys),0,4096);
-
- *((std::uint64_t*)Other::toVirt(phys)) = freelist_page;
- freelist_page = phys;
- return 0;
-}
-
-std::int64_t memory::freelist::alloc() {
- if(!freelist_page) { // request memory from buddy, 1 mb will be enough
- std::uint64_t phys = memory::buddy::alloc(1024 * 1024 * 4);
-
- freelist_aloc_mem.arr[freelist_aloc_mem_ptr++] = phys;
-
- std::uint64_t ptr = phys;
- while(1) {
- if(ptr >= phys + (1024 * 1024 * 4))
- break;
- free(ptr);
- ptr += 4096;
- }
- }
- std::uint64_t freelist_mem = freelist_page;
-
- freelist_page = *((std::uint64_t*)Other::toVirt(freelist_mem));
-
- memset(Other::toVirt(freelist_mem),0,4096);
- return freelist_mem;
-}
-
-/* pmm wrapper */
-
-void memory::pmm::_physical::init() {
- memset(&freelist_aloc_mem,0,sizeof(freelist_aloc_mem));
- memory::buddy::init();
-}
-
-int __is_in_freelist_array(std::uint64_t phys) {
- for(int i = 0;i < freelist_aloc_mem_ptr; i++) {
- if(phys >= freelist_aloc_mem.arr[i] && phys < freelist_aloc_mem.arr[i] + (1024 * 1024))
- return 1;
- }
- return 0;
-}
-
-void memory::pmm::_physical::free(std::uint64_t phys) {
- return;
- asm volatile("cli");
- pmm_lock.lock();
- int status = -1;
- if(!__is_in_freelist_array(phys)) // not used by freelist ?
- status = memory::buddy::free(phys);
- if(status != 0)
- memory::freelist::free(phys);
- pmm_lock.unlock();
-}
-
-void memory::pmm::_physical::fullfree(std::uint32_t id) {
- pmm_lock.lock();
- memory::buddy::fullfree(id);
- pmm_lock.unlock();
-}
-
-std::int64_t memory::pmm::_physical::alloc(std::size_t size) {
- asm volatile("cli");
- pmm_lock.lock();
- std::int64_t p = 0;
- if(size <= 4096) { // sure we can do freelist optimization
- p = memory::freelist::alloc();
- } else {
- p = memory::buddy::alloc(size);
- }
- pmm_lock.unlock();
- return p;
-}
-
-std::int64_t memory::pmm::_physical::allocid(std::size_t size, std::uint32_t id) {
- asm volatile("cli");
- pmm_lock.lock();
- std::int64_t p = 0;
- if(size <= 4096) { // sure we can do freelist optimization
- p = memory::freelist::alloc();
- } else {
- p = memory::buddy::allocid(size,id);
- }
- pmm_lock.unlock();
- return p;
-}
-
-void memory::pmm::_physical::lock() {
- pmm_lock.lock();
-}
-
-void memory::pmm::_physical::unlock() {
- pmm_lock.unlock();
-}
-
-void memory::pmm::_virtual::free(void* virt) {
- memory::pmm::_physical::free(Other::toPhys(virt));
-}
-
-void* memory::pmm::_virtual::alloc(std::size_t size) {
- asm volatile("cli");
- return Other::toVirt(memory::pmm::_physical::alloc(size));
-}
-
-alloc_t memory::pmm::_physical::alloc_ext(std::size_t size) {
- asm volatile("cli");
- pmm_lock.lock();
- alloc_t result;
- if(size <= 4096) {
- result.real_size = 4096;
- result.virt = memory::freelist::alloc();
- } else
- result = memory::buddy::alloc_ext(size);
- result.virt = (std::uint64_t)Other::toVirt(result.virt);
- pmm_lock.unlock();
- return result;
-}
-
-/* some helper functions */
-
-#include <generic/mm/paging.hpp>
-
-std::uint64_t memory::pmm::helper::alloc_kernel_stack(std::size_t size) {
- std::uint64_t stack = memory::pmm::_physical::alloc(size); /* extra page */
- memory::paging::alwaysmappedadd(stack,size);
- return (std::uint64_t)Other::toVirt(stack) + size;
-} \ No newline at end of file
diff --git a/kernel/src/generic/paging.cpp b/kernel/src/generic/paging.cpp
new file mode 100644
index 0000000..5605e14
--- /dev/null
+++ b/kernel/src/generic/paging.cpp
@@ -0,0 +1,85 @@
+#include <cstdint>
+#include <generic/arch.hpp>
+#include <generic/pmm.hpp>
+#include <generic/hhdm.hpp>
+#include <klibc/string.hpp>
+#include <generic/bootloader/bootloader.hpp>
+#include <utils/align.hpp>
+#include <utils/gobject.hpp>
+#include <klibc/stdio.hpp>
+#include <generic/paging.hpp>
+
+void __map_kernel(std::uintptr_t root) {
+ extern std::uint64_t kernel_start;
+ extern std::uint64_t kernel_end;
+ std::uint64_t virt_base = bootloader::bootloader->get_kernel_virt();
+ std::uint64_t phys_base = bootloader::bootloader->get_kernel_phys();
+
+ for (std::uint64_t i = ALIGNDOWN((std::uint64_t) &kernel_start, 4096); i < ALIGNUP((std::uint64_t) &kernel_end, 4096); i += 4096) {
+ paging::map_range(root, i - virt_base + phys_base, i, PAGE_SIZE, PAGING_PRESENT | PAGING_RW);
+ }
+}
+
+namespace paging {
+
+ void map_kernel(std::uintptr_t root) {
+ return __map_kernel(root);
+ }
+
+ void mapentry(std::uintptr_t root, std::uint8_t type, std::uint32_t flags) {
+ limine_memmap_response* mmap = bootloader::bootloader->get_memory_map();
+ limine_memmap_entry* current = mmap->entries[0];
+ for (uint64_t i = 0; i < mmap->entry_count; i++) {
+ current = mmap->entries[i];
+ if (current->type == type)
+ paging::map_range(root, current->base, current->base + etc::hhdm(), current->length, PAGING_PRESENT | PAGING_RW | flags);
+ }
+ }
+
+
+ void map_range(std::uintptr_t root, std::uint64_t phys, std::uintptr_t virt, std::size_t size, int flags) {
+ for(std::size_t i = 0;i < size;i += PAGE_SIZE) {
+ arch::map_page(root,phys + i, virt + i, flags);
+ }
+ }
+
+ void zero_range(std::uintptr_t root, std::uintptr_t virt, std::size_t size) {
+ for(std::size_t i = 0;i < size;i += PAGE_SIZE) {
+ arch::map_page(root,0, virt + i, 0);
+ }
+ }
+
+ void free_range(std::uintptr_t root, std::uintptr_t virt, std::uintptr_t len) {
+ for (std::uint64_t i = 0; i < len; i += 4096) {
+ std::int64_t phys = arch::get_phys_from_page(root, virt + i);
+ if (phys != -1 && phys != 0) {
+ pmm::freelist::free((std::uint64_t) phys);
+ arch::map_page(root, 0, virt + i, 0);
+ }
+ }
+ }
+
+ void duplicate_range(std::uintptr_t root, std::uintptr_t src_root, std::uintptr_t virt, std::uintptr_t len, std::uint32_t flags) {
+ zero_range(root, virt, len);
+ for (std::uint64_t i = 0; i < len; i += 4096) {
+ std::int64_t phys = arch::get_phys_from_page(src_root, virt + i);
+ if (phys != -1) {
+ std::uint64_t new_phys = pmm::freelist::alloc_4k();
+ klibc::memcpy((void*)(new_phys + etc::hhdm()), (void*) (phys + etc::hhdm()), 4096);
+ arch::map_page(root, new_phys, virt + i, flags);
+ }
+ }
+ }
+
+ void init() {
+ std::uintptr_t kernel_root = pmm::freelist::alloc_4k();
+ gobject::kernel_root = kernel_root;
+ mapentry(kernel_root, LIMINE_MEMMAP_USABLE, 0);
+ mapentry(kernel_root, LIMINE_MEMMAP_BOOTLOADER_RECLAIMABLE, 0);
+ mapentry(kernel_root, LIMINE_MEMMAP_FRAMEBUFFER, PAGING_WC);
+ mapentry(kernel_root, LIMINE_MEMMAP_EXECUTABLE_AND_MODULES, 0);
+ map_kernel(kernel_root);
+ arch::enable_paging(kernel_root);
+ klibc::printf("Paging: Enabled kernel root with %d level paging\n\r", arch::level_paging());
+ }
+};
diff --git a/kernel/src/generic/paging.hpp b/kernel/src/generic/paging.hpp
new file mode 100644
index 0000000..56e88cc
--- /dev/null
+++ b/kernel/src/generic/paging.hpp
@@ -0,0 +1,20 @@
+#pragma once
+#include <cstdint>
+#include <generic/arch.hpp>
+#include <generic/pmm.hpp>
+#include <generic/hhdm.hpp>
+#include <klibc/string.hpp>
+#include <generic/bootloader/bootloader.hpp>
+#include <utils/align.hpp>
+#include <utils/gobject.hpp>
+#include <klibc/stdio.hpp>
+
+namespace paging {
+ void map_kernel(std::uintptr_t root);
+ void mapentry(std::uintptr_t root, std::uint8_t type, std::uint32_t flags);
+ void map_range(std::uintptr_t root, std::uint64_t phys, std::uintptr_t virt, std::size_t size, int flags);
+ void zero_range(std::uintptr_t root, std::uintptr_t virt, std::size_t size);
+ void free_range(std::uintptr_t root, std::uintptr_t virt, std::uintptr_t len);
+ void duplicate_range(std::uintptr_t root, std::uintptr_t src_root, std::uintptr_t virt, std::uintptr_t len, std::uint32_t flags);
+ void init();
+};
diff --git a/kernel/src/generic/pmm.cpp b/kernel/src/generic/pmm.cpp
new file mode 100644
index 0000000..01d38f0
--- /dev/null
+++ b/kernel/src/generic/pmm.cpp
@@ -0,0 +1,270 @@
+#include <cstdint>
+#include <generic/pmm.hpp>
+#include <generic/bootloader/bootloader.hpp>
+#include <generic/lock/spinlock.hpp>
+#include <generic/hhdm.hpp>
+#include <klibc/string.hpp>
+#include <klibc/stdio.hpp>
+#include <utils/align.hpp>
+#include <atomic>
+
+locks::spinlock pmm_lock;
+std::uint64_t* freelist_hhdm = 0;
+std::size_t memory_size = 0;
+
+buddy_t mem;
+
+buddy_info_t* buddy_find_by_parent(buddy_info_t* blud,char split_x) {
+ if(split_x) {
+ for(std::uint64_t i = 0;i < mem.buddy_queue;i++) {
+ if(mem.mem[i].parent == blud && mem.mem[i].split_x)
+ return &mem.mem[i];
+ }
+ } else {
+ for(std::uint64_t i = 0;i < mem.buddy_queue;i++) {
+ if(mem.mem[i].parent == blud && !mem.mem[i].split_x)
+ return &mem.mem[i];
+ }
+ }
+ return nullptr;
+}
+
+buddy_info_t* buddy_find_by_phys(std::uint64_t phys) {
+ for(std::uint64_t i = 0;i < mem.buddy_queue;i++) {
+ if(mem.mem[i].phys == phys)
+ return &mem.mem[i];
+ }
+ return 0;
+}
+
+buddy_info_t* buddy_find_by_phys_without_split(std::uint64_t phys) {
+ for(std::uint64_t i = 0;i < mem.buddy_queue;i++) {
+ if(mem.mem[i].phys == phys && !mem.mem[i].is_splitted)
+ return &mem.mem[i];
+ }
+ return 0;
+}
+
+buddy_info_t* pmm::buddy::put(std::uint64_t phys, std::uint8_t level) {
+ buddy_info_t* blud = &mem.mem[mem.buddy_queue++];
+ blud->level = level;
+ blud->phys = phys;
+ blud->is_free = 1;
+ blud->is_splitted = 0;
+ blud->is_was_splitted = 0;
+ blud->parent = 0;
+ blud->split_x = 0;
+ return blud;
+}
+
+buddy_info_t* pmm::buddy::split_maximum(buddy_info_t* blud, std::uint64_t size) {
+ if((size <= LEVEL_TO_SIZE(blud->level) && LEVEL_TO_SIZE(blud->level - 1) < size) || LEVEL_TO_SIZE(blud->level) == 4096)
+ return blud;
+ return split_maximum(split(blud).first,size);
+}
+
+void pmm::buddy::merge(buddy_info_t* budy) {
+ buddy_info_t* bl = budy;
+ buddy_info_t* ud = budy->twin;
+ if(!bl || !ud || !bl->is_free || !ud->is_free)
+ return;
+
+ buddy_info_t* blud = budy->parent;
+ bl->is_free = 0;
+ ud->is_free = 0;
+ blud->is_splitted = 0;
+ blud->is_was_splitted = 1;
+ blud->is_free = 1;
+ blud->id = 0;
+ bl->id = 0;
+ ud->id = 0;
+ if(blud->parent)
+ merge(blud);
+ return;
+}
+
+buddy_split_t pmm::buddy::split(buddy_info_t* info) {
+ if(!info || LEVEL_TO_SIZE(info->level) == 4096 || !info->is_free)
+ return {info,info};
+ buddy_info_t* bl = 0;
+ buddy_info_t* ud = 0;
+ if(!info->is_was_splitted) {
+ bl = put(info->phys,info->level - 1);
+ ud = put(info->phys + LEVEL_TO_SIZE(info->level - 1), info->level - 1);
+ bl->split_x = 0;
+ bl->is_free = 1;
+ ud->split_x = 1;
+ ud->is_free = 1;
+ bl->parent = info;
+ ud->parent = info;
+ bl->twin = ud;
+ ud->twin = bl;
+ } else {
+ bl = buddy_find_by_parent(info,0);
+ ud = bl->twin;
+ bl->is_free = 1;
+ ud->is_free = 1;
+ }
+ info->is_splitted = 1;
+ info->is_free = 0;
+ info->is_was_splitted = 1;
+ return {bl,ud};
+}
+
+int __buddy_align_power(uint64_t number) {
+ if (number == 0) return 0;
+
+ uint64_t power = 12;
+
+ while (LEVEL_TO_SIZE(power) <= number && power < MAX_LEVEL) {
+ power++;
+ }
+
+ return power - 1;
+}
+
+void pmm::buddy::init() {
+ limine_memmap_response* mmap = bootloader::bootloader->get_memory_map();
+ limine_memmap_entry* current = mmap->entries[0];
+ std::uint64_t top,top_size,total_pages;
+ top = 0;
+ top_size = 0;
+ total_pages = 0;
+ total_pages = 0;
+ for(std::size_t i = 0;i < mmap->entry_count; i++) {
+ current = mmap->entries[i];
+ if(current->type == LIMINE_MEMMAP_USABLE) {
+ total_pages += current->length / 4096;
+ memory_size += current->length;
+ if(current->length > top_size) {
+ top = current->base;
+ top_size = current->length;
+ }
+ }
+ }
+
+ std::uint64_t buddy_size = (total_pages * sizeof(buddy_info_t));
+
+ klibc::memset(&mem,0,sizeof(buddy_t));
+ mem.mem = (buddy_info_t*)(top + etc::hhdm());
+ klibc::memset(mem.mem,0,buddy_size);
+
+ mem.buddy_queue = 0;
+
+ for(std::size_t i = 0;i < mmap->entry_count; i++) {
+ current = mmap->entries[i];
+ if(current->type == LIMINE_MEMMAP_USABLE) {
+ std::int64_t new_len = 0;
+ std::uint64_t new_base = 0;
+ new_len = current->length;
+ new_base = current->base;
+ if(new_base == top) {
+ new_len = top_size - buddy_size;
+ new_base = ALIGNUP(top + buddy_size,4096);
+ }
+ while(new_len > 4096) {
+ put(new_base,__buddy_align_power(new_len));
+ new_base += LEVEL_TO_SIZE(__buddy_align_power(new_len));
+ new_len -= LEVEL_TO_SIZE(__buddy_align_power(new_len));
+ }
+ }
+ }
+
+}
+
+int pmm::buddy::nlfree(std::uint64_t phys) {
+ auto blud = buddy_find_by_phys_without_split(phys);
+ if(!blud || blud->is_splitted)
+ return -1;
+ blud->is_free = 1;
+ blud->id = 0;
+ if(blud->parent)
+ merge(blud);
+ return 0;
+}
+
+alloc_t pmm::buddy::nlalloc_ext(std::size_t size) {
+ std::uint64_t top_size = UINT64_MAX;
+ buddy_info_t* nearest_buddy = 0;
+
+ if(size < 4096)
+ size = 4096;
+
+ for(std::uint64_t i = 0;i < mem.buddy_queue; i++) {
+ if(LEVEL_TO_SIZE(mem.mem[i].level) >= size && LEVEL_TO_SIZE(mem.mem[i].level) < top_size && mem.mem[i].is_free) {
+ top_size = LEVEL_TO_SIZE(mem.mem[i].level);
+ nearest_buddy = &mem.mem[i];
+ if(top_size == size)
+ break;
+ }
+ }
+
+ if(nearest_buddy) {
+ auto blud = split_maximum(nearest_buddy,size);
+ blud->is_free = 0;
+ klibc::memset((void*)(blud->phys + etc::hhdm()),0,LEVEL_TO_SIZE(blud->level));
+
+ alloc_t result;
+ result.real_size = LEVEL_TO_SIZE(blud->level);
+ result.phys = blud->phys;
+
+ return result;
+ }
+
+ klibc::printf("There's no memory !\n\r");
+ return {0,0};
+}
+
+alloc_t pmm::buddy::alloc(std::size_t size) {
+ pmm_lock.lock();
+ alloc_t res = pmm::buddy::nlalloc_ext(size);
+ pmm_lock.unlock();
+ return res;
+}
+
+int pmm::buddy::free(std::uint64_t phys) {
+ pmm_lock.lock();
+ int res = pmm::buddy::nlfree(phys);
+ pmm_lock.unlock();
+ return res;
+}
+
+void pmm::init() {
+ buddy::init();
+ klibc::printf("PMM: Total usable memory: %lli bytes\r\n",memory_size);
+}
+
+std::uint64_t pmm::freelist::alloc_4k() {
+ pmm_lock.lock();
+
+ if(!freelist_hhdm) { // request memory from buddy, 4 mb will be enough
+ alloc_t res = buddy::nlalloc_ext(1024 * 1024 * 4);
+ std::uint64_t phys = res.phys;
+
+ std::uint64_t ptr = phys;
+ while(1) {
+ if(ptr >= phys + (1024 * 1024 * 4))
+ break;
+ freelist::nlfree(ptr);
+ ptr += PAGE_SIZE;
+ }
+ }
+
+ std::uint64_t mem = (std::uint64_t)freelist_hhdm - etc::hhdm();
+ freelist_hhdm = (std::uint64_t*)(*freelist_hhdm);
+ klibc::memset((void*)(mem + etc::hhdm()),0,PAGE_SIZE);
+ pmm_lock.unlock();
+ return mem;
+}
+
+void pmm::freelist::nlfree(std::uint64_t phys) {
+ std::uint64_t virt = phys + etc::hhdm();
+ *(std::uint64_t**)virt = freelist_hhdm;
+ freelist_hhdm = (std::uint64_t*)virt;
+}
+
+void pmm::freelist::free(std::uint64_t phys) {
+ pmm_lock.lock();
+ freelist::nlfree(phys);
+ pmm_lock.unlock();
+} \ No newline at end of file
diff --git a/kernel/src/generic/pmm.hpp b/kernel/src/generic/pmm.hpp
new file mode 100644
index 0000000..d3279a9
--- /dev/null
+++ b/kernel/src/generic/pmm.hpp
@@ -0,0 +1,66 @@
+#pragma once
+
+#include <cstdint>
+
+#define LEVEL_TO_SIZE(level) (1U << (level))
+#define MAX_LEVEL 32
+
+typedef struct buddy_info {
+ union {
+ struct {
+ std::uint16_t level : 8;
+ std::uint16_t is_was_splitted : 1;
+ std::uint16_t is_splitted : 1;
+ std::uint16_t is_free : 1;
+ std::uint16_t split_x : 1;
+ };
+ std::uint16_t buddy_info_raw;
+ };
+ struct buddy_info* parent;
+ struct buddy_info* twin;
+ std::uint32_t id;
+ std::uint64_t phys;
+} __attribute__((packed)) buddy_info_t;
+
+typedef struct {
+ buddy_info_t* first;
+ buddy_info_t* second;
+} buddy_split_t;
+
+typedef struct {
+ uint64_t buddy_queue;
+ uint64_t total_size;
+ buddy_info_t* mem;
+} __attribute__((packed)) buddy_t;
+
+typedef struct {
+ std::uint64_t phys;
+ std::uint64_t real_size; //optimization for tmpfs
+} alloc_t;
+
+
+namespace pmm {
+ void init();
+
+ class buddy {
+ private:
+ static buddy_info_t* split_maximum(buddy_info_t* blud, std::uint64_t size);
+ static buddy_info_t* put(std::uint64_t phys, std::uint8_t level);
+ static buddy_split_t split(buddy_info_t* info);
+ static void merge(buddy_info_t* budy);
+ public:
+ static void init();
+ static int nlfree(std::uint64_t phys);
+ static alloc_t nlalloc_ext(std::size_t size);
+
+ static alloc_t alloc(std::size_t size);
+ static int free(std::uint64_t phys);
+
+ };
+
+ namespace freelist {
+ std::uint64_t alloc_4k();
+ void free(std::uint64_t phys);
+ void nlfree(std::uint64_t phys);
+ };
+}; \ No newline at end of file
diff --git a/kernel/src/generic/time.cpp b/kernel/src/generic/time.cpp
deleted file mode 100644
index 58cfa1d..0000000
--- a/kernel/src/generic/time.cpp
+++ /dev/null
@@ -1,36 +0,0 @@
-
-#include <generic/time.hpp>
-#include <cstdint>
-
-#include <drivers/tsc.hpp>
-#include <drivers/kvmtimer.hpp>
-#include <drivers/hpet.hpp>
-
-std::uint64_t time::counter() {
- extern std::uint16_t KERNEL_GOOD_TIMER;
- switch(KERNEL_GOOD_TIMER) {
- case TSC_TIMER:
- return drivers::tsc::currentnano();
- case KVM_TIMER:
- return drivers::kvmclock::currentnano();
- case HPET_TIMER:
- return drivers::hpet::nanocurrent();
-
- }
-}
-
-void time::sleep(std::uint64_t us) {
- extern std::uint16_t KERNEL_GOOD_TIMER;
- switch(KERNEL_GOOD_TIMER) {
- case TSC_TIMER:
- drivers::tsc::sleep(us);
- break;
- case KVM_TIMER:
- drivers::kvmclock::sleep(us);
- break;
- case HPET_TIMER:
- drivers::hpet::sleep(us);
- break;
- }
- return;
-} \ No newline at end of file
diff --git a/kernel/src/generic/time.hpp b/kernel/src/generic/time.hpp
new file mode 100644
index 0000000..a3653cc
--- /dev/null
+++ b/kernel/src/generic/time.hpp
@@ -0,0 +1,27 @@
+#pragma once
+#include <cstdint>
+#include <klibc/stdio.hpp>
+
+namespace time {
+ class generic_timer {
+ public:
+ virtual int get_priority() = 0;
+
+ virtual std::uint64_t current_nano() = 0;
+ virtual void sleep(std::uint64_t us) = 0;
+ };
+
+ inline generic_timer* timer = nullptr;
+ inline generic_timer* previous_timer = nullptr;
+
+ inline void setup_timer(generic_timer* ztimer) {
+ if(!time::timer) {
+ time::timer = ztimer;
+ } else {
+ if(time::timer->get_priority() < ztimer->get_priority()) {
+ time::previous_timer = time::timer;
+ time::timer = ztimer;
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/kernel/src/generic/vfs/devfs.cpp b/kernel/src/generic/vfs/devfs.cpp
deleted file mode 100644
index ffe503e..0000000
--- a/kernel/src/generic/vfs/devfs.cpp
+++ /dev/null
@@ -1,1019 +0,0 @@
-
-#include <generic/vfs/vfs.hpp>
-#include <cstdint>
-
-#include <generic/vfs/devfs.hpp>
-
-#include <generic/mm/pmm.hpp>
-
-#include <etc/libc.hpp>
-#include <etc/logging.hpp>
-
-#include <generic/mm/paging.hpp>
-
-#include <drivers/ioapic.hpp>
-#include <arch/x86_64/interrupts/irq.hpp>
-
-#include <etc/assembly.hpp>
-
-#include <etc/errno.hpp>
-
-vfs::devfs_node_t* __devfs_head;
-
-int dev_num = 0;
-int is_slave = 0;
-
-bool isdigit(char ch) {
- return ch >= '0' && ch <= '9';
-}
-
-long reverse_number(long num) {
- long reversed_num = 0;
-
- while(num > 0) {
- int digit = num % 10;
- reversed_num = reversed_num * 10 + digit;
- num /= 10;
- }
-
- return reversed_num;
-}
-
-
-vfs::devfs_node_t* devfs_find_dev(char* loc) {
-
- vfs::devfs_node_t* dev = __devfs_head;
- char temp[256];
- int len = strlen((char*)loc);
- int i = len - 1;
-
- dev_num = 0;
-
- while (i >= 0 && isdigit(loc[i])) {
- dev_num = dev_num * 10 + (loc[i] - '0');
- i--;
- }
-
- dev_num = reverse_number(dev_num);
-
- memcpy(temp, loc, i + 1);
- temp[i + 1] = '\0';
-
- while (dev) {
- if (!strcmp(temp, dev->slavepath) && dev_num == dev->dev_num) {
- is_slave = 1;
- return dev;
- } else if(!strcmp(temp,dev->masterpath) && dev_num == dev->dev_num) {
- is_slave = 0;
- return dev;
- }
- dev = dev->next;
- }
-
- return 0;
-}
-
-std::int32_t __devfs__open(userspace_fd_t* fd, char* path) {
- vfs::devfs_node_t* node = devfs_find_dev(path);
-
- if(!node)
- return ENOENT;
-
- if(node->open)
- return node->open(fd,path);
-
- if(!node->open_flags.is_pipe && !node->readring)
- return 0;
-
- if(node->open_flags.is_pipe) {
- fd->pipe = (vfs::pipe*)(node->pipe0 | (((uint64_t)node->pipe0 & (1 << 62)) << 63));
- fd->state = USERSPACE_FD_STATE_PIPE;
- fd->pipe_side = (node->pipe0 & (1 << 63)) ? PIPE_SIDE_WRITE : PIPE_SIDE_READ;
- } else {
- fd->queue = is_slave == 1 ? node->readring->ring.tail : node->writering->ring.tail;
- fd->cycle = is_slave == 1 ? node->readring->ring.cycle : node->writering->ring.cycle;
- }
-
- fd->is_a_tty = node->is_tty;
- fd->other_state = is_slave == 1 ? USERSPACE_FD_OTHERSTATE_SLAVE : USERSPACE_FD_OTHERSTATE_MASTER;
- return 0;
-}
-
-int is_printable(char c) {
- return (c >= 32 && c <= 126) || c == 10;
-}
-
-std::int64_t __devfs__write(userspace_fd_t* fd, char* path, void* buffer, std::uint64_t size) {
-
- vfs::devfs_node_t* node = devfs_find_dev(path);
-
- if(!node) { vfs::vfs::unlock();
- return -ENOENT; }
-
- if(node->write)
- return node->write(fd,buffer,size);
-
- if(is_slave == 1 && node->slave_write)
- return node->slave_write(fd,buffer,size);
-
- if(node->is_tty && !is_slave) { // handle stdio logic from /dev/pty writing
- vfs::vfs::unlock();
- for(int i = 0;i < size;i++) {
-
-
-
- char c = ((char*)buffer)[i];
-
- if(!(node->term_flags->c_lflag & ICANON)) {
- if(c == '\n') c = 13;
- }
-
- if((node->term_flags->c_lflag & ECHO) && (is_printable(c) || c == 13)) {
- if(c == 13) {
- node->writepipe->write("\n",1,0);
- } else if(c == '\n')
- node->writepipe->write("\r",1,0);
- asm volatile("cli");
- node->writepipe->write(&((char*)buffer)[i],1,0);
- asm volatile("cli");
- }
-
- if(c == '\b' || c == '\x7f' || c == '\x08') {
- if(node->readpipe->size > 0) {
- if(node->term_flags->c_lflag & ECHO) {
- const char* back = "\b \b";
- node->writepipe->write(back,strlen(back),0);
- asm volatile("cli");
- }
- node->readpipe->lock.lock();
- node->readpipe->read_counter--;
- node->readpipe->buffer[node->readpipe->size--] = '\0';
- node->readpipe->lock.unlock();
- }
- }
-
- if(is_printable(c) || !(node->term_flags->c_lflag & ICANON)) {
- node->readpipe->write(&c,1,0);
- asm volatile("cli");
- } else if(c == 13) {
- node->readpipe->write("\n",1,0);
- asm volatile("cli");
- }
-
- if((c == '\n' || c == 13) && (node->term_flags->c_lflag & ICANON)) {
- node->readpipe->set_tty_ret();
- }
-
- if(!(node->term_flags->c_lflag & ICANON) && node->readpipe->size >= node->term_flags->c_cc[VMIN]) {
- node->readpipe->set_tty_ret();
- }
-
- asm volatile("cli");
- }
- return size;
- } else if(node->is_tty && is_slave) {
- vfs::vfs::unlock();
- for(int i = 0;i < size;i++) {
- char c = ((char*)buffer)[i];
- if(c == '\n') {
- node->writepipe->write("\r\n",2,0);
- } else
- node->writepipe->write(&c,1,0);
- asm volatile("cli");
- }
- return size;
- }
-
- std::uint64_t status;
- int is_master = !is_slave;
- if(node->open_flags.is_pipe_rw) {
- vfs::vfs::unlock();
- status = is_master ? node->readpipe->write((char*)buffer,size,0) : node->writepipe->write((char*)buffer,size,0);
- } else {
- if(!is_master) {
- if(node->writering->ring.bytelen == 1) {
- node->writering->send(*(char*)buffer);
- } else if(node->writering->ring.bytelen == 2) {
- node->writering->send(*(short*)buffer);
- } else if(node->writering->ring.bytelen == 4) {
- node->writering->send(*(int*)buffer);
- } else if(node->writering->ring.bytelen == 8) {
- node->writering->send(*(long long*)buffer);
- }
- } else {
- if(node->readring->ring.bytelen == 1) {
- node->readring->send(*(char*)buffer);
- } else if(node->readring->ring.bytelen == 2) {
- node->readring->send(*(short*)buffer);
- } else if(node->readring->ring.bytelen == 4) {
- node->readring->send(*(int*)buffer);
- } else if(node->readring->ring.bytelen == 8) {
- node->readring->send(*(long long*)buffer);
- }
- }
- vfs::vfs::unlock();
- return node->writering->ring.bytelen;
- }
-
- return status;
-}
-
-std::int64_t __devfs__read(userspace_fd_t* fd, char* path, void* buffer, std::uint64_t count) {
-
- vfs::devfs_node_t* node = devfs_find_dev(path);
-
- if(!node) { vfs::vfs::unlock();
- return -ENOENT; }
-
- if(node->read)
- return node->read(fd,buffer,count);
-
- std::uint64_t status;
- int is_master = !is_slave;
-
- if(node->open_flags.is_pipe_rw) {
- vfs::vfs::unlock();
- if(!node->is_tty)
- status = is_master ? node->writepipe->read(&fd->read_counter,(char*)buffer,count,(fd->flags & O_NONBLOCK) ? 1 : 0) : node->readpipe->read(&fd->read_counter,(char*)buffer,count,(fd->flags & O_NONBLOCK) ? 1 : 0);
- else
- status = is_master ? node->writepipe->read(&fd->read_counter,(char*)buffer,count,(fd->flags & O_NONBLOCK) ? 1 : 0) : node->readpipe->ttyread(&fd->read_counter,(char*)buffer,count,(fd->flags & O_NONBLOCK) ? 1 : 0);
- } else {
- //DEBUG(1,"read %s ring count %d",path,count);
- status = is_master ? node->writering->receivevals(buffer,dev_num,count,&fd->cycle,&fd->queue) : node->readring->receivevals(buffer,dev_num,count,&fd->cycle,&fd->queue);
- vfs::vfs::unlock();
- }
-
- return status;
-}
-
-#define TIOCGPGRP 0x540F
-#define TIOCSPGRP 0x5410
-
-
-std::int32_t __devfs__ioctl(userspace_fd_t* fd, char* path, unsigned long req, void *arg, int *res) {
-
- vfs::devfs_node_t* node = devfs_find_dev(path);
- if(!node)
- return ENOENT;
-
- if(node->ioctl)
- return node->ioctl(fd,req,arg,res);
-
- if(!arg)
- return 0;
-
- if(req == 0x80045430 && node->is_tty) {
- // get pty num
- vfs::devfs_packet_t packet;
- packet.request = devfs_packet_get_num;
- packet.value = 0;
- std::int64_t status = vfs::devfs::send_packet(path,&packet);
- *res = status;
- *((int*)arg) = packet.value;
- return status;
- } else if(req == TIOCGPGRP && node->is_tty) {
- *(int*)arg = node->pgrp;
- *res = 0;
- return 0;
- } else if(req == TIOCSPGRP && node->is_tty) {
- node->pgrp = *(int*)arg;
- *res = 0;
- return 0;
- }
-
- vfs::devfs_packet_t packet;
- packet.request = DEVFS_PACKET_IOCTL;
- packet.ioctl.arg = (std::uint64_t)arg;
- packet.ioctl.ioctlreq = req;
- std::int64_t status = vfs::devfs::send_packet(path,&packet);
- *res = status;
- return status;
-}
-
-std::int32_t __devfs__mmap(userspace_fd_t* fd, char* path, std::uint64_t* outp, std::uint64_t* outsz, std::uint64_t* outflags) {
- vfs::devfs_node_t* node = devfs_find_dev(path);
- if(!node)
- return ENOENT;
-
- *outp = node->mmap_base;
- *outsz = node->mmap_size;
- *outflags = node->mmap_flags;
-
- return 0;
-}
-
-std::int32_t __devfs__var(userspace_fd_t* fd, char* path, std::uint64_t value, std::uint8_t request) {
-
- vfs::devfs_node_t* node = devfs_find_dev(path);
- if(!node)
- return ENOENT;
-
- int status = 0;
- if(request == DEVFS_VAR_ISATTY)
- status = node->is_tty ? 0 : ENOTTY;
-
- if((request & ~(1 << 7)) == TMPFS_VAR_CHMOD) {
- if(request & (1 << 7))
- node->mode = value & 0xFFFFFFFF;
- else
- *(std::uint64_t*)value = (std::uint64_t)node->mode;
- }
-
- return status;
-}
-
-std::int32_t __devfs__stat(userspace_fd_t* fd, char* path, vfs::stat_t* out) {
- if(!path)
- return EFAULT;
-
- DEBUG(1,"stat %s:%s",path,fd->path);
-
- if(path[0] == '\0') {
- path[0] = '/';
- path[1] = '\0';
- out->st_size = 0;
- out->st_mode = S_IFDIR;
- out->st_ino = 0;
- return 0;
- }
-
- vfs::devfs_node_t* node = devfs_find_dev(path);
-
- if(!node)
- return ENOENT;
-
- if(!out)
- return EINVAL;
-
- if(node->slavepath[0] == '/' && node->slavepath[1] == '\0') {
- out->st_size = 0;
- out->st_mode = S_IFDIR;
- out->st_ino = node->ino;
- out->st_mode |= 020666;
- } else {
- out->st_size = 0;
- out->st_mode = node->is_dir ? S_IFDIR : S_IFCHR;
- out->st_ino = node->ino;
- out->st_mode |= 0666;
- }
- return 0;
-}
-
-std::int32_t __devfs__ls(userspace_fd_t* fd, char* path, vfs::dirent_t* out) {
-
- if(!path)
- return EFAULT;
-
-againdev:
-
- vfs::devfs_node_t* nod = 0;
-
- if(fd->rv0 == 0 & fd->rv1 == 0) {
- fd->rv0 = (std::uint64_t)__devfs_head->next;
- nod = __devfs_head;
- } else if(fd->rv0 != 0) {
- nod = (vfs::devfs_node_t*)fd->rv0;
- fd->rv0 = (std::uint64_t)nod->next;
- }
-
- if(!nod) {
- out->d_reclen = 0;
- memset(out->d_name,0,sizeof(out->d_name));
- return 0;
- }
-
- if(nod->slavepath[0] == '/' && nod->slavepath[1] == '\0') {
- if(nod->slavepath[0] == '/' && nod->slavepath[1] == '\0')
- goto againdev;
- }
-
- memset(out->d_name,0,sizeof(out->d_name));
- __printfbuf(out->d_name,1024,nod->show_num == 1 ? "%s" : "%s%d",nod->slavepath + 1,nod->dev_num);
-
- out->d_reclen = sizeof(vfs::dirent_t);
- out->d_ino = fd->rv1++;
- out->d_off = 0;
- out->d_type = nod->is_dir ? S_IFDIR : S_IFCHR;
- fd->offset++;
-
- return 0;
-}
-
-std::int64_t __devfs__poll(userspace_fd_t* fd, char* path, int operation_type) {
-
- vfs::devfs_node_t* node = devfs_find_dev(path);
-
- std::int64_t ret = 0;
- if(node->open_flags.is_pipe_rw) {
- node->writepipe->lock.lock();
- node->readpipe->lock.lock();
- if(operation_type == POLLIN) {
- if(!is_slave) {
- ret = node->writepipe->size != 0 ? 1 : 0;
- } else {
- if(!node->is_tty)
- ret = node->readpipe->size != 0 ? 1 : 0;
- else {
- ret = (node->readpipe->tty_ret && node->readpipe->size != 0) != 0 ? 1 : 0;
- }
- }
- } else if(operation_type == POLLOUT) {
- if(!is_slave) {
- ret = node->writepipe->size != node->writepipe->total_size ? 1 : 0;
- } else {
- ret = node->readpipe->size != node->readpipe->total_size ? 1 : 0;
- }
- }
- node->writepipe->lock.unlock();
- node->readpipe->lock.unlock();
- } else {
- if(operation_type == POLLIN) {
- ret = 0;
- if(!is_slave) {
- if(node->writering->isnotempty((int*)&fd->queue,(char*)&fd->cycle)) {
- ret = 1;
- }
- } else if(is_slave) {
- if(node->readring->isnotempty((int*)&fd->queue,(char*)&fd->cycle)) {
- ret = 1;
-
- }
- }
-
- } else if(operation_type == POLLOUT) {
- ret = 1;
- }
- }
-
- return ret;
-}
-
-extern locks::spinlock* vfs_lock;
-
-std::uint64_t devfs_ino_ptr = 1;
-
-std::int64_t vfs::devfs::send_packet(char* path,devfs_packet_t* packet) {
- devfs_node_t* node = devfs_find_dev(path);
-
- switch(packet->request) {
- case DEVFS_PACKET_CREATE_DEV: {
- devfs_node_t* new_node = (devfs_node_t*)memory::pmm::_virtual::alloc(4096);
- memcpy(new_node->slavepath,path,strlen(path));
- memcpy(new_node->masterpath,(char*)packet->value,strlen((const char*)packet->value)); /* Actually path is slavepath and pcket.value is masterpath when driver creates new device */
- new_node->readring = new Lists::Ring(128);
- new_node->writering = new Lists::Ring(128);
- new_node->dev_num = packet->size;
- new_node->next = __devfs_head;
- new_node->ino = devfs_ino_ptr++;
- __devfs_head = new_node;
- return 0;
- }
-
- case DEVFS_PACKET_CREATE_PIPE_DEV: {
- devfs_node_t* new_node = (devfs_node_t*)memory::pmm::_virtual::alloc(4096);
- memcpy(new_node->slavepath,path,strlen(path));
- memcpy(new_node->masterpath,(char*)packet->value,strlen((const char*)packet->value));
- new_node->readpipe = new pipe(0);
- new_node->writepipe = new pipe(0);
- //DEBUG(1,"%d %d\n",new_node->readpipe->size.load(),new_node->writepipe->size.load());
- new_node->readpipe->create(PIPE_SIDE_READ);
- new_node->readpipe->create(PIPE_SIDE_WRITE);
- new_node->writepipe->create(PIPE_SIDE_READ);
- new_node->writepipe->create(PIPE_SIDE_WRITE);
- new_node->dev_num = packet->size;
- new_node->open_flags.is_pipe_rw = 1;
- new_node->next = __devfs_head;
- new_node->ino = devfs_ino_ptr++;
- __devfs_head = new_node;
- return 0;
- }
-
- case DEVFS_PACKET_IOCTL: {
-
- if(!node)
- return ENOENT;
-
- if(!packet->ioctl.arg)
- return 0;
-
- std::uint64_t originalreq = packet->ioctl.ioctlreq;
-
- if(packet->ioctl.ioctlreq == TCGETS2)
- packet->ioctl.ioctlreq = TCGETS;
-
- if(packet->ioctl.ioctlreq == TCSETS2 || packet->ioctl.ioctlreq == TCSETSW2 || packet->ioctl.ioctlreq == TCSETSF2)
- packet->ioctl.ioctlreq = TCSETS;
-
- for(int i = 0;i < 32;i++) {
- if(node->ioctls[i].read_req == packet->ioctl.ioctlreq) { /* Read */
- if(node->is_tty) {
- if(originalreq == TCGETS2)
- memcpy((void*)packet->ioctl.arg,node->ioctls[i].pointer_to_struct,sizeof(termios_t));
- else if(originalreq == TCGETS)
- memcpy((void*)packet->ioctl.arg,node->ioctls[i].pointer_to_struct,sizeof(termiosold_t));
- else
- memcpy((void*)packet->ioctl.arg,node->ioctls[i].pointer_to_struct,node->ioctls[i].size);
- } else
- memcpy((void*)packet->ioctl.arg,node->ioctls[i].pointer_to_struct,node->ioctls[i].size);
- return 0;
- } else if(node->ioctls[i].write_req == packet->ioctl.ioctlreq) { /* Write */
- if(node->is_tty) {
- if(originalreq == TCSETS) {
- memcpy(node->ioctls[i].pointer_to_struct,(void*)packet->ioctl.arg,sizeof(termiosold_t));
- } else
- memcpy(node->ioctls[i].pointer_to_struct,(void*)packet->ioctl.arg,node->ioctls[i].size);
-
- } else
- memcpy(node->ioctls[i].pointer_to_struct,(void*)packet->ioctl.arg,node->ioctls[i].size);
- return 0;
- }
- }
- return 0;
- }
- case DEVFS_PACKET_SIZE_IOCTL: {
-
- if(!node)
- return -ENOENT;
-
- for(int i = 0;i < 32;i++) {
- if(node->ioctls[i].read_req == packet->ioctl.ioctlreq) { /* Read */
- return node->ioctls[i].size;
- } else if(node->ioctls[i].write_req == packet->ioctl.ioctlreq) { /* Write */
- return node->ioctls[i].size;
- }
- }
- return -EINVAL;
- }
- case DEVFS_PACKET_CREATE_IOCTL: {
-
- if(!node)
- return ENOENT;
-
- for(int i = 0;i < 32;i++) {
- if(node->ioctls[i].pointer_to_struct == 0) {
- devfs_ioctl_packet_t* current = &node->ioctls[i];
- current->read_req = packet->create_ioctl.readreg;
- current->write_req = packet->create_ioctl.writereg;
- current->pointer_to_struct = (void*)packet->create_ioctl.pointer;
- current->size = packet->create_ioctl.size;
-
- if(current->write_req == TCSETS) {
- node->writepipe->ttyflags = 0;
- node->readpipe->ttyflags = (termios_t*)packet->create_ioctl.pointer;
- node->term_flags = (termios_t*)packet->create_ioctl.pointer;
- }
-
- return 0;
- }
- }
- }
- case DEVFS_ENABLE_PIPE: {
-
- if(!node)
- return ENOENT;
-
- node->pipe0 = packet->enable_pipe.pipe_pointer;
- node->open_flags.is_pipe = 1;
- return 0;
- }
-
- case DEVFS_SETUP_MMAP: {
-
- if(!node)
- return ENOENT;
-
- node->mmap_base = packet->setup_mmap.dma_addr;
- node->mmap_size = packet->setup_mmap.size;
- node->mmap_flags = packet->setup_mmap.flags;
- return 0;
- }
-
- case DEVFS_PACKET_ISATTY:
-
- if(!node)
- return ENOENT;
-
- if(node->is_tty)
- return 0;
- else
- return ENOTTY;
-
- case DEVFS_PACKET_SETUPTTY:
-
- if(!node)
- return ENOENT;
-
- node->is_tty = 1;
- return 0;
-
- case devfs_packet_get_num:
-
- if(!node)
- return ENOENT;
-
- packet->value = node->dev_num;
- return 0;
-
- case DEVFS_GETSLAVE_BY_MASTER:
-
- if(!node)
- return ENOENT;
-
- __printfbuf((char*)packet->value,256,"%s%d",node->slavepath,node->dev_num);
-
- return 0;
-
- case DEVFS_PACKET_SETUP_RING_SIZE:
-
- if(!node)
- return ENOENT;
-
- if(!node->open_flags.is_pipe) {
- node->readring->setup_bytelen(packet->size);
- node->writering->setup_bytelen(packet->size);
- }
-
- return 0;
-
- }
-
- vfs::vfs::unlock();
- return 0;
-}
-
-# define NLDLY 0000400 /* Select newline delays: */
-# define NL0 0000000 /* Newline type 0. */
-# define NL1 0000400 /* Newline type 1. */
-# define CRDLY 0003000 /* Select carriage-return delays: */
-# define CR0 0000000 /* Carriage-return delay type 0. */
-# define CR1 0001000 /* Carriage-return delay type 1. */
-# define CR2 0002000 /* Carriage-return delay type 2. */
-# define CR3 0003000 /* Carriage-return delay type 3. */
-# define TABDLY 0014000 /* Select horizontal-tab delays: */
-# define TAB0 0000000 /* Horizontal-tab delay type 0. */
-# define TAB1 0004000 /* Horizontal-tab delay type 1. */
-# define TAB2 0010000 /* Horizontal-tab delay type 2. */
-# define TAB3 0014000 /* Expand tabs to spaces. */
-# define BSDLY 0020000 /* Select backspace delays: */
-# define BS0 0000000 /* Backspace-delay type 0. */
-# define BS1 0020000 /* Backspace-delay type 1. */
-# define FFDLY 0100000 /* Select form-feed delays: */
-# define FF0 0000000 /* Form-feed delay type 0. */
-# define FF1 0100000 /* Form-feed delay type 1. */
-
-#define OPOST 0000001 /* Post-process output. */
-#define OLCUC 0000002
-#define ONLCR 0000004 /* Map NL to CR-NL on output. */
-#define OCRNL 0000010 /* Map CR to NL on output. */
-#define ONOCR 0000020 /* No CR output at column 0. */
-#define ONLRET 0000040 /* NL performs CR function. */
-#define OFILL 0000100 /* Use fill characters for delay. */
-
-#define IUCLC 0x0200
-#define IXON 0x0400
-#define IXOFF 0x1000
-#define IMAXBEL 0x2000
-#define IUTF8 0x4000
-#define CREAD 0x00000080
-#define PARENB 0x00000100
-#define PARODD 0x00000200
-#define HUPCL 0x00000400
-#define CLOCAL 0x00000800
-#define CBAUDEX 0x00001000
-#define BOTHER 0x00001000
-#define B57600 0x00001001
-#define B115200 0x00001002
-#define B230400 0x00001003
-#define B460800 0x00001004
-#define B500000 0x00001005
-#define B576000 0x00001006
-#define B921600 0x00001007
-#define B1000000 0x00001008
-#define B1152000 0x00001009
-#define B1500000 0x0000100a
-#define B2000000 0x0000100b
-#define B2500000 0x0000100c
-#define B3000000 0x0000100d
-
-#define ISIG 0x00001
-#define XCASE 0x00004
-#define ECHOE 0x00010
-#define ECHOK 0x00020
-#define ECHONL 0x00040
-#define NOFLSH 0x00080
-#define TOSTOP 0x00100
-#define ECHOCTL 0x00200
-#define ECHOPRT 0x00400
-#define ECHOKE 0x00800
-#define FLUSHO 0x01000
-#define PENDIN 0x04000
-#define IEXTEN 0x08000
-#define EXTPROC 0x10000
-
-int is_early = 1;
-
-int tty_ptr = 0;
-std::int32_t __ptmx_open(userspace_fd_t* fd, char* path) {
-
- memset(fd->path,0,2048);
- __printfbuf(fd->path,2048,"/dev/tty");
- char ttyname[2048];
- memset(ttyname,0,2048);
- __printfbuf(ttyname,2048,"/dev/pts/");
-
- vfs::devfs_packet_t packet;
- packet.size = tty_ptr;
- packet.request = DEVFS_PACKET_CREATE_PIPE_DEV;
- packet.value = (std::uint64_t)fd->path + 4;
-
- vfs::devfs::send_packet(ttyname + 4,&packet);
-
- memset(fd->path,0,2048);
- __printfbuf(fd->path,2048,"/dev/tty%d",tty_ptr);
- memset(ttyname,0,2048);
- __printfbuf(ttyname,2048,"/dev/pts/%d",tty_ptr);
-
- packet.request = DEVFS_PACKET_SETUPTTY;
- packet.value = (std::uint64_t)fd->path + 4;
-
- vfs::devfs::send_packet(ttyname + 4,&packet);
-
- termios_t* t = (termios_t*)memory::pmm::_virtual::alloc(4096);
-
- t->c_lflag |= (ICANON | ECHO);
-
- t->c_iflag = IGNPAR | ICRNL;
- t->c_oflag = OPOST;
- t->c_cflag |= (CS8);
-
- packet.request = DEVFS_PACKET_CREATE_IOCTL;
- packet.create_ioctl.pointer = (std::uint64_t)t;
- packet.create_ioctl.size = sizeof(termios_t);
- packet.create_ioctl.readreg = TCGETS;
- packet.create_ioctl.writereg = TCSETS;
-
- vfs::devfs::send_packet(ttyname + 4,&packet);
-
- std::uint64_t wins = (uint64_t)memory::pmm::_virtual::alloc(4096);
-
- packet.request = DEVFS_PACKET_CREATE_IOCTL;
- packet.create_ioctl.pointer = (uint64_t)wins;
- packet.create_ioctl.size = sizeof(struct winsize);
- packet.create_ioctl.readreg = TIOCGWINSZ;
- packet.create_ioctl.writereg = TIOCSWINSZ;
-
- if(is_early) {
- winsizez ws = Log::GetDimensions();
- memcpy((void*)wins,&ws,sizeof(winsize));
- is_early = 0;
- }
-
- vfs::devfs::send_packet(ttyname + 4,&packet);
-
- fd->other_state = USERSPACE_FD_OTHERSTATE_MASTER;
- __printfbuf(fd->path,2048,"/dev/tty%d",tty_ptr);
-
- tty_ptr++;
-
- return 0;
-}
-
-std::int64_t __irq_write(userspace_fd_t* fd, void* buffer, std::uint64_t size) {
- drivers::ioapic::unmask(dev_num);
- vfs::vfs::unlock();
- return size;
-}
-
-std::int64_t __pic_write(userspace_fd_t* fd, void* buffer, std::uint64_t size) {
- if(size != 10) {vfs::vfs::unlock();
- return -EINVAL; }
-
- std::uint16_t irq_num = *(std::uint16_t*)((std::uint64_t)buffer);
- std::uint64_t ioapic_flags = *(std::uint64_t*)((std::uint64_t)buffer + 2);
-
- const char* path0 = "/masterirq";
- const char* path1 = "/irq";
-
- vfs::devfs_node_t* new_node = (vfs::devfs_node_t*)memory::pmm::_virtual::alloc(4096);
- memcpy(new_node->slavepath,path1,strlen(path1));
- memcpy(new_node->masterpath,(char*)path0,strlen((const char*)path0));
- new_node->readring = new Lists::Ring(128);
- new_node->writering = new Lists::Ring(128);
- new_node->dev_num = irq_num;
- new_node->next = __devfs_head;
- new_node->slave_write = __irq_write;
- __devfs_head = new_node;
-
- new_node->writering->setup_bytelen(1);
- new_node->readring->setup_bytelen(1);
-
- arch::x86_64::interrupts::irq::create(irq_num,IRQ_TYPE_LEGACY_USERSPACE,0,0,ioapic_flags);
- drivers::ioapic::unmask(irq_num);
-
- vfs::vfs::unlock();
- return 10;
-
-}
-
-std::int64_t __zero_write(userspace_fd_t* fd, void* buffer, std::uint64_t size) {
- vfs::vfs::unlock();
- return size;
-}
-
-std::int64_t __zero_read(userspace_fd_t* fd, void* buffer, std::uint64_t count) {
- vfs::vfs::unlock(); // dont waste time on this
- memset(buffer,0,count);
- return 0;
-}
-
-std::int64_t __random_write(userspace_fd_t* fd, void* buffer, std::uint64_t size) {
- vfs::vfs::unlock();
- return size;
-}
-
-std::uint64_t next = 2;
-
-std::uint64_t __rand() {
- uint64_t t = __rdtsc();
- return t * (++next);
-}
-
-std::int64_t __random_read(userspace_fd_t* fd, void* buffer, std::uint64_t count) {
- vfs::vfs::unlock(); // dont waste time on this
- memset(buffer,0,count);
- for(std::uint64_t i = 0; i < count; i++) {
- ((char*)buffer)[i] = __rand() & 0xFF;
- }
- return count;
-}
-
-#include <etc/bootloaderinfo.hpp>
-
-#define FBIOGET_VSCREENINFO 0x4600
-#define FBIOPUT_VSCREENINFO 0x4601
-#define FBIOGET_FSCREENINFO 0x4602
-#define FB_VISUAL_TRUECOLOR 2 /* True color */
-#define FB_TYPE_PACKED_PIXELS 0 /* Packed Pixels */
-
-vfs::devfs_node_t* ktty_node = 0;
-
-void vfs::devfs::mount(vfs_node_t* node) {
- __devfs_head = (devfs_node_t*)memory::pmm::_virtual::alloc(4096);
- memcpy(__devfs_head->slavepath,"/\0",2);
-
- __devfs_head->show_num = 1;
- node->open = __devfs__open;
- node->read = __devfs__read;
- node->write = __devfs__write;
- node->ioctl = __devfs__ioctl;
- node->mmap = __devfs__mmap;
- node->var = __devfs__var;
- node->stat = __devfs__stat;
- node->poll = __devfs__poll;
- node->ls = __devfs__ls;
-
- const char* name = "/ptmx";
-
- devfs_packet_t packet;
- packet.size = tty_ptr;
- packet.request = DEVFS_PACKET_CREATE_PIPE_DEV;
- packet.value = (std::uint64_t)name;
-
- send_packet((char*)name,&packet);
-
- __devfs_head->show_num = 1;
- __devfs_head->open = __ptmx_open;
-
- packet.size = tty_ptr;
- packet.request = DEVFS_PACKET_CREATE_PIPE_DEV;
- packet.value = (std::uint64_t)"/input";
-
- send_packet((char*)"/input",&packet);
-
- __devfs_head->is_dir = 1;
- __devfs_head->show_num = 1;
-
- const char* name0 = "/pic";
-
- packet.size = tty_ptr;
- packet.request = DEVFS_PACKET_CREATE_DEV;
- packet.value = (std::uint64_t)name0;
-
- send_packet((char*)name0,&packet);
-
- /* The head should be this dev so all ok */
-
- __devfs_head->show_num = 1;
- __devfs_head->write = __pic_write;
-
-
- const char* name00 = "/null";
-
- packet.size = 0;
- packet.request = DEVFS_PACKET_CREATE_DEV;
- packet.value = (std::uint64_t)name00;
-
- send_packet((char*)name00,&packet);
-
- __devfs_head->show_num = 1;
- __devfs_head->write = __zero_write;
- __devfs_head->read = __zero_read;
-
- const char* name001 = "/urandom";
-
- packet.size = 0;
- packet.request = DEVFS_PACKET_CREATE_DEV;
- packet.value = (std::uint64_t)name001;
-
- send_packet((char*)name001,&packet);
-
- __devfs_head->show_num = 1;
- __devfs_head->write = __random_write;
- __devfs_head->read = __random_read;
-
- // liborange_create_dev(((uint64_t)DEVFS_PACKET_CREATE_DEV << 32) | 0, "/ps2keyboard", "/masterps2keyboard");
- // liborange_setup_ring_bytelen("/ps2keyboard0",1);
-
- // liborange_create_dev(((uint64_t)DEVFS_PACKET_CREATE_DEV << 32) | 0, "/mouse", "/mastermouse");
- // liborange_setup_ring_bytelen("/mouse0",4);
-
- packet.size = 0;
- __devfs_head->show_num = 1;
- packet.request = DEVFS_PACKET_CREATE_DEV;
- packet.value = (std::uint64_t)"/masterps2keyboard";
-
- send_packet((char*)"/ps2keyboard",&packet);
-
- __devfs_head->readring->setup_bytelen(1);
- __devfs_head->writering->setup_bytelen(1);
-
- packet.size = 0;
- __devfs_head->show_num = 1;
- packet.request = DEVFS_PACKET_CREATE_DEV;
- packet.value = (std::uint64_t)"/mastermouse";
-
- send_packet("/mouse",&packet);
-
- __devfs_head->readring->setup_bytelen(4);
- __devfs_head->writering->setup_bytelen(4);
-
- struct limine_framebuffer fb = *BootloaderInfo::AccessFramebuffer();
-
- packet.size = 0;
- packet.request = DEVFS_PACKET_CREATE_DEV;
- packet.value = (std::uint64_t)"/zfb";
-
- send_packet("/fb",&packet);
-
- __devfs_head->mmap_base = (std::uint64_t)((std::uint64_t)fb.address - BootloaderInfo::AccessHHDM());
- __devfs_head->mmap_size = fb.pitch * fb.height;
- __devfs_head->mmap_flags = PTE_WC;
-
- struct fb_var_screeninfo* vinfo = (struct fb_var_screeninfo*)memory::pmm::_virtual::alloc(sizeof(struct fb_var_screeninfo));;
- struct fb_fix_screeninfo* finfo = (struct fb_fix_screeninfo*)memory::pmm::_virtual::alloc(sizeof(struct fb_fix_screeninfo));
-
- devfs_packet_t packeta;
- packeta.create_ioctl.readreg = FBIOGET_VSCREENINFO;
- packeta.create_ioctl.writereg = 0;
- packeta.create_ioctl.request = DEVFS_PACKET_CREATE_IOCTL;
- packeta.create_ioctl.size = sizeof(struct fb_var_screeninfo);
- packeta.create_ioctl.pointer = (std::uint64_t)vinfo;
- send_packet("/fb0",&packeta);
-
- packeta.create_ioctl.readreg = FBIOGET_FSCREENINFO;
- packeta.create_ioctl.writereg = 0;
- packeta.create_ioctl.request = DEVFS_PACKET_CREATE_IOCTL;
- packeta.create_ioctl.size = sizeof(struct fb_fix_screeninfo);
- packeta.create_ioctl.pointer = (std::uint64_t)finfo;
- send_packet("/fb0",&packeta);
-
- vinfo->red.length = fb.red_mask_size;
- vinfo->red.offset = fb.red_mask_shift;
- vinfo->blue.offset = fb.blue_mask_shift;
- vinfo->blue.length = fb.blue_mask_size;
- vinfo->green.length = fb.green_mask_size;
- vinfo->green.offset = fb.green_mask_shift;
- vinfo->xres = fb.width;
- vinfo->yres = fb.height;
- vinfo->bits_per_pixel = fb.bpp < 5 ? (fb.bpp * 8) : fb.bpp;
- vinfo->xres_virtual = fb.width;
- vinfo->yres_virtual = fb.height;
- vinfo->red.msb_right = 1;
- vinfo->green.msb_right = 1;
- vinfo->blue.msb_right = 1;
- vinfo->transp.msb_right = 1;
- vinfo->height = -1;
- vinfo->width = -1;
- finfo->line_length = fb.pitch;
- finfo->smem_len = fb.pitch * fb.height;
- finfo->visual = FB_VISUAL_TRUECOLOR;
- finfo->type = FB_TYPE_PACKED_PIXELS;
- finfo->mmio_len = fb.pitch * fb.height;
-
- // now init kernel tty
- userspace_fd_t hi;
- memset(&hi,0,sizeof(userspace_fd_t));
- memcpy(hi.path,"/dev/ptmx",sizeof("/dev/ptmx"));
- __ptmx_open(&hi,"/ptmx");
-
-} \ No newline at end of file
diff --git a/kernel/src/generic/vfs/evdev.cpp b/kernel/src/generic/vfs/evdev.cpp
deleted file mode 100644
index 4868473..0000000
--- a/kernel/src/generic/vfs/evdev.cpp
+++ /dev/null
@@ -1,304 +0,0 @@
-
-#include <generic/vfs/vfs.hpp>
-#include <generic/vfs/devfs.hpp>
-#include <generic/vfs/evdev.hpp>
-#include <etc/logging.hpp>
-
-#include <cstdint>
-
-vfs::evdev_node* evdev_head_node = 0;
-
-int evdev_num = 0;
-
-inline bool isdigit(char ch) {
- return ch >= '0' && ch <= '9';
-}
-
-inline long reverse_number(long num) {
- long reversed_num = 0;
-
- while(num > 0) {
- int digit = num % 10;
- reversed_num = reversed_num * 10 + digit;
- num /= 10;
- }
-
- return reversed_num;
-}
-
-vfs::evdev_node* evdev_find_by_num(int num) {
- vfs::evdev_node* dev = evdev_head_node;
- while (dev) {
- if (num == dev->num) {
- return dev;
- }
- dev = dev->next;
- }
-
- return 0;
-}
-
-vfs::evdev_node* evdev_find_dev(const char* loc) {
- vfs::evdev_node* dev = evdev_head_node;
- char temp[256];
- int len = strlen((char*)loc);
- int i = len - 1;
-
- evdev_num = 0;
-
- while (i >= 0 && isdigit(loc[i])) {
- evdev_num = evdev_num * 10 + (loc[i] - '0');
- i--;
- }
-
- evdev_num = reverse_number(evdev_num);
-
- memcpy(temp, loc, i + 1);
- temp[i + 1] = '\0';
-
- while (dev) {
- if (!strcmp(temp,"/event") && evdev_num == dev->num) {
- return dev;
- }
- dev = dev->next;
- }
-
- return 0;
-}
-
-std::int32_t __evdev__open(userspace_fd_t* fd, char* path) {
-
- if(path[0] == '\0' || (path[0] == '/' && path[1] == '\0'))
- return 0;
-
- vfs::evdev_node* node = evdev_find_dev(path);
- if(!node)
- return ENOENT;
-
- if(node->main_ring) {
- fd->queue = node->main_ring->ring.tail;
- fd->cycle = node->main_ring->ring.cycle;
- }
-
- return 0;
-}
-
-std::int32_t __evdev__stat(userspace_fd_t* fd, char* path, vfs::stat_t* out) {
- memset(out,0,sizeof(vfs::stat_t));
- if(path[0] == '\0' || (path[0] == '/' && path[1] == '\0')) {
- out->st_ino = 0;
- out->st_mode |= S_IFDIR;
- return 0;
- }
-
- vfs::evdev_node* node = evdev_find_dev(path);
- if(!node)
- return -EINVAL;
-
- out->st_ino = node->num + 1;
- out->st_mode = S_IFCHR;
- return 0;
-}
-
-std::int32_t __evdev__statx(userspace_fd_t* fd, char* path, int flags, int mask, statx_t* out) {
- memset(out,0,sizeof(statx_t));
-
- if(path[0] == '\0' || (path[0] == '/' && path[1] == '\0')) {
- out->stx_mask = STATX_BASIC_STATS;
- out->stx_blksize = 4096;
- out->stx_nlink = 0;
- out->stx_uid = 0;
- out->stx_gid = 0;
- out->stx_mode = S_IFDIR;
- out->stx_ino = 0;
- out->stx_size = 0;
- out->stx_blocks = 0;
- out->stx_atime.tv_sec = 0;
- out->stx_atime.tv_nsec = 0;
- out->stx_btime.tv_sec = 0;
- out->stx_btime.tv_nsec = 0;
- out->stx_ctime.tv_sec = 0;
- out->stx_ctime.tv_nsec = 0;
- out->stx_mtime.tv_sec = 0;
- out->stx_mtime.tv_nsec = 0;
- out->stx_rdev_major = 0;
- out->stx_rdev_minor = 0;
- out->stx_dev_major = 0;
- out->stx_dev_minor = 0;
- return 0;
- }
-
- vfs::evdev_node* node = evdev_find_dev(path);
- if(!node)
- return -EINVAL;
-
- out->stx_mask = STATX_BASIC_STATS;
- out->stx_blksize = 4096;
- out->stx_nlink = 0;
- out->stx_uid = 0;
- out->stx_gid = 0;
- out->stx_mode = S_IFCHR;
- out->stx_ino = node->num + 1;
- out->stx_size = 0;
- out->stx_blocks = 0;
- out->stx_atime.tv_sec = 0;
- out->stx_atime.tv_nsec = 0;
- out->stx_btime.tv_sec = 0;
- out->stx_btime.tv_nsec = 0;
- out->stx_ctime.tv_sec = 0;
- out->stx_ctime.tv_nsec = 0;
- out->stx_mtime.tv_sec = 0;
- out->stx_mtime.tv_nsec = 0;
- out->stx_rdev_major = 0;
- out->stx_rdev_minor = 0;
- out->stx_dev_major = 0;
- out->stx_dev_minor = 0;
- return 0;
-}
-
-std::int32_t __evdev__ls(userspace_fd_t* fd, char* path, vfs::dirent_t* out) {
-againdev:
- vfs::evdev_node* nod = 0;
-
- if(fd->rv0 == 0 & fd->rv1 == 0) {
- fd->rv0 = (std::uint64_t)evdev_head_node->next;
- nod = evdev_head_node;
- } else if(fd->rv0 != 0) {
- nod = (vfs::evdev_node*)fd->rv0;
- fd->rv0 = (std::uint64_t)nod->next;
- }
-
- if(!nod) {
- out->d_reclen = 0;
- memset(out->d_name,0,sizeof(out->d_name));
- return 0;
- }
-
- memset(out->d_name,0,sizeof(out->d_name));
- __printfbuf(out->d_name,1024,"event%d",nod->num);
-
- out->d_reclen = sizeof(vfs::dirent_t);
- out->d_ino = fd->rv1++;
- out->d_off = 0;
- out->d_type = S_IFCHR;
- fd->offset++;
- return 0;
-}
-
-std::int64_t __evdev__read(userspace_fd_t* fd, char* path, void* buffer, std::uint64_t count) {
- vfs::evdev_node* node = evdev_find_dev(path);
- if(!node) {
- vfs::vfs::unlock();
- return -ENOENT;
- }
-
- if(node->main_ring) {
- std::uint64_t c = node->main_ring->receivevals(buffer, count, &fd->cycle, &fd->queue);
- vfs::vfs::unlock();
- return c;
- }
- assert(0,"BROOOOOO");
- return -EFAULT;
-}
-
-std::int64_t __evdev__write(userspace_fd_t* fd, char* path, void* buffer, std::uint64_t size) {
- vfs::vfs::unlock();
- return -ENOTSUP;
-}
-
-int __bitmap_size(int c) {
- return ALIGNUP(c,8) / 8;
-}
-
-std::int32_t __evdev__ioctl(userspace_fd_t* fd, char* path, unsigned long req, void *arg, int *res) {
-
- vfs::evdev_node* node = evdev_find_dev(path);
- if(!node)
- return -EINVAL;
-
- std::uint64_t size = _IOC_SIZE(req);
-
- if (_IOC_DIR(req) == _IOC_READ && (_IOC_NR(req) & ~EV_MAX) == _IOC_NR(EVIOCGBIT(0, 0))) {
- switch(_IOC_NR(req) & EV_MAX) {
- case 0:
- memcpy(arg,node->ev_bitmap->pool,__bitmap_size(EV_MAX));
- return 0;
- }
- assert(0,"doing req %d",_IOC_NR(req) & EV_MAX);
- } else {
- switch(EVIOC_MASK_SIZE(req)) {
- case EVIOCGNAME(0):
- memcpy(arg, node->name, size > strlen(node->name) ? size : strlen(node->name));
- return 0;
- };
- }
-
- assert(0, "ioctl req 0x%p arg 0x%p path %s rev 0x%p",EVIOC_MASK_SIZE(req),arg,path,_IOC_NR(req) & EV_MAX);
-}
-
-std::int64_t __evdev__poll(userspace_fd_t* fd, char* path, int operation_type) {
-
- vfs::evdev_node* node = evdev_find_dev(path);
- if(!node)
- return -EINVAL;
-
- if(!node->main_ring)
- return 0; // always return will block
-
- int ret;
- if(operation_type == POLLIN) {
- ret = 0;
- if(node->main_ring->isnotempty((int*)&fd->queue,(char*)&fd->cycle)) {
- ret = 1;
- }
-
- } else if(operation_type == POLLOUT) {
- ret = 1;
- }
- return ret;
-}
-
-#define BITS_PER_LONG (8 * sizeof(long))
-#define IS_SET(bit, array) ((array[(bit) / BITS_PER_LONG] >> ((bit) % BITS_PER_LONG)) & 1)
-
-int vfs::evdev::create(char* name, int type) {
- evdev_node* new_node = (evdev_node*)memory::pmm::_virtual::alloc(4096);
- new_node->num = evdev_num++;
- memcpy(new_node->path,"/event\0",7);
- new_node->main_ring = new evdev_modif_ring(256);
- memcpy(new_node->name,name,strlen(name) + 1);
-
- if(type == EVDEV_TYPE_KEYBOARD) {
- new_node->ev_bitmap = new Lists::Bitmap(EV_MAX + 1);
- new_node->ev_bitmap->set(EV_KEY);
- new_node->ev_bitmap->set(EV_REP);
- } else if(type == EVDEV_TYPE_MOUSE) {
- new_node->ev_bitmap = new Lists::Bitmap(EV_MAX + 1);
- new_node->ev_bitmap->set(EV_REL);
- new_node->ev_bitmap->set(EV_SYN);
- }
-
- new_node->next = evdev_head_node;
- new_node->type = type;
- evdev_head_node = new_node;
- Log::Display(LEVEL_MESSAGE_INFO,"evdev: new device /dev/input/event%d with name \"%s\" and type %d\n",new_node->num,name,type);
- return new_node->num;
-}
-
-void vfs::evdev::submit(int num, input_event event) {
- evdev_node* node = evdev_find_by_num(num);
- assert(node, "evdev node with num %d not found",num);
- assert(node->main_ring, "wtf !7&77177171???!?!!?771711771 %d %s 0x%p",num,node->name,node->main_ring);
- node->main_ring->send(event);
-}
-
-void vfs::evdev::mount(vfs_node_t* node) {
- node->open = __evdev__open;
- node->stat = __evdev__stat;
- node->statx = __evdev__statx;
- node->ls = __evdev__ls;
- node->read = __evdev__read;
- node->write = __evdev__write;
- node->poll = __evdev__poll;
- node->ioctl = __evdev__ioctl;
-} \ No newline at end of file
diff --git a/kernel/src/generic/vfs/tmpfs.cpp b/kernel/src/generic/vfs/tmpfs.cpp
deleted file mode 100644
index b3ad3c1..0000000
--- a/kernel/src/generic/vfs/tmpfs.cpp
+++ /dev/null
@@ -1,1065 +0,0 @@
-
-#include <cstdint>
-#include <generic/vfs/tmpfs.hpp>
-#include <generic/vfs/vfs.hpp>
-
-#include <generic/mm/pmm.hpp>
-#include <generic/mm/heap.hpp>
-
-#include <etc/etc.hpp>
-
-#include <etc/hash.hpp>
-
-#include <etc/libc.hpp>
-#include <etc/errno.hpp>
-
-#include <drivers/cmos.hpp>
-#include <drivers/tsc.hpp>
-
-#include <etc/logging.hpp>
-
-std::uint64_t __tmpfs_ptr_id = 0;
-
-vfs::tmpfs_node_t* head_node = 0;
-vfs::tmpfs_node_t* root_node = 0;
-
-vfs::tmpfs_node_t* __tmpfs__find(const char* path) {
-
- extern locks::spinlock* vfs_lock;
-
- if(path[0] == '/' && path[1] == '\0')
- return root_node;
-
- if(path[0] == '\0')
- return root_node;
-
- char built_path[2048];
- char copied_path[2048];
- memcpy(copied_path,path,strlen(path) + 1);
- memset(built_path,0,2048);
- char* next = 0;
- char* token = __vfs__strtok(&next, copied_path, "/");
-
- std::uint64_t need_hash = hash_fnv1(path);
- std::uint64_t ptr = 0;
-
- vfs::tmpfs_node_t* current = root_node;
- while(token) {
-
- built_path[ptr] = '/';
- ptr++;
-
- memcpy((char*)((uint64_t)built_path + ptr),token,strlen(token));
- ptr += strlen(token);
- built_path[ptr] = '\0';
-
- std::uint64_t rehashed = hash_fnv1(built_path);
- if(current->type != VFS_TYPE_DIRECTORY) {
- return 0;
- } else if(current->path_hash == need_hash)
- return current;
-
- int is_cont = 1;
-
- std::uint64_t* cont = (std::uint64_t*)current->content;
- if(current->content) {
- for(std::uint64_t i = 0; (i < (current->size / 8)) && is_cont; i++) {
- vfs::tmpfs_node_t* chld = (vfs::tmpfs_node_t*)cont[i];
- if(chld) {
- if(chld->path_hash == rehashed) {
- current = chld;
- is_cont = 0;
- goto end;
- }
- }
- }
- }
-end:
- if(is_cont)
- return 0;
-
- if(current->path_hash == need_hash)
- return current;
-
- token = __vfs__strtok(&next,0,"/");
- }
-
- if(current->path_hash == need_hash)
- return current;
-
- return 0;
-}
-
-void __tmpfs__find_dir(char *path) {
- char *last_slash = strrchr(path, '/');
- if (last_slash!= NULL && last_slash!= path) {
- *last_slash = '\0';
- } else {
- path[1] = '\0';
- }
-}
-
-char* __tmpfs__find_name(char* path) {
- char* last_slash = 0;
- while (*path) {
- if (*path == '/') {
- last_slash = path;
- }
- path++;
- }
- if (last_slash) {
- return last_slash + 1;
- }
- return path;
-}
-
-vfs::tmpfs_node_t* __tmpfs__symfind(char* path) {
- return __tmpfs__find(path); // symlinks will be handled by vfs
-}
-
-std::uint8_t __tmpfs__exists(char* path) {
- vfs::tmpfs_node_t* node = __tmpfs__find(path);
- if(node) {
- return 1;
- }
-
- return 0;
-}
-
-std::uint8_t __tmpfs__create_parent_dirs_by_default = 1; /* Used for ustar */
-
-NodePoolBlock* node_pool_blocks_head = 0;
-
-vfs::tmpfs_node_t* node_pool_current = 0;
-size_t node_pool_offset = 0;
-size_t node_pool_capacity = 0;
-
-static void allocate_node_pool_block() {
- void* block = memory::pmm::_virtual::alloc(NODE_POOL_BLOCK_SIZE);
- if (!block) {
- return;
- }
-
- NodePoolBlock* new_block = (NodePoolBlock*)memory::pmm::_virtual::alloc(sizeof(NodePoolBlock));
- if (!new_block) {
- return;
- }
- new_block->block = reinterpret_cast<vfs::tmpfs_node_t*>(block);
- new_block->next = node_pool_blocks_head;
- node_pool_blocks_head = new_block;
-
- node_pool_current = new_block->block;
- node_pool_offset = 0;
- node_pool_capacity = NODE_POOL_BLOCK_SIZE / sizeof(vfs::tmpfs_node_t);;
-}
-
-static vfs::tmpfs_node_t* allocate_node_from_pool() {
- if (!node_pool_current || node_pool_offset >= node_pool_capacity) {
- allocate_node_pool_block();
- if (!node_pool_current) {
- return 0;
- }
- }
- vfs::tmpfs_node_t* node = node_pool_current + node_pool_offset;
- node_pool_offset++;
- memset(node, 0, sizeof(vfs::tmpfs_node_t));
- return node;
-}
-
-
-int __tmpfs__is_busy(vfs::tmpfs_node_t* node) {
-
- if(!node)
- return 0;
-
- if(node->busy != 0)
- return 1;
-
- if(node->type != TMPFS_TYPE_DIRECTORY)
- return 0; // node->busy is ok so return 0
-
- if(node->type == TMPFS_TYPE_DIRECTORY) {
-
- std::uint64_t* cont = (std::uint64_t*)node->content;
- for(std::uint64_t i = 0; i < (node->size / 8); i++) {
- if(cont[i] != 0) {
- vfs::tmpfs_node_t* chld_node = (vfs::tmpfs_node_t*)(((std::uint64_t*)node->content)[i]);
- if(chld_node->busy != 0)
- return 1;
-
- if(chld_node->type == TMPFS_TYPE_DIRECTORY) {
- int c = __tmpfs__is_busy(chld_node);
- if(c == 1)
- return c;
- }
- }
-
- }
- }
-
- return 0;
-}
-
-vfs::tmpfs_node_t* last = 0;
-
-std::int32_t __tmpfs__create(char* path,std::uint8_t type, vfs::tmpfs_node_t** out) {
-
- if(out) {
- if(__tmpfs__exists(path))
- return -EEXIST;
- }
-
- char copy[2048];
- memset(copy,0,2048);
- memcpy(copy,path,strlen(path));
-
- if(path[0] == '\0')
- return -EINVAL;
-
- __tmpfs__find_dir(copy);
-
- if(copy[0] == '\0') {
- copy[0] = '/';
- copy[1] = '\0';
- }
-
- vfs::tmpfs_node_t* parent = __tmpfs__find(copy);
-
- if(!parent) {
- if(!__tmpfs__create_parent_dirs_by_default)
- return -ENOENT;
- else {
- __tmpfs__create(copy,TMPFS_TYPE_DIRECTORY,&parent);
- }
- }
-
- vfs::tmpfs_node_t* node = head_node;
-
- int is_success_find = 0;
-
- while(node) {
- if(node->name[0] == '\0') {
- vfs::tmpfs_node_t* nex = node->next;
- memset(node,0,sizeof(vfs::tmpfs_node_t));
- node->next = nex;
- is_success_find = 1;
- break;
- }
-
- node = node->next;
- }
-
- if(!node)
- node = (vfs::tmpfs_node_t*)memory::pmm::_virtual::alloc(4096);
-
- node->type = type;
- node->content = 0;
- node->size = 0;
- node->busy = 0;
- node->id = ++__tmpfs_ptr_id;
-
-
-
- node->create_time = getUnixTime();
- node->access_time = getUnixTime();
-
- memcpy(node->name,path,strlen(path));
-
- node->path_hash = hash_fnv1(node->name);
-
- if(!is_success_find) {
- node->next = head_node;
- head_node = node;
- }
-
- if(!(parent->size <= parent->real_size)) {
- // overflow ! increase size
- parent->content = (std::uint8_t*)memory::pmm::_virtual::realloc(parent->content,parent->real_size,parent->real_size + PAGE_SIZE);
- parent->real_size += PAGE_SIZE;
- }
-
- if(parent->size <= parent->real_size) {
- // first: find free entry
-
- std::uint64_t* free_entry = 0;
- for(std::uint64_t i = 0; i < (parent->size / 8); i++) {
- if(((std::uint64_t*)parent->content)[i] == 0) {
- free_entry = &(((std::uint64_t*)parent->content)[i]);
- break;
- }
- }
-
- if(!free_entry) {
- free_entry = &((std::uint64_t*)parent->content)[parent->size / 8];
- parent->size += 8;
- }
-
- *free_entry = (std::uint64_t)node;
-
- }
-
- if(node->type == VFS_TYPE_DIRECTORY) {
- node->content = (std::uint8_t*)memory::pmm::_virtual::alloc(DIRECTORY_LIST_SIZE);
- node->real_size = DIRECTORY_LIST_SIZE;
- node->size = 0;
- }
-
- last = node;
-
- if(out) {
- *out = node;
- }
-
- return 0;
-}
-
-void __tmpfs__dealloc(vfs::tmpfs_node_t* node){
- if(!node->content)
- return;
- memory::pmm::_virtual::free(node->content);
-}
-
-std::uint8_t __tmpfs__dont_alloc_memory = 0;
-
-std::int64_t __tmpfs__write(userspace_fd_t* fd, char* path, void* buffer, std::uint64_t size) {
- if (!path || !buffer || !size) { vfs::vfs::unlock();
- return -EBADF; }
-
- vfs::tmpfs_node_t* node = __tmpfs__symfind(path);
-
- if (!node) { vfs::vfs::unlock();
- return -ENOENT; }
-
- if (!node) { vfs::vfs::unlock();
- return -ENOENT; }
-
- if (node->type == TMPFS_TYPE_DIRECTORY) { vfs::vfs::unlock();
- return -EISDIR; }
-
- if (!fd) {
- __tmpfs__dealloc(node);
- node->content = (std::uint8_t*)memory::pmm::_virtual::alloc(size);
- memcpy(node->content, buffer, size);
- node->size = size;
- } else {
- std::uint64_t offset = fd->offset;
- std::uint64_t new_size = offset + size;
-
- if (new_size > node->real_size || node->is_non_allocated) {
- alloc_t new_content0 = memory::pmm::_physical::alloc_ext(new_size);
- std::uint8_t* new_content = (std::uint8_t*)new_content0.virt;
- if (node->content) {
- memcpy(new_content, node->content, node->size);
- if(!node->is_non_allocated)
- __tmpfs__dealloc(node);
- }
- node->is_non_allocated = 0;
- node->content = new_content;
- node->real_size = new_content0.real_size;
- }
-
- if(new_size > node->size)
- node->size = new_size;
-
- node->access_time = getUnixTime();
- memcpy(node->content + offset, buffer, size);
-
- fd->offset += size;
- }
-
- vfs::vfs::unlock();
- return size;
-}
-
-std::int64_t __tmpfs__read(userspace_fd_t* fd, char* path, void* buffer, std::uint64_t count) {
- if (!path || !buffer) { vfs::vfs::unlock();
- return -EBADF; }
-
- if(!count) { vfs::vfs::unlock();
- return 0; }
-
- vfs::tmpfs_node_t* node = __tmpfs__symfind(path);
-
- if (!node) { vfs::vfs::unlock();
- return -ENOENT; }
-
- if (!node) { vfs::vfs::unlock();
- return -ENOENT; }
-
- if (node->type == TMPFS_TYPE_DIRECTORY) { vfs::vfs::unlock();
- return -EISDIR; }
-
- if (!fd) {
- std::uint64_t to_read = (count >= node->size) ? node->size : count;
- memcpy(buffer, node->content, to_read);
- vfs::vfs::unlock();
- return to_read;
- } else {
- std::uint64_t offset = fd->offset;
- if (offset >= node->size) {
- vfs::vfs::unlock();
- return 0;
- }
- std::uint64_t available = node->size - offset;
- std::uint64_t to_read = (count > available) ? available : count;
-
- memcpy(buffer, node->content + offset, to_read);
- fd->offset += to_read;
-
- vfs::vfs::unlock();
- return to_read;
- }
-}
-
-void __tmpfs__opt_create_and_write(char* path, int type, char* content, std::uint64_t content_len, int chmod) {
-
- char copy[2048];
- memcpy(copy,path,strlen(path) + 1);
-
- if(path[0] == '\0')
- return;
-
- __tmpfs__find_dir(copy);
-
- if(copy[0] == '\0') {
- copy[0] = '/';
- copy[1] = '\0';
- }
-
- vfs::tmpfs_node_t* parent = __tmpfs__find(copy);
-
- if(!parent) {
- if(!__tmpfs__create_parent_dirs_by_default)
- return;
- else {
- __tmpfs__create(copy,TMPFS_TYPE_DIRECTORY,&parent);
- }
- }
-
- vfs::tmpfs_node_t* node = 0;
-
- if(!node)
- node = (vfs::tmpfs_node_t*)allocate_node_from_pool();
-
- node->type = type;
- node->content = 0;
- node->size = 0;
- node->busy = 0;
- node->id = ++__tmpfs_ptr_id;
-
- node->create_time = getUnixTime();
- node->access_time = getUnixTime();
-
- memcpy(node->name,path,strlen(path) + 1);
-
- node->path_hash = hash_fnv1(node->name);
-
- node->next = head_node;
- head_node = node;
-
- assert(parent,"parent is null %s (%d)",copy,__tmpfs__create_parent_dirs_by_default);
-
- if(!parent->content) {
- node->content = (std::uint8_t*)memory::pmm::_virtual::alloc(DIRECTORY_LIST_SIZE);
- node->real_size = DIRECTORY_LIST_SIZE;
- node->size = 0;
- }
-
- if(!(parent->size <= parent->real_size)) {
- // overflow ! increase size
- parent->content = (std::uint8_t*)memory::pmm::_virtual::realloc(parent->content,parent->real_size,parent->real_size + PAGE_SIZE);
- parent->real_size += PAGE_SIZE;
- }
-
- if(parent->size <= parent->real_size) {
- std::uint64_t* free_entry = &((std::uint64_t*)parent->content)[parent->size / 8];
- parent->size += 8;
-
- *free_entry = (std::uint64_t)node;
- }
-
- if(node->type == VFS_TYPE_DIRECTORY) {
- node->content = (std::uint8_t*)memory::pmm::_virtual::alloc(DIRECTORY_LIST_SIZE);
- node->real_size = DIRECTORY_LIST_SIZE;
- node->size = 0;
- } else {
- alloc_t new_content0 = memory::pmm::_physical::alloc_ext(content_len);
- std::uint8_t* new_content = (std::uint8_t*)new_content0.virt;
- if (node->content) {
- memcpy(new_content, node->content, node->size);
- if(!node->is_non_allocated)
- __tmpfs__dealloc(node);
- }
- node->is_non_allocated = 0;
- node->content = new_content;
- node->real_size = new_content0.real_size;
- node->size = content_len;
- memcpy(node->content,content,content_len);
- }
-
- node->vars[TMPFS_VAR_CHMOD] = chmod;
-
- return;
-
-}
-
-std::int32_t __tmpfs__open(userspace_fd_t* fd, char* path) {
- if(!path)
- return EFAULT;
-
- vfs::tmpfs_node_t* node = __tmpfs__symfind(path);
-
- if(!node)
- return ENOENT;
-
- node->busy++;
-
- /* TmpFS doesnt need to change something in fd */
-
- return 0;
-}
-
-std::int32_t __tmpfs__var(userspace_fd_t* fd, char* path, std::uint64_t value, std::uint8_t request) {
- if(!path)
- return EFAULT;
-
- vfs::tmpfs_node_t* node = __tmpfs__symfind(path);
-
- if(!node)
- return ENOENT;
-
- if(request == DEVFS_VAR_ISATTY)
- return ENOTTY;
-
- if(request & (1 << 7))
- node->vars[request & ~(1 << 7)] = value;
- else
- *(std::uint64_t*)value = node->vars[request & ~(1 << 7)];
-
- return 0;
-
-}
-
-std::int32_t __tmpfs__ls(userspace_fd_t* fd, char* path, vfs::dirent_t* out) {
-
-again:
-
- if(!path)
- return EFAULT;
-
- vfs::tmpfs_node_t* node = __tmpfs__symfind(path);
-
- if(!node)
- return ENOENT;
-
- if(node->type != VFS_TYPE_DIRECTORY)
- return ENOTDIR;
-
- if(fd->offset == node->size / 8) {
- out->d_reclen = 0;
- memset(out->d_name,0,sizeof(out->d_name));
- return 0;
- }
-
- vfs::tmpfs_node_t* next = (vfs::tmpfs_node_t*)(((std::uint64_t*)node->content)[fd->offset]);
-
- if(next == 0) { // null pointer fix
- fd->offset++;
- goto again;
- }
-
- memset(out->d_name,0,sizeof(out->d_name));
- memcpy(out->d_name,__tmpfs__find_name(next->name),strlen(__tmpfs__find_name(next->name)));
-
- std::uint64_t mod = next->type == TMPFS_TYPE_DIRECTORY ? DT_DIR : DT_REG;
- if(next->type == TMPFS_TYPE_SYMLINK)
- mod = DT_LNK;
-
- out->d_reclen = sizeof(vfs::dirent_t);
- out->d_ino = next->id;
- out->d_off = 0;
- out->d_type = mod;
- fd->offset++;
-
- if(out->d_name[0] == 0)
- goto again;
-
- return 0;
-}
-
-std::int32_t __tmpfs__remove(userspace_fd_t* fd, char* path) {
- if(!path)
- return -EFAULT;
-
- vfs::tmpfs_node_t* node = __tmpfs__find(path);
-
- if(!node)
- return -ENOENT;
-
- char copy[2048];
- memset(copy,0,2048);
- memcpy(copy,path,strlen(path));
-
- if(path[0] == '\0')
- return -EINVAL;
-
- __tmpfs__find_dir(copy);
-
- if(copy[0] == '\0') {
- copy[0] = '/';
- copy[1] = '\0';
- }
-
- vfs::tmpfs_node_t* parent = __tmpfs__find(copy);
-
- if(__tmpfs__is_busy(node))
- return -EBUSY;
-
- if(node->type != TMPFS_TYPE_DIRECTORY) {
-
- } else {
- for(std::uint64_t i = 0;i < node->size / 8;i++) {
- __tmpfs__remove(fd,((vfs::tmpfs_node_t*)(((std::uint64_t*)node->content)[fd->offset / 8]))->name);
- }
- }
-
- if(parent) {
- if(parent->type == TMPFS_TYPE_DIRECTORY) {
- std::uint64_t* cont = (std::uint64_t*)parent->content;
-
- for(std::uint64_t i = 0; i < (parent->size / 8); i++) {
- if(cont[i] != 0) {
- vfs::tmpfs_node_t* chld_node = (vfs::tmpfs_node_t*)cont[i];
- if((std::uint64_t)chld_node == (std::uint64_t)node) {
- cont[i] = 0;
- }
- }
- }
- }
- }
-
- memset(node->name,0,2048);
- __tmpfs__dealloc(node);
-
- return 0;
-}
-
-std::int32_t __tmpfs__touch(char* path, int mode) {
- if(!path)
- return EFAULT;
-
- vfs::tmpfs_node_t* node = __tmpfs__symfind(path);
-
- if(!node) {
- int status = __tmpfs__create(path,VFS_TYPE_FILE,0);
- node = __tmpfs__symfind(path);
- if(node)
- node->vars[TMPFS_VAR_CHMOD] |= (mode & ~(S_IFDIR | S_IFREG | S_IFCHR | S_IFBLK | S_IFIFO | S_IFDIR | S_IFIFO | S_IFMT | S_IFLNK));
- }
-
- return 0;
-
-}
-
-#define STATX_BASIC_STATS 0x7ff
-#define STATX_BTIME 0x800
-
-
-
-std::int32_t __tmpfs__statx(userspace_fd_t* fd, char* path, int flags, int mask, statx_t* out) {
- if(!path)
- return -EFAULT;
-
- if(!__tmpfs__exists(path))
- return -ENOENT;
-
- if(!out)
- return -EINVAL;
-
- vfs::tmpfs_node_t* node = __tmpfs__symfind(path);
-
- memset(out,0,sizeof(statx_t));
-
- out->stx_mask = STATX_BASIC_STATS | STATX_BTIME;
- out->stx_blksize = 4096;
- out->stx_nlink = 0;
- out->stx_uid = 0;
- out->stx_gid = 0;
- out->stx_mode = 0;
- switch(node->type) {
- case TMPFS_TYPE_DIRECTORY:
- out->stx_mode |= S_IFDIR;
- break;
- case TMPFS_TYPE_FILE:
- out->stx_mode |= S_IFREG;
- break;
- case TMPFS_TYPE_SYMLINK:
- out->stx_mode |= S_IFLNK;
- break;
- default:
- out->stx_mode |= S_IFREG;
- break;
- }
- out->stx_ino = node->id;
- out->stx_size = node->size;
- out->stx_blocks = node->real_size / 512;
- out->stx_atime.tv_sec = node->access_time;
- out->stx_atime.tv_nsec = 0;
- out->stx_btime.tv_sec = node->create_time;
- out->stx_btime.tv_nsec = 0;
- out->stx_ctime.tv_sec = node->access_time;
- out->stx_ctime.tv_nsec = 0;
- out->stx_mtime.tv_sec = node->access_time;
- out->stx_mtime.tv_nsec = 0;
- out->stx_rdev_major = 0;
- out->stx_rdev_minor = 0;
- out->stx_dev_major = 0;
- out->stx_dev_minor = 0;
- return 0;
-}
-
-std::int32_t __tmpfs__stat(userspace_fd_t* fd, char* path, vfs::stat_t* out) {
- if(!path)
- return EFAULT;
-
-vfs::tmpfs_node_t* node = __tmpfs__symfind(path);
-
- if(!node)
- return ENOENT;
-
- if(!out)
- return EINVAL;
-
-
- if(!node)
- return ENOENT;
-
- out->st_size = node->type == TMPFS_TYPE_DIRECTORY ? 0 : node->size;
- out->st_mode = node->type == TMPFS_TYPE_DIRECTORY ? S_IFDIR : S_IFREG;
- if(node->type == TMPFS_TYPE_SYMLINK)
- out->st_mode = S_IFLNK;
- out->st_mode |= ((node->vars[0] & ~(S_IFDIR | S_IFREG | S_IFCHR | S_IFBLK | S_IFIFO | S_IFDIR | S_IFIFO | S_IFMT | S_IFLNK)) & 0xFFFFFFFF);
- out->st_uid = 0;
- out->st_gid = 0;
- out->st_blksize = 4096;
- out->st_ino = node->id;
- out->st_nlink = 0; // unimplemented
- out->st_dev = 0;
- out->st_rdev = 0;
- out->st_blocks = node->real_size / 4096;
- out->st_atim.tv_sec = node->access_time;
- out->st_mtim.tv_sec = node->access_time;
- out->st_ctim.tv_sec = node->create_time;
- out->st_atim.tv_nsec = 0;
- out->st_mtim.tv_nsec = 0;
- out->st_ctim.tv_nsec = 0;
-
- return 0;
-}
-
-// note for me never touch this in future
-std::int32_t __tmpfs__readlink(char* path, char* out, std::uint32_t out_len) {
- if(!path)
- return EFAULT;
-
- vfs::tmpfs_node_t* node = __tmpfs__symfind(path);
-
- if(!node)
- return ENOENT;
-
- if(!out)
- return EINVAL;
-
- if(!node)
- return ENOENT;
-
- if(node->type != TMPFS_TYPE_SYMLINK)
- return EINVAL;
-
- if(node->size >= out_len) {
- Log::SerialDisplay(LEVEL_MESSAGE_INFO,"ur taking too long nodesize %d outlen %d",node->size,out_len);
- return EINVAL;
- }
-
- if(!node->content)
- return EINVAL; // symlink is not initializied now :(
-
- memcpy(out,node->content,node->size + 1);
-
- return 0;
-}
-
-void __tmpfs_build_newfile(char* path, char* new_path, int path_start_len, char* result) {
- char temp_path[2048]; // /usr/bin -> /bin
- memset(temp_path,0,2048);
- memcpy(temp_path,path + path_start_len,strlen(path + path_start_len));
- memcpy(result,new_path,strlen(new_path));
- memcpy(result + strlen(new_path),temp_path,strlen(temp_path) + 1);
- if(result[0] == '/' && result[1] == '/') {
- // fix
- memset(temp_path,0,2048);
- memcpy(temp_path,result + 1, strlen(result + 1));
- memcpy(result,temp_path,strlen(temp_path) + 1);
- }
-}
-
-void __tmpfs__rename_dirents(char* path, char* new_path, int path_start_len) {
- if(!__tmpfs__exists(path))
- return;
-
- vfs::tmpfs_node_t* node = __tmpfs__symfind(path);
-
- if(!node)
- return;
-
- if(node->busy != 0)
- return;
-
- char old_node_path[2048];
- memcpy(old_node_path,node->name,strlen(node->name) + 1);
-
- if(node->type == TMPFS_TYPE_DIRECTORY) {
-
- std::uint64_t* cont = (std::uint64_t*)node->content;
- for(std::uint64_t i = 0; i < (node->size / 8); i++) {
- if(cont[i] != 0) {
- vfs::tmpfs_node_t* chld_node = (vfs::tmpfs_node_t*)cont[i];
- char old_name[2048];
- memset(old_name,0,2048);
- memcpy(old_name,chld_node->name,strlen(chld_node->name) + 1);
- memset(chld_node->name,0,sizeof(chld_node->name));
- __tmpfs_build_newfile(old_name,node->name,path_start_len,chld_node->name);
- chld_node->path_hash = hash_fnv1(chld_node->name);
- DEBUG(1,"new_path %s\n",chld_node->name);
- if(chld_node->type == TMPFS_TYPE_DIRECTORY) {
- __tmpfs__rename_dirents(chld_node->name,new_path,path_start_len);
- }
- }
- }
- }
- return;
-}
-
-std::int32_t __tmpfs__rename(char* path, char* new_path) {
- if(!__tmpfs__exists(path))
- return -ENOENT;
-
- vfs::tmpfs_node_t* node = __tmpfs__symfind(path);
-
- if(!node)
- return -ENOENT;
-
- if(node->busy != 0)
- return -EBUSY;
-
- if(__tmpfs__is_busy(node))
- return -EBUSY;
-
- char old_node_path[2048];
- memcpy(old_node_path,node->name,strlen(node->name) + 1);
-
- vfs::tmpfs_node_t* node2 = __tmpfs__symfind(new_path);
-
- if(node2) {
-
- if(node2->busy != 0)
- return -EBUSY;
-
- if(node2->type == TMPFS_TYPE_DIRECTORY) {
- // man says it shoudl return error only if its non empty
- int is_non_empty = 1;
- for(std::uint64_t i = 0;i < node2->size / 8; i++) {
- if((node2->content[i]))
- return ENOTEMPTY;
- }
- }
-
- userspace_fd_t fd;
- memset(&fd,0,sizeof(fd));
- __tmpfs__remove(&fd,new_path);
- }
-
- char copy[2048];
- memset(copy,0,2048);
- memcpy(copy,path,strlen(path));
-
- __tmpfs__find_dir(copy);
-
- if(copy[0] == '\0') {
- copy[0] = '/';
- copy[1] = '\0';
- }
-
- if(!__tmpfs__exists(copy)) {
- if(!__tmpfs__create_parent_dirs_by_default)
- return ENOENT;
- else {
- __tmpfs__create(copy,TMPFS_TYPE_DIRECTORY,0);
- }
- }
-
- if(__tmpfs__find(copy)->type != VFS_TYPE_DIRECTORY)
- return -ENOTDIR;
-
- vfs::tmpfs_node_t* parent = __tmpfs__find(copy);
- if(parent->size <= DIRECTORY_LIST_SIZE) {
- // first: find free entry
-
- std::uint64_t* free_entry = 0;
- for(std::uint64_t i = 0; i < (parent->size / 8); i++) {
- if(((std::uint64_t*)parent->content)[i] == (std::uint64_t)node) {
- free_entry = &(((std::uint64_t*)parent->content)[i]);
- *free_entry = 0;
- }
- }
-
- }
-
- int path_start_len = strlen(node->name);
- if(node->name[0] == '/' && node->name[1] == '\0')
- path_start_len = 0;
-
- memset(node->name,0,2048);
- memcpy(node->name,new_path,strlen(new_path));
-
- node->path_hash = hash_fnv1(node->name);
-
- if(node->type == TMPFS_TYPE_DIRECTORY) {
-
- std::uint64_t* cont = (std::uint64_t*)node->content;
- for(std::uint64_t i = 0; i < (node->size / 8); i++) {
- if(cont[i] != 0) {
- vfs::tmpfs_node_t* chld_node = (vfs::tmpfs_node_t*)cont[i];
- char old_name[2048];
- memset(old_name,0,2048);
- memcpy(old_name,chld_node->name,strlen(chld_node->name) + 1);
- memset(chld_node->name,0,sizeof(chld_node->name));
- __tmpfs_build_newfile(old_name,node->name,path_start_len,chld_node->name);
- chld_node->path_hash = hash_fnv1(chld_node->name);
- DEBUG(1,"new_path %s\n",chld_node->name);
- if(chld_node->type == TMPFS_TYPE_DIRECTORY) {
- __tmpfs__rename_dirents(chld_node->name,new_path,path_start_len);
- }
- }
- }
- }
-
- memset(copy,0,2048);
- memcpy(copy,path,strlen(path));
-
- __tmpfs__find_dir(copy);
-
- if(copy[0] == '\0') {
- copy[0] = '/';
- copy[1] = '\0';
- }
-
- if(!__tmpfs__exists(copy)) {
- if(!__tmpfs__create_parent_dirs_by_default)
- return ENOENT;
- else {
- __tmpfs__create(copy,TMPFS_TYPE_DIRECTORY,0);
- }
- }
-
- if(__tmpfs__find(copy)->type != VFS_TYPE_DIRECTORY)
- return ENOTDIR;
-
- parent = __tmpfs__find(copy);
- if(parent->size <= DIRECTORY_LIST_SIZE) {
- // first: find free entry
-
- std::uint64_t* free_entry = 0;
- for(std::uint64_t i = 0; i < (parent->size / 8); i++) {
- if(((std::uint64_t*)parent->content)[i] == 0) {
- free_entry = &(((std::uint64_t*)parent->content)[i]);
- break;
- }
- }
-
- if(!free_entry) {
- free_entry = &((std::uint64_t*)parent->content)[parent->size / 8];
- parent->size += 8;
- }
-
- *free_entry = (std::uint64_t)node;
-
- }
-
- return 0;
-
-}
-
-void __tmpfs__close(userspace_fd_t* fd, char* path) {
-
- vfs::tmpfs_node_t* node = __tmpfs__symfind(path);
-
- if(!node)
- return;
-
- if(!node)
- return;
-
- if(node->busy > 0)
- node->busy--;
-
- if(node->is_request_unlink) {
- if(node->busy == 0) {
- __tmpfs__remove(fd,path);
- }
- }
-
- return;
-}
-
-std::int32_t __tmpfs__unlink(userspace_fd_t* fd, char* path) {
-
- if(!path)
- return -EINVAL;
-
- vfs::tmpfs_node_t* node = __tmpfs__symfind(path);
- if(!node)
- return -ENOENT;
-
- node->is_request_unlink = 1;
- if(node->busy == 0) {
- __tmpfs__remove(fd,path);
- }
-
- return 0;
-}
-
-void vfs::tmpfs::mount(vfs_node_t* node) {
-
- head_node = (tmpfs_node_t*)memory::pmm::_virtual::alloc(4096);
-
- head_node->type = TMPFS_TYPE_DIRECTORY;
- head_node->id = 0;
-
- root_node = head_node;
-
- memcpy(head_node->name,"/",1);
-
- head_node->path_hash = hash_fnv1(head_node->name);
-
- head_node->content = (std::uint8_t*)memory::pmm::_virtual::alloc(DIRECTORY_LIST_SIZE);
-
- node->readlink = __tmpfs__readlink;
- node->create = (int (*)(char*,uint8_t))__tmpfs__create;
- node->remove = __tmpfs__remove;
- node->rename = __tmpfs__rename;
- node->write = __tmpfs__write;
- node->touch = __tmpfs__touch;
- node->close = __tmpfs__close;
- node->read = __tmpfs__read;
- node->open = __tmpfs__open;
- node->stat = __tmpfs__stat;
- node->var = __tmpfs__var;
- node->ls = __tmpfs__ls;
-
- node->statx = __tmpfs__statx;
- node->unlink = __tmpfs__unlink;
-
- node->opt_create_and_write = __tmpfs__opt_create_and_write;
-
-} \ No newline at end of file
diff --git a/kernel/src/generic/vfs/ustar.cpp b/kernel/src/generic/vfs/ustar.cpp
deleted file mode 100644
index 7aa2c6d..0000000
--- a/kernel/src/generic/vfs/ustar.cpp
+++ /dev/null
@@ -1,177 +0,0 @@
-
-#include <cstdint>
-
-#include <generic/vfs/ustar.hpp>
-#include <generic/vfs/vfs.hpp>
-
-#include <etc/bootloaderinfo.hpp>
-#include <etc/logging.hpp>
-#include <limine.h>
-
-#include <etc/etc.hpp>
-
-inline int oct2bin(unsigned char *str, int size) {
-
- if(!str)
- return 0;
-
- std::uint64_t n = 0;
- volatile unsigned char *c = str;
- for(int i = 0;i < size;i++) {
- n *= 8;
- n += *c - '0';
- c++;
-
- }
- return n;
-}
-
-
-void __ustar_fault(const char* msg) {
-
- Log::Display(LEVEL_MESSAGE_FAIL,"Can't continue kernel work ! initrd error, msg \"%s\"\n",msg);
-
- while(1) {
- asm volatile("hlt");
- }
-}
-
-#define TAR_BLOCK_SIZE 512
-
-std::uint64_t count_tar_files_simple(const unsigned char *data, size_t size) {
- int count = 0;
- size_t pos = 0;
-
- while (pos + TAR_BLOCK_SIZE <= size) {
- int all_zero = 1;
- for (int i = 0; i < TAR_BLOCK_SIZE; i++) {
- if (data[pos + i] != 0) {
- all_zero = 0;
- break;
- }
- }
-
- if (all_zero) {
- if (pos + 2 * TAR_BLOCK_SIZE <= size) {
- all_zero = 1;
- for (int i = 0; i < TAR_BLOCK_SIZE; i++) {
- if (data[pos + TAR_BLOCK_SIZE + i] != 0) {
- all_zero = 0;
- break;
- }
- }
- if (all_zero) break;
- }
- }
-
- count++;
-
- unsigned long file_size = 0;
- for (int i = 0; i < 11; i++) {
- unsigned char c = data[pos + 124 + i];
- if (c < '0' || c > '7') break;
- file_size = file_size * 8 + (c - '0');
- }
-
- unsigned long blocks = (file_size + TAR_BLOCK_SIZE - 1) / TAR_BLOCK_SIZE;
- pos += (1 + blocks) * TAR_BLOCK_SIZE;
-
- if (pos > size) break;
- }
-
- return count;
-}
-
-
-extern const char* level_messages[];
-void update_progress_bar(int current, int total, int bar_width) {
- static int last_percent = -1;
-
- int percent = 0;
- if (total > 0) {
- percent = (current * 100) / total;
- }
-
- if (percent == last_percent && current != total) {
- return;
- }
- last_percent = percent;
-
- int filled_width = 0;
- if (percent > 0) {
- filled_width = (percent * bar_width) / 100;
- if (filled_width > bar_width) {
- filled_width = bar_width;
- }
- }
-
- printf("\r%sLoading initrd ",level_messages[LEVEL_MESSAGE_INFO]);
-
- printf("[");
- for (int i = 0; i < bar_width; i++) {
- if (i < filled_width) {
- printf("=");
- } else if (i == filled_width && percent < 100) {
- printf(">");
- } else {
- printf(" ");
- }
- }
- printf("] %3d%% (%d/%d)", percent, current, total);
-
- if (current >= total) {
- printf("\n");
- }
-
-}
-
-extern std::uint8_t __tmpfs__create_parent_dirs_by_default;
-extern std::uint8_t __tmpfs__dont_alloc_memory;
-
-
-void vfs::ustar::copy() {
- struct limine_module_response* initrd = BootloaderInfo::AccessInitrd();
- if(!initrd || initrd->module_count < 1)
- __ustar_fault("there's no initrd");
-
- ustar_header_t* current = (ustar_header_t*)initrd->modules[0]->address;
-
- std::uint64_t total = count_tar_files_simple((std::uint8_t*)current,initrd->modules[0]->size);
- std::uint64_t currentp = 0;
-
- Log::Raw("%sLoading initrd ",level_messages[LEVEL_MESSAGE_INFO]);
-
- std::uint64_t actual_tar_ptr_end = ((uint64_t)initrd->modules[0]->address + initrd->modules[0]->size) - 1024;
- while((std::uint64_t)current < actual_tar_ptr_end) {
- std::uint8_t type = oct2bin((uint8_t*)&current->type,1);
- switch(type) {
- case 0: {
- char* file = (char*)((uint64_t)current->file_name + 1);
- int size = oct2bin((uint8_t*)current->file_size,strlen(current->file_size));
- std::uint64_t actual_mode = oct2bin((uint8_t*)current->file_mode,7);
- vfs::vfs::opt_create_and_write(file,VFS_TYPE_FILE,(char*)((std::uint64_t)current + 512),size,actual_mode);
- break;
- }
-
- case 5: {
- char* file = (char*)((uint64_t)current->file_name + 1);
- std::uint64_t actual_mode = oct2bin((uint8_t*)current->file_mode,7);
- vfs::vfs::opt_create_and_write(file,VFS_TYPE_DIRECTORY,0,0,actual_mode);
- break;
- }
-
- case 2: {
- char* file = (char*)((uint64_t)current->file_name + 1);
- std::uint64_t actual_mode = oct2bin((uint8_t*)current->file_mode,7);
- vfs::vfs::opt_create_and_write(file,VFS_TYPE_SYMLINK,current->name_linked,strlen(current->name_linked),actual_mode);
- break;
- }
- }
- currentp++;
- update_progress_bar(currentp,total,25);
- current = (ustar_header_t*)((uint64_t)current + ALIGNUP(oct2bin((uint8_t*)&current->file_size,strlen(current->file_size)),512) + 512);
- }
-
- __tmpfs__create_parent_dirs_by_default = 0;
-
-} \ No newline at end of file
diff --git a/kernel/src/generic/vfs/vfs.cpp b/kernel/src/generic/vfs/vfs.cpp
deleted file mode 100644
index e7f2fd2..0000000
--- a/kernel/src/generic/vfs/vfs.cpp
+++ /dev/null
@@ -1,922 +0,0 @@
-
-#include <generic/mm/pmm.hpp>
-#include <generic/vfs/vfs.hpp>
-#include <generic/vfs/tmpfs.hpp>
-#include <generic/locks/spinlock.hpp>
-#include <generic/vfs/devfs.hpp>
-
-#include <generic/vfs/evdev.hpp>
-
-#include <arch/x86_64/syscalls/sockets.hpp>
-
-#include <cstdint>
-#include <etc/errno.hpp>
-
-#include <etc/logging.hpp>
-
-vfs::vfs_node_t vfs_nodes[512];
-locks::spinlock* vfs_lock;
-
-vfs::vfs_node_t* find_node(char* path) {
- std::uint64_t r = 0;
- vfs::vfs_node_t* match;
- for(int i = 0;i < 512;i++) {
- if(!strncmp(path,vfs_nodes[i].path,strlen(vfs_nodes[i].path))) {
- if(strlen(vfs_nodes[i].path) > r) {
- match = &vfs_nodes[i];
- }
- }
-
- if(!strncmp(path, vfs_nodes[i].path,strlen(vfs_nodes[i].path) - 1) && path[strlen(vfs_nodes[i].path) + 1] == '\0') {
- return &vfs_nodes[i];
- }
-
- }
- return match;
-}
-
-vfs::fifo_node_t* fifo_head = 0;
-
-int is_fifo_exists(char* path) {
- vfs::fifo_node_t* current = fifo_head;
- while(current) {
- if(!strcmp(current->path,path))
- return 1;
- current = current->next;
- }
- return 0;
-}
-
-vfs::fifo_node_t* fifo_get(char* path) {
-
- vfs::fifo_node_t* current = fifo_head;
- while(current) {
- if(!strcmp(current->path,path))
- return current;
- current = current->next;
- }
- return 0;
-
-}
-
-char * __vfs__strtok(char **next,char *str, const char *delim) {
- if (str) *next = str;
- if (!*next) return NULL;
-
- char *start = *next;
- while (*start && strchr(delim, *start)) {
- start++;
- }
- if (!*start) {
- *next = NULL;
- return NULL;
- }
-
- char *end = start;
- while (*end && !strchr(delim, *end)) {
- end++;
- }
-
- if (*end) {
- *end = '\0';
- *next = end + 1;
- } else {
- *next = NULL;
- }
-
- return start;
-}
-
-int cc = 0; // symlink resolve only used from lock
-
-// /bin/path -> /usr/bin/path
-void __vfs_symlink_resolve_no_at_symlink_follow(char* path, char* out) {
- char *next = NULL;
- char buffer[2048];
-
- int e = vfs::vfs::readlink(path,buffer,2048);
-
- if(!vfs_lock->test())
- Log::Display(LEVEL_MESSAGE_WARN,"vfs_lock didnt set lock in symlink resolve");
-
- if(e == ENOSYS)
- memcpy(out,path,strlen(path) + 1);
-
- if(e == EINVAL)
- memcpy(out,path,strlen(path) + 1);
- else if(e == 0) {
-
- memcpy(out,path,strlen(path) + 1);
- } else if(e == ENOENT) {
- memcpy(out,path,strlen(path) + 1);
- // maybe it wants directory symlink ?
- char path0[2048];
- memcpy(path0,path,strlen(path) + 1);
-
- char result[2048];
-
- int c = 0;
-
- char* token = __vfs__strtok(&next, path0, "/");
-
- /* Start building path from null and trying to find symlink */
- while(token) {
-
- result[c] = '/';
- c++;
-
- std::uint64_t mm = 0;
- mm = strlen(token);
- memcpy((char*)((std::uint64_t)result + c),token,mm);
- c += mm;
- result[c] = '\0';
-
- e = vfs::vfs::readlink(result,buffer,2048);
- if(e == 0) {
- char buffer2[2048];
- vfs::resolve_path(buffer,result,buffer2,0,1);
- c = strlen(buffer2);
- buffer2[c++] = '/';
- memcpy(buffer2 + c, path + strlen(result) + 1, strlen(path) - strlen(result));
- __vfs_symlink_resolve_no_at_symlink_follow(buffer2,out);
- return;
- } else if(e == ENOENT) {
- memcpy(out,path,strlen(path) + 1);
- }
-
- token = __vfs__strtok(&next,0,"/");
- }
- memcpy(out,path,strlen(path) + 1);
- }
-}
-
-void __vfs_symlink_resolve(char* path, char* out, int level) {
-
- char *next = NULL;
-
- char buffer[2048];
-
- if(level == 25) {
- // hell no :skull:
- memcpy(out,path,strlen(path) + 1);
- return;
- }
-
- int e = vfs::vfs::readlink(path,buffer,2048);
-
- if(e == ENOSYS)
- memcpy(out,path,strlen(path) + 1);
-
- if(e == EINVAL)
- memcpy(out,path,strlen(path) + 1);
- else if(e == 0) {
-
- char result[2048];
- vfs::resolve_path(buffer,path,result,0,1);
- __vfs_symlink_resolve(result,out, level + 1);
- } else if(e == ENOENT) {
- memcpy(out,path,strlen(path) + 1);
- // maybe it wants directory symlink ?
- char path0[2048];
- memcpy(path0,path,strlen(path) + 1);
-
- char result[2048];
-
- int c = 0;
-
- char* token = __vfs__strtok(&next, path0, "/");
-
- /* Start building path from null and trying to find symlink */
- while(token) {
-
- result[c] = '/';
- c++;
-
- std::uint64_t mm = 0;
- mm = strlen(token);
- memcpy((char*)((std::uint64_t)result + c),token,mm);
- c += mm;
- result[c] = '\0';
-
- e = vfs::vfs::readlink(result,buffer,2048);
- if(e == 0) {
- char buffer2[2048];
- vfs::resolve_path(buffer,result,buffer2,0,1);
- c = strlen(buffer2);
- buffer2[c++] = '/';
- memcpy(buffer2 + c, path + strlen(result) + 1, strlen(path) - strlen(result));
- __vfs_symlink_resolve(buffer2,out, level + 1);
- return;
- } else if(e == ENOENT) {
- memcpy(out,path,strlen(path) + 1);
- return;
- } else {
- memcpy(out,path,strlen(path) + 1);
- return;
- }
-
- token = __vfs__strtok(&next,0,"/");
- }
- memcpy(out,path,strlen(path) + 1);
- }
-}
-
-std::uint32_t vfs::vfs::create_fifo(char* path) {
-
- vfs_lock->lock();
-
- if(!path) {
- vfs_lock->unlock();
- return EINVAL;
- }
-
- if(is_fifo_exists(path)) {
- vfs_lock->unlock();
- return EEXIST;
- }
-
- fifo_node_t* current = fifo_head;
- while(current) {
- if(!current->is_used)
- break;
- current = current->next;
- }
-
- if(!current) {
- current = new fifo_node_t;
- current->next = fifo_head;
- fifo_head = current;
- }
-
- current->main_pipe = new pipe(0);
- current->main_pipe->connected_to_pipe_write = 2;
-
- memset(current->path,0,2048);
- memcpy(current->path,path,strlen(path));
-
- current->is_used = 1;
-
- vfs_lock->unlock();
- return 0;
-}
-
-std::int64_t vfs::vfs::write(userspace_fd_t* fd, void* buffer, std::uint64_t size) {
- vfs_lock->lock();
-
- char out[2048];
-
- if(!fd->is_cached_path) {
- __vfs_symlink_resolve(fd->path,out,0);
- memcpy(fd->path,out,strlen(out) + 1);
- fd->is_cached_path = 1;
- } else
- memcpy(out,fd->path,strlen(fd->path) + 1);
-
-
- if(is_fifo_exists(out)) {
- fifo_node_t* fifo = fifo_get(out);
- vfs_lock->unlock();
- return fifo->main_pipe->write((const char*)buffer,size,0);
- }
-
- vfs_node_t* node = find_node(out);
- if(!node) { vfs::vfs::unlock();
- return -ENOENT; }
-
- char* fs_love_name = &out[0] + strlen(node->path) - 1;
- if(!node->write) { vfs::vfs::unlock();
- return -ENOSYS; }
-
- std::int64_t status = node->write(fd,fs_love_name,buffer,size);
- return status;
-}
-
-std::int64_t vfs::vfs::read(userspace_fd_t* fd, void* buffer, std::uint64_t count) {
- vfs_lock->lock();
-
- char out[2048];
-
- if(!fd->is_cached_path) {
- __vfs_symlink_resolve(fd->path,out,0);
- memcpy(fd->path,out,strlen(out) + 1);
- fd->is_cached_path = 1;
- } else
- memcpy(out,fd->path,strlen(fd->path) + 1);
-
- if(is_fifo_exists(out)) {
- fifo_node_t* fifo = fifo_get(out);
- vfs_lock->unlock();
- return fifo->main_pipe->read(&fd->read_counter,(char*)buffer,count,(fd->flags & O_NONBLOCK) ? 1 : 0);
- }
-
- vfs_node_t* node = find_node(out);
- if(!node) { vfs::vfs::unlock();
- return -ENOENT; }
-
- char* fs_love_name = out + strlen(node->path) - 1;
- if(!node->read) { vfs::vfs::unlock();
- return -ENOSYS; }
-
- std::int64_t status = node->read(fd,fs_love_name,buffer,count);
- assert(status != -9,"omg");
- return status;
-}
-
-std::int32_t vfs::vfs::create(char* path, std::uint8_t type) {
- vfs_lock->lock();
-
- char out[2048];
- memset(out,0,2048);
-
- __vfs_symlink_resolve(path,out,0);
-
- if(sockets::is_exists(out) || is_fifo_exists(out)) {
- vfs_lock->unlock();
- return -EEXIST;
- }
-
- vfs_node_t* node = find_node(out);
- if(!node) { vfs::vfs::unlock();
- return -ENOENT; }
-
- char* fs_love_name = out + strlen(node->path) - 1;
- if(!node->create) { vfs::vfs::unlock();
- return -ENOSYS; }
-
-
- std::int32_t status = ((std::int32_t (*)(char*,int,long long))node->create)(out,type,0);
- vfs_lock->unlock();
- return status;
-}
-
-std::int32_t vfs::vfs::mmap(userspace_fd_t* fd, std::uint64_t* outp, std::uint64_t* outsz, std::uint64_t* outflags) {
- vfs_lock->lock();
-
- char out[2048];
- memset(out,0,2048);
-
- if(!fd->is_cached_path) {
- __vfs_symlink_resolve(fd->path,out,0);
- memcpy(fd->path,out,strlen(out));
- fd->is_cached_path = 1;
- } else
- memcpy(out,fd->path,strlen(fd->path));
-
- vfs_node_t* node = find_node(out);
- if(!node) { vfs::vfs::unlock();
- return ENOENT; }
-
- char* fs_love_name = out + strlen(node->path) - 1;
- if(!node->mmap) { vfs::vfs::unlock();
- return ENOSYS; }
-
- std::int32_t status = node->mmap(fd,fs_love_name,outp,outsz,outflags);
- vfs_lock->unlock();
- return status;
-}
-
-std::int32_t vfs::vfs::open(userspace_fd_t* fd) {
- vfs_lock->lock();
-
- char out[2048];
- memset(out,0,2048);
-
- if(!fd->is_cached_path) {
- __vfs_symlink_resolve(fd->path,out,0);
- memcpy(fd->path,out,strlen(out) + 1);
- fd->is_cached_path = 1;
- } else
- memcpy(out,fd->path,strlen(fd->path));
-
- if(is_fifo_exists(out)) {
- fifo_node_t* fifo = fifo_get(out);
- vfs_lock->unlock();
- return 0;
- }
-
- vfs_node_t* node = find_node(out);
-
- if(!node) { vfs::vfs::unlock();
- return ENOENT; }
-
- char* fs_love_name = out + strlen(node->path) - 1;
- if(!node->open) { vfs::vfs::unlock();
- return ENOSYS; }
-
- std::int32_t status = node->open(fd,fs_love_name);
- vfs_lock->unlock();
- return status;
-}
-
-std::int32_t vfs::vfs::remove(userspace_fd_t* fd) {
- vfs_lock->lock();
-
- char out[2048];
- memset(out,0,2048);
-
- __vfs_symlink_resolve(fd->path,out,0);
-
- if(is_fifo_exists(out)) {
- fifo_node_t* fifo = fifo_get(out);
- memset(fifo->path,0,2048);
- fifo->is_used = 0;
- delete fifo->main_pipe;
- vfs_lock->unlock();
- return 0;
- }
-
- vfs_node_t* node = find_node(out);
- if(!node) { vfs::vfs::unlock();
- return ENOENT; }
-
- char* fs_love_name = out + strlen(node->path) - 1;
- if(!node->remove) {vfs::vfs::unlock();
- return ENOSYS; }
-
- std::int32_t status = node->remove(fd,fs_love_name);
- vfs_lock->unlock();
- return status;
-}
-
-std::int32_t vfs::vfs::ls(userspace_fd_t* fd, dirent_t* out) {
- vfs_lock->lock();
-
- char out0[2048];
- memset(out0,0,2048);
-
- if(!fd->is_cached_path) {
- __vfs_symlink_resolve(fd->path,out0,0);
- memcpy(fd->path,out0,strlen(out0));
- fd->is_cached_path = 1;
- } else
- memcpy(out0,fd->path,strlen(fd->path));
-
- vfs_node_t* node = find_node(out0);
- if(!node) { vfs::vfs::unlock();
- return ENOENT; }
-
- char* fs_love_name = out0 + strlen(node->path) - 1;
- if(!node->ls) { vfs::vfs::unlock();
- return ENOSYS; }
-
- std::int32_t status = node->ls(fd,fs_love_name,out);
- vfs_lock->unlock();
- return status;
-}
-
-std::int32_t vfs::vfs::var(userspace_fd_t* fd, std::uint64_t value, std::uint8_t request) {
- vfs_lock->lock();
-
- char out[2048];
- memset(out,0,2048);
-
- if(!fd->is_cached_path) {
- __vfs_symlink_resolve(fd->path,out,0);
- memcpy(fd->path,out,strlen(out));
- fd->is_cached_path = 1;
- } else
- memcpy(out,fd->path,strlen(fd->path));
-
- if((sockets::is_exists(out))) {
- socket_node_t* node = sockets::find(out);
- if(request & (1 << 7))
- node->vars[request & ~(1 << 7)] = value;
- else
- *(std::uint64_t*)value = node->vars[request & ~(1 << 7)];
- vfs_lock->unlock();
- return 0;
- }
-
- vfs_node_t* node = find_node(out);
- if(!node) { vfs::vfs::unlock();
- return ENOENT; }
-
- char* fs_love_name = out + strlen(node->path) - 1;
- if(!node->var) { vfs::vfs::unlock();
- return ENOSYS; }
-
- std::int32_t status = node->var(fd,fs_love_name,value,request);
- vfs_lock->unlock();
- return status;
-}
-
-std::int32_t vfs::vfs::touch(char* path, int mode) {
- vfs_lock->lock();
-
- char out[2048];
- memset(out,0,2048);
-
- __vfs_symlink_resolve(path,out,0);
-
- if(sockets::is_exists(out) || is_fifo_exists(out)) {
- vfs_lock->unlock();
- return EEXIST;
- }
-
- vfs_node_t* node = find_node(out);
- if(!node) { vfs::vfs::unlock();
- return ENOENT; }
-
- char* fs_love_name = out + strlen(node->path) - 1;
- if(!node->touch) { vfs::vfs::unlock();
- return ENOSYS; }
-
- std::int32_t status = node->touch(fs_love_name, mode);
- vfs_lock->unlock();
- return status;
-}
-
-std::int32_t vfs::vfs::nosym_stat(userspace_fd_t* fd, stat_t* out) {
- vfs_lock->lock();
-
- char out0[2048];
- memset(out0,0,2048);
-
- __vfs_symlink_resolve_no_at_symlink_follow(fd->path,out0);
-
- if(is_fifo_exists(out0)) {
- memset(out,0,sizeof(stat_t));
- out->st_mode |= S_IFIFO;
- vfs_lock->unlock();
- return 0;
- }
-
- if(sockets::is_exists(out0)) {
- memset(out,0,sizeof(stat_t));
- out->st_mode |= S_IFSOCK;
- vfs_lock->unlock();
- return 0;
- }
-
- vfs_node_t* node = find_node(out0);
- if(!node) { vfs::vfs::unlock();
- return ENOENT; }
-
- char* fs_love_name = out0 + strlen(node->path) - 1;
- if(!node->stat) { vfs::vfs::unlock();
- return ENOSYS; }
-
- std::int32_t status = node->stat(fd,fs_love_name,out);
- vfs_lock->unlock();
- return status;
-}
-
-std::int32_t vfs::vfs::statx(userspace_fd_t* fd, int flags, int mask, statx_t* out) {
- vfs_lock->lock();
-
- char out0[2048];
- memset(out0,0,2048);
-
- if(!fd->is_cached_path) {
- if(flags & AT_SYMLINK_NOFOLLOW) {
- __vfs_symlink_resolve_no_at_symlink_follow(fd->path,out0);
- } else
- __vfs_symlink_resolve(fd->path,out0,0);
- memcpy(fd->path,out0,strlen(out0));
- fd->is_cached_path = 1;
- } else
- memcpy(out0,fd->path,strlen(fd->path));
-
- vfs_node_t* node = find_node(out0);
- if(!node) { vfs::vfs::unlock();
- return -ENOENT; }
-
- char* fs_love_name = out0 + strlen(node->path) - 1;
- if(!node->statx) { vfs::vfs::unlock();
- return -ENOSYS; }
-
- std::int32_t status = node->statx(fd,fs_love_name,flags,mask,out);
- vfs_lock->unlock();
- return status;
-}
-
-std::int32_t vfs::vfs::stat(userspace_fd_t* fd, stat_t* out) {
- vfs_lock->lock();
-
- char out0[2048];
- memset(out0,0,2048);
-
- if(!fd->is_cached_path) {
- __vfs_symlink_resolve(fd->path,out0,0);
- memcpy(fd->path,out0,strlen(out0));
- fd->is_cached_path = 1;
- } else
- memcpy(out0,fd->path,strlen(fd->path));
-
- if(is_fifo_exists(out0)) {
- memset(out,0,sizeof(stat_t));
- out->st_mode |= S_IFIFO;
- vfs_lock->unlock();
- return 0;
- }
-
- if(sockets::is_exists(out0)) {
- memset(out,0,sizeof(stat_t));
- out->st_mode |= S_IFSOCK;
- vfs_lock->unlock();
- return 0;
- }
-
- vfs_node_t* node = find_node(out0);
- if(!node) { vfs::vfs::unlock();
- return ENOENT; }
-
- char* fs_love_name = out0 + strlen(node->path) - 1;
- if(!node->stat) { vfs::vfs::unlock();
- return ENOSYS; }
-
- std::int32_t status = node->stat(fd,fs_love_name,out);
- vfs_lock->unlock();
- return status;
-}
-
-std::int64_t vfs::vfs::ioctl(userspace_fd_t* fd, unsigned long req, void *arg, int *res) {
- vfs_lock->lock();
-
- char out0[2048];
- memset(out0,0,2048);
-
- if(!fd->is_cached_path) {
- __vfs_symlink_resolve(fd->path,out0,0);
- memcpy(fd->path,out0,strlen(out0));
- fd->is_cached_path = 1;
- } else
- memcpy(out0,fd->path,strlen(fd->path));
-
- vfs_node_t* node = find_node(out0);
- if(!node) { vfs::vfs::unlock();
- return ENOENT; }
-
- char* fs_love_name = out0 + strlen(node->path) - 1;
- if(!node->ioctl) { vfs::vfs::unlock();
- return ENOTTY; }
-
- std::int64_t status = node->ioctl(fd,fs_love_name,req,arg,res);
- vfs_lock->unlock();
- return status;
-}
-
-std::int32_t vfs::vfs::unlink(userspace_fd_t* fd) {
- vfs_lock->lock();
-
- char out0[2048];
- memset(out0,0,2048);
-
- if(!fd->is_cached_path) {
- __vfs_symlink_resolve(fd->path,out0,0);
- memcpy(fd->path,out0,strlen(out0));
- fd->is_cached_path = 1;
- } else
- memcpy(out0,fd->path,strlen(fd->path));
-
- vfs_node_t* node = find_node(out0);
- if(!node) { vfs::vfs::unlock();
- return -ENOENT; }
-
- char* fs_love_name = out0 + strlen(node->path) - 1;
- if(!node->unlink) { vfs::vfs::unlock();
- return -ENOTSUP; }
-
- std::int32_t ret = node->unlink(fd,fs_love_name);
- vfs_lock->unlock();
- return ret;
-}
-
-
-void vfs::vfs::close(userspace_fd_t* fd) {
- vfs_lock->lock();
-
- char out0[2048];
- memset(out0,0,2048);
-
- if(fd->state == USERSPACE_FD_STATE_SOCKET) {
- // fd->read_socket_pipe->lock.lock();
- // fd->write_socket_pipe->lock.lock();
- // fd->read_socket_pipe->is_closed.test_and_set();
- // fd->write_socket_pipe->is_closed.test_and_set();
- // fd->read_socket_pipe->lock.unlock();
- // fd->write_socket_pipe->lock.unlock();
- vfs_lock->unlock();
- return;
- }
-
- if(!fd->is_cached_path) {
- __vfs_symlink_resolve(fd->path,out0,0);
- memcpy(fd->path,out0,strlen(out0));
- fd->is_cached_path = 1;
- } else
- memcpy(out0,fd->path,strlen(fd->path));
-
- if(is_fifo_exists(out0)) {
- fifo_node_t* fifo = fifo_get(out0);
- fifo->main_pipe->fifoclose();
- vfs_lock->unlock();
- return;
- }
-
- vfs_node_t* node = find_node(out0);
- if(!node) { vfs::vfs::unlock();
- return; }
-
- char* fs_love_name = out0 + strlen(node->path) - 1;
- if(!node->close) { vfs::vfs::unlock();
- return; }
-
- node->close(fd,fs_love_name);
- vfs_lock->unlock();
- return;
-}
-
-std::int32_t vfs::vfs::rename(char* path, char* new_path) {
- vfs_lock->lock();
-
- char out0[2048];
- char new_path0[2048];
-
- __vfs_symlink_resolve(path,out0,0);
- __vfs_symlink_resolve(new_path,new_path0,0);
-
- if(is_fifo_exists(out0)) {
- return -ENOSYS;
- }
-
- vfs_node_t* node = find_node(out0);
- if(!node) { vfs::vfs::unlock();
- return -ENOENT; }
-
- vfs_node_t* new_node = find_node(new_path0);
- if(new_node != node) {
- vfs::vfs::unlock();
- return -EXDEV;
- }
-
- char* fs_love_name = out0 + strlen(node->path) - 1;
- char* fs_love_name0 = new_path0 + strlen(node->path) - 1;
- if(!node->rename) { vfs::vfs::unlock();
- return -ENOSYS; }
-
- int status = node->rename(fs_love_name,fs_love_name0);
-
- if(status != 0)
- Log::SerialDisplay(LEVEL_MESSAGE_WARN,"non zero ret %d from rename %s to %s\n",status,path,new_path);
-
- vfs_lock->unlock();
- return 0;
-}
-
-// internal readlink
-std::int32_t vfs::vfs::readlink(char* path, char* out, std::uint32_t out_len) {
- if(is_fifo_exists(path)) {
- return EINVAL;
- } else if(sockets::is_exists(path)) {
- return EINVAL;
- }
-
- if(path[0] == '\0') {
- path[0] = '/';
- path[1] = '\n';
- }
-
- vfs_node_t* node = find_node(path);
- if(!node) {
- return ENOENT; }
-
- char* fs_love_name = path + strlen(node->path) - 1;
- if(!node->readlink) {
- return EINVAL; }
-
- return node->readlink(fs_love_name,out,out_len);
-}
-
-void vfs::vfs::opt_create_and_write(char* path, int type, char* content, std::uint64_t content_len, int chmod) {
- vfs_lock->lock();
- vfs_node_t* node = find_node(path);
- if(!node) { vfs_lock->unlock();
- return; }
-
- char* fs_love_name = path + strlen(node->path) - 1;
- if(!node->opt_create_and_write) { vfs_lock->unlock();
- return; }
-
- node->opt_create_and_write(fs_love_name,type,content,content_len,chmod);
- vfs_lock->unlock();
- return;
-}
-
-// readlink syscall
-std::int32_t vfs::vfs::extern_readlink(char* path, char* out, std::uint32_t out_len) {
-
- char out0[2048];
- memset(out0,0,2048);
-
- if(path[0] == '\0') {
- path[0] = '/';
- path[1] = '\n';
- }
-
- __vfs_symlink_resolve_no_at_symlink_follow(path,out0);
-
- if(is_fifo_exists(out0)) {
- return EINVAL;
- } else if(sockets::is_exists(out0)) {
- return EINVAL;
- }
-
- vfs_node_t* node = find_node(out0);
- if(!node) {
- return ENOENT; }
-
- char* fs_love_name = out0 + strlen(node->path) - 1;
- if(!node->readlink) {
- return EINVAL; }
-
- return node->readlink(fs_love_name,out,out_len);
-}
-
-
-std::int64_t vfs::vfs::poll(userspace_fd_t* fd, int operation_type) {
-
- vfs::vfs::lock();
-
- char out0[2048];
- memset(out0,0,2048);
-
- if(!fd) {
- vfs::vfs::unlock();
- return 0;
- }
-
- if(!fd->is_cached_path) {
- __vfs_symlink_resolve(fd->path,out0,0);
- memcpy(fd->path,out0,strlen(out0));
- fd->is_cached_path = 1;
- } else
- memcpy(out0,fd->path,strlen(fd->path));
-
- if(is_fifo_exists(out0)) {
- fifo_node_t* fifo = fifo_get(out0);
- std::int64_t ret = 0;
- switch (operation_type)
- {
-
- case POLLIN:
- fifo->main_pipe->lock.lock();
- ret = fifo->main_pipe->size != 0 ? 1 : 0;
- fifo->main_pipe->lock.lock();
- break;
-
- case POLLOUT:
- fifo->main_pipe->lock.lock();
- ret = fifo->main_pipe->size < fifo->main_pipe->total_size ? 1 : 0;
- fifo->main_pipe->lock.lock();
- break;
-
- default:
- break;
- }
- vfs::vfs::unlock();
- return ret;
- }
-
- vfs_node_t* node = find_node(out0);
- if(!node) { vfs::vfs::unlock();
- return -ENOENT; }
-
- char* fs_love_name = out0 + strlen(node->path) - 1;
- if(!node->poll) { vfs::vfs::unlock();
- return -ENOSYS ; }
-
- std::int64_t ret = node->poll(fd,fs_love_name,operation_type);
- vfs::vfs::unlock();
- return ret;
-}
-
-
-void vfs::vfs::unlock() {
- vfs_lock->unlock();
-}
-
-void vfs::vfs::lock() {
- vfs_lock->lock();
-}
-
-void vfs::vfs::init() {
-
- memset(vfs_nodes,0,sizeof(vfs_nodes));
-
- vfs_lock = new locks::spinlock;
- vfs_lock->unlock();
-
- tmpfs::mount(&vfs_nodes[0]);
- memcpy(vfs_nodes[0].path,"/",1);
- Log::Display(LEVEL_MESSAGE_OK,"TmpFS initializied\n");
-
- devfs::mount(&vfs_nodes[1]);
- memcpy(vfs_nodes[1].path,"/dev/",5);
- Log::Display(LEVEL_MESSAGE_OK,"DevFS initializied\n");
-
- evdev::mount(&vfs_nodes[2]);
- memcpy(vfs_nodes[2].path,"/dev/input/",sizeof("/dev/input/"));
- Log::Display(LEVEL_MESSAGE_OK,"EvDev initializied\n");
-
-}
diff --git a/kernel/src/klibc/c/assert.h b/kernel/src/klibc/c/assert.h
new file mode 100644
index 0000000..0798878
--- /dev/null
+++ b/kernel/src/klibc/c/assert.h
@@ -0,0 +1,2 @@
+
+#define assert(x) 100 \ No newline at end of file
diff --git a/kernel/src/klibc/c/stdlib.h b/kernel/src/klibc/c/stdlib.h
new file mode 100644
index 0000000..d97c7f4
--- /dev/null
+++ b/kernel/src/klibc/c/stdlib.h
@@ -0,0 +1,32 @@
+#pragma once
+
+#include <klibc/string.hpp>
+#include <klibc/stdlib.hpp>
+
+using namespace klibc;
+
+#define realloc(ptr, new_size) \
+ ({ \
+ void *__new_ptr = NULL; \
+ size_t __new_size = (new_size); \
+ \
+ if (__new_size == 0) { \
+ /* Если размер 0 - free и возвращаем NULL */ \
+ if (ptr) free(ptr); \
+ __new_ptr = NULL; \
+ } else { \
+ /* Выделяем новую память */ \
+ __new_ptr = malloc(__new_size); \
+ if (__new_ptr && ptr) { \
+ /* Копируем старые данные (размер неизвестен, копируем сколько влезет) */ \
+ /* Примечание: old_size неизвестен, поэтому копируем весь новый размер */ \
+ /* Это безопасно только если старый размер >= нового */ \
+ memcpy(__new_ptr, ptr, __new_size); \
+ } \
+ /* Освобождаем старый указатель */ \
+ if (ptr) { \
+ free(ptr); \
+ } \
+ } \
+ __new_ptr; \
+ }) \ No newline at end of file
diff --git a/kernel/src/klibc/c/string.h b/kernel/src/klibc/c/string.h
new file mode 100644
index 0000000..200c7e4
--- /dev/null
+++ b/kernel/src/klibc/c/string.h
@@ -0,0 +1,3 @@
+#pragma once
+#define memset(a,b,c) klibc::memset(a,b,c)
+#define memcpy(a,b,c) klibc::memcpy(a,b,c) \ No newline at end of file
diff --git a/kernel/src/klibc/stdio.cpp b/kernel/src/klibc/stdio.cpp
new file mode 100644
index 0000000..7e8e283
--- /dev/null
+++ b/kernel/src/klibc/stdio.cpp
@@ -0,0 +1,34 @@
+#include <klibc/stdio.hpp>
+#include <klibc/string.hpp>
+#include <utils/flanterm.hpp>
+#include <cstdint>
+#include <cstddef>
+#include <cstdarg>
+
+#define NANOPRINTF_USE_FIELD_WIDTH_FORMAT_SPECIFIERS 1
+#define NANOPRINTF_USE_PRECISION_FORMAT_SPECIFIERS 1
+#define NANOPRINTF_USE_LARGE_FORMAT_SPECIFIERS 1
+#define NANOPRINTF_USE_SMALL_FORMAT_SPECIFIERS 1
+#define NANOPRINTF_USE_FLOAT_FORMAT_SPECIFIERS 0
+#define NANOPRINTF_USE_BINARY_FORMAT_SPECIFIERS 1
+#define NANOPRINTF_USE_WRITEBACK_FORMAT_SPECIFIERS 0
+#define NANOPRINTF_IMPLEMENTATION
+#include <nanoprintf.h>
+
+#include <cstdint>
+#include <cstddef>
+
+int klibc::_snprintf(char *buffer, std::size_t bufsz, char const *fmt, va_list vlist) {
+ int const rv = npf_vsnprintf(buffer, bufsz, fmt, vlist);
+ return rv;
+}
+
+void klibc::printf(const char* fmt, ...) {
+ va_list val;
+ va_start(val, fmt);
+ char buffer[4096];
+ memset(buffer,0,4096);
+ int len = _snprintf(buffer,4096,fmt,val);
+ utils::flanterm::write(buffer,len);
+ va_end(val);
+} \ No newline at end of file
diff --git a/kernel/src/klibc/stdio.hpp b/kernel/src/klibc/stdio.hpp
new file mode 100644
index 0000000..cce2bcf
--- /dev/null
+++ b/kernel/src/klibc/stdio.hpp
@@ -0,0 +1,18 @@
+#pragma once
+
+#include <cstdint>
+#include <cstdarg>
+
+namespace klibc {
+
+ int _snprintf(char *buffer, std::size_t bufsz, char const *fmt, va_list vlist);
+
+ inline static int __printfbuf(char* buffer, std::size_t bufsf, char const* fmt, ...) {
+ va_list val;
+ va_start(val, fmt);
+ return _snprintf(buffer,bufsf,fmt,val);
+ va_end(val);
+ }
+
+ void printf(const char* fmt, ...);
+}; \ No newline at end of file
diff --git a/kernel/src/klibc/stdlib.cpp b/kernel/src/klibc/stdlib.cpp
new file mode 100644
index 0000000..ab6e06e
--- /dev/null
+++ b/kernel/src/klibc/stdlib.cpp
@@ -0,0 +1,14 @@
+#include <generic/heap.hpp>
+#include <cstdint>
+
+namespace klibc {
+
+ void* malloc(std::size_t size) {
+ return kheap::malloc(size);
+ }
+
+ void free(void* ptr) {
+ kheap::free(ptr);
+ }
+
+}; \ No newline at end of file
diff --git a/kernel/src/klibc/stdlib.hpp b/kernel/src/klibc/stdlib.hpp
new file mode 100644
index 0000000..582a2a8
--- /dev/null
+++ b/kernel/src/klibc/stdlib.hpp
@@ -0,0 +1,7 @@
+#pragma once
+#include <cstdint>
+
+namespace klibc {
+ void* malloc(std::size_t size);
+ void free(void* ptr);
+}; \ No newline at end of file
diff --git a/kernel/src/klibc/string.cpp b/kernel/src/klibc/string.cpp
new file mode 100644
index 0000000..27884ad
--- /dev/null
+++ b/kernel/src/klibc/string.cpp
@@ -0,0 +1,62 @@
+
+#include <cstdint>
+#include <klibc/string.hpp>
+
+void* klibc::memcpy(void *__restrict dest, const void *__restrict src, std::size_t n) {
+ std::uint8_t *__restrict pdest = static_cast<std::uint8_t *__restrict>(dest);
+ const std::uint8_t *__restrict psrc = static_cast<const std::uint8_t *__restrict>(src);
+
+ for (std::size_t i = 0; i < n; i++) {
+ pdest[i] = psrc[i];
+ }
+
+ return dest;
+}
+
+void* klibc::memset(void *s, int c, std::size_t n) {
+ std::uint8_t *p = static_cast<std::uint8_t *>(s);
+
+ for (std::size_t i = 0; i < n; i++) {
+ p[i] = static_cast<uint8_t>(c);
+ }
+
+ return s;
+}
+
+void* klibc::memmove(void *dest, const void *src, std::size_t n) {
+ std::uint8_t *pdest = static_cast<std::uint8_t *>(dest);
+ const std::uint8_t *psrc = static_cast<const std::uint8_t *>(src);
+
+ if (reinterpret_cast<std::uintptr_t>(src) > reinterpret_cast<std::uintptr_t>(dest)) {
+ for (std::size_t i = 0; i < n; i++) {
+ pdest[i] = psrc[i];
+ }
+ } else if (reinterpret_cast<std::uintptr_t>(src) < reinterpret_cast<std::uintptr_t>(dest)) {
+ for (std::size_t i = n; i > 0; i--) {
+ pdest[i-1] = psrc[i-1];
+ }
+ }
+
+ return dest;
+}
+
+int klibc::memcmp(const void *s1, const void *s2, std::size_t n) {
+ const std::uint8_t *p1 = static_cast<const std::uint8_t *>(s1);
+ const std::uint8_t *p2 = static_cast<const std::uint8_t *>(s2);
+
+ for (std::size_t i = 0; i < n; i++) {
+ if (p1[i] != p2[i]) {
+ return p1[i] < p2[i] ? -1 : 1;
+ }
+ }
+
+ return 0;
+}
+
+int klibc::strlen(const char *str) {
+ int len = 0;
+ while (str[len] != '\0') {
+ len++;
+ }
+ return len;
+} \ No newline at end of file
diff --git a/kernel/src/klibc/string.hpp b/kernel/src/klibc/string.hpp
new file mode 100644
index 0000000..c900862
--- /dev/null
+++ b/kernel/src/klibc/string.hpp
@@ -0,0 +1,10 @@
+#pragma once
+#include <cstdint>
+
+namespace klibc {
+ int strlen(const char* str);
+ void* memcpy(void *__restrict dest, const void *__restrict src, std::size_t n);
+ void* memset(void *s, int c, std::size_t n);
+ void* memmove(void *dest, const void *src, std::size_t n);
+ int memcmp(const void *s1, const void *s2, std::size_t n);
+}; \ No newline at end of file
diff --git a/kernel/src/lib/Flanterm/.gitignore b/kernel/src/lib/Flanterm/.gitignore
deleted file mode 100644
index cc62e43..0000000
--- a/kernel/src/lib/Flanterm/.gitignore
+++ /dev/null
@@ -1,2 +0,0 @@
-*.d
-*.o \ No newline at end of file
diff --git a/kernel/src/lib/Flanterm/LICENSE b/kernel/src/lib/Flanterm/LICENSE
deleted file mode 100644
index b3f6075..0000000
--- a/kernel/src/lib/Flanterm/LICENSE
+++ /dev/null
@@ -1,22 +0,0 @@
-Copyright (C) 2022-2025 mintsuki and contributors.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
-1. Redistributions of source code must retain the above copyright notice, this
- list of conditions and the following disclaimer.
-
-2. Redistributions in binary form must reproduce the above copyright notice,
- this list of conditions and the following disclaimer in the documentation
- and/or other materials provided with the distribution.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
-ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
-FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
-SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
-CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
-OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/kernel/src/lib/Flanterm/README.md b/kernel/src/lib/Flanterm/README.md
deleted file mode 100644
index f392efc..0000000
--- a/kernel/src/lib/Flanterm/README.md
+++ /dev/null
@@ -1,43 +0,0 @@
-# Flanterm
-
-Flanterm is a fast and reasonably complete terminal emulator with support for
-multiple output backends. Included is a fast framebuffer backend.
-
-### Quick usage
-
-To quickly set up and use a framebuffer Flanterm instance, it is possible to
-use the `flanterm_fb_init()` function as such:
-```c
-#include <flanterm.h>
-#include <flanterm_backends/fb.h>
-
-struct flanterm_context *ft_ctx = flanterm_fb_init(
- NULL,
- NULL,
- framebuffer_ptr, width, height, pitch,
- red_mask_size, red_mask_shift,
- green_mask_size, green_mask_shift,
- blue_mask_size, blue_mask_shift,
- NULL,
- NULL, NULL,
- NULL, NULL,
- NULL, NULL,
- NULL, 0, 0, 1,
- 0, 0,
- 0
- );
-```
-Where `framebuffer_ptr, width, height, pitch` and `{red,green,blue}_mask_{size,shift}`
-represent the corresponding info about the framebuffer to use for this given instance.
-
-The meaning of the other arguments can be found in `flanterm_backends/fb.h`.
-
-To then print to the terminal instance, simply use the `flanterm_write()`
-function on the given instance. For example:
-```c
-#include <flanterm.h>
-
-const char msg[] = "Hello world\n";
-
-flanterm_write(ft_ctx, msg, sizeof(msg));
-```
diff --git a/kernel/src/lib/Flanterm/src/flanterm.c b/kernel/src/lib/Flanterm/src/flanterm.c
deleted file mode 100644
index 822db63..0000000
--- a/kernel/src/lib/Flanterm/src/flanterm.c
+++ /dev/null
@@ -1,1424 +0,0 @@
-/* Copyright (C) 2022-2025 mintsuki and contributors.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifdef __cplusplus
-#error "Please do not compile Flanterm as C++ code! Flanterm should be compiled as C99 or newer."
-#endif
-
-#ifndef __STDC_VERSION__
-#error "Flanterm must be compiled as C99 or newer."
-#endif
-
-#include <stdint.h>
-#include <stddef.h>
-#include <stdbool.h>
-
-#ifndef FLANTERM_IN_FLANTERM
-#define FLANTERM_IN_FLANTERM
-#endif
-
-#include "flanterm.h"
-
-// Tries to implement this standard for terminfo
-// https://man7.org/linux/man-pages/man4/console_codes.4.html
-
-static const uint32_t col256[] = {
- 0x000000, 0x00005f, 0x000087, 0x0000af, 0x0000d7, 0x0000ff, 0x005f00, 0x005f5f,
- 0x005f87, 0x005faf, 0x005fd7, 0x005fff, 0x008700, 0x00875f, 0x008787, 0x0087af,
- 0x0087d7, 0x0087ff, 0x00af00, 0x00af5f, 0x00af87, 0x00afaf, 0x00afd7, 0x00afff,
- 0x00d700, 0x00d75f, 0x00d787, 0x00d7af, 0x00d7d7, 0x00d7ff, 0x00ff00, 0x00ff5f,
- 0x00ff87, 0x00ffaf, 0x00ffd7, 0x00ffff, 0x5f0000, 0x5f005f, 0x5f0087, 0x5f00af,
- 0x5f00d7, 0x5f00ff, 0x5f5f00, 0x5f5f5f, 0x5f5f87, 0x5f5faf, 0x5f5fd7, 0x5f5fff,
- 0x5f8700, 0x5f875f, 0x5f8787, 0x5f87af, 0x5f87d7, 0x5f87ff, 0x5faf00, 0x5faf5f,
- 0x5faf87, 0x5fafaf, 0x5fafd7, 0x5fafff, 0x5fd700, 0x5fd75f, 0x5fd787, 0x5fd7af,
- 0x5fd7d7, 0x5fd7ff, 0x5fff00, 0x5fff5f, 0x5fff87, 0x5fffaf, 0x5fffd7, 0x5fffff,
- 0x870000, 0x87005f, 0x870087, 0x8700af, 0x8700d7, 0x8700ff, 0x875f00, 0x875f5f,
- 0x875f87, 0x875faf, 0x875fd7, 0x875fff, 0x878700, 0x87875f, 0x878787, 0x8787af,
- 0x8787d7, 0x8787ff, 0x87af00, 0x87af5f, 0x87af87, 0x87afaf, 0x87afd7, 0x87afff,
- 0x87d700, 0x87d75f, 0x87d787, 0x87d7af, 0x87d7d7, 0x87d7ff, 0x87ff00, 0x87ff5f,
- 0x87ff87, 0x87ffaf, 0x87ffd7, 0x87ffff, 0xaf0000, 0xaf005f, 0xaf0087, 0xaf00af,
- 0xaf00d7, 0xaf00ff, 0xaf5f00, 0xaf5f5f, 0xaf5f87, 0xaf5faf, 0xaf5fd7, 0xaf5fff,
- 0xaf8700, 0xaf875f, 0xaf8787, 0xaf87af, 0xaf87d7, 0xaf87ff, 0xafaf00, 0xafaf5f,
- 0xafaf87, 0xafafaf, 0xafafd7, 0xafafff, 0xafd700, 0xafd75f, 0xafd787, 0xafd7af,
- 0xafd7d7, 0xafd7ff, 0xafff00, 0xafff5f, 0xafff87, 0xafffaf, 0xafffd7, 0xafffff,
- 0xd70000, 0xd7005f, 0xd70087, 0xd700af, 0xd700d7, 0xd700ff, 0xd75f00, 0xd75f5f,
- 0xd75f87, 0xd75faf, 0xd75fd7, 0xd75fff, 0xd78700, 0xd7875f, 0xd78787, 0xd787af,
- 0xd787d7, 0xd787ff, 0xd7af00, 0xd7af5f, 0xd7af87, 0xd7afaf, 0xd7afd7, 0xd7afff,
- 0xd7d700, 0xd7d75f, 0xd7d787, 0xd7d7af, 0xd7d7d7, 0xd7d7ff, 0xd7ff00, 0xd7ff5f,
- 0xd7ff87, 0xd7ffaf, 0xd7ffd7, 0xd7ffff, 0xff0000, 0xff005f, 0xff0087, 0xff00af,
- 0xff00d7, 0xff00ff, 0xff5f00, 0xff5f5f, 0xff5f87, 0xff5faf, 0xff5fd7, 0xff5fff,
- 0xff8700, 0xff875f, 0xff8787, 0xff87af, 0xff87d7, 0xff87ff, 0xffaf00, 0xffaf5f,
- 0xffaf87, 0xffafaf, 0xffafd7, 0xffafff, 0xffd700, 0xffd75f, 0xffd787, 0xffd7af,
- 0xffd7d7, 0xffd7ff, 0xffff00, 0xffff5f, 0xffff87, 0xffffaf, 0xffffd7, 0xffffff,
- 0x080808, 0x121212, 0x1c1c1c, 0x262626, 0x303030, 0x3a3a3a, 0x444444, 0x4e4e4e,
- 0x585858, 0x626262, 0x6c6c6c, 0x767676, 0x808080, 0x8a8a8a, 0x949494, 0x9e9e9e,
- 0xa8a8a8, 0xb2b2b2, 0xbcbcbc, 0xc6c6c6, 0xd0d0d0, 0xdadada, 0xe4e4e4, 0xeeeeee
-};
-
-#define CHARSET_DEFAULT 0
-#define CHARSET_DEC_SPECIAL 1
-
-void flanterm_context_reinit(struct flanterm_context *ctx) {
- ctx->tab_size = 8;
- ctx->autoflush = true;
- ctx->cursor_enabled = true;
- ctx->scroll_enabled = true;
- ctx->control_sequence = false;
- ctx->escape = false;
- ctx->osc = false;
- ctx->osc_escape = false;
- ctx->rrr = false;
- ctx->discard_next = false;
- ctx->bold = false;
- ctx->bg_bold = false;
- ctx->reverse_video = false;
- ctx->dec_private = false;
- ctx->insert_mode = false;
- ctx->csi_unhandled = false;
- ctx->unicode_remaining = 0;
- ctx->g_select = 0;
- ctx->charsets[0] = CHARSET_DEFAULT;
- ctx->charsets[1] = CHARSET_DEC_SPECIAL;
- ctx->current_charset = 0;
- ctx->escape_offset = 0;
- ctx->esc_values_i = 0;
- ctx->saved_cursor_x = 0;
- ctx->saved_cursor_y = 0;
- ctx->current_primary = (size_t)-1;
- ctx->current_bg = (size_t)-1;
- ctx->scroll_top_margin = 0;
- ctx->scroll_bottom_margin = ctx->rows;
- ctx->oob_output = FLANTERM_OOB_OUTPUT_ONLCR;
-}
-
-static void flanterm_putchar(struct flanterm_context *ctx, uint8_t c);
-
-void flanterm_write(struct flanterm_context *ctx, const char *buf, size_t count) {
- for (size_t i = 0; i < count; i++) {
- flanterm_putchar(ctx, buf[i]);
- }
-
- if (ctx->autoflush) {
- ctx->double_buffer_flush(ctx);
- }
-}
-
-static void sgr(struct flanterm_context *ctx) {
- size_t i = 0;
-
- if (!ctx->esc_values_i)
- goto def;
-
- for (; i < ctx->esc_values_i; i++) {
- size_t offset;
-
- if (ctx->esc_values[i] == 0) {
-def:
- if (ctx->reverse_video) {
- ctx->reverse_video = false;
- ctx->swap_palette(ctx);
- }
- ctx->bold = false;
- ctx->bg_bold = false;
- ctx->current_primary = (size_t)-1;
- ctx->current_bg = (size_t)-1;
- ctx->set_text_bg_default(ctx);
- ctx->set_text_fg_default(ctx);
- continue;
- }
-
- else if (ctx->esc_values[i] == 1) {
- ctx->bold = true;
- if (ctx->current_primary != (size_t)-1) {
- if (!ctx->reverse_video) {
- ctx->set_text_fg_bright(ctx, ctx->current_primary);
- } else {
- ctx->set_text_bg_bright(ctx, ctx->current_primary);
- }
- } else {
- if (!ctx->reverse_video) {
- ctx->set_text_fg_default_bright(ctx);
- } else {
- ctx->set_text_bg_default_bright(ctx);
- }
- }
- continue;
- }
-
- else if (ctx->esc_values[i] == 5) {
- ctx->bg_bold = true;
- if (ctx->current_bg != (size_t)-1) {
- if (!ctx->reverse_video) {
- ctx->set_text_bg_bright(ctx, ctx->current_bg);
- } else {
- ctx->set_text_fg_bright(ctx, ctx->current_bg);
- }
- } else {
- if (!ctx->reverse_video) {
- ctx->set_text_bg_default_bright(ctx);
- } else {
- ctx->set_text_fg_default_bright(ctx);
- }
- }
- continue;
- }
-
- else if (ctx->esc_values[i] == 22) {
- ctx->bold = false;
- if (ctx->current_primary != (size_t)-1) {
- if (!ctx->reverse_video) {
- ctx->set_text_fg(ctx, ctx->current_primary);
- } else {
- ctx->set_text_bg(ctx, ctx->current_primary);
- }
- } else {
- if (!ctx->reverse_video) {
- ctx->set_text_fg_default(ctx);
- } else {
- ctx->set_text_bg_default(ctx);
- }
- }
- continue;
- }
-
- else if (ctx->esc_values[i] == 25) {
- ctx->bg_bold = false;
- if (ctx->current_bg != (size_t)-1) {
- if (!ctx->reverse_video) {
- ctx->set_text_bg(ctx, ctx->current_bg);
- } else {
- ctx->set_text_fg(ctx, ctx->current_bg);
- }
- } else {
- if (!ctx->reverse_video) {
- ctx->set_text_bg_default(ctx);
- } else {
- ctx->set_text_fg_default(ctx);
- }
- }
- continue;
- }
-
- else if (ctx->esc_values[i] >= 30 && ctx->esc_values[i] <= 37) {
- offset = 30;
- ctx->current_primary = ctx->esc_values[i] - offset;
-
- if (ctx->reverse_video) {
- goto set_bg;
- }
-
-set_fg:
- if ((ctx->bold && !ctx->reverse_video)
- || (ctx->bg_bold && ctx->reverse_video)) {
- ctx->set_text_fg_bright(ctx, ctx->esc_values[i] - offset);
- } else {
- ctx->set_text_fg(ctx, ctx->esc_values[i] - offset);
- }
- continue;
- }
-
- else if (ctx->esc_values[i] >= 40 && ctx->esc_values[i] <= 47) {
- offset = 40;
- ctx->current_bg = ctx->esc_values[i] - offset;
-
- if (ctx->reverse_video) {
- goto set_fg;
- }
-
-set_bg:
- if ((ctx->bold && ctx->reverse_video)
- || (ctx->bg_bold && !ctx->reverse_video)) {
- ctx->set_text_bg_bright(ctx, ctx->esc_values[i] - offset);
- } else {
- ctx->set_text_bg(ctx, ctx->esc_values[i] - offset);
- }
- continue;
- }
-
- else if (ctx->esc_values[i] >= 90 && ctx->esc_values[i] <= 97) {
- offset = 90;
- ctx->current_primary = ctx->esc_values[i] - offset;
-
- if (ctx->reverse_video) {
- goto set_bg_bright;
- }
-
-set_fg_bright:
- ctx->set_text_fg_bright(ctx, ctx->esc_values[i] - offset);
- continue;
- }
-
- else if (ctx->esc_values[i] >= 100 && ctx->esc_values[i] <= 107) {
- offset = 100;
- ctx->current_bg = ctx->esc_values[i] - offset;
-
- if (ctx->reverse_video) {
- goto set_fg_bright;
- }
-
-set_bg_bright:
- ctx->set_text_bg_bright(ctx, ctx->esc_values[i] - offset);
- continue;
- }
-
- else if (ctx->esc_values[i] == 39) {
- ctx->current_primary = (size_t)-1;
-
- if (ctx->reverse_video) {
- ctx->swap_palette(ctx);
- }
-
- if (!ctx->bold) {
- ctx->set_text_fg_default(ctx);
- } else {
- ctx->set_text_fg_default_bright(ctx);
- }
-
- if (ctx->reverse_video) {
- ctx->swap_palette(ctx);
- }
-
- continue;
- }
-
- else if (ctx->esc_values[i] == 49) {
- ctx->current_bg = (size_t)-1;
-
- if (ctx->reverse_video) {
- ctx->swap_palette(ctx);
- }
-
- if (!ctx->bg_bold) {
- ctx->set_text_bg_default(ctx);
- } else {
- ctx->set_text_bg_default_bright(ctx);
- }
-
- if (ctx->reverse_video) {
- ctx->swap_palette(ctx);
- }
-
- continue;
- }
-
- else if (ctx->esc_values[i] == 7) {
- if (!ctx->reverse_video) {
- ctx->reverse_video = true;
- ctx->swap_palette(ctx);
- }
- continue;
- }
-
- else if (ctx->esc_values[i] == 27) {
- if (ctx->reverse_video) {
- ctx->reverse_video = false;
- ctx->swap_palette(ctx);
- }
- continue;
- }
-
- // 256/RGB
- else if (ctx->esc_values[i] == 38 || ctx->esc_values[i] == 48) {
- bool fg = ctx->esc_values[i] == 38;
-
- i++;
- if (i >= ctx->esc_values_i) {
- break;
- }
-
- switch (ctx->esc_values[i]) {
- case 2: { // RGB
- if (i + 3 >= ctx->esc_values_i) {
- goto out;
- }
-
- uint32_t rgb_value = 0;
-
- rgb_value |= ctx->esc_values[i + 1] << 16;
- rgb_value |= ctx->esc_values[i + 2] << 8;
- rgb_value |= ctx->esc_values[i + 3];
-
- i += 3;
-
- (fg ? ctx->set_text_fg_rgb : ctx->set_text_bg_rgb)(ctx, rgb_value);
-
- break;
- }
- case 5: { // 256 colors
- if (i + 1 >= ctx->esc_values_i) {
- goto out;
- }
-
- uint32_t col = ctx->esc_values[i + 1];
-
- i++;
-
- if (col < 8) {
- (fg ? ctx->set_text_fg : ctx->set_text_bg)(ctx, col);
- } else if (col < 16) {
- (fg ? ctx->set_text_fg_bright : ctx->set_text_bg_bright)(ctx, col - 8);
- } else if (col < 256) {
- uint32_t rgb_value = col256[col - 16];
- (fg ? ctx->set_text_fg_rgb : ctx->set_text_bg_rgb)(ctx, rgb_value);
- }
-
- break;
- }
- default: continue;
- }
- }
- }
-
-out:;
-}
-
-static void dec_private_parse(struct flanterm_context *ctx, uint8_t c) {
- ctx->dec_private = false;
-
- if (ctx->esc_values_i == 0) {
- return;
- }
-
- bool set;
-
- switch (c) {
- case 'h':
- set = true; break;
- case 'l':
- set = false; break;
- default:
- return;
- }
-
- switch (ctx->esc_values[0]) {
- case 25: {
- if (set) {
- ctx->cursor_enabled = true;
- } else {
- ctx->cursor_enabled = false;
- }
- return;
- }
- }
-
- if (ctx->callback != NULL) {
- ctx->callback(ctx, FLANTERM_CB_DEC, ctx->esc_values_i, (uintptr_t)ctx->esc_values, c);
- }
-}
-
-static void linux_private_parse(struct flanterm_context *ctx) {
- if (ctx->esc_values_i == 0) {
- return;
- }
-
- if (ctx->callback != NULL) {
- ctx->callback(ctx, FLANTERM_CB_LINUX, ctx->esc_values_i, (uintptr_t)ctx->esc_values, 0);
- }
-}
-
-static void mode_toggle(struct flanterm_context *ctx, uint8_t c) {
- if (ctx->esc_values_i == 0) {
- return;
- }
-
- bool set;
-
- switch (c) {
- case 'h':
- set = true; break;
- case 'l':
- set = false; break;
- default:
- return;
- }
-
- switch (ctx->esc_values[0]) {
- case 4:
- ctx->insert_mode = set; return;
- }
-
- if (ctx->callback != NULL) {
- ctx->callback(ctx, FLANTERM_CB_MODE, ctx->esc_values_i, (uintptr_t)ctx->esc_values, c);
- }
-}
-
-static bool osc_parse(struct flanterm_context *ctx, uint8_t c) {
- // ESC \ terminates an OSC sequence cleanly
- // but if ESC is followed by non-\, report failure from osc_parse and
- // try parsing the character as another escape code
- if (ctx->osc_escape) {
- if (c == '\\') {
- ctx->osc = false;
- ctx->osc_escape = false;
- ctx->escape = false;
- return true;
- } else {
- ctx->osc_escape = false;
- ctx->osc = false;
- // escape stays true here
- return false;
- }
- }
- switch (c) {
- case 0x1b:
- ctx->osc_escape = true;
- break;
- // BEL is the other terminator
- case '\a':
- ctx->osc_escape = false;
- ctx->osc = false;
- ctx->escape = false;
- break;
- default:
- break;
- }
- return true;
-}
-
-static void control_sequence_parse(struct flanterm_context *ctx, uint8_t c) {
- if (ctx->escape_offset == 2) {
- switch (c) {
- case '[':
- ctx->discard_next = true;
- goto cleanup;
- case '?':
- ctx->dec_private = true;
- return;
- }
- }
-
- if (c >= '0' && c <= '9') {
- if (ctx->esc_values_i == FLANTERM_MAX_ESC_VALUES) {
- return;
- }
- ctx->rrr = true;
- ctx->esc_values[ctx->esc_values_i] *= 10;
- ctx->esc_values[ctx->esc_values_i] += c - '0';
- return;
- }
-
- if (ctx->rrr == true) {
- ctx->esc_values_i++;
- ctx->rrr = false;
- if (c == ';')
- return;
- } else if (c == ';') {
- if (ctx->esc_values_i == FLANTERM_MAX_ESC_VALUES) {
- return;
- }
- ctx->esc_values[ctx->esc_values_i] = 0;
- ctx->esc_values_i++;
- return;
- }
-
- size_t esc_default;
- switch (c) {
- case 'J': case 'K': case 'q':
- esc_default = 0; break;
- default:
- esc_default = 1; break;
- }
-
- for (size_t i = ctx->esc_values_i; i < FLANTERM_MAX_ESC_VALUES; i++) {
- ctx->esc_values[i] = esc_default;
- }
-
- if (ctx->dec_private == true) {
- dec_private_parse(ctx, c);
- goto cleanup;
- }
-
- bool r = ctx->scroll_enabled;
- ctx->scroll_enabled = false;
- size_t x, y;
- ctx->get_cursor_pos(ctx, &x, &y);
-
- // CSI sequences are terminated by a byte in [0x40,0x7E]
- // so skip all bytes until the terminator byte
- if (ctx->csi_unhandled) {
- if (c >= 0x40 && c <= 0x7E) {
- ctx->csi_unhandled = false;
- goto cleanup;
- }
- return;
- }
-
- switch (c) {
- // Got ESC in the middle of an escape sequence, start a new one
- case 0x1B:
- return;
- case 'F':
- x = 0;
- // FALLTHRU
- case 'A': {
- if (ctx->esc_values[0] > y)
- ctx->esc_values[0] = y;
- size_t orig_y = y;
- size_t dest_y = y - ctx->esc_values[0];
- bool will_be_in_scroll_region = false;
- if ((ctx->scroll_top_margin >= dest_y && ctx->scroll_top_margin <= orig_y)
- || (ctx->scroll_bottom_margin >= dest_y && ctx->scroll_bottom_margin <= orig_y)) {
- will_be_in_scroll_region = true;
- }
- if (will_be_in_scroll_region && dest_y < ctx->scroll_top_margin) {
- dest_y = ctx->scroll_top_margin;
- }
- ctx->set_cursor_pos(ctx, x, dest_y);
- break;
- }
- case 'E':
- x = 0;
- // FALLTHRU
- case 'e':
- case 'B': {
- if (y + ctx->esc_values[0] > ctx->rows - 1)
- ctx->esc_values[0] = (ctx->rows - 1) - y;
- size_t orig_y = y;
- size_t dest_y = y + ctx->esc_values[0];
- bool will_be_in_scroll_region = false;
- if ((ctx->scroll_top_margin >= orig_y && ctx->scroll_top_margin <= dest_y)
- || (ctx->scroll_bottom_margin >= orig_y && ctx->scroll_bottom_margin <= dest_y)) {
- will_be_in_scroll_region = true;
- }
- if (will_be_in_scroll_region && dest_y >= ctx->scroll_bottom_margin) {
- dest_y = ctx->scroll_bottom_margin - 1;
- }
- ctx->set_cursor_pos(ctx, x, dest_y);
- break;
- }
- case 'a':
- case 'C':
- if (x + ctx->esc_values[0] > ctx->cols - 1)
- ctx->esc_values[0] = (ctx->cols - 1) - x;
- ctx->set_cursor_pos(ctx, x + ctx->esc_values[0], y);
- break;
- case 'D':
- if (ctx->esc_values[0] > x)
- ctx->esc_values[0] = x;
- ctx->set_cursor_pos(ctx, x - ctx->esc_values[0], y);
- break;
- case 'c':
- if (ctx->callback != NULL) {
- ctx->callback(ctx, FLANTERM_CB_PRIVATE_ID, 0, 0, 0);
- }
- break;
- case 'd':
- ctx->esc_values[0] -= 1;
- if (ctx->esc_values[0] >= ctx->rows)
- ctx->esc_values[0] = ctx->rows - 1;
- ctx->set_cursor_pos(ctx, x, ctx->esc_values[0]);
- break;
- case 'G':
- case '`':
- ctx->esc_values[0] -= 1;
- if (ctx->esc_values[0] >= ctx->cols)
- ctx->esc_values[0] = ctx->cols - 1;
- ctx->set_cursor_pos(ctx, ctx->esc_values[0], y);
- break;
- case 'H':
- case 'f':
- if (ctx->esc_values[0] != 0) {
- ctx->esc_values[0]--;
- }
- if (ctx->esc_values[1] != 0) {
- ctx->esc_values[1]--;
- }
- if (ctx->esc_values[1] >= ctx->cols)
- ctx->esc_values[1] = ctx->cols - 1;
- if (ctx->esc_values[0] >= ctx->rows)
- ctx->esc_values[0] = ctx->rows - 1;
- ctx->set_cursor_pos(ctx, ctx->esc_values[1], ctx->esc_values[0]);
- break;
- case 'M': {
- size_t count = ctx->esc_values[0] > ctx->rows ? ctx->rows : ctx->esc_values[0];
- for (size_t i = 0; i < count; i++) {
- ctx->scroll(ctx);
- }
- break;
- }
- case 'L': {
- size_t old_scroll_top_margin = ctx->scroll_top_margin;
- ctx->scroll_top_margin = y;
- size_t count = ctx->esc_values[0] > ctx->rows ? ctx->rows : ctx->esc_values[0];
- for (size_t i = 0; i < count; i++) {
- ctx->revscroll(ctx);
- }
- ctx->scroll_top_margin = old_scroll_top_margin;
- break;
- }
- case 'n':
- switch (ctx->esc_values[0]) {
- case 5:
- if (ctx->callback != NULL) {
- ctx->callback(ctx, FLANTERM_CB_STATUS_REPORT, 0, 0, 0);
- }
- break;
- case 6:
- if (ctx->callback != NULL) {
- ctx->callback(ctx, FLANTERM_CB_POS_REPORT, x + 1, y + 1, 0);
- }
- break;
- }
- break;
- case 'q':
- if (ctx->callback != NULL) {
- ctx->callback(ctx, FLANTERM_CB_KBD_LEDS, ctx->esc_values[0], 0, 0);
- }
- break;
- case 'J':
- switch (ctx->esc_values[0]) {
- case 0: {
- size_t rows_remaining = ctx->rows - (y + 1);
- size_t cols_diff = ctx->cols - (x + 1);
- size_t to_clear = rows_remaining * ctx->cols + cols_diff + 1;
- for (size_t i = 0; i < to_clear; i++) {
- ctx->raw_putchar(ctx, ' ');
- }
- ctx->set_cursor_pos(ctx, x, y);
- break;
- }
- case 1: {
- ctx->set_cursor_pos(ctx, 0, 0);
- bool b = false;
- for (size_t yc = 0; yc < ctx->rows; yc++) {
- for (size_t xc = 0; xc < ctx->cols; xc++) {
- ctx->raw_putchar(ctx, ' ');
- if (xc == x && yc == y) {
- ctx->set_cursor_pos(ctx, x, y);
- b = true;
- break;
- }
- }
- if (b == true)
- break;
- }
- break;
- }
- case 2:
- case 3:
- ctx->clear(ctx, false);
- break;
- }
- break;
- case '@':
- for (size_t i = ctx->cols - 1; ; i--) {
- ctx->move_character(ctx, i + ctx->esc_values[0], y, i, y);
- ctx->set_cursor_pos(ctx, i, y);
- ctx->raw_putchar(ctx, ' ');
- if (i == x) {
- break;
- }
- }
- ctx->set_cursor_pos(ctx, x, y);
- break;
- case 'P':
- for (size_t i = x + ctx->esc_values[0]; i < ctx->cols; i++)
- ctx->move_character(ctx, i - ctx->esc_values[0], y, i, y);
- ctx->set_cursor_pos(ctx, ctx->cols - ctx->esc_values[0], y);
- // FALLTHRU
- case 'X': {
- size_t count = ctx->esc_values[0] > ctx->cols ? ctx->cols : ctx->esc_values[0];
- for (size_t i = 0; i < count; i++)
- ctx->raw_putchar(ctx, ' ');
- ctx->set_cursor_pos(ctx, x, y);
- break;
- }
- case 'm':
- sgr(ctx);
- break;
- case 's':
- ctx->get_cursor_pos(ctx, &ctx->saved_cursor_x, &ctx->saved_cursor_y);
- break;
- case 'u':
- ctx->set_cursor_pos(ctx, ctx->saved_cursor_x, ctx->saved_cursor_y);
- break;
- case 'K':
- switch (ctx->esc_values[0]) {
- case 0: {
- for (size_t i = x; i < ctx->cols; i++)
- ctx->raw_putchar(ctx, ' ');
- ctx->set_cursor_pos(ctx, x, y);
- break;
- }
- case 1: {
- ctx->set_cursor_pos(ctx, 0, y);
- for (size_t i = 0; i < x; i++)
- ctx->raw_putchar(ctx, ' ');
- break;
- }
- case 2: {
- ctx->set_cursor_pos(ctx, 0, y);
- for (size_t i = 0; i < ctx->cols; i++)
- ctx->raw_putchar(ctx, ' ');
- ctx->set_cursor_pos(ctx, x, y);
- break;
- }
- }
- break;
- case 'r':
- if (ctx->esc_values[0] == 0) {
- ctx->esc_values[0] = 1;
- }
- if (ctx->esc_values[1] == 0) {
- ctx->esc_values[1] = 1;
- }
- ctx->scroll_top_margin = 0;
- ctx->scroll_bottom_margin = ctx->rows;
- if (ctx->esc_values_i > 0) {
- ctx->scroll_top_margin = ctx->esc_values[0] - 1;
- }
- if (ctx->esc_values_i > 1) {
- ctx->scroll_bottom_margin = ctx->esc_values[1];
- }
- if (ctx->scroll_top_margin >= ctx->rows
- || ctx->scroll_bottom_margin > ctx->rows
- || ctx->scroll_top_margin >= (ctx->scroll_bottom_margin - 1)) {
- ctx->scroll_top_margin = 0;
- ctx->scroll_bottom_margin = ctx->rows;
- }
- ctx->set_cursor_pos(ctx, 0, 0);
- break;
- case 'l':
- case 'h':
- mode_toggle(ctx, c);
- break;
- case ']':
- linux_private_parse(ctx);
- break;
- default:
- ctx->csi_unhandled = true;
- return;
- }
-
- ctx->scroll_enabled = r;
-
-cleanup:
- ctx->control_sequence = false;
- ctx->escape = false;
-}
-
-static void restore_state(struct flanterm_context *ctx) {
- ctx->bold = ctx->saved_state_bold;
- ctx->bg_bold = ctx->saved_state_bg_bold;
- ctx->reverse_video = ctx->saved_state_reverse_video;
- ctx->current_charset = ctx->saved_state_current_charset;
- ctx->current_primary = ctx->saved_state_current_primary;
- ctx->current_bg = ctx->saved_state_current_bg;
-
- ctx->restore_state(ctx);
-}
-
-static void save_state(struct flanterm_context *ctx) {
- ctx->save_state(ctx);
-
- ctx->saved_state_bold = ctx->bold;
- ctx->saved_state_bg_bold = ctx->bg_bold;
- ctx->saved_state_reverse_video = ctx->reverse_video;
- ctx->saved_state_current_charset = ctx->current_charset;
- ctx->saved_state_current_primary = ctx->current_primary;
- ctx->saved_state_current_bg = ctx->current_bg;
-}
-
-static void escape_parse(struct flanterm_context *ctx, uint8_t c) {
- ctx->escape_offset++;
-
- if (ctx->osc == true) {
- // ESC \ is one of the two possible terminators of OSC sequences,
- // so osc_parse consumes ESC.
- // If it is then followed by \ it cleans correctly,
- // otherwise it returns false, and it tries parsing it as another escape sequence
- if (osc_parse(ctx, c)) {
- return;
- }
- }
-
- if (ctx->control_sequence == true) {
- control_sequence_parse(ctx, c);
- return;
- }
-
- size_t x, y;
- ctx->get_cursor_pos(ctx, &x, &y);
-
- switch (c) {
- case ']':
- ctx->osc_escape = false;
- ctx->osc = true;
- return;
- case '[':
- for (size_t i = 0; i < FLANTERM_MAX_ESC_VALUES; i++)
- ctx->esc_values[i] = 0;
- ctx->esc_values_i = 0;
- ctx->rrr = false;
- ctx->csi_unhandled = false;
- ctx->control_sequence = true;
- return;
- case '7':
- save_state(ctx);
- break;
- case '8':
- restore_state(ctx);
- break;
- case 'c':
- flanterm_context_reinit(ctx);
- ctx->clear(ctx, true);
- break;
- case 'D':
- if (y == ctx->scroll_bottom_margin - 1) {
- ctx->scroll(ctx);
- ctx->set_cursor_pos(ctx, x, y);
- } else {
- ctx->set_cursor_pos(ctx, x, y + 1);
- }
- break;
- case 'E':
- if (y == ctx->scroll_bottom_margin - 1) {
- ctx->scroll(ctx);
- ctx->set_cursor_pos(ctx, 0, y);
- } else {
- ctx->set_cursor_pos(ctx, 0, y + 1);
- }
- break;
- case 'M':
- // "Reverse linefeed"
- if (y == ctx->scroll_top_margin) {
- ctx->revscroll(ctx);
- ctx->set_cursor_pos(ctx, 0, y);
- } else {
- ctx->set_cursor_pos(ctx, 0, y - 1);
- }
- break;
- case 'Z':
- if (ctx->callback != NULL) {
- ctx->callback(ctx, FLANTERM_CB_PRIVATE_ID, 0, 0, 0);
- }
- break;
- case '(':
- case ')':
- ctx->g_select = c - '\'';
- break;
- }
-
- ctx->escape = false;
-}
-
-static bool dec_special_print(struct flanterm_context *ctx, uint8_t c) {
-#define FLANTERM_DEC_SPCL_PRN(C) ctx->raw_putchar(ctx, (C)); return true;
- switch (c) {
- case '`': FLANTERM_DEC_SPCL_PRN(0x04)
- case '0': FLANTERM_DEC_SPCL_PRN(0xdb)
- case '-': FLANTERM_DEC_SPCL_PRN(0x18)
- case ',': FLANTERM_DEC_SPCL_PRN(0x1b)
- case '.': FLANTERM_DEC_SPCL_PRN(0x19)
- case 'a': FLANTERM_DEC_SPCL_PRN(0xb1)
- case 'f': FLANTERM_DEC_SPCL_PRN(0xf8)
- case 'g': FLANTERM_DEC_SPCL_PRN(0xf1)
- case 'h': FLANTERM_DEC_SPCL_PRN(0xb0)
- case 'j': FLANTERM_DEC_SPCL_PRN(0xd9)
- case 'k': FLANTERM_DEC_SPCL_PRN(0xbf)
- case 'l': FLANTERM_DEC_SPCL_PRN(0xda)
- case 'm': FLANTERM_DEC_SPCL_PRN(0xc0)
- case 'n': FLANTERM_DEC_SPCL_PRN(0xc5)
- case 'q': FLANTERM_DEC_SPCL_PRN(0xc4)
- case 's': FLANTERM_DEC_SPCL_PRN(0x5f)
- case 't': FLANTERM_DEC_SPCL_PRN(0xc3)
- case 'u': FLANTERM_DEC_SPCL_PRN(0xb4)
- case 'v': FLANTERM_DEC_SPCL_PRN(0xc1)
- case 'w': FLANTERM_DEC_SPCL_PRN(0xc2)
- case 'x': FLANTERM_DEC_SPCL_PRN(0xb3)
- case 'y': FLANTERM_DEC_SPCL_PRN(0xf3)
- case 'z': FLANTERM_DEC_SPCL_PRN(0xf2)
- case '~': FLANTERM_DEC_SPCL_PRN(0xfa)
- case '_': FLANTERM_DEC_SPCL_PRN(0xff)
- case '+': FLANTERM_DEC_SPCL_PRN(0x1a)
- case '{': FLANTERM_DEC_SPCL_PRN(0xe3)
- case '}': FLANTERM_DEC_SPCL_PRN(0x9c)
- }
-#undef FLANTERM_DEC_SPCL_PRN
-
- return false;
-}
-
-// Following wcwidth related code inherited from:
-// https://www.cl.cam.ac.uk/~mgk25/ucs/wcwidth.c
-
-struct interval {
- uint32_t first;
- uint32_t last;
-};
-
-/* auxiliary function for binary search in interval table */
-static int bisearch(uint32_t ucs, const struct interval *table, int max) {
- int min = 0;
- int mid;
-
- if (ucs < table[0].first || ucs > table[max].last)
- return 0;
- while (max >= min) {
- mid = (min + max) / 2;
- if (ucs > table[mid].last)
- min = mid + 1;
- else if (ucs < table[mid].first)
- max = mid - 1;
- else
- return 1;
- }
-
- return 0;
-}
-
-int mk_wcwidth(uint32_t ucs) {
- /* sorted list of non-overlapping intervals of non-spacing characters */
- /* generated by "uniset +cat=Me +cat=Mn +cat=Cf -00AD +1160-11FF +200B c" */
- static const struct interval combining[] = {
- { 0x0300, 0x036F }, { 0x0483, 0x0486 }, { 0x0488, 0x0489 },
- { 0x0591, 0x05BD }, { 0x05BF, 0x05BF }, { 0x05C1, 0x05C2 },
- { 0x05C4, 0x05C5 }, { 0x05C7, 0x05C7 }, { 0x0600, 0x0603 },
- { 0x0610, 0x0615 }, { 0x064B, 0x065E }, { 0x0670, 0x0670 },
- { 0x06D6, 0x06E4 }, { 0x06E7, 0x06E8 }, { 0x06EA, 0x06ED },
- { 0x070F, 0x070F }, { 0x0711, 0x0711 }, { 0x0730, 0x074A },
- { 0x07A6, 0x07B0 }, { 0x07EB, 0x07F3 }, { 0x0901, 0x0902 },
- { 0x093C, 0x093C }, { 0x0941, 0x0948 }, { 0x094D, 0x094D },
- { 0x0951, 0x0954 }, { 0x0962, 0x0963 }, { 0x0981, 0x0981 },
- { 0x09BC, 0x09BC }, { 0x09C1, 0x09C4 }, { 0x09CD, 0x09CD },
- { 0x09E2, 0x09E3 }, { 0x0A01, 0x0A02 }, { 0x0A3C, 0x0A3C },
- { 0x0A41, 0x0A42 }, { 0x0A47, 0x0A48 }, { 0x0A4B, 0x0A4D },
- { 0x0A70, 0x0A71 }, { 0x0A81, 0x0A82 }, { 0x0ABC, 0x0ABC },
- { 0x0AC1, 0x0AC5 }, { 0x0AC7, 0x0AC8 }, { 0x0ACD, 0x0ACD },
- { 0x0AE2, 0x0AE3 }, { 0x0B01, 0x0B01 }, { 0x0B3C, 0x0B3C },
- { 0x0B3F, 0x0B3F }, { 0x0B41, 0x0B43 }, { 0x0B4D, 0x0B4D },
- { 0x0B56, 0x0B56 }, { 0x0B82, 0x0B82 }, { 0x0BC0, 0x0BC0 },
- { 0x0BCD, 0x0BCD }, { 0x0C3E, 0x0C40 }, { 0x0C46, 0x0C48 },
- { 0x0C4A, 0x0C4D }, { 0x0C55, 0x0C56 }, { 0x0CBC, 0x0CBC },
- { 0x0CBF, 0x0CBF }, { 0x0CC6, 0x0CC6 }, { 0x0CCC, 0x0CCD },
- { 0x0CE2, 0x0CE3 }, { 0x0D41, 0x0D43 }, { 0x0D4D, 0x0D4D },
- { 0x0DCA, 0x0DCA }, { 0x0DD2, 0x0DD4 }, { 0x0DD6, 0x0DD6 },
- { 0x0E31, 0x0E31 }, { 0x0E34, 0x0E3A }, { 0x0E47, 0x0E4E },
- { 0x0EB1, 0x0EB1 }, { 0x0EB4, 0x0EB9 }, { 0x0EBB, 0x0EBC },
- { 0x0EC8, 0x0ECD }, { 0x0F18, 0x0F19 }, { 0x0F35, 0x0F35 },
- { 0x0F37, 0x0F37 }, { 0x0F39, 0x0F39 }, { 0x0F71, 0x0F7E },
- { 0x0F80, 0x0F84 }, { 0x0F86, 0x0F87 }, { 0x0F90, 0x0F97 },
- { 0x0F99, 0x0FBC }, { 0x0FC6, 0x0FC6 }, { 0x102D, 0x1030 },
- { 0x1032, 0x1032 }, { 0x1036, 0x1037 }, { 0x1039, 0x1039 },
- { 0x1058, 0x1059 }, { 0x1160, 0x11FF }, { 0x135F, 0x135F },
- { 0x1712, 0x1714 }, { 0x1732, 0x1734 }, { 0x1752, 0x1753 },
- { 0x1772, 0x1773 }, { 0x17B4, 0x17B5 }, { 0x17B7, 0x17BD },
- { 0x17C6, 0x17C6 }, { 0x17C9, 0x17D3 }, { 0x17DD, 0x17DD },
- { 0x180B, 0x180D }, { 0x18A9, 0x18A9 }, { 0x1920, 0x1922 },
- { 0x1927, 0x1928 }, { 0x1932, 0x1932 }, { 0x1939, 0x193B },
- { 0x1A17, 0x1A18 }, { 0x1B00, 0x1B03 }, { 0x1B34, 0x1B34 },
- { 0x1B36, 0x1B3A }, { 0x1B3C, 0x1B3C }, { 0x1B42, 0x1B42 },
- { 0x1B6B, 0x1B73 }, { 0x1DC0, 0x1DCA }, { 0x1DFE, 0x1DFF },
- { 0x200B, 0x200F }, { 0x202A, 0x202E }, { 0x2060, 0x2063 },
- { 0x206A, 0x206F }, { 0x20D0, 0x20EF }, { 0x302A, 0x302F },
- { 0x3099, 0x309A }, { 0xA806, 0xA806 }, { 0xA80B, 0xA80B },
- { 0xA825, 0xA826 }, { 0xFB1E, 0xFB1E }, { 0xFE00, 0xFE0F },
- { 0xFE20, 0xFE23 }, { 0xFEFF, 0xFEFF }, { 0xFFF9, 0xFFFB },
- { 0x10A01, 0x10A03 }, { 0x10A05, 0x10A06 }, { 0x10A0C, 0x10A0F },
- { 0x10A38, 0x10A3A }, { 0x10A3F, 0x10A3F }, { 0x1D167, 0x1D169 },
- { 0x1D173, 0x1D182 }, { 0x1D185, 0x1D18B }, { 0x1D1AA, 0x1D1AD },
- { 0x1D242, 0x1D244 }, { 0xE0001, 0xE0001 }, { 0xE0020, 0xE007F },
- { 0xE0100, 0xE01EF }
- };
-
- /* test for 8-bit control characters */
- if (ucs == 0)
- return 0;
- if (ucs < 32 || (ucs >= 0x7f && ucs < 0xa0))
- return 1;
-
- /* binary search in table of non-spacing characters */
- if (bisearch(ucs, combining,
- sizeof(combining) / sizeof(struct interval) - 1))
- return 0;
-
- /* if we arrive here, ucs is not a combining or C0/C1 control character */
-
- return 1 +
- (ucs >= 0x1100 &&
- (ucs <= 0x115f || /* Hangul Jamo init. consonants */
- ucs == 0x2329 || ucs == 0x232a ||
- (ucs >= 0x2e80 && ucs <= 0xa4cf &&
- ucs != 0x303f) || /* CJK ... Yi */
- (ucs >= 0xac00 && ucs <= 0xd7a3) || /* Hangul Syllables */
- (ucs >= 0xf900 && ucs <= 0xfaff) || /* CJK Compatibility Ideographs */
- (ucs >= 0xfe10 && ucs <= 0xfe19) || /* Vertical forms */
- (ucs >= 0xfe30 && ucs <= 0xfe6f) || /* CJK Compatibility Forms */
- (ucs >= 0xff00 && ucs <= 0xff60) || /* Fullwidth Forms */
- (ucs >= 0xffe0 && ucs <= 0xffe6) ||
- (ucs >= 0x20000 && ucs <= 0x2fffd) ||
- (ucs >= 0x30000 && ucs <= 0x3fffd)));
-}
-
-// End of https://www.cl.cam.ac.uk/~mgk25/ucs/wcwidth.c inherited code
-
-static int unicode_to_cp437(uint64_t code_point) {
- switch (code_point) {
- case 0x263a: return 1;
- case 0x263b: return 2;
- case 0x2665: return 3;
- case 0x2666: return 4;
- case 0x2663: return 5;
- case 0x2660: return 6;
- case 0x2022: return 7;
- case 0x25d8: return 8;
- case 0x25cb: return 9;
- case 0x25d9: return 10;
- case 0x2642: return 11;
- case 0x2640: return 12;
- case 0x266a: return 13;
- case 0x266b: return 14;
- case 0x263c: return 15;
- case 0x25ba: return 16;
- case 0x25c4: return 17;
- case 0x2195: return 18;
- case 0x203c: return 19;
- case 0x00b6: return 20;
- case 0x00a7: return 21;
- case 0x25ac: return 22;
- case 0x21a8: return 23;
- case 0x2191: return 24;
- case 0x2193: return 25;
- case 0x2192: return 26;
- case 0x2190: return 27;
- case 0x221f: return 28;
- case 0x2194: return 29;
- case 0x25b2: return 30;
- case 0x25bc: return 31;
-
- case 0x2302: return 127;
- case 0x00c7: return 128;
- case 0x00fc: return 129;
- case 0x00e9: return 130;
- case 0x00e2: return 131;
- case 0x00e4: return 132;
- case 0x00e0: return 133;
- case 0x00e5: return 134;
- case 0x00e7: return 135;
- case 0x00ea: return 136;
- case 0x00eb: return 137;
- case 0x00e8: return 138;
- case 0x00ef: return 139;
- case 0x00ee: return 140;
- case 0x00ec: return 141;
- case 0x00c4: return 142;
- case 0x00c5: return 143;
- case 0x00c9: return 144;
- case 0x00e6: return 145;
- case 0x00c6: return 146;
- case 0x00f4: return 147;
- case 0x00f6: return 148;
- case 0x00f2: return 149;
- case 0x00fb: return 150;
- case 0x00f9: return 151;
- case 0x00ff: return 152;
- case 0x00d6: return 153;
- case 0x00dc: return 154;
- case 0x00a2: return 155;
- case 0x00a3: return 156;
- case 0x00a5: return 157;
- case 0x20a7: return 158;
- case 0x0192: return 159;
- case 0x00e1: return 160;
- case 0x00ed: return 161;
- case 0x00f3: return 162;
- case 0x00fa: return 163;
- case 0x00f1: return 164;
- case 0x00d1: return 165;
- case 0x00aa: return 166;
- case 0x00ba: return 167;
- case 0x00bf: return 168;
- case 0x2310: return 169;
- case 0x00ac: return 170;
- case 0x00bd: return 171;
- case 0x00bc: return 172;
- case 0x00a1: return 173;
- case 0x00ab: return 174;
- case 0x00bb: return 175;
- case 0x2591: return 176;
- case 0x2592: return 177;
- case 0x2593: return 178;
- case 0x2502: return 179;
- case 0x2524: return 180;
- case 0x2561: return 181;
- case 0x2562: return 182;
- case 0x2556: return 183;
- case 0x2555: return 184;
- case 0x2563: return 185;
- case 0x2551: return 186;
- case 0x2557: return 187;
- case 0x255d: return 188;
- case 0x255c: return 189;
- case 0x255b: return 190;
- case 0x2510: return 191;
- case 0x2514: return 192;
- case 0x2534: return 193;
- case 0x252c: return 194;
- case 0x251c: return 195;
- case 0x2500: return 196;
- case 0x253c: return 197;
- case 0x255e: return 198;
- case 0x255f: return 199;
- case 0x255a: return 200;
- case 0x2554: return 201;
- case 0x2569: return 202;
- case 0x2566: return 203;
- case 0x2560: return 204;
- case 0x2550: return 205;
- case 0x256c: return 206;
- case 0x2567: return 207;
- case 0x2568: return 208;
- case 0x2564: return 209;
- case 0x2565: return 210;
- case 0x2559: return 211;
- case 0x2558: return 212;
- case 0x2552: return 213;
- case 0x2553: return 214;
- case 0x256b: return 215;
- case 0x256a: return 216;
- case 0x2518: return 217;
- case 0x250c: return 218;
- case 0x2588: return 219;
- case 0x2584: return 220;
- case 0x258c: return 221;
- case 0x2590: return 222;
- case 0x2580: return 223;
- case 0x03b1: return 224;
- case 0x00df: return 225;
- case 0x0393: return 226;
- case 0x03c0: return 227;
- case 0x03a3: return 228;
- case 0x03c3: return 229;
- case 0x00b5: return 230;
- case 0x03c4: return 231;
- case 0x03a6: return 232;
- case 0x0398: return 233;
- case 0x03a9: return 234;
- case 0x03b4: return 235;
- case 0x221e: return 236;
- case 0x03c6: return 237;
- case 0x03b5: return 238;
- case 0x2229: return 239;
- case 0x2261: return 240;
- case 0x00b1: return 241;
- case 0x2265: return 242;
- case 0x2264: return 243;
- case 0x2320: return 244;
- case 0x2321: return 245;
- case 0x00f7: return 246;
- case 0x2248: return 247;
- case 0x00b0: return 248;
- case 0x2219: return 249;
- case 0x00b7: return 250;
- case 0x221a: return 251;
- case 0x207f: return 252;
- case 0x00b2: return 253;
- case 0x25a0: return 254;
- }
-
- return -1;
-}
-
-static void flanterm_putchar(struct flanterm_context *ctx, uint8_t c) {
- if (ctx->discard_next || (c == 0x18 || c == 0x1a)) {
- ctx->discard_next = false;
- ctx->escape = false;
- ctx->control_sequence = false;
- ctx->unicode_remaining = 0;
- ctx->osc = false;
- ctx->osc_escape = false;
- ctx->g_select = 0;
- return;
- }
-
- if (ctx->unicode_remaining != 0) {
- if ((c & 0xc0) != 0x80) {
- ctx->unicode_remaining = 0;
- goto unicode_error;
- }
-
- ctx->unicode_remaining--;
- ctx->code_point |= (uint64_t)(c & 0x3f) << (6 * ctx->unicode_remaining);
- if (ctx->unicode_remaining != 0) {
- return;
- }
-
- int cc = unicode_to_cp437(ctx->code_point);
-
- if (cc == -1) {
- size_t replacement_width = (size_t)mk_wcwidth(ctx->code_point);
- if (replacement_width > 0) {
- ctx->raw_putchar(ctx, 0xfe);
- }
- for (size_t i = 1; i < replacement_width; i++) {
- ctx->raw_putchar(ctx, ' ');
- }
- } else {
- ctx->raw_putchar(ctx, cc);
- }
- return;
- }
-
-unicode_error:
- if (c >= 0xc0 && c <= 0xf7) {
- if (c >= 0xc0 && c <= 0xdf) {
- ctx->unicode_remaining = 1;
- ctx->code_point = (uint64_t)(c & 0x1f) << 6;
- } else if (c >= 0xe0 && c <= 0xef) {
- ctx->unicode_remaining = 2;
- ctx->code_point = (uint64_t)(c & 0x0f) << (6 * 2);
- } else if (c >= 0xf0 && c <= 0xf7) {
- ctx->unicode_remaining = 3;
- ctx->code_point = (uint64_t)(c & 0x07) << (6 * 3);
- }
- return;
- }
-
- if (ctx->escape == true) {
- escape_parse(ctx, c);
- return;
- }
-
- if (ctx->g_select) {
- ctx->g_select--;
- switch (c) {
- case 'B':
- ctx->charsets[ctx->g_select] = CHARSET_DEFAULT; break;
- case '0':
- ctx->charsets[ctx->g_select] = CHARSET_DEC_SPECIAL; break;
- }
- ctx->g_select = 0;
- return;
- }
-
- size_t x, y;
- ctx->get_cursor_pos(ctx, &x, &y);
-
- switch (c) {
- case 0x00:
- case 0x7f:
- return;
- case 0x1b:
- ctx->escape_offset = 0;
- ctx->escape = true;
- return;
- case '\t':
- if ((x / ctx->tab_size + 1) >= ctx->cols) {
- ctx->set_cursor_pos(ctx, ctx->cols - 1, y);
- return;
- }
- ctx->set_cursor_pos(ctx, (x / ctx->tab_size + 1) * ctx->tab_size, y);
- return;
- case 0x0b:
- case 0x0c:
- case '\n':
- if (y == ctx->scroll_bottom_margin - 1) {
- ctx->scroll(ctx);
- ctx->set_cursor_pos(ctx, (ctx->oob_output & FLANTERM_OOB_OUTPUT_ONLCR) ? 0 : x, y);
- } else {
- ctx->set_cursor_pos(ctx, (ctx->oob_output & FLANTERM_OOB_OUTPUT_ONLCR) ? 0 : x, y + 1);
- }
- return;
- case '\b':
- ctx->set_cursor_pos(ctx, x - 1, y);
- return;
- case '\r':
- ctx->set_cursor_pos(ctx, 0, y);
- return;
- case '\a':
- // The bell is handled by the kernel
- if (ctx->callback != NULL) {
- ctx->callback(ctx, FLANTERM_CB_BELL, 0, 0, 0);
- }
- return;
- case 14:
- // Move to G1 set
- ctx->current_charset = 1;
- return;
- case 15:
- // Move to G0 set
- ctx->current_charset = 0;
- return;
- }
-
- if (ctx->insert_mode == true) {
- for (size_t i = ctx->cols - 1; ; i--) {
- ctx->move_character(ctx, i + 1, y, i, y);
- if (i == x) {
- break;
- }
- }
- }
-
- // Translate character set
- switch (ctx->charsets[ctx->current_charset]) {
- case CHARSET_DEFAULT:
- break;
- case CHARSET_DEC_SPECIAL:
- if (dec_special_print(ctx, c)) {
- return;
- }
- break;
- }
-
- if (c >= 0x20 && c <= 0x7e) {
- ctx->raw_putchar(ctx, c);
- } else {
- ctx->raw_putchar(ctx, 0xfe);
- }
-}
-
-void flanterm_flush(struct flanterm_context *ctx) {
- ctx->double_buffer_flush(ctx);
-}
-
-void flanterm_full_refresh(struct flanterm_context *ctx) {
- ctx->full_refresh(ctx);
-}
-
-void flanterm_deinit(struct flanterm_context *ctx, void (*_free)(void *, size_t)) {
- ctx->deinit(ctx, _free);
-}
-
-void flanterm_get_dimensions(struct flanterm_context *ctx, size_t *cols, size_t *rows) {
- *cols = ctx->cols;
- *rows = ctx->rows;
-}
-
-void flanterm_set_autoflush(struct flanterm_context *ctx, bool state) {
- ctx->autoflush = state;
-}
-
-void flanterm_set_callback(struct flanterm_context *ctx, void (*callback)(struct flanterm_context *, uint64_t, uint64_t, uint64_t, uint64_t)) {
- ctx->callback = callback;
-}
-
-uint64_t flanterm_get_oob_output(struct flanterm_context *ctx) {
- return ctx->oob_output;
-}
-
-void flanterm_set_oob_output(struct flanterm_context *ctx, uint64_t oob_output) {
- ctx->oob_output = oob_output;
-}
diff --git a/kernel/src/lib/Flanterm/src/flanterm.h b/kernel/src/lib/Flanterm/src/flanterm.h
deleted file mode 100644
index 9e23cb5..0000000
--- a/kernel/src/lib/Flanterm/src/flanterm.h
+++ /dev/null
@@ -1,80 +0,0 @@
-/* Copyright (C) 2022-2025 mintsuki and contributors.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef FLANTERM_H
-#define FLANTERM_H 1
-
-#include <stddef.h>
-#include <stdint.h>
-#include <stdbool.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#define FLANTERM_CB_DEC 10
-#define FLANTERM_CB_BELL 20
-#define FLANTERM_CB_PRIVATE_ID 30
-#define FLANTERM_CB_STATUS_REPORT 40
-#define FLANTERM_CB_POS_REPORT 50
-#define FLANTERM_CB_KBD_LEDS 60
-#define FLANTERM_CB_MODE 70
-#define FLANTERM_CB_LINUX 80
-
-#define FLANTERM_OOB_OUTPUT_OCRNL (1 << 0)
-#define FLANTERM_OOB_OUTPUT_OFDEL (1 << 1)
-#define FLANTERM_OOB_OUTPUT_OFILL (1 << 2)
-#define FLANTERM_OOB_OUTPUT_OLCUC (1 << 3)
-#define FLANTERM_OOB_OUTPUT_ONLCR (1 << 4)
-#define FLANTERM_OOB_OUTPUT_ONLRET (1 << 5)
-#define FLANTERM_OOB_OUTPUT_ONOCR (1 << 6)
-#define FLANTERM_OOB_OUTPUT_OPOST (1 << 7)
-
-#ifdef FLANTERM_IN_FLANTERM
-
-#include "flanterm_private.h"
-
-#else
-
-struct flanterm_context;
-
-#endif
-
-void flanterm_write(struct flanterm_context *ctx, const char *buf, size_t count);
-void flanterm_flush(struct flanterm_context *ctx);
-void flanterm_full_refresh(struct flanterm_context *ctx);
-void flanterm_deinit(struct flanterm_context *ctx, void (*_free)(void *ptr, size_t size));
-
-void flanterm_get_dimensions(struct flanterm_context *ctx, size_t *cols, size_t *rows);
-void flanterm_set_autoflush(struct flanterm_context *ctx, bool state);
-void flanterm_set_callback(struct flanterm_context *ctx, void (*callback)(struct flanterm_context *, uint64_t, uint64_t, uint64_t, uint64_t));
-uint64_t flanterm_get_oob_output(struct flanterm_context *ctx);
-void flanterm_set_oob_output(struct flanterm_context *ctx, uint64_t oob_output);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/kernel/src/lib/Flanterm/src/flanterm_backends/fb.c b/kernel/src/lib/Flanterm/src/flanterm_backends/fb.c
deleted file mode 100644
index da00f9a..0000000
--- a/kernel/src/lib/Flanterm/src/flanterm_backends/fb.c
+++ /dev/null
@@ -1,1254 +0,0 @@
-/* Copyright (C) 2022-2025 mintsuki and contributors.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifdef __cplusplus
-#error "Please do not compile Flanterm as C++ code! Flanterm should be compiled as C99 or newer."
-#endif
-
-#ifndef __STDC_VERSION__
-#error "Flanterm must be compiled as C99 or newer."
-#endif
-
-#if defined(_MSC_VER)
-#define ALWAYS_INLINE __forceinline
-#elif defined(__GNUC__) || defined(__clang__)
-#define ALWAYS_INLINE __attribute__((always_inline)) inline
-#else
-#define ALWAYS_INLINE inline
-#endif
-
-#include <stdint.h>
-#include <stddef.h>
-#include <stdbool.h>
-
-#ifndef FLANTERM_IN_FLANTERM
-#define FLANTERM_IN_FLANTERM
-#endif
-
-#include "../flanterm.h"
-#include "fb.h"
-
-void *memset(void *, int, size_t);
-void *memcpy(void *, const void *, size_t);
-
-#ifndef FLANTERM_FB_DISABLE_BUMP_ALLOC
-
-#ifndef FLANTERM_FB_BUMP_ALLOC_POOL_SIZE
-#define FLANTERM_FB_BUMP_ALLOC_POOL_SIZE 873000
-
-#define FLANTERM_FB_WIDTH_LIMIT 1920
-#define FLANTERM_FB_HEIGHT_LIMIT 1200
-#endif
-
-static uint8_t bump_alloc_pool[FLANTERM_FB_BUMP_ALLOC_POOL_SIZE];
-static size_t bump_alloc_ptr = 0;
-
-static void *bump_alloc(size_t s) {
- static bool base_offset_added = false;
- if (!base_offset_added) {
- if ((uintptr_t)bump_alloc_pool & 0xf) {
- bump_alloc_ptr += 0x10 - ((uintptr_t)bump_alloc_pool & 0xf);
- }
- base_offset_added = true;
- }
-
- if ((s & 0xf) != 0) {
- s += 0x10;
- s &= ~(size_t)0xf;
- }
-
- size_t next_ptr = bump_alloc_ptr + s;
- if (next_ptr > FLANTERM_FB_BUMP_ALLOC_POOL_SIZE) {
- return NULL;
- }
- void *ret = &bump_alloc_pool[bump_alloc_ptr];
- bump_alloc_ptr = next_ptr;
- return ret;
-}
-
-static bool bump_allocated_instance = false;
-
-#endif
-
-// Builtin font originally taken from:
-// https://github.com/viler-int10h/vga-text-mode-fonts/raw/master/FONTS/PC-OTHER/TOSH-SAT.F16
-static const uint8_t builtin_font[] = {
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x42, 0x81, 0x81, 0xa5, 0xa5, 0x81,
- 0x81, 0xa5, 0x99, 0x81, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x3c, 0x7e, 0xff,
- 0xff, 0xdb, 0xdb, 0xff, 0xff, 0xdb, 0xe7, 0xff, 0x7e, 0x3c, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x6c, 0xfe, 0xfe, 0xfe, 0x7c, 0x7c, 0x38, 0x38, 0x10,
- 0x10, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x38, 0x38, 0x7c, 0x7c, 0xfe,
- 0x7c, 0x7c, 0x38, 0x38, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18,
- 0x3c, 0x3c, 0xdb, 0xff, 0xff, 0xdb, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x18, 0x3c, 0x7e, 0xff, 0xff, 0xff, 0x66, 0x18, 0x18,
- 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x78,
- 0x78, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xe7, 0xc3, 0xc3, 0xe7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0xcc, 0x84, 0x84, 0xcc, 0x78, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc3, 0x99, 0xbd,
- 0xbd, 0x99, 0xc3, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x1e,
- 0x0e, 0x1e, 0x32, 0x78, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x78, 0xcc, 0xcc, 0xcc, 0x78, 0x30, 0xfc, 0x30, 0x30,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x18, 0x1c, 0x1e, 0x16, 0x12,
- 0x10, 0x10, 0x70, 0xf0, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x30, 0x38, 0x2c,
- 0x26, 0x32, 0x3a, 0x2e, 0x26, 0x22, 0x62, 0xe2, 0xc6, 0x0e, 0x0c, 0x00,
- 0x00, 0x00, 0x00, 0x18, 0x18, 0xdb, 0x3c, 0xe7, 0x3c, 0xdb, 0x18, 0x18,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xc0, 0xe0, 0xf8, 0xfe,
- 0xf8, 0xe0, 0xc0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
- 0x06, 0x0e, 0x3e, 0xfe, 0x3e, 0x0e, 0x06, 0x02, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x30, 0x78, 0xfc, 0x30, 0x30, 0x30, 0x30, 0x30, 0xfc, 0x78,
- 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc,
- 0xcc, 0xcc, 0x00, 0xcc, 0xcc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xdb,
- 0xdb, 0xdb, 0xdb, 0x7b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x7c, 0xc6, 0x60, 0x38, 0x6c, 0xc6, 0xc6, 0x6c, 0x38, 0x0c,
- 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0xfe, 0xfe, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x78,
- 0xfc, 0x30, 0x30, 0x30, 0x30, 0x30, 0xfc, 0x78, 0x30, 0xfc, 0x00, 0x00,
- 0x00, 0x00, 0x30, 0x78, 0xfc, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
- 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
- 0x30, 0x30, 0xfc, 0x78, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x18, 0x0c, 0xfe, 0xfe, 0x0c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x60, 0xfe, 0xfe, 0x60, 0x30, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0,
- 0xc0, 0xc0, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x24, 0x66, 0xff, 0xff, 0x66, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x38, 0x38, 0x7c, 0x7c, 0xfe, 0xfe,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xfe, 0x7c, 0x7c,
- 0x38, 0x38, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x30, 0x78, 0x78, 0x78, 0x78, 0x30, 0x30, 0x30, 0x00, 0x30,
- 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6c, 0x6c,
- 0x6c, 0xfe, 0x6c, 0x6c, 0x6c, 0xfe, 0x6c, 0x6c, 0x6c, 0x00, 0x00, 0x00,
- 0x00, 0x18, 0x18, 0x7c, 0xc6, 0xc0, 0xc0, 0x7c, 0x06, 0x06, 0xc6, 0x7c,
- 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0x0c, 0x0c, 0x18, 0x38,
- 0x30, 0x60, 0x60, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x6c,
- 0x6c, 0x38, 0x30, 0x76, 0xde, 0xcc, 0xcc, 0xde, 0x76, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x18, 0x18, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x30, 0x60, 0x60, 0x60, 0x60,
- 0x60, 0x60, 0x60, 0x30, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x30,
- 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x30, 0x60, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x6c, 0x38, 0xfe, 0x38, 0x6c, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x7e,
- 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x30, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x06,
- 0x0c, 0x0c, 0x18, 0x38, 0x30, 0x60, 0x60, 0xc0, 0xc0, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xd6, 0xd6, 0xd6, 0xc6, 0xc6, 0xc6,
- 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x38, 0x78, 0x18, 0x18, 0x18,
- 0x18, 0x18, 0x18, 0x18, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6,
- 0x06, 0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0xc0, 0xfe, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x7c, 0xc6, 0x06, 0x06, 0x3c, 0x06, 0x06, 0x06, 0x06, 0xc6,
- 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x0c, 0x1c, 0x3c, 0x6c, 0xcc,
- 0xfe, 0x0c, 0x0c, 0x0c, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc0,
- 0xc0, 0xc0, 0xfc, 0x06, 0x06, 0x06, 0x06, 0xc6, 0x7c, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x3c, 0x60, 0xc0, 0xc0, 0xfc, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6,
- 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc6, 0x06, 0x06, 0x0c, 0x18,
- 0x30, 0x30, 0x30, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6,
- 0xc6, 0xc6, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x06, 0x06, 0x0c,
- 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18,
- 0x18, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x18, 0x18, 0x30, 0x00, 0x00,
- 0x00, 0x00, 0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0x60, 0x30, 0x18, 0x0c,
- 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x00,
- 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x60,
- 0x30, 0x18, 0x0c, 0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0x06, 0x0c, 0x18, 0x30, 0x30, 0x00, 0x30,
- 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xde, 0xde,
- 0xde, 0xde, 0xc0, 0xc0, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x6c,
- 0xc6, 0xc6, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0xfc, 0xc6, 0xc6, 0xc6, 0xfc, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6,
- 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc0, 0xc0, 0xc0, 0xc0,
- 0xc0, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xcc,
- 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xcc, 0xf8, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0xfe, 0xc0, 0xc0, 0xc0, 0xfc, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0,
- 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc0, 0xc0, 0xc0, 0xfc, 0xc0,
- 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6,
- 0xc0, 0xc0, 0xc0, 0xde, 0xc6, 0xc6, 0xc6, 0xc6, 0x7e, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6,
- 0xc6, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x30, 0x30, 0x30, 0x30, 0x30,
- 0x30, 0x30, 0x30, 0x30, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x0c,
- 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0xc6, 0xc6, 0xcc, 0xd8, 0xf0, 0xe0, 0xf0, 0xd8, 0xcc, 0xc6,
- 0xc6, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0,
- 0xc0, 0xc0, 0xc0, 0xc0, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6,
- 0xee, 0xfe, 0xd6, 0xd6, 0xd6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0xc6, 0xc6, 0xe6, 0xe6, 0xf6, 0xde, 0xce, 0xce, 0xc6, 0xc6,
- 0xc6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6,
- 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xc6,
- 0xc6, 0xc6, 0xc6, 0xfc, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xf6, 0xda,
- 0x6c, 0x06, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xc6, 0xc6, 0xc6, 0xc6, 0xfc,
- 0xd8, 0xcc, 0xcc, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6,
- 0xc0, 0x60, 0x30, 0x18, 0x0c, 0x06, 0x06, 0xc6, 0x7c, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
- 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6,
- 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6,
- 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x6c, 0x38, 0x10, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xd6, 0xd6, 0xd6, 0xd6, 0xfe, 0x6c,
- 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0x6c, 0x38, 0x38,
- 0x38, 0x6c, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00, 0x00, 0xcc, 0xcc,
- 0xcc, 0xcc, 0xcc, 0x78, 0x30, 0x30, 0x30, 0x30, 0x30, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0xfe, 0x06, 0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0xc0, 0xc0,
- 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x60, 0x60, 0x60, 0x60, 0x60,
- 0x60, 0x60, 0x60, 0x60, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0,
- 0x60, 0x60, 0x30, 0x38, 0x18, 0x0c, 0x0c, 0x06, 0x06, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x78, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
- 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00,
- 0x00, 0x00, 0x18, 0x18, 0x18, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x06, 0x06,
- 0x7e, 0xc6, 0xc6, 0xc6, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0,
- 0xc0, 0xdc, 0xe6, 0xc6, 0xc6, 0xc6, 0xc6, 0xe6, 0xdc, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc0, 0xc0, 0xc0, 0xc0, 0xc6,
- 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x06, 0x06, 0x76, 0xce, 0xc6,
- 0xc6, 0xc6, 0xc6, 0xce, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x7c, 0xc6, 0xc6, 0xfe, 0xc0, 0xc0, 0xc0, 0x7e, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x1c, 0x36, 0x30, 0x30, 0xfc, 0x30, 0x30, 0x30, 0x30, 0x30,
- 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xce, 0xc6,
- 0xc6, 0xc6, 0xce, 0x76, 0x06, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0xc0, 0xc0,
- 0xc0, 0xdc, 0xe6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x18, 0x00, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
- 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x1e, 0x06, 0x06,
- 0x06, 0x06, 0x06, 0x06, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0xc0, 0xc0,
- 0xc0, 0xc6, 0xcc, 0xd8, 0xf0, 0xf0, 0xd8, 0xcc, 0xc6, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
- 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xec, 0xfe, 0xd6,
- 0xd6, 0xd6, 0xd6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0xdc, 0xe6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6,
- 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0xe6, 0xc6,
- 0xc6, 0xc6, 0xe6, 0xdc, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x76, 0xce, 0xc6, 0xc6, 0xc6, 0xce, 0x76, 0x06, 0x06, 0x06, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0xe6, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0,
- 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc0,
- 0x70, 0x1c, 0x06, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x30,
- 0x30, 0xfe, 0x30, 0x30, 0x30, 0x30, 0x30, 0x36, 0x1c, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6,
- 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0xc6,
- 0xc6, 0xc6, 0x6c, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0xc6, 0xc6, 0xd6, 0xd6, 0xd6, 0xd6, 0xfe, 0x6c, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0x6c, 0x38, 0x38, 0x6c, 0xc6,
- 0xc6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0xc6,
- 0xc6, 0xc6, 0xce, 0x76, 0x06, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0xfe, 0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0xfe, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x1c, 0x30, 0x30, 0x30, 0x30, 0xe0, 0x30, 0x30, 0x30, 0x30,
- 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x30, 0x30, 0x30, 0x30, 0x00,
- 0x30, 0x30, 0x30, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x30,
- 0x30, 0x30, 0x30, 0x1c, 0x30, 0x30, 0x30, 0x30, 0xe0, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x76, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x38, 0x38, 0x6c,
- 0x6c, 0xc6, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66,
- 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0x66, 0x3c, 0x18, 0xcc, 0x78, 0x00,
- 0x00, 0x00, 0x6c, 0x6c, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6,
- 0x7c, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x18, 0x30, 0x00, 0x7c, 0xc6, 0xc6,
- 0xfe, 0xc0, 0xc0, 0xc0, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x6c,
- 0x00, 0x7c, 0x06, 0x06, 0x7e, 0xc6, 0xc6, 0xc6, 0x7e, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x6c, 0x6c, 0x00, 0x7c, 0x06, 0x06, 0x7e, 0xc6, 0xc6, 0xc6,
- 0x7e, 0x00, 0x00, 0x00, 0x00, 0x60, 0x30, 0x18, 0x00, 0x7c, 0x06, 0x06,
- 0x7e, 0xc6, 0xc6, 0xc6, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x38, 0x6c, 0x38,
- 0x00, 0x7c, 0x06, 0x06, 0x7e, 0xc6, 0xc6, 0xc6, 0x7e, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc0, 0xc0, 0xc0, 0xc0, 0xc6,
- 0x7c, 0x18, 0x0c, 0x38, 0x00, 0x10, 0x38, 0x6c, 0x00, 0x7c, 0xc6, 0xc6,
- 0xfe, 0xc0, 0xc0, 0xc0, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6c, 0x6c,
- 0x00, 0x7c, 0xc6, 0xc6, 0xfe, 0xc0, 0xc0, 0xc0, 0x7e, 0x00, 0x00, 0x00,
- 0x00, 0x60, 0x30, 0x18, 0x00, 0x7c, 0xc6, 0xc6, 0xfe, 0xc0, 0xc0, 0xc0,
- 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6c, 0x6c, 0x00, 0x38, 0x18, 0x18,
- 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x6c,
- 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00,
- 0x00, 0x60, 0x30, 0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
- 0x3c, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xc6,
- 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x38, 0x6c, 0x38, 0x00,
- 0x38, 0x6c, 0xc6, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00,
- 0x18, 0x30, 0x60, 0x00, 0xfe, 0xc0, 0xc0, 0xfc, 0xc0, 0xc0, 0xc0, 0xc0,
- 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xec, 0x36, 0x36,
- 0x76, 0xde, 0xd8, 0xd8, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x3c,
- 0x6c, 0xcc, 0xcc, 0xfe, 0xcc, 0xcc, 0xcc, 0xcc, 0xce, 0x00, 0x00, 0x00,
- 0x00, 0x10, 0x38, 0x6c, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6,
- 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6c, 0x6c, 0x00, 0x7c, 0xc6, 0xc6,
- 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x60, 0x30, 0x18,
- 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00,
- 0x00, 0x10, 0x38, 0x6c, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6,
- 0x7c, 0x00, 0x00, 0x00, 0x00, 0x60, 0x30, 0x18, 0x00, 0xc6, 0xc6, 0xc6,
- 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6c, 0x6c,
- 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xce, 0x76, 0x06, 0xc6, 0x7c, 0x00,
- 0x6c, 0x6c, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6,
- 0x7c, 0x00, 0x00, 0x00, 0x6c, 0x6c, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6,
- 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30,
- 0x30, 0x78, 0xcc, 0xc0, 0xc0, 0xcc, 0x78, 0x30, 0x30, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x38, 0x6c, 0x60, 0x60, 0x60, 0xf8, 0x60, 0x60, 0x60, 0xe6,
- 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0xcc, 0xcc, 0xcc, 0x78, 0x30, 0xfc,
- 0x30, 0xfc, 0x30, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xcc,
- 0xcc, 0xf8, 0xc4, 0xcc, 0xde, 0xcc, 0xcc, 0xcc, 0xc6, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x0e, 0x1b, 0x18, 0x18, 0x18, 0x7e, 0x18, 0x18, 0x18, 0x18,
- 0x18, 0xd8, 0x70, 0x00, 0x00, 0x0c, 0x18, 0x30, 0x00, 0x7c, 0x06, 0x06,
- 0x7e, 0xc6, 0xc6, 0xc6, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x18, 0x30,
- 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00,
- 0x00, 0x0c, 0x18, 0x30, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6,
- 0x7c, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x18, 0x30, 0x00, 0xc6, 0xc6, 0xc6,
- 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x76, 0xdc, 0x00,
- 0x00, 0xdc, 0xe6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00,
- 0x76, 0xdc, 0x00, 0xc6, 0xc6, 0xe6, 0xf6, 0xfe, 0xde, 0xce, 0xc6, 0xc6,
- 0xc6, 0x00, 0x00, 0x00, 0x00, 0x78, 0xd8, 0xd8, 0x6c, 0x00, 0xfc, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x6c, 0x6c,
- 0x38, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x18, 0x18, 0x00, 0x18, 0x18, 0x30, 0x60, 0xc0, 0xc6, 0xc6,
- 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0xfe, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0xfe, 0x06, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0xc0, 0xc2, 0xc6, 0xcc, 0xd8, 0x30, 0x60, 0xdc, 0x86, 0x0c,
- 0x18, 0x3e, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc2, 0xc6, 0xcc, 0xd8, 0x30,
- 0x66, 0xce, 0x9e, 0x3e, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00, 0x30, 0x30,
- 0x00, 0x30, 0x30, 0x30, 0x78, 0x78, 0x78, 0x78, 0x30, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x6c, 0xd8, 0x6c, 0x36, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x6c, 0x36,
- 0x6c, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22, 0x88, 0x22, 0x88,
- 0x22, 0x88, 0x22, 0x88, 0x22, 0x88, 0x22, 0x88, 0x22, 0x88, 0x22, 0x88,
- 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa,
- 0x55, 0xaa, 0x55, 0xaa, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77,
- 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0x18, 0x18, 0x18, 0x18,
- 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
- 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0xf8, 0x18, 0x18, 0x18,
- 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0xf8, 0x18,
- 0x18, 0xf8, 0xf8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x36, 0x36, 0x36, 0x36,
- 0x36, 0x36, 0x36, 0xf6, 0xf6, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xfe, 0x36, 0x36, 0x36,
- 0x36, 0x36, 0x36, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xf8, 0x18,
- 0x18, 0xf8, 0xf8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x36, 0x36, 0x36, 0x36,
- 0x36, 0xf6, 0xf6, 0x06, 0x06, 0xf6, 0xf6, 0x36, 0x36, 0x36, 0x36, 0x36,
- 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
- 0x36, 0x36, 0x36, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xfe, 0x06,
- 0x06, 0xf6, 0xf6, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
- 0x36, 0xf6, 0xf6, 0x06, 0x06, 0xfe, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xfe, 0xfe, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0xf8, 0x18,
- 0x18, 0xf8, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0xf8, 0xf8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
- 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x1f, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xff,
- 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0xff, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
- 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x1f, 0x18, 0x18, 0x18,
- 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
- 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18,
- 0x18, 0x18, 0x18, 0xff, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
- 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x1f, 0x18, 0x18, 0x1f, 0x1f, 0x18,
- 0x18, 0x18, 0x18, 0x18, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x37,
- 0x37, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
- 0x36, 0x37, 0x37, 0x30, 0x30, 0x3f, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x3f, 0x30, 0x30, 0x37, 0x37, 0x36,
- 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xf7, 0xf7, 0x00,
- 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0xff, 0xff, 0x00, 0x00, 0xf7, 0xf7, 0x36, 0x36, 0x36, 0x36, 0x36,
- 0x36, 0x36, 0x36, 0x36, 0x36, 0x37, 0x37, 0x30, 0x30, 0x37, 0x37, 0x36,
- 0x36, 0x36, 0x36, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00,
- 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x36, 0x36, 0x36,
- 0x36, 0xf7, 0xf7, 0x00, 0x00, 0xf7, 0xf7, 0x36, 0x36, 0x36, 0x36, 0x36,
- 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xff,
- 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x36, 0x36, 0x36,
- 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x3f,
- 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18,
- 0x18, 0x1f, 0x1f, 0x18, 0x18, 0x1f, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x1f, 0x18, 0x18, 0x1f, 0x1f, 0x18,
- 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f,
- 0x3f, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
- 0x36, 0x36, 0x36, 0xff, 0xff, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
- 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0xff, 0x18, 0x18, 0xff, 0xff, 0x18,
- 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8,
- 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x1f, 0x1f, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0xf0, 0xf0, 0xf0,
- 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0,
- 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f,
- 0x0f, 0x0f, 0x0f, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x76, 0xd6, 0xdc, 0xc8, 0xc8, 0xdc, 0xd6, 0x76, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x78, 0xcc, 0xcc, 0xcc, 0xd8, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc,
- 0xd8, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0xfe, 0xc6, 0xc6, 0xc0, 0xc0, 0xc0,
- 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x7e, 0xfe, 0x24, 0x24, 0x24, 0x24, 0x66, 0xc6, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0xfe, 0xfe, 0xc2, 0x60, 0x30, 0x18, 0x30, 0x60, 0xc2, 0xfe,
- 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0xc8, 0xcc,
- 0xcc, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x76, 0x6c, 0x60, 0xc0, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0xfc, 0x98, 0x18, 0x18, 0x18, 0x18,
- 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x30, 0x30, 0x78, 0xcc, 0xcc,
- 0xcc, 0x78, 0x30, 0x30, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x6c,
- 0xc6, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0x6c, 0x38, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x38, 0x6c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x6c, 0x6c, 0x6c,
- 0xee, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0xcc, 0x60, 0x30, 0x78, 0xcc,
- 0xcc, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x76, 0xbb, 0x99, 0x99, 0xdd, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x02, 0x06, 0x3c, 0x6c, 0xce, 0xd6, 0xd6, 0xe6, 0x6c, 0x78,
- 0xc0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x30, 0x60, 0xc0, 0xc0, 0xfe,
- 0xc0, 0xc0, 0x60, 0x30, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x6c,
- 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0xfe, 0x00, 0x00, 0xfe, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x30, 0xfc,
- 0x30, 0x30, 0x00, 0x00, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x60, 0x30, 0x18, 0x0c, 0x18, 0x30, 0x60, 0x00, 0xfc, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x18, 0x30, 0x60, 0xc0, 0x60, 0x30, 0x18, 0x00,
- 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x36, 0x36, 0x30, 0x30, 0x30,
- 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x18, 0x18, 0x18, 0x18,
- 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xd8, 0xd8, 0x70, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x30, 0x30, 0x00, 0xfc, 0x00, 0x30, 0x30, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xdc, 0x00,
- 0x76, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0xcc, 0xcc,
- 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x0c, 0x0c,
- 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0xcc, 0x6c, 0x3c, 0x1c, 0x0c, 0x00, 0x00,
- 0x00, 0xd8, 0xec, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x6c, 0x0c, 0x18, 0x30, 0x60, 0x7c,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00
-};
-
-static ALWAYS_INLINE uint32_t convert_colour(struct flanterm_context *_ctx, uint32_t colour) {
- struct flanterm_fb_context *ctx = (void *)_ctx;
- uint32_t r = (colour >> 16) & 0xff;
- uint32_t g = (colour >> 8) & 0xff;
- uint32_t b = colour & 0xff;
- return (r << ctx->red_mask_shift) | (g << ctx->green_mask_shift) | (b << ctx->blue_mask_shift);
-}
-
-static void flanterm_fb_save_state(struct flanterm_context *_ctx) {
- struct flanterm_fb_context *ctx = (void *)_ctx;
- ctx->saved_state_text_fg = ctx->text_fg;
- ctx->saved_state_text_bg = ctx->text_bg;
- ctx->saved_state_cursor_x = ctx->cursor_x;
- ctx->saved_state_cursor_y = ctx->cursor_y;
-}
-
-static void flanterm_fb_restore_state(struct flanterm_context *_ctx) {
- struct flanterm_fb_context *ctx = (void *)_ctx;
- ctx->text_fg = ctx->saved_state_text_fg;
- ctx->text_bg = ctx->saved_state_text_bg;
- ctx->cursor_x = ctx->saved_state_cursor_x;
- ctx->cursor_y = ctx->saved_state_cursor_y;
-}
-
-static void flanterm_fb_swap_palette(struct flanterm_context *_ctx) {
- struct flanterm_fb_context *ctx = (void *)_ctx;
- uint32_t tmp = ctx->text_bg;
- ctx->text_bg = ctx->text_fg;
- ctx->text_fg = tmp;
-}
-
-static void plot_char_scaled_canvas(struct flanterm_context *_ctx, struct flanterm_fb_char *c, size_t x, size_t y) {
- struct flanterm_fb_context *ctx = (void *)_ctx;
-
- if (x >= _ctx->cols || y >= _ctx->rows) {
- return;
- }
-
- x = ctx->offset_x + x * ctx->glyph_width;
- y = ctx->offset_y + y * ctx->glyph_height;
-
- bool *glyph = &ctx->font_bool[c->c * ctx->font_height * ctx->font_width];
- // naming: fx,fy for font coordinates, gx,gy for glyph coordinates
- for (size_t gy = 0; gy < ctx->glyph_height; gy++) {
- uint8_t fy = gy / ctx->font_scale_y;
- volatile uint32_t *fb_line = ctx->framebuffer + x + (y + gy) * (ctx->pitch / 4);
- uint32_t *canvas_line = ctx->canvas + x + (y + gy) * ctx->width;
- bool *glyph_pointer = glyph + (fy * ctx->font_width);
- for (size_t fx = 0; fx < ctx->font_width; fx++) {
- for (size_t i = 0; i < ctx->font_scale_x; i++) {
- size_t gx = ctx->font_scale_x * fx + i;
- uint32_t bg = c->bg == 0xffffffff ? canvas_line[gx] : c->bg;
- uint32_t fg = c->fg == 0xffffffff ? canvas_line[gx] : c->fg;
- fb_line[gx] = *glyph_pointer ? fg : bg;
- }
- glyph_pointer++;
- }
- }
-}
-
-static void plot_char_scaled_uncanvas(struct flanterm_context *_ctx, struct flanterm_fb_char *c, size_t x, size_t y) {
- struct flanterm_fb_context *ctx = (void *)_ctx;
-
- if (x >= _ctx->cols || y >= _ctx->rows) {
- return;
- }
-
- uint32_t default_bg = ctx->default_bg;
-
- uint32_t bg = c->bg == 0xffffffff ? default_bg : c->bg;
- uint32_t fg = c->fg == 0xffffffff ? default_bg : c->fg;
-
- x = ctx->offset_x + x * ctx->glyph_width;
- y = ctx->offset_y + y * ctx->glyph_height;
-
- bool *glyph = &ctx->font_bool[c->c * ctx->font_height * ctx->font_width];
- // naming: fx,fy for font coordinates, gx,gy for glyph coordinates
- for (size_t gy = 0; gy < ctx->glyph_height; gy++) {
- uint8_t fy = gy / ctx->font_scale_y;
- volatile uint32_t *fb_line = ctx->framebuffer + x + (y + gy) * (ctx->pitch / 4);
- bool *glyph_pointer = glyph + (fy * ctx->font_width);
- for (size_t fx = 0; fx < ctx->font_width; fx++) {
- for (size_t i = 0; i < ctx->font_scale_x; i++) {
- size_t gx = ctx->font_scale_x * fx + i;
- fb_line[gx] = *glyph_pointer ? fg : bg;
- }
- glyph_pointer++;
- }
- }
-}
-
-static void plot_char_unscaled_canvas(struct flanterm_context *_ctx, struct flanterm_fb_char *c, size_t x, size_t y) {
- struct flanterm_fb_context *ctx = (void *)_ctx;
-
- if (x >= _ctx->cols || y >= _ctx->rows) {
- return;
- }
-
- x = ctx->offset_x + x * ctx->glyph_width;
- y = ctx->offset_y + y * ctx->glyph_height;
-
- bool *glyph = &ctx->font_bool[c->c * ctx->font_height * ctx->font_width];
- // naming: fx,fy for font coordinates, gx,gy for glyph coordinates
- for (size_t gy = 0; gy < ctx->glyph_height; gy++) {
- volatile uint32_t *fb_line = ctx->framebuffer + x + (y + gy) * (ctx->pitch / 4);
- uint32_t *canvas_line = ctx->canvas + x + (y + gy) * ctx->width;
- bool *glyph_pointer = glyph + (gy * ctx->font_width);
- for (size_t fx = 0; fx < ctx->font_width; fx++) {
- uint32_t bg = c->bg == 0xffffffff ? canvas_line[fx] : c->bg;
- uint32_t fg = c->fg == 0xffffffff ? canvas_line[fx] : c->fg;
- fb_line[fx] = *(glyph_pointer++) ? fg : bg;
- }
- }
-}
-
-static void plot_char_unscaled_uncanvas(struct flanterm_context *_ctx, struct flanterm_fb_char *c, size_t x, size_t y) {
- struct flanterm_fb_context *ctx = (void *)_ctx;
-
- if (x >= _ctx->cols || y >= _ctx->rows) {
- return;
- }
-
- uint32_t default_bg = ctx->default_bg;
-
- uint32_t bg = c->bg == 0xffffffff ? default_bg : c->bg;
- uint32_t fg = c->fg == 0xffffffff ? default_bg : c->fg;
-
- x = ctx->offset_x + x * ctx->glyph_width;
- y = ctx->offset_y + y * ctx->glyph_height;
-
- bool *glyph = &ctx->font_bool[c->c * ctx->font_height * ctx->font_width];
- // naming: fx,fy for font coordinates, gx,gy for glyph coordinates
- for (size_t gy = 0; gy < ctx->glyph_height; gy++) {
- volatile uint32_t *fb_line = ctx->framebuffer + x + (y + gy) * (ctx->pitch / 4);
- bool *glyph_pointer = glyph + (gy * ctx->font_width);
- for (size_t fx = 0; fx < ctx->font_width; fx++) {
- fb_line[fx] = *(glyph_pointer++) ? fg : bg;
- }
- }
-}
-
-static inline bool compare_char(struct flanterm_fb_char *a, struct flanterm_fb_char *b) {
- return !(a->c != b->c || a->bg != b->bg || a->fg != b->fg);
-}
-
-static void push_to_queue(struct flanterm_context *_ctx, struct flanterm_fb_char *c, size_t x, size_t y) {
- struct flanterm_fb_context *ctx = (void *)_ctx;
-
- if (x >= _ctx->cols || y >= _ctx->rows) {
- return;
- }
-
- size_t i = y * _ctx->cols + x;
-
- struct flanterm_fb_queue_item *q = ctx->map[i];
-
- if (q == NULL) {
- if (compare_char(&ctx->grid[i], c)) {
- return;
- }
- q = &ctx->queue[ctx->queue_i++];
- q->x = x;
- q->y = y;
- ctx->map[i] = q;
- }
-
- q->c = *c;
-}
-
-static void flanterm_fb_revscroll(struct flanterm_context *_ctx) {
- struct flanterm_fb_context *ctx = (void *)_ctx;
-
- for (size_t i = (_ctx->scroll_bottom_margin - 1) * _ctx->cols - 1;
- i >= _ctx->scroll_top_margin * _ctx->cols; i--) {
- if (i == (size_t)-1) {
- break;
- }
- struct flanterm_fb_char *c;
- struct flanterm_fb_queue_item *q = ctx->map[i];
- if (q != NULL) {
- c = &q->c;
- } else {
- c = &ctx->grid[i];
- }
- push_to_queue(_ctx, c, (i + _ctx->cols) % _ctx->cols, (i + _ctx->cols) / _ctx->cols);
- }
-
- // Clear the first line of the screen.
- struct flanterm_fb_char empty;
- empty.c = ' ';
- empty.fg = ctx->text_fg;
- empty.bg = ctx->text_bg;
- for (size_t i = 0; i < _ctx->cols; i++) {
- push_to_queue(_ctx, &empty, i, _ctx->scroll_top_margin);
- }
-}
-
-static void flanterm_fb_scroll(struct flanterm_context *_ctx) {
- struct flanterm_fb_context *ctx = (void *)_ctx;
-
- for (size_t i = (_ctx->scroll_top_margin + 1) * _ctx->cols;
- i < _ctx->scroll_bottom_margin * _ctx->cols; i++) {
- struct flanterm_fb_char *c;
- struct flanterm_fb_queue_item *q = ctx->map[i];
- if (q != NULL) {
- c = &q->c;
- } else {
- c = &ctx->grid[i];
- }
- push_to_queue(_ctx, c, (i - _ctx->cols) % _ctx->cols, (i - _ctx->cols) / _ctx->cols);
- }
-
- // Clear the last line of the screen.
- struct flanterm_fb_char empty;
- empty.c = ' ';
- empty.fg = ctx->text_fg;
- empty.bg = ctx->text_bg;
- for (size_t i = 0; i < _ctx->cols; i++) {
- push_to_queue(_ctx, &empty, i, _ctx->scroll_bottom_margin - 1);
- }
-}
-
-static void flanterm_fb_clear(struct flanterm_context *_ctx, bool move) {
- struct flanterm_fb_context *ctx = (void *)_ctx;
-
- struct flanterm_fb_char empty;
- empty.c = ' ';
- empty.fg = ctx->text_fg;
- empty.bg = ctx->text_bg;
- for (size_t i = 0; i < _ctx->rows * _ctx->cols; i++) {
- push_to_queue(_ctx, &empty, i % _ctx->cols, i / _ctx->cols);
- }
-
- if (move) {
- ctx->cursor_x = 0;
- ctx->cursor_y = 0;
- }
-}
-
-static void flanterm_fb_set_cursor_pos(struct flanterm_context *_ctx, size_t x, size_t y) {
- struct flanterm_fb_context *ctx = (void *)_ctx;
-
- if (x >= _ctx->cols) {
- if ((int)x < 0) {
- x = 0;
- } else {
- x = _ctx->cols - 1;
- }
- }
- if (y >= _ctx->rows) {
- if ((int)y < 0) {
- y = 0;
- } else {
- y = _ctx->rows - 1;
- }
- }
- ctx->cursor_x = x;
- ctx->cursor_y = y;
-}
-
-static void flanterm_fb_get_cursor_pos(struct flanterm_context *_ctx, size_t *x, size_t *y) {
- struct flanterm_fb_context *ctx = (void *)_ctx;
-
- *x = ctx->cursor_x >= _ctx->cols ? _ctx->cols - 1 : ctx->cursor_x;
- *y = ctx->cursor_y >= _ctx->rows ? _ctx->rows - 1 : ctx->cursor_y;
-}
-
-static void flanterm_fb_move_character(struct flanterm_context *_ctx, size_t new_x, size_t new_y, size_t old_x, size_t old_y) {
- struct flanterm_fb_context *ctx = (void *)_ctx;
-
- if (old_x >= _ctx->cols || old_y >= _ctx->rows
- || new_x >= _ctx->cols || new_y >= _ctx->rows) {
- return;
- }
-
- size_t i = old_x + old_y * _ctx->cols;
-
- struct flanterm_fb_char *c;
- struct flanterm_fb_queue_item *q = ctx->map[i];
- if (q != NULL) {
- c = &q->c;
- } else {
- c = &ctx->grid[i];
- }
-
- push_to_queue(_ctx, c, new_x, new_y);
-}
-
-static void flanterm_fb_set_text_fg(struct flanterm_context *_ctx, size_t fg) {
- struct flanterm_fb_context *ctx = (void *)_ctx;
-
- ctx->text_fg = ctx->ansi_colours[fg];
-}
-
-static void flanterm_fb_set_text_bg(struct flanterm_context *_ctx, size_t bg) {
- struct flanterm_fb_context *ctx = (void *)_ctx;
-
- ctx->text_bg = ctx->ansi_colours[bg];
-}
-
-static void flanterm_fb_set_text_fg_bright(struct flanterm_context *_ctx, size_t fg) {
- struct flanterm_fb_context *ctx = (void *)_ctx;
-
- ctx->text_fg = ctx->ansi_bright_colours[fg];
-}
-
-static void flanterm_fb_set_text_bg_bright(struct flanterm_context *_ctx, size_t bg) {
- struct flanterm_fb_context *ctx = (void *)_ctx;
-
- ctx->text_bg = ctx->ansi_bright_colours[bg];
-}
-
-static void flanterm_fb_set_text_fg_rgb(struct flanterm_context *_ctx, uint32_t fg) {
- struct flanterm_fb_context *ctx = (void *)_ctx;
-
- ctx->text_fg = convert_colour(_ctx, fg);
-}
-
-static void flanterm_fb_set_text_bg_rgb(struct flanterm_context *_ctx, uint32_t bg) {
- struct flanterm_fb_context *ctx = (void *)_ctx;
-
- ctx->text_bg = convert_colour(_ctx, bg);
-}
-
-static void flanterm_fb_set_text_fg_default(struct flanterm_context *_ctx) {
- struct flanterm_fb_context *ctx = (void *)_ctx;
-
- ctx->text_fg = ctx->default_fg;
-}
-
-static void flanterm_fb_set_text_bg_default(struct flanterm_context *_ctx) {
- struct flanterm_fb_context *ctx = (void *)_ctx;
-
- ctx->text_bg = 0xffffffff;
-}
-
-static void flanterm_fb_set_text_fg_default_bright(struct flanterm_context *_ctx) {
- struct flanterm_fb_context *ctx = (void *)_ctx;
-
- ctx->text_fg = ctx->default_fg_bright;
-}
-
-static void flanterm_fb_set_text_bg_default_bright(struct flanterm_context *_ctx) {
- struct flanterm_fb_context *ctx = (void *)_ctx;
-
- ctx->text_bg = ctx->default_bg_bright;
-}
-
-static void draw_cursor(struct flanterm_context *_ctx) {
- struct flanterm_fb_context *ctx = (void *)_ctx;
-
- if (ctx->cursor_x >= _ctx->cols || ctx->cursor_y >= _ctx->rows) {
- return;
- }
-
- size_t i = ctx->cursor_x + ctx->cursor_y * _ctx->cols;
-
- struct flanterm_fb_char c;
- struct flanterm_fb_queue_item *q = ctx->map[i];
- if (q != NULL) {
- c = q->c;
- } else {
- c = ctx->grid[i];
- }
- uint32_t tmp = c.fg;
- c.fg = c.bg;
- c.bg = tmp;
- ctx->plot_char(_ctx, &c, ctx->cursor_x, ctx->cursor_y);
- if (q != NULL) {
- ctx->grid[i] = q->c;
- ctx->map[i] = NULL;
- }
-}
-
-static void flanterm_fb_double_buffer_flush(struct flanterm_context *_ctx) {
- struct flanterm_fb_context *ctx = (void *)_ctx;
-
- if (_ctx->cursor_enabled) {
- draw_cursor(_ctx);
- }
-
- for (size_t i = 0; i < ctx->queue_i; i++) {
- struct flanterm_fb_queue_item *q = &ctx->queue[i];
- size_t offset = q->y * _ctx->cols + q->x;
- if (ctx->map[offset] == NULL) {
- continue;
- }
- ctx->plot_char(_ctx, &q->c, q->x, q->y);
- ctx->grid[offset] = q->c;
- ctx->map[offset] = NULL;
- }
-
- if ((ctx->old_cursor_x != ctx->cursor_x || ctx->old_cursor_y != ctx->cursor_y) || _ctx->cursor_enabled == false) {
- if (ctx->old_cursor_x < _ctx->cols && ctx->old_cursor_y < _ctx->rows) {
- ctx->plot_char(_ctx, &ctx->grid[ctx->old_cursor_x + ctx->old_cursor_y * _ctx->cols], ctx->old_cursor_x, ctx->old_cursor_y);
- }
- }
-
- ctx->old_cursor_x = ctx->cursor_x;
- ctx->old_cursor_y = ctx->cursor_y;
-
- ctx->queue_i = 0;
-}
-
-static void flanterm_fb_raw_putchar(struct flanterm_context *_ctx, uint8_t c) {
- struct flanterm_fb_context *ctx = (void *)_ctx;
-
- if (ctx->cursor_x >= _ctx->cols && (ctx->cursor_y < _ctx->scroll_bottom_margin - 1 || _ctx->scroll_enabled)) {
- ctx->cursor_x = 0;
- ctx->cursor_y++;
- if (ctx->cursor_y == _ctx->scroll_bottom_margin) {
- ctx->cursor_y--;
- flanterm_fb_scroll(_ctx);
- }
- if (ctx->cursor_y >= _ctx->cols) {
- ctx->cursor_y = _ctx->cols - 1;
- }
- }
-
- struct flanterm_fb_char ch;
- ch.c = c;
- ch.fg = ctx->text_fg;
- ch.bg = ctx->text_bg;
- push_to_queue(_ctx, &ch, ctx->cursor_x++, ctx->cursor_y);
-}
-
-static void flanterm_fb_full_refresh(struct flanterm_context *_ctx) {
- struct flanterm_fb_context *ctx = (void *)_ctx;
-
- uint32_t default_bg = ctx->default_bg;
-
- for (size_t y = 0; y < ctx->height; y++) {
- for (size_t x = 0; x < ctx->width; x++) {
- if (ctx->canvas != NULL) {
- ctx->framebuffer[y * (ctx->pitch / sizeof(uint32_t)) + x] = ctx->canvas[y * ctx->width + x];
- } else {
- ctx->framebuffer[y * (ctx->pitch / sizeof(uint32_t)) + x] = default_bg;
- }
- }
- }
-
- for (size_t i = 0; i < (size_t)_ctx->rows * _ctx->cols; i++) {
- size_t x = i % _ctx->cols;
- size_t y = i / _ctx->cols;
-
- ctx->plot_char(_ctx, &ctx->grid[i], x, y);
- }
-
- if (_ctx->cursor_enabled) {
- draw_cursor(_ctx);
- }
-}
-
-static void flanterm_fb_deinit(struct flanterm_context *_ctx, void (*_free)(void *, size_t)) {
- struct flanterm_fb_context *ctx = (void *)_ctx;
-
- if (_free == NULL) {
-#ifndef FLANTERM_FB_DISABLE_BUMP_ALLOC
- if (bump_allocated_instance == true) {
- bump_alloc_ptr = 0;
- bump_allocated_instance = false;
- }
-#endif
- return;
- }
-
- _free(ctx->font_bits, ctx->font_bits_size);
- _free(ctx->font_bool, ctx->font_bool_size);
- _free(ctx->grid, ctx->grid_size);
- _free(ctx->queue, ctx->queue_size);
- _free(ctx->map, ctx->map_size);
-
- if (ctx->canvas != NULL) {
- _free(ctx->canvas, ctx->canvas_size);
- }
-
- _free(ctx, sizeof(struct flanterm_fb_context));
-}
-
-struct flanterm_context *flanterm_fb_init(
- void *(*_malloc)(size_t),
- void (*_free)(void *, size_t),
- uint32_t *framebuffer, size_t width, size_t height, size_t pitch,
- uint8_t red_mask_size, uint8_t red_mask_shift,
- uint8_t green_mask_size, uint8_t green_mask_shift,
- uint8_t blue_mask_size, uint8_t blue_mask_shift,
- uint32_t *canvas,
- uint32_t *ansi_colours, uint32_t *ansi_bright_colours,
- uint32_t *default_bg, uint32_t *default_fg,
- uint32_t *default_bg_bright, uint32_t *default_fg_bright,
- void *font, size_t font_width, size_t font_height, size_t font_spacing,
- size_t font_scale_x, size_t font_scale_y,
- size_t margin
-) {
- if (font_scale_x == 0 || font_scale_y == 0) {
- font_scale_x = 1;
- font_scale_y = 1;
- if (width >= (1920 + 1920 / 3) && height >= (1080 + 1080 / 3)) {
- font_scale_x = 2;
- font_scale_y = 2;
- }
- if (width >= (3840 + 3840 / 3) && height >= (2160 + 2160 / 3)) {
- font_scale_x = 4;
- font_scale_y = 4;
- }
- }
-
- if (red_mask_size < 8 || red_mask_size != green_mask_size || red_mask_size != blue_mask_size) {
- return NULL;
- }
-
- if (_malloc == NULL) {
-#ifndef FLANTERM_FB_DISABLE_BUMP_ALLOC
- if (bump_allocated_instance == true) {
- return NULL;
- }
- _malloc = bump_alloc;
- // Limit terminal size if needed
- if (width > FLANTERM_FB_WIDTH_LIMIT || height > FLANTERM_FB_HEIGHT_LIMIT) {
- size_t width_limit = width > FLANTERM_FB_WIDTH_LIMIT ? FLANTERM_FB_WIDTH_LIMIT : width;
- size_t height_limit = height > FLANTERM_FB_HEIGHT_LIMIT ? FLANTERM_FB_HEIGHT_LIMIT : height;
-
- framebuffer = (uint32_t *)((uintptr_t)framebuffer + ((((height / 2) - (height_limit / 2)) * pitch) + (((width / 2) - (width_limit / 2)) * 4)));
-
- width = width_limit;
- height = height_limit;
- }
-
- // Force disable canvas
- canvas = NULL;
-#else
- return NULL;
-#endif
- }
-
- struct flanterm_fb_context *ctx = NULL;
- ctx = _malloc(sizeof(struct flanterm_fb_context));
- if (ctx == NULL) {
- goto fail;
- }
-
- struct flanterm_context *_ctx = (void *)ctx;
- memset(ctx, 0, sizeof(struct flanterm_fb_context));
-
- ctx->red_mask_size = red_mask_size;
- ctx->red_mask_shift = red_mask_shift + (red_mask_size - 8);
- ctx->green_mask_size = green_mask_size;
- ctx->green_mask_shift = green_mask_shift + (green_mask_size - 8);
- ctx->blue_mask_size = blue_mask_size;
- ctx->blue_mask_shift = blue_mask_shift + (blue_mask_size - 8);
-
- if (ansi_colours != NULL) {
- for (size_t i = 0; i < 8; i++) {
- ctx->ansi_colours[i] = convert_colour(_ctx, ansi_colours[i]);
- }
- } else {
- ctx->ansi_colours[0] = convert_colour(_ctx, 0x00000000); // black
- ctx->ansi_colours[1] = convert_colour(_ctx, 0x00aa0000); // red
- ctx->ansi_colours[2] = convert_colour(_ctx, 0x0000aa00); // green
- ctx->ansi_colours[3] = convert_colour(_ctx, 0x00aa5500); // brown
- ctx->ansi_colours[4] = convert_colour(_ctx, 0x000000aa); // blue
- ctx->ansi_colours[5] = convert_colour(_ctx, 0x00aa00aa); // magenta
- ctx->ansi_colours[6] = convert_colour(_ctx, 0x0000aaaa); // cyan
- ctx->ansi_colours[7] = convert_colour(_ctx, 0x00aaaaaa); // grey
- }
-
- if (ansi_bright_colours != NULL) {
- for (size_t i = 0; i < 8; i++) {
- ctx->ansi_bright_colours[i] = convert_colour(_ctx, ansi_bright_colours[i]);
- }
- } else {
- ctx->ansi_bright_colours[0] = convert_colour(_ctx, 0x00555555); // black
- ctx->ansi_bright_colours[1] = convert_colour(_ctx, 0x00ff5555); // red
- ctx->ansi_bright_colours[2] = convert_colour(_ctx, 0x0055ff55); // green
- ctx->ansi_bright_colours[3] = convert_colour(_ctx, 0x00ffff55); // brown
- ctx->ansi_bright_colours[4] = convert_colour(_ctx, 0x005555ff); // blue
- ctx->ansi_bright_colours[5] = convert_colour(_ctx, 0x00ff55ff); // magenta
- ctx->ansi_bright_colours[6] = convert_colour(_ctx, 0x0055ffff); // cyan
- ctx->ansi_bright_colours[7] = convert_colour(_ctx, 0x00ffffff); // grey
- }
-
- if (default_bg != NULL) {
- ctx->default_bg = convert_colour(_ctx, *default_bg);
- } else {
- ctx->default_bg = 0x00000000; // background (black)
- }
-
- if (default_fg != NULL) {
- ctx->default_fg = convert_colour(_ctx, *default_fg);
- } else {
- ctx->default_fg = convert_colour(_ctx, 0x00aaaaaa); // foreground (grey)
- }
-
- if (default_bg_bright != NULL) {
- ctx->default_bg_bright = convert_colour(_ctx, *default_bg_bright);
- } else {
- ctx->default_bg_bright = convert_colour(_ctx, 0x00555555); // background (black)
- }
-
- if (default_fg_bright != NULL) {
- ctx->default_fg_bright = convert_colour(_ctx, *default_fg_bright);
- } else {
- ctx->default_fg_bright = convert_colour(_ctx, 0x00ffffff); // foreground (grey)
- }
-
- ctx->text_fg = ctx->default_fg;
- ctx->text_bg = 0xffffffff;
-
- ctx->framebuffer = (void *)framebuffer;
- ctx->width = width;
- ctx->height = height;
- ctx->pitch = pitch;
-
-#define FONT_BYTES ((font_width * font_height * FLANTERM_FB_FONT_GLYPHS) / 8)
-
- if (font != NULL) {
- ctx->font_width = font_width;
- ctx->font_height = font_height;
- ctx->font_bits_size = FONT_BYTES;
- ctx->font_bits = _malloc(ctx->font_bits_size);
- if (ctx->font_bits == NULL) {
- goto fail;
- }
- memcpy(ctx->font_bits, font, ctx->font_bits_size);
- } else {
- ctx->font_width = font_width = 8;
- ctx->font_height = font_height = 16;
- ctx->font_bits_size = FONT_BYTES;
- font_spacing = 1;
- ctx->font_bits = _malloc(ctx->font_bits_size);
- if (ctx->font_bits == NULL) {
- goto fail;
- }
- memcpy(ctx->font_bits, builtin_font, ctx->font_bits_size);
- }
-
-#undef FONT_BYTES
-
- ctx->font_width += font_spacing;
-
- ctx->font_bool_size = FLANTERM_FB_FONT_GLYPHS * font_height * ctx->font_width * sizeof(bool);
- ctx->font_bool = _malloc(ctx->font_bool_size);
- if (ctx->font_bool == NULL) {
- goto fail;
- }
-
- for (size_t i = 0; i < FLANTERM_FB_FONT_GLYPHS; i++) {
- uint8_t *glyph = &ctx->font_bits[i * font_height];
-
- for (size_t y = 0; y < font_height; y++) {
- // NOTE: the characters in VGA fonts are always one byte wide.
- // 9 dot wide fonts have 8 dots and one empty column, except
- // characters 0xC0-0xDF replicate column 9.
- for (size_t x = 0; x < 8; x++) {
- size_t offset = i * font_height * ctx->font_width + y * ctx->font_width + x;
-
- if ((glyph[y] & (0x80 >> x))) {
- ctx->font_bool[offset] = true;
- } else {
- ctx->font_bool[offset] = false;
- }
- }
- // fill columns above 8 like VGA Line Graphics Mode does
- for (size_t x = 8; x < ctx->font_width; x++) {
- size_t offset = i * font_height * ctx->font_width + y * ctx->font_width + x;
-
- if (i >= 0xc0 && i <= 0xdf) {
- ctx->font_bool[offset] = (glyph[y] & 1);
- } else {
- ctx->font_bool[offset] = false;
- }
- }
- }
- }
-
- ctx->font_scale_x = font_scale_x;
- ctx->font_scale_y = font_scale_y;
-
- ctx->glyph_width = ctx->font_width * font_scale_x;
- ctx->glyph_height = font_height * font_scale_y;
-
- _ctx->cols = (ctx->width - margin * 2) / ctx->glyph_width;
- _ctx->rows = (ctx->height - margin * 2) / ctx->glyph_height;
-
- ctx->offset_x = margin + ((ctx->width - margin * 2) % ctx->glyph_width) / 2;
- ctx->offset_y = margin + ((ctx->height - margin * 2) % ctx->glyph_height) / 2;
-
- ctx->grid_size = _ctx->rows * _ctx->cols * sizeof(struct flanterm_fb_char);
- ctx->grid = _malloc(ctx->grid_size);
- if (ctx->grid == NULL) {
- goto fail;
- }
- for (size_t i = 0; i < _ctx->rows * _ctx->cols; i++) {
- ctx->grid[i].c = ' ';
- ctx->grid[i].fg = ctx->text_fg;
- ctx->grid[i].bg = ctx->text_bg;
- }
-
- ctx->queue_size = _ctx->rows * _ctx->cols * sizeof(struct flanterm_fb_queue_item);
- ctx->queue = _malloc(ctx->queue_size);
- if (ctx->queue == NULL) {
- goto fail;
- }
- ctx->queue_i = 0;
- memset(ctx->queue, 0, ctx->queue_size);
-
- ctx->map_size = _ctx->rows * _ctx->cols * sizeof(struct flanterm_fb_queue_item *);
- ctx->map = _malloc(ctx->map_size);
- if (ctx->map == NULL) {
- goto fail;
- }
- memset(ctx->map, 0, ctx->map_size);
-
- if (canvas != NULL) {
- ctx->canvas_size = ctx->width * ctx->height * sizeof(uint32_t);
- ctx->canvas = _malloc(ctx->canvas_size);
- if (ctx->canvas == NULL) {
- goto fail;
- }
- for (size_t i = 0; i < ctx->width * ctx->height; i++) {
- ctx->canvas[i] = convert_colour(_ctx, canvas[i]);
- }
- }
-
- if (font_scale_x == 1 && font_scale_y == 1) {
- if (canvas == NULL) {
- ctx->plot_char = plot_char_unscaled_uncanvas;
- } else {
- ctx->plot_char = plot_char_unscaled_canvas;
- }
- } else {
- if (canvas == NULL) {
- ctx->plot_char = plot_char_scaled_uncanvas;
- } else {
- ctx->plot_char = plot_char_scaled_canvas;
- }
- }
-
- _ctx->raw_putchar = flanterm_fb_raw_putchar;
- _ctx->clear = flanterm_fb_clear;
- _ctx->set_cursor_pos = flanterm_fb_set_cursor_pos;
- _ctx->get_cursor_pos = flanterm_fb_get_cursor_pos;
- _ctx->set_text_fg = flanterm_fb_set_text_fg;
- _ctx->set_text_bg = flanterm_fb_set_text_bg;
- _ctx->set_text_fg_bright = flanterm_fb_set_text_fg_bright;
- _ctx->set_text_bg_bright = flanterm_fb_set_text_bg_bright;
- _ctx->set_text_fg_rgb = flanterm_fb_set_text_fg_rgb;
- _ctx->set_text_bg_rgb = flanterm_fb_set_text_bg_rgb;
- _ctx->set_text_fg_default = flanterm_fb_set_text_fg_default;
- _ctx->set_text_bg_default = flanterm_fb_set_text_bg_default;
- _ctx->set_text_fg_default_bright = flanterm_fb_set_text_fg_default_bright;
- _ctx->set_text_bg_default_bright = flanterm_fb_set_text_bg_default_bright;
- _ctx->move_character = flanterm_fb_move_character;
- _ctx->scroll = flanterm_fb_scroll;
- _ctx->revscroll = flanterm_fb_revscroll;
- _ctx->swap_palette = flanterm_fb_swap_palette;
- _ctx->save_state = flanterm_fb_save_state;
- _ctx->restore_state = flanterm_fb_restore_state;
- _ctx->double_buffer_flush = flanterm_fb_double_buffer_flush;
- _ctx->full_refresh = flanterm_fb_full_refresh;
- _ctx->deinit = flanterm_fb_deinit;
-
- flanterm_context_reinit(_ctx);
- flanterm_fb_full_refresh(_ctx);
-
-#ifndef FLANTERM_FB_DISABLE_BUMP_ALLOC
- if (_malloc == bump_alloc) {
- bump_allocated_instance = true;
- }
-#endif
-
- return _ctx;
-
-fail:
- if (ctx == NULL) {
- return NULL;
- }
-
-#ifndef FLANTERM_FB_DISABLE_BUMP_ALLOC
- if (_malloc == bump_alloc) {
- bump_alloc_ptr = 0;
- return NULL;
- }
-#endif
-
- if (_free == NULL) {
- return NULL;
- }
-
- if (ctx->canvas != NULL) {
- _free(ctx->canvas, ctx->canvas_size);
- }
- if (ctx->map != NULL) {
- _free(ctx->map, ctx->map_size);
- }
- if (ctx->queue != NULL) {
- _free(ctx->queue, ctx->queue_size);
- }
- if (ctx->grid != NULL) {
- _free(ctx->grid, ctx->grid_size);
- }
- if (ctx->font_bool != NULL) {
- _free(ctx->font_bool, ctx->font_bool_size);
- }
- if (ctx->font_bits != NULL) {
- _free(ctx->font_bits, ctx->font_bits_size);
- }
- if (ctx != NULL) {
- _free(ctx, sizeof(struct flanterm_fb_context));
- }
-
- return NULL;
-}
diff --git a/kernel/src/lib/Flanterm/src/flanterm_backends/fb.h b/kernel/src/lib/Flanterm/src/flanterm_backends/fb.h
deleted file mode 100644
index f4e5e4a..0000000
--- a/kernel/src/lib/Flanterm/src/flanterm_backends/fb.h
+++ /dev/null
@@ -1,68 +0,0 @@
-/* Copyright (C) 2022-2025 mintsuki and contributors.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef FLANTERM_FB_H
-#define FLANTERM_FB_H 1
-
-#include <stdint.h>
-#include <stddef.h>
-#include <stdbool.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include "../flanterm.h"
-
-#ifdef FLANTERM_IN_FLANTERM
-
-#include "fb_private.h"
-
-#endif
-
-struct flanterm_context *flanterm_fb_init(
- /* If _malloc and _free are nulled, use the bump allocated instance (1 use only). */
- void *(*_malloc)(size_t size),
- void (*_free)(void *ptr, size_t size),
- uint32_t *framebuffer, size_t width, size_t height, size_t pitch,
- uint8_t red_mask_size, uint8_t red_mask_shift,
- uint8_t green_mask_size, uint8_t green_mask_shift,
- uint8_t blue_mask_size, uint8_t blue_mask_shift,
- uint32_t *canvas, /* If nulled, no canvas. */
- uint32_t *ansi_colours, uint32_t *ansi_bright_colours, /* If nulled, default. */
- uint32_t *default_bg, uint32_t *default_fg, /* If nulled, default. */
- uint32_t *default_bg_bright, uint32_t *default_fg_bright, /* If nulled, default. */
- /* If font is null, use default font and font_width and font_height ignored. */
- void *font, size_t font_width, size_t font_height, size_t font_spacing,
- /* If scale_x and scale_y are 0, automatically scale font based on resolution. */
- size_t font_scale_x, size_t font_scale_y,
- size_t margin
-);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/kernel/src/lib/Flanterm/src/flanterm_backends/fb_private.h b/kernel/src/lib/Flanterm/src/flanterm_backends/fb_private.h
deleted file mode 100644
index 532e1ab..0000000
--- a/kernel/src/lib/Flanterm/src/flanterm_backends/fb_private.h
+++ /dev/null
@@ -1,121 +0,0 @@
-/* Copyright (C) 2022-2025 mintsuki and contributors.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef FLANTERM_FB_PRIVATE_H
-#define FLANTERM_FB_PRIVATE_H 1
-
-#ifndef FLANTERM_IN_FLANTERM
-#error "Do not use fb_private.h. Use interfaces defined in fb.h only."
-#endif
-
-#include <stdint.h>
-#include <stddef.h>
-#include <stdbool.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#define FLANTERM_FB_FONT_GLYPHS 256
-
-struct flanterm_fb_char {
- uint32_t c;
- uint32_t fg;
- uint32_t bg;
-};
-
-struct flanterm_fb_queue_item {
- size_t x, y;
- struct flanterm_fb_char c;
-};
-
-struct flanterm_fb_context {
- struct flanterm_context term;
-
- void (*plot_char)(struct flanterm_context *ctx, struct flanterm_fb_char *c, size_t x, size_t y);
-
- size_t font_width;
- size_t font_height;
- size_t glyph_width;
- size_t glyph_height;
-
- size_t font_scale_x;
- size_t font_scale_y;
-
- size_t offset_x, offset_y;
-
- volatile uint32_t *framebuffer;
- size_t pitch;
- size_t width;
- size_t height;
- size_t bpp;
-
- uint8_t red_mask_size, red_mask_shift;
- uint8_t green_mask_size, green_mask_shift;
- uint8_t blue_mask_size, blue_mask_shift;
-
- size_t font_bits_size;
- uint8_t *font_bits;
- size_t font_bool_size;
- bool *font_bool;
-
- uint32_t ansi_colours[8];
- uint32_t ansi_bright_colours[8];
- uint32_t default_fg, default_bg;
- uint32_t default_fg_bright, default_bg_bright;
-
- size_t canvas_size;
- uint32_t *canvas;
-
- size_t grid_size;
- size_t queue_size;
- size_t map_size;
-
- struct flanterm_fb_char *grid;
-
- struct flanterm_fb_queue_item *queue;
- size_t queue_i;
-
- struct flanterm_fb_queue_item **map;
-
- uint32_t text_fg;
- uint32_t text_bg;
- size_t cursor_x;
- size_t cursor_y;
-
- uint32_t saved_state_text_fg;
- uint32_t saved_state_text_bg;
- size_t saved_state_cursor_x;
- size_t saved_state_cursor_y;
-
- size_t old_cursor_x;
- size_t old_cursor_y;
-};
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/kernel/src/lib/Flanterm/src/flanterm_private.h b/kernel/src/lib/Flanterm/src/flanterm_private.h
deleted file mode 100644
index 8a2d5fa..0000000
--- a/kernel/src/lib/Flanterm/src/flanterm_private.h
+++ /dev/null
@@ -1,123 +0,0 @@
-/* Copyright (C) 2022-2025 mintsuki and contributors.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef FLANTERM_PRIVATE_H
-#define FLANTERM_PRIVATE_H 1
-
-#ifndef FLANTERM_IN_FLANTERM
-#error "Do not use flanterm_private.h. Use interfaces defined in flanterm.h only."
-#endif
-
-#include <stddef.h>
-#include <stdint.h>
-#include <stdbool.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#define FLANTERM_MAX_ESC_VALUES 16
-
-struct flanterm_context {
- /* internal use */
-
- size_t tab_size;
- bool autoflush;
- bool cursor_enabled;
- bool scroll_enabled;
- bool control_sequence;
- bool escape;
- bool osc;
- bool osc_escape;
- bool rrr;
- bool discard_next;
- bool bold;
- bool bg_bold;
- bool reverse_video;
- bool dec_private;
- bool insert_mode;
- bool csi_unhandled;
- uint64_t code_point;
- size_t unicode_remaining;
- uint8_t g_select;
- uint8_t charsets[2];
- size_t current_charset;
- size_t escape_offset;
- size_t esc_values_i;
- size_t saved_cursor_x;
- size_t saved_cursor_y;
- size_t current_primary;
- size_t current_bg;
- size_t scroll_top_margin;
- size_t scroll_bottom_margin;
- uint32_t esc_values[FLANTERM_MAX_ESC_VALUES];
- uint64_t oob_output;
- bool saved_state_bold;
- bool saved_state_bg_bold;
- bool saved_state_reverse_video;
- size_t saved_state_current_charset;
- size_t saved_state_current_primary;
- size_t saved_state_current_bg;
-
- /* to be set by backend */
-
- size_t rows, cols;
-
- void (*raw_putchar)(struct flanterm_context *, uint8_t c);
- void (*clear)(struct flanterm_context *, bool move);
- void (*set_cursor_pos)(struct flanterm_context *, size_t x, size_t y);
- void (*get_cursor_pos)(struct flanterm_context *, size_t *x, size_t *y);
- void (*set_text_fg)(struct flanterm_context *, size_t fg);
- void (*set_text_bg)(struct flanterm_context *, size_t bg);
- void (*set_text_fg_bright)(struct flanterm_context *, size_t fg);
- void (*set_text_bg_bright)(struct flanterm_context *, size_t bg);
- void (*set_text_fg_rgb)(struct flanterm_context *, uint32_t fg);
- void (*set_text_bg_rgb)(struct flanterm_context *, uint32_t bg);
- void (*set_text_fg_default)(struct flanterm_context *);
- void (*set_text_bg_default)(struct flanterm_context *);
- void (*set_text_fg_default_bright)(struct flanterm_context *);
- void (*set_text_bg_default_bright)(struct flanterm_context *);
- void (*move_character)(struct flanterm_context *, size_t new_x, size_t new_y, size_t old_x, size_t old_y);
- void (*scroll)(struct flanterm_context *);
- void (*revscroll)(struct flanterm_context *);
- void (*swap_palette)(struct flanterm_context *);
- void (*save_state)(struct flanterm_context *);
- void (*restore_state)(struct flanterm_context *);
- void (*double_buffer_flush)(struct flanterm_context *);
- void (*full_refresh)(struct flanterm_context *);
- void (*deinit)(struct flanterm_context *, void (*)(void *, size_t));
-
- /* to be set by client */
-
- void (*callback)(struct flanterm_context *, uint64_t, uint64_t, uint64_t, uint64_t);
-};
-
-void flanterm_context_reinit(struct flanterm_context *ctx);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/kernel/src/lib/uACPI b/kernel/src/lib/uACPI
deleted file mode 160000
-Subproject e5e5deea6f4dea0ea81237db39ca061ead048e6
diff --git a/kernel/src/main.asm b/kernel/src/main.asm
deleted file mode 100644
index 88b0d53..0000000
--- a/kernel/src/main.asm
+++ /dev/null
@@ -1,22 +0,0 @@
-
-section .text
-
-extern main
-global kmain
-kmain:
- mov rsp,stack_top
- call main
- hlt
-
-global setwp
-setwp:
- mov rax,cr0
- or rax, 0x10000
- mov cr0,rax
- ret
-
-
-section .data
-stack_bottom:
-resb 1024*128
-stack_top: \ No newline at end of file
diff --git a/kernel/src/main.cpp b/kernel/src/main.cpp
index 292386e..e90731a 100644
--- a/kernel/src/main.cpp
+++ b/kernel/src/main.cpp
@@ -1,275 +1,33 @@
-
-#include <drivers/xhci.hpp>
-#include <drivers/pci.hpp>
-
-#include <arch/x86_64/syscalls/syscalls.hpp>
-#include <arch/x86_64/syscalls/sockets.hpp>
-#include <arch/x86_64/interrupts/idt.hpp>
-#include <arch/x86_64/interrupts/irq.hpp>
-#include <arch/x86_64/interrupts/pic.hpp>
-#include <arch/x86_64/interrupts/pit.hpp>
-#include <arch/x86_64/scheduling.hpp>
-#include <arch/x86_64/cpu/lapic.hpp>
-#include <arch/x86_64/cpu/gdt.hpp>
-#include <arch/x86_64/cpu/smp.hpp>
-#include <arch/x86_64/cpu/sse.hpp>
-#include <generic/mm/paging.hpp>
-#include <generic/vfs/ustar.hpp>
-#include <drivers/kvmtimer.hpp>
-#include <generic/vfs/vfs.hpp>
-#include <generic/mm/heap.hpp>
-#include <generic/mm/pmm.hpp>
-#include <drivers/serial.hpp>
-#include <drivers/cmos.hpp>
+#include <cstdint>
+#include <generic/bootloader/bootloader.hpp>
+#include <utils/cxx/cxx_constructors.hpp>
+#include <generic/arch.hpp>
+#include <utils/flanterm.hpp>
+#include <generic/pmm.hpp>
+#include <generic/paging.hpp>
+#include <generic/heap.hpp>
#include <drivers/acpi.hpp>
-#include <etc/assembly.hpp>
-#include <drivers/tsc.hpp>
-#include <etc/logging.hpp>
-#include <uacpi/event.h>
-#include <etc/etc.hpp>
-#include <limine.h>
-
-#include <drivers/ps2.hpp>
-
-#include <generic/vfs/fd.hpp>
-
-char is_shift_pressed = 0;
-char is_ctrl_pressed = 0;
-
-const char en_layout_translation[] = {
- '\0', '\e', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '-', '=', '\b', '\t',
- 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', '[', ']', '\n', '\0', 'a', 's',
- 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', '\'', '`', '\0', '\\', 'z', 'x', 'c', 'v',
- 'b', 'n', 'm', ',', '.', '/', '\0', '\0', '\0', ' '
-};
-
-const char en_layout_translation_shift[] = {
- '\0', '\e', '!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '_', '+', '\b', '\t',
- 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', 'O', 'P', '{', '}', '\n', '\0', 'A', 'S',
- 'D', 'F', 'G', 'H', 'J', 'K', 'L', ':', '\"', '~', '\0', '|', 'Z', 'X', 'C', 'V',
- 'B', 'N', 'M', '<', '>', '?', '\0', '\0', '\0', ' '
-};
-\
-#define ASCII_CTRL_OFFSET 96
-
-#define SHIFT_PRESSED 0x2A
-#define SHIFT_RELEASED 0xAA
-#define CTRL_PRESSED 29
-#define CTRL_RELEASED 157
-
-#include <generic/locks/spinlock.hpp>
-
-std::uint16_t KERNEL_GOOD_TIMER = HPET_TIMER;
-
-static uacpi_interrupt_ret handle_power_button(uacpi_handle ctx) {
- Log::Display(LEVEL_MESSAGE_OK,"Got uacpi power_button !\n");
- return UACPI_INTERRUPT_HANDLED;
-}
-
-void interrupt_process_handle(void* arg) {
- while(1) {
- asm volatile("sti");
- asm volatile("pause");
- asm volatile("cli");
- yield();
- }
-}
-
-arch::x86_64::process_t* init = 0;
-
-static void doKeyWork(uint8_t key,userspace_fd_t* fd_to_write) {
-
- if(key == SHIFT_PRESSED) {
- is_shift_pressed = 1;
- return;
- } else if(key == SHIFT_RELEASED) {
- is_shift_pressed = 0;
- return;
- }
-
- if(key == CTRL_PRESSED) {
- is_ctrl_pressed = 1;
- return;
- } else if(key == CTRL_RELEASED) {
- is_ctrl_pressed = 0;
- return;
- }
-
- if(!(key & (1 << 7))) {
- char layout_key;
-
- if(!is_shift_pressed)
- layout_key = en_layout_translation[key];
- else
- layout_key = en_layout_translation_shift[key];
-
- if(is_ctrl_pressed)
- layout_key = en_layout_translation[key] - ASCII_CTRL_OFFSET;
-
- vfs::vfs::write(fd_to_write,&layout_key,1);
- }
-}
-
-void ktty(void* arg) {
- userspace_fd_t kbd;
- userspace_fd_t tty;
- memset(&kbd,0,sizeof(userspace_fd_t));
- memset(&tty,0,sizeof(userspace_fd_t));
- memcpy(kbd.path,"/dev/ps2keyboard0",sizeof("/dev/ps2keyboard0"));
- memcpy(tty.path,"/dev/tty0",sizeof("/dev/tty0")); // tty0 is reserved for kernel tty
-
- while(1) {
- asm volatile("cli");
- std::int32_t kbd_poll = vfs::vfs::poll(&kbd,POLLIN);
- std::int32_t tty_poll = vfs::vfs::poll(&tty,POLLIN);
- asm volatile("sti");
-
- if(kbd_poll > 0) {
- char buffer[32];
- memset(buffer,0,32);
- asm volatile("cli");
- std::int64_t bytes_read = vfs::vfs::read(&kbd,buffer,32);
- for(int i = 0;i < bytes_read;i++) {
- doKeyWork(buffer[i], &tty);
- }
- asm volatile("sti");
- }
-
- if(tty_poll > 0) {
- char buffer[128];
- memset(buffer,0,128);
- asm volatile("cli");
- std::int64_t bytes_read = vfs::vfs::read(&tty,buffer,32);
- asm volatile("sti");
- if(bytes_read > 0) {
- Log::RawDisp(buffer,bytes_read);
- }
- }
- asm volatile("cli");
- yield();
- asm volatile("sti");
- }
-
-}
-
-extern "C" void main() {
-
- Other::ConstructorsInit();
- asm volatile("cli");
-
- drivers::serial serial(DEFAULT_SERIAL_PORT);
-
- __wrmsr(0xC0000101,0);
-
- memory::pmm::_physical::init();
- memory::heap::init();
-
- Log::Init();
-
- memory::paging::init();
- //Log::Display(LEVEL_MESSAGE_OK,"Paging initializied\n");
-
- arch::x86_64::cpu::gdt::init();
- //Log::Display(LEVEL_MESSAGE_OK,"GDT initializied\n");
-
- arch::x86_64::interrupts::idt::init();
- //Log::Display(LEVEL_MESSAGE_OK,"IDT initializied\n");
-
- arch::x86_64::interrupts::pic::init();
- Log::Display(LEVEL_MESSAGE_OK,"PIC initializied\n");
-
- drivers::kvmclock::init();
- drivers::acpi::init();
- Log::Display(LEVEL_MESSAGE_OK,"ACPI initializied\n");
-
- vfs::vfs::init();
- Log::Display(LEVEL_MESSAGE_OK,"VFS initializied\n");
-
- arch::x86_64::cpu::sse::init();
- //Log::Display(LEVEL_MESSAGE_OK,"SSE initializied\n");
-
- arch::x86_64::cpu::mp::init();
- arch::x86_64::cpu::mp::sync(0);
- Log::Display(LEVEL_MESSAGE_OK,"SMP initializied\n");
-
- arch::x86_64::scheduling::init();
- Log::Display(LEVEL_MESSAGE_OK,"Scheduling initializied\n");
-
- init = arch::x86_64::scheduling::create();
- extern int how_much_cpus;
-
- for(int i = 0;i < how_much_cpus; i++) {
- arch::x86_64::scheduling::create_kernel_thread(interrupt_process_handle,0); // we need to have processes which will do sti for interrupt waiting
- }
-
- xhci_init();
-
- arch::x86_64::scheduling::create_kernel_thread(ktty,0);
-
- drivers::pci::initworkspace();
- Log::Display(LEVEL_MESSAGE_OK,"PCI initializied\n");
-
- drivers::ps2::init();
-
- vfs::ustar::copy();
- Log::Display(LEVEL_MESSAGE_OK,"USTAR parsed\n");
-
- arch::x86_64::syscall::init();
- Log::Display(LEVEL_MESSAGE_OK,"Syscalls initializied\n");
-
- sockets::init();
- Log::Display(LEVEL_MESSAGE_OK,"Sockets initializied\n");
-
- uacpi_status ret = uacpi_install_fixed_event_handler(
- UACPI_FIXED_EVENT_POWER_BUTTON,
- handle_power_button, UACPI_NULL
- );
-
- char* argv[] = {0};
- char* envp[] = {"TERM=linux","SHELL=/bin/bash","PATH=/usr/bin:/bin",0};
-
- Log::Display(LEVEL_MESSAGE_INFO,"Trying to sync cpus...\n");
- arch::x86_64::cpu::mp::sync(1);
-
- arch::x86_64::scheduling::loadelf(init,"/bin/bash",argv,envp,0);
- arch::x86_64::scheduling::wakeup(init);
-
- vfs::fdmanager* fd = (vfs::fdmanager*)init->fd;
-
- int stdin = fd->create(init);
- int stdout = fd->create(init);
- int stderr = fd->create(init);
-
- userspace_fd_t *stdins = fd->search(init,stdin);
- userspace_fd_t *stdouts = fd->search(init,stdout);
- userspace_fd_t* stderrs = fd->search(init,stderr);
-
- memcpy(stdins->path,"/dev/pts/0",sizeof("/dev/pts/0"));
- memcpy(stdouts->path,"/dev/pts/0",sizeof("/dev/pts/0"));
- memcpy(stderrs->path,"/dev/pts/0",sizeof("/dev/pts/0"));
-
- stdins->index = 0;
- stdouts->index = 1;
- stderrs->index = 2;
-
- stdins->is_cached_path = 0;
- stdouts->is_cached_path = 0;
- stderrs->is_cached_path = 0;
-
- extern locks::spinlock* vfs_lock;
- extern locks::spinlock pmm_lock;
-
- Log::Display(LEVEL_MESSAGE_FAIL,"\e[1;1H\e[2J");
- arch::x86_64::cpu::lapic::tick(arch::x86_64::cpu::data()->lapic_block);
-
- dmesg("Now we are in userspace...");
-
- setwp();
-
- asm volatile("sti");
- while(1) {
-
- asm volatile("hlt");
- }
+extern std::size_t memory_size;
+
+extern "C" void kmain() {
+ utils::cxx::init_constructors();
+ bootloader::init();
+ utils::flanterm::init();
+ pmm::init();
+ paging::init();
+ kheap::init();
+ utils::flanterm::fullinit();
+ klibc::printf("PMM: Total usable memory: %lli bytes\r\n",memory_size); // i dont want to forgot these messages
+ klibc::printf("Paging: Enabled kernel root with %d level paging\n\r", arch::level_paging());
+ klibc::printf("KHeap: Available memory %lli bytes\r\n",KHEAP_SIZE);
+ acpi::init_tables();
+ arch::init(ARCH_INIT_EARLY);
+ acpi::full_init();
+ arch::init(ARCH_INIT_COMMON);
+ extern int is_early;
+ is_early = 0;
+ klibc::printf("Boot is done\r\n");
+ //*(int*)0x100 = 0;
+ arch::hcf();
}
diff --git a/kernel/src/utils/align.hpp b/kernel/src/utils/align.hpp
new file mode 100644
index 0000000..2f2c665
--- /dev/null
+++ b/kernel/src/utils/align.hpp
@@ -0,0 +1,2 @@
+#define ALIGNUP(VALUE, c) ((VALUE + c - 1) & ~(c - 1))
+#define ALIGNDOWN(VALUE, c) ((VALUE / c) * c) \ No newline at end of file
diff --git a/kernel/src/utils/assembly.hpp b/kernel/src/utils/assembly.hpp
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/kernel/src/utils/assembly.hpp
diff --git a/kernel/src/utils/bitmap.hpp b/kernel/src/utils/bitmap.hpp
new file mode 100644
index 0000000..0ebbb15
--- /dev/null
+++ b/kernel/src/utils/bitmap.hpp
@@ -0,0 +1,37 @@
+#pragma once
+#include <klibc/stdio.hpp>
+#include <klibc/stdlib.hpp>
+#include <klibc/string.hpp>
+#include <utils/align.hpp>
+
+namespace utils {
+ class bitmap {
+ private:
+ std::uint8_t* pool;
+ std::uint32_t pool_size;
+
+ public:
+ bitmap(std::uint32_t size, std::uint8_t* custom_pool = 0) {
+ if (custom_pool) {
+ this->pool = custom_pool;
+ this->pool_size = (ALIGNUP(size, 8) / 8);
+ } else {
+ this->pool_size = (ALIGNUP(size, 8) / 8) + 1;
+ this->pool = (std::uint8_t*) klibc::malloc(pool_size);
+ }
+ klibc::memset(pool, 0, pool_size);
+ }
+
+ std::uint8_t test(std::uint32_t idx) {
+ return pool[ALIGNDOWN(idx, 8) / 8] & (1 << (idx - ALIGNDOWN(idx, 8)));
+ }
+
+ void clear(std::uint32_t idx) {
+ pool[ALIGNDOWN(idx, 8) / 8] &= ~(1 << (idx - ALIGNDOWN(idx, 8)));
+ }
+
+ void set(std::uint32_t idx) {
+ pool[ALIGNDOWN(idx, 8) / 8] |= (1 << (idx - ALIGNDOWN(idx, 8)));
+ }
+ };
+}; \ No newline at end of file
diff --git a/kernel/src/utils/cxx/cxx_constructors.cpp b/kernel/src/utils/cxx/cxx_constructors.cpp
new file mode 100644
index 0000000..b1ee037
--- /dev/null
+++ b/kernel/src/utils/cxx/cxx_constructors.cpp
@@ -0,0 +1,12 @@
+
+extern void (*__init_array[])();
+extern void (*__init_array_end[])();
+
+#include <utils/cxx/cxx_constructors.hpp>
+#include <cstdint>
+
+void utils::cxx::init_constructors() {
+ for (std::size_t i = 0; &__init_array[i] != __init_array_end; i++) {
+ __init_array[i]();
+ }
+} \ No newline at end of file
diff --git a/kernel/src/utils/cxx/cxx_constructors.hpp b/kernel/src/utils/cxx/cxx_constructors.hpp
new file mode 100644
index 0000000..f269745
--- /dev/null
+++ b/kernel/src/utils/cxx/cxx_constructors.hpp
@@ -0,0 +1,6 @@
+
+namespace utils {
+ namespace cxx {
+ void init_constructors();
+ }
+} \ No newline at end of file
diff --git a/kernel/src/etc/etc.cpp b/kernel/src/utils/cxx/cxx_stuff.cpp
index 2cf3d8c..c12546a 100644
--- a/kernel/src/etc/etc.cpp
+++ b/kernel/src/utils/cxx/cxx_stuff.cpp
@@ -1,7 +1,4 @@
-
-#include <etc/etc.hpp>
#include <cstdint>
-#include <cstddef>
extern "C" {
@@ -30,11 +27,11 @@ void *memmove(void *dest, const void *src, std::size_t n) {
std::uint8_t *pdest = static_cast<std::uint8_t *>(dest);
const std::uint8_t *psrc = static_cast<const std::uint8_t *>(src);
- if (src > dest) {
+ if (reinterpret_cast<std::uintptr_t>(src) > reinterpret_cast<std::uintptr_t>(dest)) {
for (std::size_t i = 0; i < n; i++) {
pdest[i] = psrc[i];
}
- } else if (src < dest) {
+ } else if (reinterpret_cast<std::uintptr_t>(src) < reinterpret_cast<std::uintptr_t>(dest)) {
for (std::size_t i = n; i > 0; i--) {
pdest[i-1] = psrc[i-1];
}
@@ -58,48 +55,50 @@ int memcmp(const void *s1, const void *s2, std::size_t n) {
}
-extern void (*__init_array[])();
-extern void (*__init_array_end[])();
-
-void Other::ConstructorsInit() {
- for (std::size_t i = 0; &__init_array[i] != __init_array_end; i++) {
- __init_array[i]();
- }
-}
+#include <generic/arch.hpp>
extern "C" {
int __cxa_atexit(void (*)(void *), void *, void *) { return 0; }
- void __cxa_pure_virtual() { asm volatile("hlt"); }
+ void __cxa_pure_virtual() { arch::hcf(); }
void *__dso_handle;
}
-#include <generic/mm/heap.hpp>
+#include <generic/heap.hpp>
+
+typedef unsigned long size_t;
void *operator new(size_t size)
{
- void* ptr = memory::heap::malloc(size);
- memset(ptr,0,size);
- return ptr;
+ void* p = kheap::malloc(size);
+ memset(p,0,size);
+ return p;
}
void *operator new[](size_t size)
{
- void* ptr = memory::heap::malloc(size);
- memset(ptr,0,size);
- return ptr;
+ void* p = kheap::malloc(size);
+ memset(p,0,size);
+ return p;
}
void operator delete(void *p)
{
- memory::heap::free(p);
+ kheap::free(p);
}
-void operator delete(void *p,unsigned long sz)
+void operator delete[](void *p)
{
- memory::heap::free(p);
+ kheap::free(p);
}
-void operator delete[](void *p)
+void operator delete(void *p, size_t size)
{
- memory::heap::free(p);
+ (void)size;
+ kheap::free(p);
}
+
+void operator delete[](void *p, size_t size)
+{
+ (void)size;
+ kheap::free(p);
+} \ No newline at end of file
diff --git a/kernel/src/utils/flanterm.cpp b/kernel/src/utils/flanterm.cpp
new file mode 100644
index 0000000..1c46922
--- /dev/null
+++ b/kernel/src/utils/flanterm.cpp
@@ -0,0 +1,638 @@
+#include <cstdint>
+#include <generic/bootloader/bootloader.hpp>
+#include <utils/flanterm.hpp>
+#include <flanterm_backends/fb.h>
+#include <generic/lock/spinlock.hpp>
+#include <flanterm.h>
+
+#include <generic/pmm.hpp>
+#include <generic/hhdm.hpp>
+#include <generic/heap.hpp>
+#include <klibc/stdlib.hpp>
+#include <klibc/stdio.hpp>
+#include <klibc/string.hpp>
+
+locks::spinlock flanterm_lock;
+flanterm_context* ft_ctx0 = 0;
+int is_disabled_flanterm = 0;
+
+std::uint32_t default_fg = 0xEEEEEEEE;
+std::uint32_t default_bright_fg = 0xFFFFFFFF;
+std::uint32_t default_bg = 0;
+
+static inline int abs(int x) {
+ return x < 0 ? -x : x;
+}
+
+extern "C" void* __flanterm_malloc(size_t size) {
+ return klibc::malloc(size);
+}
+
+extern "C" void __flanterm_free(void* ptr,size_t size) {
+ (void)size;
+ klibc::free(ptr);
+}
+
+void scale_image_nn(unsigned char* src, int src_w, int src_h,
+ unsigned char* dst, int dst_w, int dst_h, int channels) {
+ for (int y = 0; y < dst_h; y++) {
+ int src_y = y * src_h / dst_h;
+ for (int x = 0; x < dst_w; x++) {
+ int src_x = x * src_w / dst_w;
+ for (int c = 0; c < channels; c++) {
+ dst[(y*dst_w + x)*channels + c] = src[(src_y*src_w + src_x)*channels + c];
+ }
+ }
+ }
+}
+
+uint32_t rgb_to_pixel(uint8_t r, uint8_t g, uint8_t b,
+ int r_len, int r_off,
+ int g_len, int g_off,
+ int b_len, int b_off) {
+ uint32_t pixel = 0;
+ uint32_t R = (r >> (8 - r_len)) << r_off;
+ uint32_t G = (g >> (8 - g_len)) << g_off;
+ uint32_t B = (b >> (8 - b_len)) << b_off;
+ pixel = R | G | B;
+ return pixel;
+}
+
+static uint32_t blend_pixel(uint32_t dst, uint8_t r_src, uint8_t g_src, uint8_t b_src, int alpha_fixed,
+ int r_len, int r_off, int g_len, int g_off, int b_len, int b_off) {
+ // alpha_fixed в диапазоне 0-256 (где 256 = 1.0)
+
+ uint8_t r_dst = (dst >> r_off) & ((1 << r_len) - 1);
+ uint8_t g_dst = (dst >> g_off) & ((1 << g_len) - 1);
+ uint8_t b_dst = (dst >> b_off) & ((1 << b_len) - 1);
+
+ // Расширяем до 8 бит
+ r_dst = (r_dst << (8 - r_len)) | (r_dst >> (2 * r_len - 8));
+ g_dst = (g_dst << (8 - g_len)) | (g_dst >> (2 * g_len - 8));
+ b_dst = (b_dst << (8 - b_len)) | (b_dst >> (2 * b_len - 8));
+
+ // Блендинг с фиксированной точкой
+ uint8_t r = (uint8_t)((r_src * alpha_fixed + r_dst * (256 - alpha_fixed)) >> 8);
+ uint8_t g = (uint8_t)((g_src * alpha_fixed + g_dst * (256 - alpha_fixed)) >> 8);
+ uint8_t b = (uint8_t)((b_src * alpha_fixed + b_dst * (256 - alpha_fixed)) >> 8);
+
+ uint32_t pixel = 0;
+ pixel |= ((r >> (8 - r_len)) << r_off);
+ pixel |= ((g >> (8 - g_len)) << g_off);
+ pixel |= ((b >> (8 - b_len)) << b_off);
+
+ return pixel;
+}
+
+static void draw_transparent_black_square(uint32_t* canvas, int width, int height,
+ int r_len, int r_off,
+ int g_len, int g_off,
+ int b_len, int b_off,
+ int margin) {
+ int square_w = width - 2 * margin;
+ int square_h = height - 2 * margin;
+ int start_x = margin;
+ int start_y = margin;
+
+ int alpha_fixed = 128;
+
+ for (int y = start_y; y < start_y + square_h; y++) {
+ for (int x = start_x; x < start_x + square_w; x++) {
+ int idx = y * width + x;
+ canvas[idx] = blend_pixel(canvas[idx], 0, 0, 0, alpha_fixed,
+ r_len, r_off, g_len, g_off, b_len, b_off);
+ }
+ }
+}
+
+#pragma pack(push, 1)
+struct BMPHeader {
+ uint16_t signature;
+ uint32_t file_size;
+ uint32_t reserved;
+ uint32_t data_offset;
+ uint32_t header_size;
+ int32_t width;
+ int32_t height;
+ uint16_t planes;
+ uint16_t bpp;
+ uint32_t compression;
+ uint32_t image_size;
+ int32_t x_pixels_per_meter;
+ int32_t y_pixels_per_meter;
+ uint32_t colors_used;
+ uint32_t important_colors;
+};
+#pragma pack(pop)
+
+static const unsigned char bg_bmp[] = {
+ #embed "src/bg.bmp"
+};
+
+static unsigned char* load_bmp_from_memory(const unsigned char* bmp_data, size_t bmp_size,
+ int* width, int* height, int* channels) {
+ if (bmp_size < sizeof(BMPHeader)) {
+ return nullptr;
+ }
+
+ BMPHeader* header = (BMPHeader*)bmp_data;
+
+ if (header->signature != 0x4D42) { // 'BM'
+ return nullptr;
+ }
+
+ if (header->bpp != 24 || header->compression != 0) {
+ return nullptr;
+ }
+
+ *width = abs(header->width);
+ *height = abs(header->height);
+ *channels = 3;
+
+ unsigned char* rgb_data = (unsigned char*)(pmm::buddy::alloc((*width) * (*height) * 3).phys + etc::hhdm());
+ if (!rgb_data) {
+ return nullptr;
+ }
+
+ int row_size = ((*width) * 3 + 3) & ~3;
+ unsigned char* bmp_pixels = (unsigned char*)(bmp_data + header->data_offset);
+
+ for (int y = 0; y < *height; y++) {
+ int src_y;
+ if (header->height > 0) {
+
+ src_y = (*height - 1 - y);
+ } else {
+
+ src_y = y;
+ }
+
+ unsigned char* src_row = bmp_pixels + src_y * row_size;
+ unsigned char* dst_row = rgb_data + y * (*width) * 3;
+
+ for (int x = 0; x < *width; x++) {
+ dst_row[x*3 + 0] = src_row[x*3 + 2]; // R
+ dst_row[x*3 + 1] = src_row[x*3 + 1]; // G
+ dst_row[x*3 + 2] = src_row[x*3 + 0]; // B
+ }
+ }
+
+ return rgb_data;
+}
+unsigned char unifont_arr[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x42, 0x81, 0xa5,
+ 0x81, 0xa5, 0x99, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x3c, 0x7e, 0xff, 0xdb, 0xff, 0xdb, 0xe7, 0x7e, 0x3c, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x7f, 0x7f, 0x7f, 0x7f, 0x3e, 0x1c,
+ 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x1c, 0x1c,
+ 0x3e, 0x3e, 0x1c, 0x1c, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x1c, 0x1c, 0x1c, 0x08, 0x7f, 0x7f, 0x6b, 0x08, 0x08, 0x1c, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x1c, 0x3e, 0x7f, 0x7f, 0x7f, 0x3e,
+ 0x08, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38,
+ 0x7c, 0x7c, 0x7c, 0x38, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xe7, 0xc3, 0xc3, 0xe7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x22, 0x41, 0x41, 0x41, 0x22, 0x1c,
+ 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe7, 0xdb, 0xbd,
+ 0xbd, 0xdb, 0xe7, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x07, 0x03, 0x05, 0x38, 0x44, 0x44, 0x44, 0x38, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x22, 0x22, 0x22, 0x1c, 0x08, 0x3e,
+ 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x0c, 0x0a, 0x0a,
+ 0x08, 0x08, 0x08, 0x38, 0x78, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c,
+ 0x17, 0x11, 0x11, 0x11, 0x11, 0x71, 0xf1, 0xe7, 0x0f, 0x0e, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x49, 0x2a, 0x1c, 0x77, 0x1c, 0x2a, 0x49,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60,
+ 0x78, 0x7e, 0x78, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x06, 0x1e, 0x7e, 0x1e, 0x06, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x08, 0x1c, 0x2a, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x2a,
+ 0x1c, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x24, 0x24, 0x24,
+ 0x24, 0x24, 0x24, 0x00, 0x24, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x3f, 0x7a, 0x7a, 0x7a, 0x3a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x3c, 0x42, 0x40, 0x3c, 0x42, 0x42, 0x3c, 0x02,
+ 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x7f,
+ 0x7f, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x1c,
+ 0x2a, 0x08, 0x08, 0x08, 0x08, 0x08, 0x2a, 0x1c, 0x08, 0x3e, 0x00, 0x00,
+ 0x00, 0x00, 0x08, 0x1c, 0x2a, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
+ 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
+ 0x08, 0x08, 0x08, 0x2a, 0x1c, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x08, 0x04, 0xfe, 0x04, 0x08, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x20, 0x7f, 0x20, 0x10,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x24, 0x42, 0xff, 0x42, 0x24, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x3c, 0x3c, 0x7e, 0x7e, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x7e, 0x3c,
+ 0x3c, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00,
+ 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0x22, 0x22, 0x22, 0x22, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x12, 0x12, 0x12, 0x7e, 0x24, 0x24, 0x7e, 0x48, 0x48, 0x48, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x08, 0x3e, 0x49, 0x48, 0x38, 0x0e, 0x09, 0x49,
+ 0x3e, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x4a, 0x4a, 0x34,
+ 0x08, 0x08, 0x16, 0x29, 0x29, 0x46, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x1c, 0x22, 0x22, 0x14, 0x18, 0x29, 0x45, 0x42, 0x46, 0x39, 0x00, 0x00,
+ 0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x08, 0x08, 0x10, 0x10,
+ 0x10, 0x10, 0x10, 0x10, 0x08, 0x08, 0x04, 0x00, 0x00, 0x00, 0x00, 0x20,
+ 0x10, 0x10, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x10, 0x10, 0x20, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x49, 0x2a, 0x1c, 0x2a, 0x49,
+ 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08,
+ 0x08, 0x7f, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x08, 0x08, 0x10,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x02, 0x02, 0x04, 0x08, 0x08, 0x10, 0x10, 0x20, 0x40, 0x40, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x18, 0x24, 0x42, 0x46, 0x4a, 0x52, 0x62, 0x42,
+ 0x24, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x18, 0x28, 0x08,
+ 0x08, 0x08, 0x08, 0x08, 0x08, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x3c, 0x42, 0x42, 0x02, 0x0c, 0x10, 0x20, 0x40, 0x40, 0x7e, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x3c, 0x42, 0x42, 0x02, 0x1c, 0x02, 0x02, 0x42,
+ 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x0c, 0x14, 0x24,
+ 0x44, 0x44, 0x7e, 0x04, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x7e, 0x40, 0x40, 0x40, 0x7c, 0x02, 0x02, 0x02, 0x42, 0x3c, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x1c, 0x20, 0x40, 0x40, 0x7c, 0x42, 0x42, 0x42,
+ 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x02, 0x02, 0x04,
+ 0x04, 0x04, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x3c, 0x42, 0x42, 0x42, 0x3c, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x3c, 0x42, 0x42, 0x42, 0x3e, 0x02, 0x02, 0x02,
+ 0x04, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18,
+ 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x18, 0x08, 0x08, 0x10, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x04, 0x08, 0x10, 0x20, 0x10, 0x08,
+ 0x04, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e,
+ 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x40, 0x20, 0x10, 0x08, 0x04, 0x08, 0x10, 0x20, 0x40, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x3c, 0x42, 0x42, 0x02, 0x04, 0x08, 0x08, 0x00,
+ 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x22, 0x4a, 0x56,
+ 0x52, 0x52, 0x52, 0x4e, 0x20, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x18, 0x24, 0x24, 0x42, 0x42, 0x7e, 0x42, 0x42, 0x42, 0x42, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x7c, 0x42, 0x42, 0x42, 0x7c, 0x42, 0x42, 0x42,
+ 0x42, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x42, 0x42, 0x40,
+ 0x40, 0x40, 0x40, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x78, 0x44, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x44, 0x78, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x7e, 0x40, 0x40, 0x40, 0x7c, 0x40, 0x40, 0x40,
+ 0x40, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x40, 0x40, 0x40,
+ 0x7c, 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x3c, 0x42, 0x42, 0x40, 0x40, 0x4e, 0x42, 0x42, 0x46, 0x3a, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x42, 0x42, 0x42, 0x42, 0x7e, 0x42, 0x42, 0x42,
+ 0x42, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x08, 0x08, 0x08,
+ 0x08, 0x08, 0x08, 0x08, 0x08, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x1f, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x44, 0x44, 0x38, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x42, 0x44, 0x48, 0x50, 0x60, 0x60, 0x50, 0x48,
+ 0x44, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x40, 0x40, 0x40,
+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x42, 0x42, 0x66, 0x66, 0x5a, 0x5a, 0x42, 0x42, 0x42, 0x42, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x42, 0x62, 0x62, 0x52, 0x52, 0x4a, 0x4a, 0x46,
+ 0x46, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x42, 0x42, 0x42,
+ 0x42, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x7c, 0x42, 0x42, 0x42, 0x7c, 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x3c, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x5a,
+ 0x66, 0x3c, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x42, 0x42, 0x42,
+ 0x7c, 0x48, 0x44, 0x44, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x3c, 0x42, 0x42, 0x40, 0x30, 0x0c, 0x02, 0x42, 0x42, 0x3c, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x7f, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
+ 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x42, 0x42, 0x42,
+ 0x42, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x41, 0x41, 0x41, 0x22, 0x22, 0x22, 0x14, 0x14, 0x08, 0x08, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x42, 0x42, 0x42, 0x42, 0x5a, 0x5a, 0x66, 0x66,
+ 0x42, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x42, 0x24, 0x24,
+ 0x18, 0x18, 0x24, 0x24, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x41, 0x41, 0x22, 0x22, 0x14, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x7e, 0x02, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40,
+ 0x40, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x08, 0x08, 0x08, 0x08,
+ 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x40, 0x40, 0x20, 0x10, 0x10, 0x08, 0x08, 0x04, 0x02, 0x02, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x70, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+ 0x10, 0x10, 0x70, 0x00, 0x00, 0x00, 0x18, 0x24, 0x42, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00,
+ 0x00, 0x20, 0x10, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x42,
+ 0x02, 0x3e, 0x42, 0x42, 0x46, 0x3a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x40, 0x40, 0x5c, 0x62, 0x42, 0x42, 0x42, 0x42, 0x62, 0x5c, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x42, 0x40, 0x40, 0x40, 0x40,
+ 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x3a, 0x46,
+ 0x42, 0x42, 0x42, 0x42, 0x46, 0x3a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x3c, 0x42, 0x42, 0x7e, 0x40, 0x40, 0x42, 0x3c, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x0c, 0x10, 0x10, 0x10, 0x7c, 0x10, 0x10, 0x10, 0x10,
+ 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x3a, 0x44,
+ 0x44, 0x44, 0x38, 0x20, 0x3c, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x40,
+ 0x40, 0x40, 0x5c, 0x62, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x08, 0x08, 0x00, 0x18, 0x08, 0x08, 0x08, 0x08, 0x08,
+ 0x08, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x04, 0x00, 0x0c, 0x04,
+ 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x48, 0x30, 0x00, 0x00, 0x00, 0x40,
+ 0x40, 0x40, 0x44, 0x48, 0x50, 0x60, 0x50, 0x48, 0x44, 0x42, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x18, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
+ 0x08, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0x49,
+ 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x5c, 0x62, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x42, 0x42, 0x42, 0x42, 0x42,
+ 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5c, 0x62,
+ 0x42, 0x42, 0x42, 0x42, 0x62, 0x5c, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x3a, 0x46, 0x42, 0x42, 0x42, 0x42, 0x46, 0x3a, 0x02, 0x02,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5c, 0x62, 0x42, 0x40, 0x40, 0x40,
+ 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x42,
+ 0x40, 0x30, 0x0c, 0x02, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x10, 0x10, 0x10, 0x7c, 0x10, 0x10, 0x10, 0x10, 0x10, 0x0c, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42,
+ 0x46, 0x3a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x42,
+ 0x42, 0x24, 0x24, 0x24, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x41, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x36, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x42, 0x24, 0x18, 0x18, 0x24,
+ 0x42, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x42,
+ 0x42, 0x42, 0x42, 0x26, 0x1a, 0x02, 0x02, 0x3c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x7e, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x7e, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x0c, 0x10, 0x10, 0x08, 0x08, 0x10, 0x20, 0x10, 0x08,
+ 0x08, 0x10, 0x10, 0x0c, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
+ 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x30,
+ 0x08, 0x08, 0x10, 0x10, 0x08, 0x04, 0x08, 0x10, 0x10, 0x08, 0x08, 0x30,
+ 0x00, 0x00, 0x00, 0x31, 0x49, 0x46, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x24,
+ 0x42, 0x42, 0x42, 0x42, 0x42, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x3c, 0x42, 0x42, 0x40, 0x40, 0x40, 0x40, 0x42, 0x42, 0x3c, 0x08, 0x30,
+ 0x00, 0x00, 0x24, 0x24, 0x00, 0x00, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42,
+ 0x46, 0x3a, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x30, 0x00, 0x00, 0x3c, 0x42,
+ 0x42, 0x7e, 0x40, 0x40, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x18, 0x24,
+ 0x00, 0x00, 0x3c, 0x42, 0x02, 0x3e, 0x42, 0x42, 0x46, 0x3a, 0x00, 0x00,
+ 0x00, 0x00, 0x24, 0x24, 0x00, 0x00, 0x3c, 0x42, 0x02, 0x3e, 0x42, 0x42,
+ 0x46, 0x3a, 0x00, 0x00, 0x00, 0x00, 0x30, 0x0c, 0x00, 0x00, 0x3c, 0x42,
+ 0x02, 0x3e, 0x42, 0x42, 0x46, 0x3a, 0x00, 0x00, 0x00, 0x18, 0x24, 0x18,
+ 0x00, 0x00, 0x3c, 0x42, 0x02, 0x3e, 0x42, 0x42, 0x46, 0x3a, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x42, 0x40, 0x40, 0x40, 0x40,
+ 0x42, 0x3c, 0x08, 0x30, 0x00, 0x00, 0x18, 0x24, 0x00, 0x00, 0x3c, 0x42,
+ 0x42, 0x7e, 0x40, 0x40, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x24, 0x24,
+ 0x00, 0x00, 0x3c, 0x42, 0x42, 0x7e, 0x40, 0x40, 0x42, 0x3c, 0x00, 0x00,
+ 0x00, 0x00, 0x30, 0x0c, 0x00, 0x00, 0x3c, 0x42, 0x42, 0x7e, 0x40, 0x40,
+ 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x24, 0x24, 0x00, 0x00, 0x18, 0x08,
+ 0x08, 0x08, 0x08, 0x08, 0x08, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x18, 0x24,
+ 0x00, 0x00, 0x18, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x3e, 0x00, 0x00,
+ 0x00, 0x00, 0x30, 0x0c, 0x00, 0x00, 0x18, 0x08, 0x08, 0x08, 0x08, 0x08,
+ 0x08, 0x3e, 0x00, 0x00, 0x24, 0x24, 0x00, 0x00, 0x18, 0x24, 0x24, 0x42,
+ 0x42, 0x7e, 0x42, 0x42, 0x42, 0x42, 0x00, 0x00, 0x18, 0x24, 0x18, 0x00,
+ 0x18, 0x24, 0x24, 0x42, 0x42, 0x7e, 0x42, 0x42, 0x42, 0x42, 0x00, 0x00,
+ 0x0c, 0x30, 0x00, 0x00, 0x7e, 0x40, 0x40, 0x40, 0x7c, 0x40, 0x40, 0x40,
+ 0x40, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x49,
+ 0x09, 0x3f, 0x48, 0x48, 0x49, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x1f, 0x28, 0x48, 0x48, 0x7f, 0x48, 0x48, 0x48, 0x48, 0x4f, 0x00, 0x00,
+ 0x00, 0x00, 0x18, 0x24, 0x00, 0x00, 0x3c, 0x42, 0x42, 0x42, 0x42, 0x42,
+ 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x24, 0x24, 0x00, 0x00, 0x3c, 0x42,
+ 0x42, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x30, 0x0c,
+ 0x00, 0x00, 0x3c, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00,
+ 0x00, 0x00, 0x18, 0x24, 0x00, 0x00, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42,
+ 0x46, 0x3a, 0x00, 0x00, 0x00, 0x00, 0x30, 0x0c, 0x00, 0x00, 0x42, 0x42,
+ 0x42, 0x42, 0x42, 0x42, 0x46, 0x3a, 0x00, 0x00, 0x00, 0x00, 0x24, 0x24,
+ 0x00, 0x00, 0x42, 0x42, 0x42, 0x42, 0x42, 0x26, 0x1a, 0x02, 0x02, 0x3c,
+ 0x24, 0x24, 0x00, 0x00, 0x3c, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42,
+ 0x42, 0x3c, 0x00, 0x00, 0x24, 0x24, 0x00, 0x00, 0x42, 0x42, 0x42, 0x42,
+ 0x42, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x08, 0x08, 0x3e, 0x49, 0x48, 0x48, 0x49, 0x3e, 0x08, 0x08, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x0e, 0x10, 0x10, 0x10, 0x7c, 0x10, 0x10, 0x10,
+ 0x3e, 0x61, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x22, 0x14, 0x08,
+ 0x7f, 0x08, 0x7f, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x68, 0x58, 0x5f, 0x5c, 0x6c, 0x4a, 0x49, 0x49, 0x49, 0x4e, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x0c, 0x10, 0x10, 0x10, 0x7c, 0x10, 0x10, 0x10, 0x10,
+ 0x10, 0x10, 0x60, 0x00, 0x00, 0x00, 0x0c, 0x30, 0x00, 0x00, 0x3c, 0x42,
+ 0x02, 0x3e, 0x42, 0x42, 0x46, 0x3a, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x30,
+ 0x00, 0x00, 0x18, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x3e, 0x00, 0x00,
+ 0x00, 0x00, 0x0c, 0x30, 0x00, 0x00, 0x3c, 0x42, 0x42, 0x42, 0x42, 0x42,
+ 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x30, 0x00, 0x00, 0x42, 0x42,
+ 0x42, 0x42, 0x42, 0x42, 0x46, 0x3a, 0x00, 0x00, 0x00, 0x00, 0x32, 0x4c,
+ 0x00, 0x00, 0x5c, 0x62, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x00, 0x00,
+ 0x32, 0x4c, 0x00, 0x00, 0x42, 0x62, 0x62, 0x52, 0x52, 0x4a, 0x4a, 0x46,
+ 0x46, 0x42, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x02, 0x1e, 0x22, 0x1e, 0x00,
+ 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x22,
+ 0x22, 0x22, 0x1c, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x00, 0x10, 0x10, 0x20, 0x40, 0x42,
+ 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x7e, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x02, 0x02, 0x02, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x22, 0x62, 0x24, 0x28, 0x28, 0x14, 0x1a, 0x22,
+ 0x44, 0x4e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22, 0x62, 0x24, 0x28,
+ 0x28, 0x12, 0x16, 0x2a, 0x4e, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x08, 0x08, 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x12, 0x24, 0x24, 0x48, 0x24, 0x24,
+ 0x12, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x48, 0x24,
+ 0x24, 0x12, 0x24, 0x24, 0x48, 0x48, 0x00, 0x00, 0x88, 0x22, 0x88, 0x22,
+ 0x88, 0x22, 0x88, 0x22, 0x88, 0x22, 0x88, 0x22, 0x88, 0x22, 0x88, 0x22,
+ 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55,
+ 0xaa, 0x55, 0xaa, 0x55, 0xee, 0xbb, 0xee, 0xbb, 0xee, 0xbb, 0xee, 0xbb,
+ 0xee, 0xbb, 0xee, 0xbb, 0xee, 0xbb, 0xee, 0xbb, 0x08, 0x08, 0x08, 0x08,
+ 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
+ 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0xf8, 0x08, 0x08, 0x08, 0x08,
+ 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0xf8, 0x08,
+ 0xf8, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x14, 0x14, 0x14, 0x14,
+ 0x14, 0x14, 0x14, 0xf4, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x14, 0x14, 0x14, 0x14,
+ 0x14, 0x14, 0x14, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x08,
+ 0xf8, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x14, 0x14, 0x14, 0x14,
+ 0x14, 0x14, 0xf4, 0x04, 0xf4, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14,
+ 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14,
+ 0x14, 0x14, 0x14, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x04,
+ 0xf4, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14,
+ 0x14, 0x14, 0xf4, 0x04, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0xfc, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0xf8, 0x08,
+ 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0xf8, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
+ 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x0f, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0xff,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0xff, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
+ 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x0f, 0x08, 0x08, 0x08, 0x08,
+ 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08,
+ 0x08, 0x08, 0x08, 0xff, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
+ 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x0f, 0x08, 0x0f, 0x08, 0x08, 0x08,
+ 0x08, 0x08, 0x08, 0x08, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x17,
+ 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14,
+ 0x14, 0x14, 0x17, 0x10, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x10, 0x17, 0x14, 0x14, 0x14,
+ 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0xf7, 0x00,
+ 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0xff, 0x00, 0xf7, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14,
+ 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x17, 0x10, 0x17, 0x14, 0x14, 0x14,
+ 0x14, 0x14, 0x14, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00,
+ 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x14, 0x14, 0x14,
+ 0x14, 0x14, 0xf7, 0x00, 0xf7, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14,
+ 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0xff,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0xff, 0x00, 0xff, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x14, 0x14, 0x14, 0x14,
+ 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x1f,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08,
+ 0x08, 0x08, 0x0f, 0x08, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x08, 0x0f, 0x08, 0x08, 0x08,
+ 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f,
+ 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14,
+ 0x14, 0x14, 0x14, 0xff, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14,
+ 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0xff, 0x08, 0xff, 0x08, 0x08, 0x08,
+ 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0xf8,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x0f, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0xf0, 0xf0, 0xf0,
+ 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0,
+ 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f,
+ 0x0f, 0x0f, 0x0f, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x32, 0x4a, 0x44, 0x44, 0x44, 0x44, 0x4a, 0x32, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x38, 0x44, 0x44, 0x48, 0x58, 0x44, 0x42, 0x42,
+ 0x52, 0x4c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x42, 0x40, 0x40,
+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x7e, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x7e, 0x40, 0x20, 0x10, 0x08, 0x08, 0x10, 0x20,
+ 0x40, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x48,
+ 0x44, 0x44, 0x44, 0x44, 0x44, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x66, 0x59, 0x40, 0x80,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x10, 0x10, 0x10, 0x10, 0x10,
+ 0x10, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x08, 0x3e, 0x49,
+ 0x49, 0x49, 0x49, 0x3e, 0x08, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x3c, 0x42, 0x42, 0x42, 0x5a, 0x5a, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x3e, 0x41, 0x41, 0x41, 0x41, 0x41, 0x22, 0x14,
+ 0x14, 0x77, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x20, 0x20, 0x20,
+ 0x18, 0x24, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x36, 0x49, 0x49, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x26, 0x49, 0x49, 0x49, 0x49, 0x49,
+ 0x49, 0x3e, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x42,
+ 0x40, 0x3c, 0x40, 0x40, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x3c, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x7e, 0x00, 0x7e,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x7f,
+ 0x08, 0x08, 0x08, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x60, 0x18, 0x06, 0x18, 0x60, 0x00, 0x7e, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x18, 0x60, 0x18, 0x06, 0x00,
+ 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x0a, 0x08, 0x08,
+ 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
+ 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x28, 0x30, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x7e, 0x00, 0x00,
+ 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x32,
+ 0x4c, 0x00, 0x32, 0x4c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x18, 0x24, 0x24, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x3c, 0x3c, 0x18,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x04,
+ 0x04, 0x04, 0x04, 0x04, 0x74, 0x14, 0x14, 0x0c, 0x0c, 0x04, 0x04, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x58, 0x64, 0x44, 0x44, 0x44, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x44, 0x04, 0x18, 0x20,
+ 0x40, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00
+};
+
+#define FONT_WIDTH 8
+#define FONT_HEIGHT 16
+
+namespace utils {
+
+ void flanterm::init() {
+ limine_framebuffer* fb0 = bootloader::bootloader->get_framebuffer();
+
+ if(fb0 == nullptr) {
+ is_disabled_flanterm = 1;
+ return;
+ }
+
+ struct flanterm_context *ft_ctx = flanterm_fb_init(
+ NULL,
+ NULL,
+ (uint32_t*)fb0->address, fb0->width, fb0->height, fb0->pitch,
+ fb0->red_mask_size, fb0->red_mask_shift,
+ fb0->green_mask_size, fb0->green_mask_shift,
+ fb0->blue_mask_size, fb0->blue_mask_shift,
+ NULL,
+ NULL, NULL,
+ &default_bg, &default_fg,
+ NULL, &default_bright_fg,
+ (void*)NULL, 0, 0, 0,
+ 1, 1, 0, 0
+ );
+ ft_ctx0 = ft_ctx;
+ const char* msg = "flanterm: Found usable framebuffer\r\n";
+ flanterm::write(msg,klibc::strlen(msg));
+ }
+
+ void flanterm::fullinit() {
+
+ limine_framebuffer* fb0 = bootloader::bootloader->get_framebuffer();
+
+ if(fb0 == nullptr) {
+ is_disabled_flanterm = 1;
+ return;
+ }
+
+
+ uint32_t* test_canvas = (uint32_t*)(pmm::buddy::alloc(fb0->pitch * fb0->height).phys + etc::hhdm());
+ if (!test_canvas) {
+ return;
+ }
+
+ int img_w, img_h, img_channels;
+ unsigned char* img_data = load_bmp_from_memory(bg_bmp, sizeof(bg_bmp), &img_w, &img_h, &img_channels);
+ if (!img_data) {
+ klibc::printf("error in stbi\n\r");
+ return;
+ }
+
+ unsigned char* scaled_rgb = (unsigned char*)(pmm::buddy::alloc(fb0->pitch * fb0->height * 3).phys + etc::hhdm());
+ if (!scaled_rgb) {
+ return;
+ }
+
+ scale_image_nn(img_data, img_w, img_h, scaled_rgb, fb0->width, fb0->height, 3);
+
+ for (std::size_t y = 0; y < fb0->height; y++) {
+ for (std::size_t x = 0; x < fb0->width; x++) {
+ int idx = (y * fb0->width + x) * 3;
+ uint8_t r = scaled_rgb[idx];
+ uint8_t g = scaled_rgb[idx + 1];
+ uint8_t b = scaled_rgb[idx + 2];
+ test_canvas[y * fb0->width + x] = rgb_to_pixel(r, g, b,
+ fb0->red_mask_size, fb0->red_mask_shift,
+ fb0->green_mask_size, fb0->green_mask_shift,
+ fb0->blue_mask_size, fb0->blue_mask_shift);
+ }
+ }
+
+ int margin = 64;
+
+ draw_transparent_black_square(test_canvas, fb0->width, fb0->height,
+ fb0->red_mask_size, fb0->red_mask_shift,
+ fb0->green_mask_size, fb0->green_mask_shift,
+ fb0->blue_mask_size, fb0->blue_mask_shift,
+ margin - 1);
+
+ flanterm_deinit(ft_ctx0, nullptr);
+
+ ft_ctx0 = flanterm_fb_init(
+ __flanterm_malloc, __flanterm_free,
+ (uint32_t*)fb0->address, fb0->width, fb0->height, fb0->pitch,
+ fb0->red_mask_size, fb0->red_mask_shift,
+ fb0->green_mask_size, fb0->green_mask_shift,
+ fb0->blue_mask_size, fb0->blue_mask_shift,
+ test_canvas,
+ NULL, NULL,
+ NULL, &default_fg,
+ NULL, &default_bright_fg,
+ (void*)unifont_arr, FONT_WIDTH, FONT_HEIGHT, 0,
+ 1, 1, margin,0
+ );
+
+ }
+
+ void flanterm::write(const char* buffer, std::size_t size) {
+ if(is_disabled_flanterm)
+ return;
+ for(std::size_t i = 0; i < size; i++) {
+ if(buffer[i] == '\n') {
+ flanterm_write(ft_ctx0,"\r",1);
+ }
+ flanterm_write(ft_ctx0,&buffer[i],1);
+ }
+ }
+
+}; \ No newline at end of file
diff --git a/kernel/src/utils/flanterm.hpp b/kernel/src/utils/flanterm.hpp
new file mode 100644
index 0000000..9f30b9d
--- /dev/null
+++ b/kernel/src/utils/flanterm.hpp
@@ -0,0 +1,11 @@
+#pragma once
+
+#include <cstdint>
+
+namespace utils {
+ namespace flanterm {
+ void init();
+ void fullinit();
+ void write(const char* buffer, std::size_t size);
+ };
+}; \ No newline at end of file
diff --git a/kernel/src/utils/gobject.hpp b/kernel/src/utils/gobject.hpp
new file mode 100644
index 0000000..18bbc57
--- /dev/null
+++ b/kernel/src/utils/gobject.hpp
@@ -0,0 +1,6 @@
+#pragma once
+#include <cstdint>
+
+namespace gobject {
+ inline std::uintptr_t kernel_root = 0;
+}; \ No newline at end of file
diff --git a/kernel/src/utils/hash/hash.hpp b/kernel/src/utils/hash/hash.hpp
new file mode 100644
index 0000000..340e3f0
--- /dev/null
+++ b/kernel/src/utils/hash/hash.hpp
@@ -0,0 +1,8 @@
+
+#include <cstdint>
+
+namespace utils {
+ namespace hash {
+
+ };
+}; \ No newline at end of file