diff options
Diffstat (limited to 'kernel/src')
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,¤t->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(¤t->current_sigset,¤t->temp_sigset,sizeof(sigset_t)); - current->is_restore_sigset = 0; - } - - sigtrace new_sigtrace; - - mcontext_t temp_mctx = {0}; - int_frame_to_mcontext(¤t->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, ¤t->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, ¤t->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 Binary files differnew file mode 100644 index 0000000..4709edd --- /dev/null +++ b/kernel/src/bg.bmp 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*)¤t->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*)¤t->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 |
