diff options
| author | cpplover0 <osdev555@yandex.com> | 2026-03-28 20:53:13 +0300 |
|---|---|---|
| committer | cpplover0 <osdev555@yandex.com> | 2026-03-28 20:53:13 +0300 |
| commit | be997311c240f49db247ccce05ecb8ea5d3bfc31 (patch) | |
| tree | e5a7e4e97d58eae7417fb71c68f99d81d1ee630c | |
| parent | a66cd5681ab96d66259275f04bbdd2b44fc1d7c4 (diff) | |
evdev support, vfs, tmpfs
40 files changed, 1517 insertions, 319 deletions
diff --git a/GNUmakefile b/GNUmakefile index 276807d..7748f12 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -144,7 +144,7 @@ edk2-ovmf: limine/limine: rm -rf limine - git clone https://codeberg.org/Limine/Limine.git limine --branch=v10.x-binary --depth=1 + git clone https://codeberg.org/Limine/Limine.git limine --branch=v11.x-binary --depth=1 $(MAKE) -C limine \ CC="$(HOST_CC)" \ CFLAGS="$(HOST_CFLAGS)" \ @@ -162,6 +162,7 @@ kernel: kernel/.deps-obtained $(IMAGE_NAME).iso: limine/limine kernel rm -rf iso_root mkdir -p iso_root/boot + cp -rf baseiso/* iso_root cp -v kernel/bin-$(ARCH)/kernel iso_root/boot/ mkdir -p iso_root/boot/limine cp -v limine.conf iso_root/boot/limine/ @@ -242,4 +243,4 @@ clean: .PHONY: distclean distclean: $(MAKE) -C kernel distclean - rm -rf iso_root *.iso *.hdd limine edk2-ovmf + rm -rf iso_root *.iso *.hdd limine edk2-ovmf
\ No newline at end of file diff --git a/baseiso/boot/OLI-D-T8.F16 b/baseiso/boot/OLI-D-T8.F16 Binary files differnew file mode 100644 index 0000000..2a00ea6 --- /dev/null +++ b/baseiso/boot/OLI-D-T8.F16 diff --git a/baseiso/boot/image.png b/baseiso/boot/image.png Binary files differnew file mode 100644 index 0000000..5821ed5 --- /dev/null +++ b/baseiso/boot/image.png diff --git a/kernel/get-deps b/kernel/get-deps index 503a9a6..4399ce3 100755 --- a/kernel/get-deps +++ b/kernel/get-deps @@ -49,7 +49,7 @@ clone_repo_commit \ clone_repo_commit \ https://codeberg.org/Limine/limine-protocol.git \ limine-protocol \ - 068b6481557db836e41bf644382367f8dee76d21 + 26519f1b598564db409e50d1d84eb30642d58ba3 clone_repo_commit \ https://codeberg.org/Mintsuki/Flanterm.git \ diff --git a/kernel/src/arch/x86_64/cpu/gdt.cpp b/kernel/src/arch/x86_64/cpu/gdt.cpp index 0498c21..f2adea1 100644 --- a/kernel/src/arch/x86_64/cpu/gdt.cpp +++ b/kernel/src/arch/x86_64/cpu/gdt.cpp @@ -47,6 +47,6 @@ void x86_64::gdt::init() { cpudata->timer_ist_stack = (std::uint64_t)(pmm::buddy::alloc(KERNEL_STACK_SIZE).phys + etc::hhdm()); static bool is_print = 0; - if(!is_print) { 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); is_print = 1; } + if(!is_print) { log("gdt", "tss->rsp0 0x%p tss->ist0 0x%p",tss->rsp[0],tss->ist[0],tss->ist[1],tss->ist[2],tss->ist[3],cpudata->timer_ist_stack); is_print = 1; } }
\ No newline at end of file diff --git a/kernel/src/arch/x86_64/cpu/idt.cpp b/kernel/src/arch/x86_64/cpu/idt.cpp index c62b1e6..def3341 100644 --- a/kernel/src/arch/x86_64/cpu/idt.cpp +++ b/kernel/src/arch/x86_64/cpu/idt.cpp @@ -43,7 +43,7 @@ void x86_64::idt::init() { load(); - if(!is_print) {klibc::printf("IDT: IDTR is 0x%p\r\n",&idtr); is_print = 1;} + if(!is_print) {log("idt", "idtr is 0x%p",&idtr); is_print = 1;} } void x86_64::idt::load() { diff --git a/kernel/src/arch/x86_64/cpu/lapic.cpp b/kernel/src/arch/x86_64/cpu/lapic.cpp index 3bea37c..da98bfd 100644 --- a/kernel/src/arch/x86_64/cpu/lapic.cpp +++ b/kernel/src/arch/x86_64/cpu/lapic.cpp @@ -32,7 +32,7 @@ std::uint64_t x86_64::lapic::init(std::uint32_t us) { if(c & (1 << 21)) { // x2apic present - if(!is_print) klibc::printf("X2APIC: Enabling x2apic (base is 0x%p)\r\n",0x800); + if(!is_print) log("x2apic", "enabling x2apic (base is 0x%p)",0x800); assembly::wrmsr(0x1B,assembly::rdmsr(0x1B) | (1 << 10) | (1 << 11)); is_x2apic = 1; } else { @@ -52,7 +52,7 @@ std::uint64_t x86_64::lapic::init(std::uint32_t us) { write(0x380,ticks); if(!is_lapic_init) { - if(!is_print) klibc::printf("LAPIC: Calibration time is %lli, ticks %lli\r\n",us,ticks); + if(!is_print) log("lapic", "calibration time is %lli, ticks %lli",us,ticks); is_print = 1; is_lapic_init = 1; } diff --git a/kernel/src/arch/x86_64/cpu/sse.cpp b/kernel/src/arch/x86_64/cpu/sse.cpp index 73d53ae..b71ed10 100644 --- a/kernel/src/arch/x86_64/cpu/sse.cpp +++ b/kernel/src/arch/x86_64/cpu/sse.cpp @@ -120,8 +120,8 @@ void x86_64::sse::print_sse_features() { std::uint32_t a,b,c,d; assembly::cpuid(1,0,&a,&b,&c,&d); - klibc::printf( - "SSE: Supported features:" "%s%s%s%s%s%s\n", + log( "sse", + "supported features:" "%s%s%s%s%s%s", (d & (1 << 25)) ? " SSE" : "\0", (d & (1 << 26)) ? " SSE2" : "\0", (c & (1 << 0)) ? " SSE3\0" : "\0", diff --git a/kernel/src/arch/x86_64/cpu_local.hpp b/kernel/src/arch/x86_64/cpu_local.hpp index d5add64..152e6fc 100644 --- a/kernel/src/arch/x86_64/cpu_local.hpp +++ b/kernel/src/arch/x86_64/cpu_local.hpp @@ -7,9 +7,11 @@ #include <generic/scheduling.hpp> #include <klibc/string.hpp> #include <klibc/stdio.hpp> +#include <cstddef> +#include <type_traits> #include <generic/arch.hpp> -typedef struct { +struct cpudata_t { std::uint64_t user_stack; std::uint64_t kernel_stack; std::uint64_t timer_ist_stack; @@ -17,7 +19,7 @@ typedef struct { std::uint64_t tsc_freq; void* pvclock_buffer; thread* current_thread; -} cpudata_t; +}; namespace x86_64 { @@ -45,4 +47,20 @@ namespace x86_64 { } return (cpudata_t*)cpudata; } + + template <typename T, std::size_t Offset> [[nodiscard]] static inline T cpu_local_read() { + T out; + asm volatile("mov %%gs:%c1, %0" : "=r"(out) : "i"(Offset)); + return out; + } + + template <typename T, std::size_t Offset, typename V> static inline void cpu_local_write(V&& value) { + static_assert(std::is_same_v<std::remove_cvref_t<V>, std::remove_cv_t<T>>, "member type and value type are not compatible"); + T v = static_cast<T>(value); + asm volatile("mov %0, %%gs:%c1" : : "r"(v), "i"(Offset)); + } + }; + +#define CPU_LOCAL_READ(field) x86_64::cpu_local_read<decltype(((cpudata_t*) nullptr)->field), offsetof(cpudata_t, field)>() +#define CPU_LOCAL_WRITE(field, value) x86_64::cpu_local_write<decltype(((cpudata_t*) nullptr)->field), offsetof(cpudata_t, field)>((value))
\ No newline at end of file diff --git a/kernel/src/arch/x86_64/drivers/hpet.cpp b/kernel/src/arch/x86_64/drivers/hpet.cpp index 152f0d9..5421157 100644 --- a/kernel/src/arch/x86_64/drivers/hpet.cpp +++ b/kernel/src/arch/x86_64/drivers/hpet.cpp @@ -23,7 +23,7 @@ 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); + log("hpet", "hpet is not detected with status %d",ret); return; } @@ -36,7 +36,7 @@ void drivers::hpet::init() { 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); + log("hpet", "Detected %s hpet, current timestamp in nano %lli (hpet_base 0x%p)",hpet_is_32_bit ? "32 bit" : "64 bit", new_hpet_inst->current_nano(),hpet_base); } namespace drivers { diff --git a/kernel/src/arch/x86_64/drivers/ioapic.cpp b/kernel/src/arch/x86_64/drivers/ioapic.cpp index 4b9c04a..ee5170f 100644 --- a/kernel/src/arch/x86_64/drivers/ioapic.cpp +++ b/kernel/src/arch/x86_64/drivers/ioapic.cpp @@ -41,13 +41,13 @@ void drivers::ioapic::init() { struct acpi_madt_ioapic* cur_ioapic = (acpi_madt_ioapic*)current; paging::map_range(gobject::kernel_root,cur_ioapic->address,cur_ioapic->address + etc::hhdm(),PAGE_SIZE,PAGING_PRESENT | PAGING_RW); apics[apic_ent++] = *cur_ioapic; - klibc::printf("IOAPIC: Found ioapic with gsi base %d, address 0x%p, id %d\r\n",cur_ioapic->gsi_base,cur_ioapic->address,cur_ioapic->id); + log("ioapic", "Found ioapic with gsi base %d, address 0x%p, id %d",cur_ioapic->gsi_base,cur_ioapic->address,cur_ioapic->id); 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; - klibc::printf("IOAPIC: Found ISO with bus %d, irq %d, gsi base %d, flags %d\r\n",cur_iso->bus,cur_iso->source,cur_iso->gsi,cur_iso->flags); + log("ioapic", "Found ISO with bus %d, irq %d, gsi base %d, flags %d",cur_iso->bus,cur_iso->source,cur_iso->gsi,cur_iso->flags); break; } } diff --git a/kernel/src/arch/x86_64/drivers/pvclock.cpp b/kernel/src/arch/x86_64/drivers/pvclock.cpp index d77ef0f..db19120 100644 --- a/kernel/src/arch/x86_64/drivers/pvclock.cpp +++ b/kernel/src/arch/x86_64/drivers/pvclock.cpp @@ -43,26 +43,42 @@ void drivers::pvclock::bsp_init() { drivers::pvclock_timer* timer = new drivers::pvclock_timer; time::setup_timer(timer); - klibc::printf("pvclock: pointer to buffer 0x%p\r\n",x86_64::cpu_data()->pvclock_buffer); + log("pvclock", "pointer to buffer 0x%p",x86_64::cpu_data()->pvclock_buffer); } namespace drivers { std::uint64_t pvclock_timer::current_nano() { - uint32_t lo, hi; - asm volatile ("rdtsc" : "=a"(lo), "=d"(hi)); - std::uint64_t tsc_v = ((uint64_t)hi << 32) | lo; - pvclock_vcpu_time_info* kvmclock_info = (pvclock_vcpu_time_info*)(x86_64::cpu_data()->pvclock_buffer); - std::uint64_t time0 = tsc_v - 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; + auto* info = (pvclock_vcpu_time_info*)CPU_LOCAL_READ(pvclock_buffer); + uint32_t version; + uint64_t time0; + + do { + version = info->version; + std::atomic_thread_fence(std::memory_order_acquire); + + uint32_t lo, hi; + asm volatile ("rdtsc" : "=a"(lo), "=d"(hi) : : "memory"); + uint64_t tsc_v = (static_cast<uint64_t>(hi) << 32) | lo; + + uint64_t delta = tsc_v - info->tsc_timestamp; + + if (info->tsc_shift >= 0) + delta <<= info->tsc_shift; + else + delta >>= -info->tsc_shift; + + uint64_t scaled_delta = (static_cast<unsigned __int128>(delta) * info->tsc_to_system_mul) >> 32; + + time0 = info->system_time + scaled_delta; + + std::atomic_thread_fence(std::memory_order_acquire); + } while ((info->version & 1) || (info->version != version)); + return time0; } + void pvclock_timer::sleep(std::uint64_t us) { std::uint64_t current = this->current_nano(); std::uint64_t end_ns = us * 1000; diff --git a/kernel/src/arch/x86_64/drivers/tsc.cpp b/kernel/src/arch/x86_64/drivers/tsc.cpp index 3776144..4203d76 100644 --- a/kernel/src/arch/x86_64/drivers/tsc.cpp +++ b/kernel/src/arch/x86_64/drivers/tsc.cpp @@ -17,7 +17,7 @@ static inline uint64_t rdtsc() { void drivers::tsc::init() { if(time::timer == nullptr) { - klibc::printf("TSC: Can't initialize without timer !\n"); + log("tsc", "can't initialize without timer !"); } uint64_t tsc_start, tsc_end; @@ -55,7 +55,7 @@ void drivers::tsc::init() { x86_64::cpu_data()->tsc_freq = tsc_freq; static bool is_print = 0; - if(!is_print) {klibc::printf("TSC: TSC Frequency is %llu\r\n", tsc_freq); is_print = 1;} + if(!is_print) {log("tsc", "tsc frequency is %llu", tsc_freq); is_print = 1;} drivers::tsc_timer* tsc_timer = new drivers::tsc_timer; time::setup_timer(tsc_timer); } diff --git a/kernel/src/arch/x86_64/schedule_timer.cpp b/kernel/src/arch/x86_64/schedule_timer.cpp index 97882c7..60bb649 100644 --- a/kernel/src/arch/x86_64/schedule_timer.cpp +++ b/kernel/src/arch/x86_64/schedule_timer.cpp @@ -35,12 +35,12 @@ void x86_64::schedule_timer::off() { std::uint32_t timeout = 10; - klibc::printf("Poweroff: Waiting for all cpus to done work\r\n"); // used from poweroff so + log("poweroff", "waiting for all cpus to done work"); // used from poweroff so while(stfu_cpus != (std::int32_t)(mp::cpu_count() - 1)) { arch::memory_barrier(); if(--timeout == 0) { - klibc::printf("Poweroff: Can't wait longer, forching them to be disabled\r\n"); + log("poweroff", "poweroff: Can't wait longer, forcing them to be disabled"); x86_64::lapic::off(); return; } diff --git a/kernel/src/bg.bmp b/kernel/src/bg.bmp Binary files differdeleted file mode 100644 index 9aa3900..0000000 --- a/kernel/src/bg.bmp +++ /dev/null diff --git a/kernel/src/drivers/disk.cpp b/kernel/src/drivers/disk.cpp index 36742f2..19142b9 100644 --- a/kernel/src/drivers/disk.cpp +++ b/kernel/src/drivers/disk.cpp @@ -173,7 +173,7 @@ void drivers::init_disk(disk* new_disk) { return; partition_style style = determine_disk_type(new_disk); - klibc::printf("Disk: Detected %s partition style\r\n", disk_type_to_str(style)); + log("disk", "detected %s partition style", disk_type_to_str(style)); switch (style) { diff --git a/kernel/src/drivers/ext2.cpp b/kernel/src/drivers/ext2.cpp index 34fdf32..74048f4 100644 --- a/kernel/src/drivers/ext2.cpp +++ b/kernel/src/drivers/ext2.cpp @@ -361,7 +361,7 @@ void ext2_free_blocks(ext2_partition* part, uint32_t count, uint64_t* blocks) { pmm::freelist::free((uint64_t)bitmap - etc::hhdm()); } -signed long ext2_read(file_descriptor* file, void* buffer, signed long count) { +signed long ext2_read(file_descriptor* file, void* buffer, std::size_t count) { if (count <= 0) return 0; file->vnode.fs->lock.lock(); @@ -387,7 +387,7 @@ signed long ext2_read(file_descriptor* file, void* buffer, signed long count) { std::uint32_t block_size = 1024 << part->sb->s_log_block_size; char* temp_block = (char*)(pmm::freelist::alloc_4k() + etc::hhdm()); - signed long total_read = 0; + std::size_t total_read = 0; char* out_ptr = (char*)buffer; while (total_read < count) { @@ -506,7 +506,7 @@ void ext2_write_inode(ext2_partition* part, uint64_t ino, ext2_inode* inode) { pmm::freelist::free((uint64_t)buf - etc::hhdm()); } -signed long ext2_write(file_descriptor* file, void* buffer, signed long count) { +signed long ext2_write(file_descriptor* file, void* buffer, std::size_t count) { if (count <= 0) return 0; file->vnode.fs->lock.lock(); @@ -515,7 +515,7 @@ signed long ext2_write(file_descriptor* file, void* buffer, signed long count) { uint32_t block_size = 1024 << part->sb->s_log_block_size; char* temp_block = (char*)(pmm::freelist::alloc_4k() + etc::hhdm()); - signed long total_written = 0; + std::size_t total_written = 0; const char* in_ptr = (const char*)buffer; bool inode_dirty = false; @@ -552,13 +552,17 @@ signed long ext2_write(file_descriptor* file, void* buffer, signed long count) { return total_written; } -std::uint32_t ext2_open(filesystem* fs, void* file_desc, char* path) { +std::uint32_t ext2_open(filesystem* fs, void* file_desc, char* path, bool is_directory) { fs->lock.lock(); ext2_inode res; std::uint64_t inode_num = 0; std::uint32_t status = ext2_lookup((ext2_partition*)(fs->fs_specific.partition), path, &res, &inode_num); if(status != 0) { fs->lock.unlock(); return status; } + + if(is_directory && !(res.i_mode & EXT2_S_IFDIR)) + return -ENOTDIR; + file_descriptor* fd = (file_descriptor*)file_desc; fd->fs_specific.ino = inode_num; fd->vnode.fs = fs; @@ -569,6 +573,7 @@ std::uint32_t ext2_open(filesystem* fs, void* file_desc, char* path) { } std::int32_t ext2_stat(file_descriptor* file, stat* out) { + file->vnode.fs->lock.lock(); std::int32_t status = 0; ext2_partition* part = (ext2_partition*)(file->vnode.fs->fs_specific.partition); ext2_inode inode = ext2_get_inode(part, file->fs_specific.ino, &status); @@ -593,7 +598,30 @@ std::int32_t ext2_stat(file_descriptor* file, stat* out) { out->st_rdev = 0; // should be filled by vfs out->st_nlink = inode.i_links_count; out->st_mode = inode.i_mode; + out->st_ino = file->fs_specific.ino; + file->vnode.fs->lock.unlock(); + return 0; +} + +std::int32_t ext2_readlink(filesystem* fs, char* path, char* buffer) { + fs->lock.lock(); + ext2_partition* part = (ext2_partition*)(fs->fs_specific.partition); + std::uint64_t inode = 0; + ext2_inode node = {}; + std::int32_t status = ext2_lookup(part, path, &node, &inode); + + if(status != 0) { fs->lock.unlock(); + return status; } + + if(!(node.i_mode & EXT2_S_IFLNK)) { fs->lock.unlock(); + return -EINVAL; } + + for(int i = 0;i < 4096 / (1024 << part->sb->s_log_block_size);i++) { + ext2_read_block(part, get_phys_block(part, &node, i), buffer); + } + + fs->lock.unlock(); return 0; } @@ -648,7 +676,7 @@ void drivers::ext2::init(disk* target_disk, std::uint64_t lba_start) { } if(sb->revision >= 1) { - klibc::printf("ext2: detected features %s %s %s\r\n",(sb->s_feature_ro_compat & EXT2_FEATURE_RO_COMPAT_LARGE_FILE) ? "EXT2_FEATURE_RO_COMPAT_LARGE_FILE" : "", (sb->s_feature_incompat & EXT4_FEATURE_INCOMPAT_64BIT) ? "EXT4_FEATURE_INCOMPAT_64BIT" : "", (sb->s_feature_incompat & EXT4_FEATURE_INCOMPAT_EXTENTS) ? "EXT4_FEATURE_INCOMPAT_EXTENTS" : ""); + log("ext2", "detected features %s %s %s",(sb->s_feature_ro_compat & EXT2_FEATURE_RO_COMPAT_LARGE_FILE) ? "EXT2_FEATURE_RO_COMPAT_LARGE_FILE" : "", (sb->s_feature_incompat & EXT4_FEATURE_INCOMPAT_64BIT) ? "EXT4_FEATURE_INCOMPAT_64BIT" : "", (sb->s_feature_incompat & EXT4_FEATURE_INCOMPAT_EXTENTS) ? "EXT4_FEATURE_INCOMPAT_EXTENTS" : ""); } uint32_t groups_count = (ext2_blocks_count(sb) + sb->s_blocks_per_group - 1); @@ -663,26 +691,28 @@ void drivers::ext2::init(disk* target_disk, std::uint64_t lba_start) { ext2_load_group_descriptors(part); - ext2_inode root = ext2_get_inode(part, 2); - klibc::printf("inode 2 size %lli links count %lli mode 0x%p block_size %lli\r\n",root.i_size, root.i_links_count, root.i_mode, 1024 << part->sb->s_log_block_size); - klibc::printf("logic blocks for root first block = %lli, second block = %lli\r\n", get_phys_block(part, &root, 0),get_phys_block(part, &root, 1)); (void)print_buffer; - char* buffer2 = (char*)(pmm::freelist::alloc_4k() + etc::hhdm()); - ext2_read_block(part, get_phys_block(part, &root, 0), buffer2); - klibc::printf("dumping first root block\r\n"); - print_buffer((const unsigned char*)buffer2, 1024 << part->sb->s_log_block_size); + // ext2_inode root = ext2_get_inode(part, 2); + // klibc::printf("inode 2 size %lli links count %lli mode 0x%p block_size %lli\r\n",root.i_size, root.i_links_count, root.i_mode, 1024 << part->sb->s_log_block_size); + // klibc::printf("logic blocks for root first block = %lli, second block = %lli\r\n", get_phys_block(part, &root, 0),get_phys_block(part, &root, 1)); + // (void)print_buffer; + + // char* buffer2 = (char*)(pmm::freelist::alloc_4k() + etc::hhdm()); + // ext2_read_block(part, get_phys_block(part, &root, 0), buffer2); + // klibc::printf("dumping first root block\r\n"); + // print_buffer((const unsigned char*)buffer2, 1024 << part->sb->s_log_block_size); - const char* file_test = "/test1/meow"; - ext2_inode res = {}; - std::uint64_t in = 0; - std::int32_t status = ext2_lookup(part, file_test, &res, &in); + // const char* file_test = "/test1/meow"; + // ext2_inode res = {}; + // std::uint64_t in = 0; + // std::int32_t status = ext2_lookup(part, file_test, &res, &in); - klibc::memset(buffer2, 0, PAGE_SIZE); - klibc::printf("reading file %s, status %d, size %lli\r\n", file_test, status, res.i_size); - ext2_read_block(part, get_phys_block(part, &res, 0), buffer2); - klibc::printf("%s\r\n", buffer2); + // klibc::memset(buffer2, 0, PAGE_SIZE); + // klibc::printf("reading file %s, status %d, size %lli\r\n", file_test, status, res.i_size); + // ext2_read_block(part, get_phys_block(part, &res, 0), buffer2); + // klibc::printf("%s\r\n", buffer2); - klibc::printf("group count %lli (size %lli)\r\n",groups_count,groups_count * sizeof(ext2_group_desc)); + // klibc::printf("group count %lli (size %lli)\r\n",groups_count,groups_count * sizeof(ext2_group_desc)); }
\ No newline at end of file diff --git a/kernel/src/drivers/ext2.hpp b/kernel/src/drivers/ext2.hpp index 4fdcd3c..2fee3fb 100644 --- a/kernel/src/drivers/ext2.hpp +++ b/kernel/src/drivers/ext2.hpp @@ -105,6 +105,10 @@ struct ext2_inode { uint32_t i_osd2[3]; }; +#define EXT2_S_IFMT 0xF000 +#define EXT2_S_IFLNK 0xA000 +#define EXT2_S_IFDIR 0040000 + struct ext2_dir_entry { uint32_t inode; uint16_t rec_len; diff --git a/kernel/src/drivers/mbr.hpp b/kernel/src/drivers/mbr.hpp index 4a78a95..6fb81a1 100644 --- a/kernel/src/drivers/mbr.hpp +++ b/kernel/src/drivers/mbr.hpp @@ -3,7 +3,7 @@ // mbr headers -#define MBR_ORANGE_TRACE +//#define MBR_ORANGE_TRACE struct __attribute__((packed)) mbr_partition { std::uint8_t drive_status; diff --git a/kernel/src/drivers/nvme.cpp b/kernel/src/drivers/nvme.cpp index 7ec7a21..cbec409 100644 --- a/kernel/src/drivers/nvme.cpp +++ b/kernel/src/drivers/nvme.cpp @@ -186,7 +186,7 @@ bool nvme_identify_namespace(struct nvme_controller* ctrl, uint32_t nsid) { } ns->valid = true; - klibc::printf("NVME: Detected namespace %d with lba_size %lli bytes and total size %lli bytes\r\n", nsid, ns->lba_size, ns->size * ns->lba_size); + log("nvme", "detected namespace %d with lba_size %lli bytes and total size %lli bytes", nsid, ns->lba_size, ns->size * ns->lba_size); return true; } @@ -438,7 +438,7 @@ bool nvme_identify(nvme_controller* ctrl) { char model[41]; klibc::memcpy(model, (void*)(phys_buffer + etc::hhdm() + 24), 40); model[40] = '\0'; - klibc::printf("NVME: Controller Model: %s\r\n", model); + log("nvme", "controller Model: %s", model); ctrl->identify = (void*)(phys_buffer + etc::hhdm()); @@ -505,7 +505,7 @@ void nvme_init(std::uint64_t base) { void nvme_pci_init(pci_t pci, std::uint8_t a, std::uint8_t b, std::uint8_t c) { if(pci.progIF == 2) { // nvme std::uint32_t cmd = x86_64::pci::pci_read_config32(a,b,c,0x4); - klibc::printf("NVME_PCI: Bus mastering %d, memory access %d\r\n",(cmd & (1 << 2)) ? 1 : 0, (cmd & (1 << 1)) ? 1 : 0); + log("nvme_pci", "bus mastering %d, memory access %d",(cmd & (1 << 2)) ? 1 : 0, (cmd & (1 << 1)) ? 1 : 0); cmd |= 1 << 2; cmd |= 1 << 1; x86_64::pci::pci_write_config32(a,b,c,0x4,cmd); diff --git a/kernel/src/drivers/powerbutton.cpp b/kernel/src/drivers/powerbutton.cpp index f34bdb9..a1ce3e4 100644 --- a/kernel/src/drivers/powerbutton.cpp +++ b/kernel/src/drivers/powerbutton.cpp @@ -16,7 +16,7 @@ void drivers::powerbutton::init() { UACPI_FIXED_EVENT_POWER_BUTTON, handle_power_button, UACPI_NULL ); - klibc::printf("PowerButton: Registered powerbutton at ip 0x%p\r\n",(std::uint64_t)handle_power_button); + log("powerbutton", "registered powerbutton at ip 0x%p",(std::uint64_t)handle_power_button); } #else diff --git a/kernel/src/drivers/uacpi_kernel_api.cpp b/kernel/src/drivers/uacpi_kernel_api.cpp index 1a4c5cb..ac8e4c4 100644 --- a/kernel/src/drivers/uacpi_kernel_api.cpp +++ b/kernel/src/drivers/uacpi_kernel_api.cpp @@ -36,7 +36,7 @@ void uacpi_kernel_unmap(void *addr, uacpi_size len) { } void uacpi_kernel_log(uacpi_log_level, const uacpi_char* msg) { - klibc::printf("uACPI: %s\r", msg); + klibc::printf("\033[1;31muacpi\033[0m: %s\r", msg); } uacpi_status uacpi_kernel_pci_device_open( diff --git a/kernel/src/generic/bootloader/bootloader.hpp b/kernel/src/generic/bootloader/bootloader.hpp index de9483e..ab9518f 100644 --- a/kernel/src/generic/bootloader/bootloader.hpp +++ b/kernel/src/generic/bootloader/bootloader.hpp @@ -14,6 +14,7 @@ namespace bootloader { virtual limine_memmap_response* get_memory_map() = 0; virtual limine_mp_response* get_mp_info() = 0; virtual bool is_5_level_paging() = 0; + virtual limine_flanterm_fb_init_params_response* get_flanterm() = 0; }; void init(); diff --git a/kernel/src/generic/bootloader/limine.cpp b/kernel/src/generic/bootloader/limine.cpp index 00a7859..e6a3c8a 100644 --- a/kernel/src/generic/bootloader/limine.cpp +++ b/kernel/src/generic/bootloader/limine.cpp @@ -6,7 +6,7 @@ namespace { __attribute__((used, section(".limine_requests"))) -volatile std::uint64_t limine_base_revision[] = LIMINE_BASE_REVISION(5); +volatile std::uint64_t limine_base_revision[] = LIMINE_BASE_REVISION(6); } @@ -31,6 +31,8 @@ __attribute__((used, section(".limine_requests"))) volatile limine_mp_request mp __attribute__((used, section(".limine_requests"))) volatile limine_rsdp_request rsdp_request = { .id = LIMINE_RSDP_REQUEST_ID, .revision = 0, .response = nullptr }; +__attribute__((used, section(".limine_requests"))) volatile limine_flanterm_fb_init_params_request flanterm = { .id = LIMINE_FLANTERM_FB_INIT_PARAMS_REQUEST_ID, .revision = 0, .response = nullptr }; + #if defined(__x86_64__) #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wmissing-field-initializers" @@ -79,6 +81,10 @@ namespace bootloader { return mp_request.response; } + limine_flanterm_fb_init_params_response* limine::get_flanterm() { + return flanterm.response; + } + #if defined(__x86_64__) bool limine::is_5_level_paging() { return _5lvl_paging.response->mode == LIMINE_PAGING_MODE_X86_64_5LVL ? true : false; diff --git a/kernel/src/generic/bootloader/limine.hpp b/kernel/src/generic/bootloader/limine.hpp index eac231d..bac22bd 100644 --- a/kernel/src/generic/bootloader/limine.hpp +++ b/kernel/src/generic/bootloader/limine.hpp @@ -12,5 +12,6 @@ public: limine_memmap_response* get_memory_map() override; limine_mp_response* get_mp_info() override; bool is_5_level_paging() override; + limine_flanterm_fb_init_params_response* get_flanterm() override; }; };
\ No newline at end of file diff --git a/kernel/src/generic/devfs.cpp b/kernel/src/generic/devfs.cpp new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/kernel/src/generic/devfs.cpp diff --git a/kernel/src/generic/devfs.hpp b/kernel/src/generic/devfs.hpp new file mode 100644 index 0000000..2c91d83 --- /dev/null +++ b/kernel/src/generic/devfs.hpp @@ -0,0 +1,13 @@ +#pragma once +#include <cstdint> +#include <generic/vfs.hpp> + +struct devfs_node { + vfs::pipe* pipe; +}; + +// for non input devices +namespace devfs { + void create(); + void init(vfs::node* new_node); +}
\ No newline at end of file diff --git a/kernel/src/generic/evdev.cpp b/kernel/src/generic/evdev.cpp new file mode 100644 index 0000000..b7bb4c1 --- /dev/null +++ b/kernel/src/generic/evdev.cpp @@ -0,0 +1,185 @@ +#include <cstdint> +#include <generic/evdev.hpp> +#include <generic/vfs.hpp> +#include <klibc/string.hpp> +#include <generic/lock/mutex.hpp> +#include <generic/pmm.hpp> +#include <generic/hhdm.hpp> +#include <utils/align.hpp> +#include <utils/errno.hpp> +#include <utils/assert.hpp> + +locks::mutex evdev_lock; +evdev::evdev_node evroot_node = {}; +evdev::evdev_node* evhead_node = nullptr; +std::uint32_t evdev_ptr = 0; + +evdev::evdev_node* evdev_lookup(char* path) { + evdev::evdev_node* current = evhead_node; + while(current) { + if(klibc::strcmp(current->name, path) == 0) { + return current; + } + } + return nullptr; +} + +int __bitmap_size(int c) { + return ALIGNUP(c,8) / 8; +} + +bool evdev_poll(file_descriptor* file, vfs_poll_type type) { + evdev::evdev_node* node = (evdev::evdev_node*)(file->fs_specific.tmpfs_pointer); + assert(node->main_ring, "say gex !!!11!11151"); + if(type == vfs_poll_type::pollin) { + return node->main_ring->is_not_empty(file->other.queue, file->other.cycle); + } else if(type == vfs_poll_type::pollout) { + return true; + } + return false; +} + +std::int32_t evdev_ioctl(file_descriptor* file, std::uint64_t req, void* arg) { + + evdev::evdev_node* node = (evdev::evdev_node*)(file->fs_specific.tmpfs_pointer); + + 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: + klibc::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): + klibc::memcpy(arg, node->name, size > (std::uint64_t)klibc::strlen(node->name) ? size : (std::uint64_t)klibc::strlen(node->name)); + return 0; + }; + } + + assert(0, "ioctl req 0x%p arg 0x%p path %s rev 0x%p",EVIOC_MASK_SIZE(req),arg,node->path,_IOC_NR(req) & EV_MAX); + return -EFAULT; +} + +signed long evdev_read(file_descriptor* file, void* buffer, std::size_t count) { + evdev::evdev_node* node = (evdev::evdev_node*)(file->fs_specific.tmpfs_pointer); + assert(node->main_ring,"FAFASF"); + + return node->main_ring->receive((input_event*)buffer, count, &file->other.cycle, &file->other.queue); +} + +void evdev::submit(int num, input_event event) { + evdev_lock.lock(); + evdev::evdev_node* node = evhead_node; + while(node) { + if(node->num == num) + break; + } + assert(node, "hlehlpehspgfdkjfs"); + assert(node->main_ring,"ffff"); + + node->main_ring->send(event); +} + +int evdev::create(char* name, int type) { + + evdev_lock.lock(); + evdev::evdev_node* new_node = (evdev::evdev_node*)(pmm::freelist::alloc_4k() + etc::hhdm()); + new_node->main_ring = new utils::ring_buffer<input_event>(256); + + if(type == EVDEV_TYPE_KEYBOARD) { + new_node->ev_bitmap = new utils::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 utils::bitmap(EV_MAX + 1); + new_node->ev_bitmap->set(EV_REL); + new_node->ev_bitmap->set(EV_SYN); + } + + new_node->num = ++evdev_ptr; + klibc::__printfbuf(new_node->path, 256, "/event%d\r\n",new_node->num); + klibc::memcpy(new_node->name, name, klibc::strlen(name)); + + new_node->type = type; + new_node->next = evhead_node; + evhead_node = new_node; + return new_node->num; +} + +std::int32_t evdev_readlink(filesystem* fs, char* path, char* buffer) { + (void)fs; + (void)path; + (void)buffer; + return -EINVAL; +} + +std::int32_t evdev_create(filesystem* fs, char* path, vfs_file_type type, std::uint32_t mode) { + (void)fs; + (void)path; + (void)type; + (void)mode; + return -ENOTSUP; +} + +signed long evdev_write(file_descriptor* file, void* buffer, std::size_t count) { + (void)file; + (void)buffer; + (void)count; + return -EACCES; +} + +std::int32_t evdev_stat(file_descriptor* file, stat* out) { + evdev::evdev_node* node = (evdev::evdev_node*)(file->fs_specific.tmpfs_pointer); + + klibc::memset(out, 0, sizeof(stat)); + + if(node->is_root) { + out->st_mode = S_IFDIR | 0666; + return 0; + } + + out->st_size = 0; + out->st_blksize = 0; + out->st_blocks = 0; + out->st_mode = S_IFCHR | 0666; + out->st_ino = node->num; + return 0; +} + +std::int32_t evdev_open(filesystem* fs, void* file_desc, char* path, bool is_directory) { + + file_descriptor* fd = (file_descriptor*)file_desc; + + if(klibc::strcmp(path, "/") == 0) { + fd->fs_specific.tmpfs_pointer = (std::uint64_t)&evroot_node; + return 0; + } + + evdev_lock.lock(); + + if(is_directory) + return -EISDIR; + + evdev::evdev_node* node = evdev_lookup(path); + fd->fs_specific.tmpfs_pointer = (std::uint64_t)node; + fd->vnode.read = evdev_read; + fd->vnode.ioctl = evdev_ioctl; + fd->vnode.write = evdev_write; + fd->vnode.stat = evdev_stat; + + evdev_lock.unlock(); + return 0; +} + +void evdev::init_default(vfs::node* node) { + evroot_node.is_root = true; + klibc::memcpy(node->path, "/dev/input/\0\0", sizeof("/dev/input/\0\0") + 1); + node->fs->readlink = evdev_readlink; + node->fs->open = evdev_open; + node->fs->create = evdev_create; + +}
\ No newline at end of file diff --git a/kernel/src/generic/evdev.hpp b/kernel/src/generic/evdev.hpp new file mode 100644 index 0000000..f10b268 --- /dev/null +++ b/kernel/src/generic/evdev.hpp @@ -0,0 +1,150 @@ +#pragma once + +#include <cstdint> +#include <atomic> +#include <utils/bitmap.hpp> +#include <utils/ringbuffer.hpp> +#include <generic/vfs.hpp> + +#define EVDEV_TYPE_MOUSE 1 +#define EVDEV_TYPE_KEYBOARD 2 + +struct evdevtimeval { + long long tv_sec; /* seconds */ + long long tv_usec; /* microseconds */ + +}; +struct input_event { + struct evdevtimeval time; +#define input_event_sec time.tv_sec +#define input_event_usec time.tv_usec + std::uint16_t type; + std::uint16_t code; + std::int32_t value; +}; + +#define BTN_MOUSE 0x110 +#define BTN_LEFT 0x110 +#define BTN_RIGHT 0x111 +#define BTN_MIDDLE 0x112 +#define BTN_SIDE 0x113 +#define BTN_EXTRA 0x114 +#define BTN_FORWARD 0x115 +#define BTN_BACK 0x116 +#define BTN_TASK 0x117 + +#define _IOC_NONE 0U +#define _IOC_WRITE 1U +#define _IOC_READ 2U + +#define _IOC_NRBITS 8 +#define _IOC_TYPEBITS 8 +#define _IOC_SIZEBITS 14 +#define _IOC_DIRBITS 2 +#define _IOC_NRMASK ((1 << _IOC_NRBITS) - 1) +#define _IOC_TYPEMASK ((1 << _IOC_TYPEBITS) - 1) +#define _IOC_SIZEMASK ((1 << _IOC_SIZEBITS) - 1) +#define _IOC_DIRMASK ((1 << _IOC_DIRBITS) - 1) +#define _IOC_NRSHIFT 0 +#define _IOC_TYPESHIFT (_IOC_NRSHIFT + _IOC_NRBITS) +#define _IOC_SIZESHIFT (_IOC_TYPESHIFT + _IOC_TYPEBITS) +#define _IOC_DIRSHIFT (_IOC_SIZESHIFT + _IOC_SIZEBITS) + +#define _IOC(dir, type, nr, size) \ + (((dir) << _IOC_DIRSHIFT) | \ + ((type) << _IOC_TYPESHIFT) | \ + ((nr) << _IOC_NRSHIFT) | \ + ((size) << _IOC_SIZESHIFT)) + +#define _IO(type, nr) _IOC(_IOC_NONE, (type), (nr), 0) +#define _IOR(type, nr, size) _IOC(_IOC_READ, (type), (nr), sizeof(size)) +#define _IOW(type, nr, size) _IOC(_IOC_WRITE, (type), (nr), sizeof(size)) +#define _IOWR(type, nr, size) _IOC(_IOC_READ | _IOC_WRITE, (type), (nr), sizeof(size)) + +#define _IOC_DIR(nr) (((nr) >> _IOC_DIRSHIFT) & _IOC_DIRMASK) +#define _IOC_TYPE(nr) (((nr) >> _IOC_TYPESHIFT) & _IOC_TYPEMASK) +#define _IOC_NR(nr) (((nr) >> _IOC_NRSHIFT) & _IOC_NRMASK) +#define _IOC_SIZE(nr) (((nr) >> _IOC_SIZESHIFT) & _IOC_SIZEMASK) + +#define EVIOC_MASK_SIZE(nr) ((nr) & ~(_IOC_SIZEMASK << _IOC_SIZESHIFT)) +#define EVIOCGVERSION _IOR('E', 0x01, int) +#define EVIOCGID _IOR('E', 0x02, struct input_id) +#define EVIOCGREP _IOR('E', 0x03, int[2]) +#define EVIOCSREP _IOW('E', 0x03, int[2]) +#define EVIOCGKEYCODE _IOR('E', 0x04, int[2]) +#define EVIOCSKEYCODE _IOW('E', 0x04, int[2]) +#define EVIOCGNAME(len) _IOC(_IOC_READ, 'E', 0x06, len) +#define EVIOCGPHYS(len) _IOC(_IOC_READ, 'E', 0x07, len) +#define EVIOCGUNIQ(len) _IOC(_IOC_READ, 'E', 0x08, len) +#define EVIOCGPROP(len) _IOC(_IOC_READ, 'E', 0x09, len) +#define EVIOCGMTSLOTS(len) _IOC(_IOC_READ, 'E', 0x0a, len) +#define EVIOCGKEY(len) _IOC(_IOC_READ, 'E', 0x18, len) +#define EVIOCGLED(len) _IOC(_IOC_READ, 'E', 0x19, len) +#define EVIOCGSND(len) _IOC(_IOC_READ, 'E', 0x1a, len) +#define EVIOCGSW(len) _IOC(_IOC_READ, 'E', 0x1b, len) +#define EVIOCGBIT(ev, len) _IOC(_IOC_READ, 'E', 0x20 + (ev), len) +#define EVIOCGABS(abs) _IOR('E', 0x40 + (abs), struct input_absinfo) +#define EVIOCSABS(abs) _IOW('E', 0x40 + (abs), struct input_absinfo) +#define EVIOCSFF _IOC(_IOC_WRITE, 'E', 0x80, sizeof(struct ff_effect)) +#define EVIOCRMFF _IOW('E', 0x81, int) +#define EVIOCGEFFECTS _IOR('E', 0x84, int) +#define EVIOCGRAB _IOW('E', 0x90, int) +#define EVIOCREVOKE _IOW('E', 0x91, int) +#define EVIOCSMASK _IOW('E', 0x92, struct input_mask) +#define EV_MAX 0x1f +#define KEY_MAX 0x2ff +#define REL_MAX 0x0f +#define ABS_MAX 0x3f +#define MSC_MAX 0x07 +#define LED_MAX 0x0f +#define SND_MAX 0x07 +#define FF_MAX 0x7f +#define SW_MAX 0x0f + +#define EV_SYN 0x00 +#define EV_KEY 0x01 +#define EV_REL 0x02 +#define EV_ABS 0x03 +#define EV_MSC 0x04 +#define EV_SW 0x05 +#define EV_LED 0x11 +#define EV_SND 0x12 +#define EV_REP 0x14 +#define EV_FF 0x15 +#define EV_PWR 0x16 +#define EV_FF_STATUS 0x17 +#define EV_MAX 0x1f +#define EV_CNT (EV_MAX+1) + +#define BTN_MOUSE 0x110 +#define BTN_LEFT 0x110 +#define BTN_RIGHT 0x111 +#define BTN_MIDDLE 0x112 +#define BTN_SIDE 0x113 +#define BTN_EXTRA 0x114 +#define BTN_FORWARD 0x115 +#define BTN_BACK 0x116 +#define BTN_TASK 0x117 + +namespace evdev { + struct evdev_node { + int num; + int type; + bool is_root; + + utils::bitmap* ev_bitmap; + utils::ring_buffer<input_event>* main_ring; + + char path[64]; + char name[2048]; + + evdev_node* next; + }; + + static_assert(sizeof(evdev_node) < 4096, "stuf"); + + int create(char* name, int type); + void submit(int num, input_event event); + void init_default(vfs::node* node); + +}
\ No newline at end of file diff --git a/kernel/src/generic/poweroff.cpp b/kernel/src/generic/poweroff.cpp index d81b3df..f9643f3 100644 --- a/kernel/src/generic/poweroff.cpp +++ b/kernel/src/generic/poweroff.cpp @@ -13,19 +13,19 @@ void poweroff::prepare_for_shutdown() { drivers::nvme::disable(); - klibc::printf("Poweroff: NVME is disabled\r\n"); + log("poweroff", "NVME is disabled"); #if defined(__x86_64__) x86_64::schedule_timer::off(); #endif locks::is_disabled = true; - klibc::printf("Poweroff: Preparing for shutdown is successful\r\n"); + log("poweroff", "preparing for shutdown is successful"); } void poweroff::off() { arch::disable_interrupts(); prepare_for_shutdown(); if(time::timer) { - klibc::printf("Poweroff: Shutdowning after 3 seconds\r\n"); + log("poweroff", "shutdowning after 3 seconds"); time::timer->sleep(3 * (1000 * 1000)); } #if defined(__x86_64__) @@ -40,7 +40,7 @@ void poweroff::reboot() { arch::disable_interrupts(); prepare_for_shutdown(); if(time::timer) { - klibc::printf("Poweroff: Rebooting after 3 seconds\r\n"); + log("poweroff","rebooting after 3 seconds"); time::timer->sleep(3 * (1000 * 1000)); } #if defined(__x86_64__) diff --git a/kernel/src/generic/tmpfs.cpp b/kernel/src/generic/tmpfs.cpp new file mode 100644 index 0000000..650fda3 --- /dev/null +++ b/kernel/src/generic/tmpfs.cpp @@ -0,0 +1,306 @@ +#include <cstdint> +#include <generic/tmpfs.hpp> +#include <generic/pmm.hpp> +#include <generic/hhdm.hpp> +#include <generic/vfs.hpp> +#include <klibc/string.hpp> +#include <utils/errno.hpp> +#include <utils/assert.hpp> +#include <atomic> + +tmpfs::tmpfs_node root_node = {}; +std::atomic<std::uint64_t> tmpfs_id_ptr = 1; + +bool tmpfs_find_child(tmpfs::tmpfs_node* node, char* name, tmpfs::tmpfs_node** out) { + if(node->type != vfs_file_type::directory) + return false; + + for(std::uint64_t i = 0;i < node->size / sizeof(std::uint64_t);i++ ) { + + if(node->directory_content[i] == nullptr) + continue; + + if(klibc::strcmp(node->directory_content[i]->name, name) == 0) { + *out = node->directory_content[i]; + return true; + } + } + + return false; +} + +tmpfs::tmpfs_node* tmpfs_lookup(char* path) { + if(klibc::strcmp(path,"/\0") == 0) + return &root_node; + + tmpfs::tmpfs_node* current_node = &root_node; + + char path_copy[4096]; + klibc::memcpy(path_copy, path, klibc::strlen(path) + 1); + + char* saveptr; + char* token = klibc::strtok(&saveptr, path_copy, "/"); + + while (token != nullptr) { + bool status = tmpfs_find_child(current_node, token, ¤t_node); + if(status == false) + return nullptr; + token = klibc::strtok(&saveptr, nullptr, "/"); + } + return current_node; +} + +tmpfs::tmpfs_node* tmpfs_get_parent(char* path) { + if (klibc::strcmp(path, "/") == 0 || klibc::strlen(path) == 0) { + return nullptr; + } + + char path_copy[4096]; + klibc::memcpy(path_copy, path, klibc::strlen(path) + 1); + + char* last_slash = nullptr; + for (int i = 0; path_copy[i] != '\0'; i++) { + if (path_copy[i] == '/') { + last_slash = &path_copy[i]; + } + } + + if (last_slash == nullptr) + return &root_node; + + if (last_slash == path_copy) + return &root_node; + + *last_slash = '\0'; + return tmpfs_lookup(path_copy); +} + +char* tmpfs_get_name_from_path(char* path) { + if (path[0] == '\0') return path; + if (klibc::strcmp(path, "/") == 0) return path; + + char* last_slash = nullptr; + int i = 0; + + while (path[i] != '\0') { + if (path[i] == '/') { + last_slash = &path[i]; + } + i++; + } + + if (last_slash == nullptr) + return path; + + return last_slash + 1; +} + +std::int32_t tmpfs_readlink(filesystem* fs, char* path, char* buffer) { + fs->lock.lock(); + tmpfs::tmpfs_node* node = tmpfs_lookup(path); + if(node == nullptr) { fs->lock.unlock(); + return -ENOENT; } + + if(node->type != vfs_file_type::symlink) { fs->lock.unlock(); + return -EINVAL; } + + assert(node->content,"meeeow meeeeeow :3"); + + klibc::memcpy(buffer, node->content, 4096); + + fs->lock.unlock(); + return 0; +} + +signed long tmpfs_ls(file_descriptor* file, char* out, std::size_t count) { + file->vnode.fs->lock.lock(); + auto node = (tmpfs::tmpfs_node*)file->fs_specific.tmpfs_pointer; + + std::size_t current_offset = 0; + dirent file_ls = {}; + + if(node->type != vfs_file_type::directory) + return -ENOTDIR; + +again: + + if(file->offset >= node->size) { + file->vnode.fs->lock.unlock(); + return 0; + } + + while(true) { + auto current_node = node->directory_content[file->offset]; + if(sizeof(dirent) + klibc::strlen(current_node->name) + 1 > count - current_offset) { + file->vnode.fs->lock.unlock(); + return current_offset; + } + + file->offset += sizeof(tmpfs::tmpfs_node**); + + if(current_node == nullptr) + goto again; + + dirent* current_dir = (dirent*)(out + current_offset); + current_dir->d_ino = current_node->ino; + current_dir->d_type = vfs_to_dt_type(current_node->type); + current_dir->d_reclen = sizeof(dirent) + klibc::strlen(current_node->name) + 1; + current_dir->d_off = 0; + current_offset += current_dir->d_reclen; + + } + + file->vnode.fs->lock.unlock(); + return 0; +} + +std::int32_t tmpfs_create(filesystem* fs, char* path, vfs_file_type type, std::uint32_t mode) { + fs->lock.lock(); + tmpfs::tmpfs_node* parent = tmpfs_get_parent(path); + + if(parent == nullptr) { fs->lock.unlock(); + return -ENOENT; } + + parent->size += sizeof(tmpfs::tmpfs_node*); + + if(parent->physical_size < parent->size) { + alloc_t res = pmm::buddy::alloc(parent->size * sizeof(tmpfs::tmpfs_node*)); + tmpfs::tmpfs_node** new_dir = (tmpfs::tmpfs_node**)(res.phys + etc::hhdm()); + klibc::memcpy(new_dir, parent->directory_content, parent->size); + pmm::buddy::free((std::uint64_t)parent->directory_content - etc::hhdm()); + parent->directory_content = new_dir; + parent->physical_size = res.real_size; + } + + tmpfs::tmpfs_node* new_node = (tmpfs::tmpfs_node*)(pmm::freelist::alloc_4k() + etc::hhdm()); + + new_node->type = type; + new_node->ino = tmpfs_id_ptr++; + new_node->mode = mode; + klibc::memcpy(new_node->name, tmpfs_get_name_from_path(path), klibc::strlen(tmpfs_get_name_from_path(path)) + 1); + + parent->directory_content[(parent->size / sizeof(tmpfs::tmpfs_node**)) - 1] = new_node; + + fs->lock.unlock(); + return 0; +} + +signed long tmpfs_read(file_descriptor* file, void* buffer, std::size_t count) { + file->vnode.fs->lock.lock(); + tmpfs::tmpfs_node* node = (tmpfs::tmpfs_node*)(file->fs_specific.tmpfs_pointer); + if(node->type == vfs_file_type::directory) { file->vnode.fs->lock.unlock(); + return -EISDIR; } + + if(file->offset >= node->size || node->content == nullptr) { + file->vnode.fs->lock.unlock(); + return 0; + } + + std::size_t available = node->size - file->offset; + std::size_t to_read = (count > available) ? available : count; + klibc::memcpy(buffer, node->content + file->offset, to_read); + file->offset += to_read; + + file->vnode.fs->lock.unlock(); + return to_read; +} + +signed long tmpfs_write(file_descriptor* file, void* buffer, std::size_t count) { + file->vnode.fs->lock.lock(); + tmpfs::tmpfs_node* node = (tmpfs::tmpfs_node*)(file->fs_specific.tmpfs_pointer); + if(node->type == vfs_file_type::directory) { file->vnode.fs->lock.unlock(); + return -EISDIR; } + + if(file->offset + count > node->physical_size || node->content == nullptr) { + alloc_t new_content = pmm::buddy::alloc(file->offset + count); + char* new_cont = (char*)(new_content.phys + etc::hhdm()); + if(node->content) { + klibc::memcpy(new_cont, node->content, node->size); + pmm::buddy::free((std::uint64_t)node->content - etc::hhdm()); + } + node->content = new_cont; + node->physical_size = new_content.real_size; + } + + if(file->offset + count > node->size) + node->size = file->offset + count; + + klibc::memcpy(node->content + file->offset, buffer, count); + + file->offset += count; + file->vnode.fs->lock.unlock(); + return count; +} + +inline static std::int32_t type_to_mode(vfs_file_type type) { + switch (type) + { + + case vfs_file_type::directory: + return S_IFDIR; + + case vfs_file_type::file: + return S_IFREG; + + case vfs_file_type::symlink: + return S_IFLNK; + + default: + assert(0,"say gex"); + } +} + +std::int32_t tmpfs_stat(file_descriptor* file, stat* out) { + file->vnode.fs->lock.lock(); + tmpfs::tmpfs_node* node = (tmpfs::tmpfs_node*)file->fs_specific.tmpfs_pointer; + out->st_gid = 0; + out->st_uid = 0; + out->st_rdev = 0; + out->st_blksize = PAGE_SIZE; + out->st_blocks = node->physical_size / PAGE_SIZE; + out->st_mode = type_to_mode(node->type) | node->mode; + out->st_size = node->size; + out->st_ino = node->ino; + file->vnode.fs->lock.unlock(); + return 0; +} + +std::int32_t tmpfs_open(filesystem* fs, void* file_desc, char* path, bool is_directory) { + fs->lock.lock(); + tmpfs::tmpfs_node* node = tmpfs_lookup(path); + if(node == nullptr) { fs->lock.unlock(); + return -ENOENT; } + + if(is_directory && node->type != vfs_file_type::directory) { fs->lock.unlock(); + return -ENOTDIR; } + + file_descriptor* fd = (file_descriptor*)file_desc; + + fd->vnode.fs = fs; + fd->vnode.stat = tmpfs_stat; + fd->vnode.read = tmpfs_read; + fd->vnode.write = tmpfs_write; + fd->vnode.ls = tmpfs_ls; + fd->fs_specific.tmpfs_pointer = (std::uint64_t)node; + + fs->lock.unlock(); + return 0; +} + +void tmpfs::init_default(vfs::node* node) { + filesystem* new_fs = new filesystem; + node->fs = new_fs; + node->fs->open = tmpfs_open; + node->fs->create = tmpfs_create; + node->fs->readlink = tmpfs_readlink; + klibc::memcpy(node->path, "/tmp/\0\0", sizeof("/tmp/\0\0") + 1); + + alloc_t root_alloc = pmm::buddy::alloc(PAGE_SIZE); + + root_node.size = 0; + root_node.physical_size = root_alloc.real_size; + klibc::memcpy(root_node.name, "/\0", sizeof("/\0") + 1); + root_node.directory_content = (tmpfs::tmpfs_node**)(root_alloc.phys + etc::hhdm()); + log("tmpfs", "root_node is 0x%p",&root_node); + +}
\ No newline at end of file diff --git a/kernel/src/generic/tmpfs.hpp b/kernel/src/generic/tmpfs.hpp new file mode 100644 index 0000000..86d9f13 --- /dev/null +++ b/kernel/src/generic/tmpfs.hpp @@ -0,0 +1,21 @@ +#pragma once +#include <cstdint> +#include <generic/vfs.hpp> + +namespace tmpfs { + + struct tmpfs_node { + union { + char* content; + tmpfs_node** directory_content; + }; + vfs_file_type type; + std::size_t size; + std::size_t physical_size; + std::uint64_t ino; + std::uint64_t mode; + char name[256]; + }; + + void init_default(vfs::node* node); +}
\ No newline at end of file diff --git a/kernel/src/generic/vfs.cpp b/kernel/src/generic/vfs.cpp index 75c3ed8..296f72c 100644 --- a/kernel/src/generic/vfs.cpp +++ b/kernel/src/generic/vfs.cpp @@ -5,6 +5,8 @@ #include <utils/errno.hpp> #include <klibc/stdio.hpp> #include <generic/lock/mutex.hpp> +#include <utils/assert.hpp> +#include <generic/tmpfs.hpp> // /bin/path -> /usr/bin/path void __vfs_symlink_resolve_no_at_symlink_follow(char* path, char* out) { @@ -13,15 +15,15 @@ void __vfs_symlink_resolve_no_at_symlink_follow(char* path, char* out) { int e = vfs::readlink(path,buffer,4096); - if(e == ENOSYS) + if(e == -ENOSYS) klibc::memcpy(out,path,klibc::strlen(path) + 1); - if(e == EINVAL) + if(e == -EINVAL) klibc::memcpy(out,path,klibc::strlen(path) + 1); else if(e == 0) { klibc::memcpy(out,path,klibc::strlen(path) + 1); - } else if(e == ENOENT) { + } else if(e == -ENOENT) { klibc::memcpy(out,path,klibc::strlen(path) + 1); // maybe it wants directory symlink ? char path0[4096]; @@ -54,7 +56,7 @@ void __vfs_symlink_resolve_no_at_symlink_follow(char* path, char* out) { klibc::memcpy(buffer2 + c, path + klibc::strlen(result) + 1, klibc::strlen(path) - klibc::strlen(result)); __vfs_symlink_resolve_no_at_symlink_follow(buffer2,out); return; - } else if(e == ENOENT) { + } else if(e == -ENOENT) { klibc::memcpy(out,path,klibc::strlen(path) + 1); } @@ -78,17 +80,17 @@ void __vfs_symlink_resolve(char* path, char* out, int level) { int e = vfs::readlink(path,buffer,4096); - if(e == ENOSYS) + if(e == -ENOSYS) klibc::memcpy(out,path,klibc::strlen(path) + 1); - if(e == EINVAL) + if(e == -EINVAL) klibc::memcpy(out,path,klibc::strlen(path) + 1); else if(e == 0) { char result[4096]; vfs::resolve_path(buffer,path,result,0); __vfs_symlink_resolve(result,out, level + 1); - } else if(e == ENOENT) { + } else if(e == -ENOENT) { klibc::memcpy(out,path,klibc::strlen(path) + 1); // maybe it wants directory symlink ? char path0[4096]; @@ -121,7 +123,7 @@ void __vfs_symlink_resolve(char* path, char* out, int level) { klibc::memcpy(buffer2 + c, path + klibc::strlen(result) + 1, klibc::strlen(path) - klibc::strlen(result)); __vfs_symlink_resolve(buffer2,out, level + 1); return; - } else if(e == ENOENT) { + } else if(e == -ENOENT) { klibc::memcpy(out,path,klibc::strlen(path) + 1); return; } else { @@ -135,7 +137,134 @@ void __vfs_symlink_resolve(char* path, char* out, int level) { } } +vfs::node vfs_nodes[512]; -void vfs::init() { + +vfs::node* find_node(char* path) { + int r = 0; + vfs::node* match; + for(int i = 0;i < 512;i++) { + if(!klibc::strncmp(path,vfs_nodes[i].path,klibc::strlen(vfs_nodes[i].path))) { + if(klibc::strlen(vfs_nodes[i].path) > r) { + match = &vfs_nodes[i]; + } + } + + if(!klibc::strncmp(path, vfs_nodes[i].path,klibc::strlen(vfs_nodes[i].path) - 1) && path[klibc::strlen(vfs_nodes[i].path) + 1] == '\0') { + return &vfs_nodes[i]; + } + + } + return match; +} + +std::int32_t vfs::open(file_descriptor* fd, char* path, bool follow_symlinks, bool is_directory) { + char out[4096]; + klibc::memset(out,0,4096); + + node* node = find_node(out); + + if(follow_symlinks) { + __vfs_symlink_resolve(path, out, 0); + } else { + __vfs_symlink_resolve_no_at_symlink_follow(path, out); + } + + if(!node) { + return -ENOENT; } + + char* fs_love_name = out + klibc::strlen(node->path) - 1; + if(!node->fs->open) { assert(0, "meow :3"); + return -ENOSYS; } + + if(fs_love_name[0] == '\0') { + fs_love_name[0] = '/'; + fs_love_name[1] = '\0'; + } + + std::int32_t status = node->fs->open(node->fs, (void*)fd, fs_love_name, is_directory); + return status; +} + +std::int32_t vfs::create(char* path, vfs_file_type type, std::uint32_t mode) { + char out[4096]; + klibc::memset(out,0,4096); + + node* node = find_node(out); + + __vfs_symlink_resolve_no_at_symlink_follow(path, out); + + if(!node) { + return -ENOENT; } + + char* fs_love_name = out + klibc::strlen(node->path) - 1; + if(!node->fs->create) { assert(0, "meow :3"); + return -ENOSYS; } + + if(fs_love_name[0] == '\0') { + fs_love_name[0] = '/'; + fs_love_name[1] = '\0'; + } + + std::int32_t status = node->fs->create(node->fs, fs_love_name, type, mode); + return status; +} + +std::int32_t vfs::readlink(char* path, char* out, std::uint32_t out_len) { + + assert(out_len == 4096, "stfu"); + + char outp[4096]; + klibc::memset(outp,0,4096); + + node* node = find_node(outp); + + klibc::memcpy(outp, path, klibc::strlen(path) + 1); + + if(!node) { + return -ENOENT; } + char* fs_love_name = outp + klibc::strlen(node->path) - 1; + if(!node->fs->readlink) { assert(0, "meow :3"); + return -ENOSYS; } + + if(fs_love_name[0] == '\0') { + fs_love_name[0] = '/'; + fs_love_name[1] = '\0'; + } + + std::int32_t status = node->fs->readlink(node->fs, fs_love_name, out); + return status; +} + +std::int32_t vfs::remove(char* path) { + char out[4096]; + klibc::memset(out,0,4096); + + node* node = find_node(out); + + __vfs_symlink_resolve_no_at_symlink_follow(path, out); + + if(!node) { + return -ENOENT; } + + char* fs_love_name = out + klibc::strlen(node->path) - 1; + if(!node->fs->remove) { assert(0, "meow remove :3"); + return -ENOSYS; } + + if(fs_love_name[0] == '\0') { + fs_love_name[0] = '/'; + fs_love_name[1] = '\0'; + } + + std::int32_t status = node->fs->remove(node->fs, fs_love_name); + return status; +} + +// will init default environment + +void vfs::init() { + klibc::memset(vfs_nodes, 0, sizeof(vfs_nodes)); + tmpfs::init_default(&vfs_nodes[0]); + log("vfs", "vfs_nodes 0x%p",vfs_nodes); }
\ No newline at end of file diff --git a/kernel/src/generic/vfs.hpp b/kernel/src/generic/vfs.hpp index d6fac32..ecfd25b 100644 --- a/kernel/src/generic/vfs.hpp +++ b/kernel/src/generic/vfs.hpp @@ -3,6 +3,144 @@ #include <drivers/disk.hpp> #include <generic/lock/mutex.hpp> #include <utils/linux.hpp> +#include <utils/assert.hpp> +#include <generic/scheduling.hpp> + +#define USERSPACE_PIPE_SIZE (64 * 1024) +#define S_IFSOCK 0140000 +#define S_IFLNK 0120000 +#define S_IFREG 0100000 +#define S_IFBLK 0060000 +#define S_IFDIR 0040000 +#define S_IFCHR 0020000 +#define S_IFIFO 0010000 +#define DT_UNKNOWN 0 +#define DT_FIFO 1 +#define DT_CHR 2 +#define DT_DIR 4 +#define DT_BLK 6 +#define DT_REG 8 +#define DT_LNK 10 +#define DT_SOCK 12 +#define DT_WHT 14 + +#define CS8 0000060 +#define ECHO 0000010 /* Enable echo. */ +#define IGNBRK 0000001 /* Ignore break condition. */ +#define BRKINT 0000002 /* Signal interrupt on break. */ +#define IGNPAR 0000004 /* Ignore characters with parity errors. */ +#define PARMRK 0000010 /* Mark parity and framing errors. */ +#define INPCK 0000020 /* Enable input parity check. */ +#define ISTRIP 0000040 /* Strip 8th bit off characters. */ +#define INLCR 0000100 /* Map NL to CR on input. */ +#define IGNCR 0000200 /* Ignore CR. */ +#define ICRNL 0000400 /* Map CR to NL on input. */ +#define OPOST 0000001 /* Post-process output. */ + +#define ICANON 0000002 +#define VMIN 6 + +#define S_IRWXU 0700 +#define S_IRUSR 0400 +#define S_IWUSR 0200 +#define S_IXUSR 0100 +#define S_IRWXG 070 +#define S_IRGRP 040 +#define S_IWGRP 020 +#define S_IXGRP 010 +#define S_IRWXO 07 +#define S_IROTH 04 +#define S_IWOTH 02 +#define S_IXOTH 01 +#define S_ISUID 04000 +#define S_ISGID 02000 +#define S_ISVTX 01000 + +/* open/fcntl. */ +#define O_ACCMODE 0003 +#define O_RDONLY 00 +#define O_WRONLY 01 +#define O_RDWR 02 +#ifndef O_CREAT +# define O_CREAT 0100 /* Not fcntl. */ +#endif +#ifndef O_EXCL +# define O_EXCL 0200 /* Not fcntl. */ +#endif +#ifndef O_NOCTTY +# define O_NOCTTY 0400 /* Not fcntl. */ +#endif +#ifndef O_TRUNC +# define O_TRUNC 01000 /* Not fcntl. */ +#endif +#ifndef O_APPEND +# define O_APPEND 02000 +#endif +#ifndef O_NONBLOCK +# define O_NONBLOCK 04000 +#endif +#ifndef O_NDELAY +# define O_NDELAY O_NONBLOCK +#endif +#ifndef O_SYNC +# define O_SYNC 04010000 +#endif +#define O_FSYNC O_SYNC +#ifndef O_ASYNC +# define O_ASYNC 020000 +#endif +#ifndef __O_LARGEFILE +# define __O_LARGEFILE 0100000 +#endif + +#ifndef __O_DIRECTORY +# define __O_DIRECTORY 0200000 +#endif +#ifndef __O_NOFOLLOW +# define __O_NOFOLLOW 0400000 +#endif +#ifndef __O_CLOEXEC +# define __O_CLOEXEC 02000000 +#endif +#ifndef __O_DIRECT +# define __O_DIRECT 040000 +#endif +#ifndef __O_NOATIME +# define __O_NOATIME 01000000 +#endif +#ifndef __O_PATH +# define __O_PATH 010000000 +#endif +#ifndef __O_DSYNC +# define __O_DSYNC 010000 +#endif +#ifndef __O_TMPFILE +# define __O_TMPFILE (020000000 | __O_DIRECTORY) +#endif + +inline static std::uint32_t s_to_dt_type(std::uint32_t s_type) { + switch (s_type) + { + case S_IFSOCK: + return DT_SOCK; + case S_IFREG: + return DT_REG; + case S_IFBLK: + return DT_BLK; + case S_IFIFO: + return DT_FIFO; + case S_IFDIR: + return DT_DIR; + case S_IFCHR: + return DT_CHR; + case S_IFLNK: + return DT_LNK; + default: + assert(0,"shitfuck"); + return 0; + } + return 0; +} enum class file_descriptor_type : std::uint8_t { unallocated = 0, @@ -13,6 +151,15 @@ enum class file_descriptor_type : std::uint8_t { memfd = 5 }; +struct dirent { + std::uint64_t d_ino; + std::int64_t d_off; + unsigned short d_reclen; + unsigned char d_type; + char d_name[]; +}; + + struct stat { dev_t st_dev; ino_t st_ino; @@ -34,6 +181,32 @@ struct stat { #define st_ctime st_ctim.tv_sec }; +enum class vfs_file_type : std::uint8_t { + file = 1, + directory = 2, + symlink = 3 +}; + +enum class vfs_poll_type : std::uint8_t { + pollin = 1, + pollout = 2 +}; + +inline static std::uint32_t vfs_to_dt_type(vfs_file_type type) { + switch(type) { + case vfs_file_type::directory: + return DT_DIR; + case vfs_file_type::file: + return DT_REG; + case vfs_file_type::symlink: + return DT_LNK; + default: + assert(0,"fsaifsi"); + return 0; // + } + return 0; +} + struct filesystem { locks::mutex lock; @@ -41,8 +214,11 @@ struct filesystem { std::uint64_t partition; } fs_specific; - std::uint32_t (*open)(filesystem* fs, void* file_desc, char* path); - + std::int32_t (*remove)(filesystem* fs, char* path); + std::int32_t (*open)(filesystem* fs, void* file_desc, char* path, bool is_directory); + std::int32_t (*readlink)(filesystem* fs, char* path, char* buffer); + std::int32_t (*create)(filesystem* fs, char* path, vfs_file_type type, std::uint32_t mode); + char path[2048]; }; @@ -59,27 +235,262 @@ struct file_descriptor { } fs_specific; struct { + int cycle; + int queue; + } other; + + struct { disk* target_disk; filesystem* fs; - signed long (*read)(file_descriptor* file, void* buffer, signed long count); - signed long (*write)(file_descriptor* file, void* buffer, signed long count); + std::int32_t (*ioctl)(file_descriptor* file, std::uint64_t req, void* arg); + signed long (*read)(file_descriptor* file, void* buffer, std::size_t count); + signed long (*write)(file_descriptor* file, void* buffer, std::size_t count); std::int32_t (*stat)(file_descriptor* file, stat* out); void (*close)(file_descriptor* file); + + signed long (*ls)(file_descriptor* file, char* out, std::size_t count); + bool (*poll)(file_descriptor* file, vfs_poll_type type); + } vnode; }; namespace vfs { + struct node { + filesystem* fs; + char path[2048]; + }; + void init(); - std::int32_t open(file_descriptor* fd, char* path, bool follow_symlinks); - std::int32_t create(char* path, std::uint32_t mode); // mode contains type too + std::int32_t open(file_descriptor* fd, char* path, bool follow_symlinks, bool is_directory); + std::int32_t create(char* path, vfs_file_type type, std::uint32_t mode); std::int32_t readlink(char* path, char* out, std::uint32_t out_len); + std::int32_t remove(char* path); } +typedef unsigned char cc_t; +typedef unsigned int speed_t; +typedef unsigned int tcflag_t; + +#define NCCS 19 + +typedef struct { + tcflag_t c_iflag; + tcflag_t c_oflag; + tcflag_t c_cflag; + tcflag_t c_lflag; + cc_t c_line; + cc_t c_cc[NCCS]; + speed_t ibaud; + speed_t obaud; +} __attribute__((packed)) termios_t; + +typedef struct { + tcflag_t c_iflag; + tcflag_t c_oflag; + tcflag_t c_cflag; + tcflag_t c_lflag; + cc_t c_line; + cc_t c_cc[NCCS]; +} __attribute__((packed)) termiosold_t; + +#define PIPE_SIDE_WRITE 1 +#define PIPE_SIDE_READ 2 + // took from old kernel namespace vfs { + + class pipe { + private: + + std::uint64_t read_ptr = 0; + + std::atomic_flag is_received = ATOMIC_FLAG_INIT; + std::atomic_flag is_n_closed = ATOMIC_FLAG_INIT; + + + int is_was_writed_ever = 0; + + public: + + char* buffer; + + locks::preempt_spinlock lock; + + std::atomic_flag is_closed = ATOMIC_FLAG_INIT; + + std::uint64_t total_size = 0; + std::atomic<std::int64_t> size = 0; + std::int64_t write_counter = 0; + std::int64_t read_counter = 0; + + std::uint32_t connected_to_pipe = 0; + std::uint32_t connected_to_pipe_write = 0; + std::uint64_t flags = 0; + + std::uint32_t zero_message_count = 0; + + int is_closed_socket = 0; + + void* fd_pass = 0; + pipe(std::uint64_t flags) { + this->buffer = (char*)(pmm::buddy::alloc(USERSPACE_PIPE_SIZE).phys + etc::hhdm()); + this->total_size = USERSPACE_PIPE_SIZE; + this->size = 0; + this->connected_to_pipe = 2; /* syscall which creates pipe should create 2 fds too */ + this->connected_to_pipe_write = 1; + this->flags = flags; + + this->is_closed.clear(std::memory_order_release); + + } + + void close(std::uint8_t side) { + bool state = this->lock.lock(); + this->connected_to_pipe--; + + if(side == PIPE_SIDE_WRITE) { + this->connected_to_pipe_write--; + if(this->connected_to_pipe_write == 0) { + this->is_received.clear(); + this->is_closed.test_and_set(std::memory_order_acquire); + } + } + + this->lock.unlock(state); + + if(this->connected_to_pipe == 0) { + delete this; + } + } + + void create(std::uint8_t side) { + bool state = this->lock.lock(); + this->connected_to_pipe++; + if(side == PIPE_SIDE_WRITE) + this->connected_to_pipe_write++; + this->lock.unlock(state); + } + + std::uint64_t force_write(const char* src_buffer, std::uint64_t count) { + if (this->size + count > this->total_size) { + count = this->total_size - this->size; + } + this->size += count; + klibc::memcpy(this->buffer + (this->size - count), src_buffer, count); + return count; + } + + std::uint64_t write(const char* src_buffer, std::uint64_t count,int id) { + + std::uint64_t written = 0; + + while (written < count) { + bool state = this->lock.lock(); + + std::uint64_t space_left = this->total_size - this->size; + if (space_left == 0) { + this->lock.unlock(state); + process::yield(); + continue; + } + + uint64_t old_size = this->size; + + std::uint64_t to_write = (count - written) < space_left ? (count - written) : space_left; + if(to_write < 0) + to_write = 0; + + + force_write(src_buffer + written, to_write); + + written += to_write; + + this->lock.unlock(state); + } + return written; + } + + std::uint64_t nolock_write(const char* src_buffer, std::uint64_t count,int id) { + + std::uint64_t written = 0; + + if(count == 0) { + this->zero_message_count = 1; + return 0; + } + + while (written < count) { + + std::uint64_t space_left = this->total_size - this->size; + + uint64_t old_size = this->size; + + std::uint64_t to_write = (count - written) < space_left ? (count - written) : space_left; + if(to_write < 0) + to_write = 0; + + + force_write(src_buffer + written, to_write); + + written += to_write; + this->read_counter++; + + } + return written; + } + + std::int64_t read(std::int64_t* read_count, char* dest_buffer, std::uint64_t count, int is_block) { + + std::uint64_t read_bytes = 0; + int tries = 0; + + while (true) { + bool state = this->lock.lock(); + + if (this->size == 0) { + + if (this->is_closed.test(std::memory_order_acquire)) { + this->lock.unlock(state); + return 0; + } + + if(this->is_closed_socket) { + this->lock.unlock(state); + return 0; + } + + if (flags & O_NONBLOCK || is_block) { + this->lock.unlock(state); + return -11; + } + this->lock.unlock(state); + process::yield(); + continue; + } + + read_bytes = (count < (std::uint64_t)this->size) ? count : (std::uint64_t)this->size; + klibc::memcpy(dest_buffer, this->buffer, read_bytes); + klibc::memmove(this->buffer, this->buffer + read_bytes, this->size - read_bytes); + this->size -= read_bytes; + + this->lock.unlock(state); + break; + } + return read_bytes; + } + + + + ~pipe() { + pmm::buddy::free((std::uint64_t)this->buffer - etc::hhdm()); + } + + }; + + static inline std::uint64_t resolve_count(char* str,std::uint64_t sptr,char delim) { char* current = str; std::uint16_t att = 0; diff --git a/kernel/src/klibc/stdio.hpp b/kernel/src/klibc/stdio.hpp index cce2bcf..71b98e5 100644 --- a/kernel/src/klibc/stdio.hpp +++ b/kernel/src/klibc/stdio.hpp @@ -15,4 +15,6 @@ namespace klibc { } void printf(const char* fmt, ...); -};
\ No newline at end of file +}; + +#define log(name, msg, ...) klibc::printf("\033[1;31m" name "\033[0m: " msg "\r\n" , ##__VA_ARGS__)
\ No newline at end of file diff --git a/kernel/src/main.cpp b/kernel/src/main.cpp index 7c9ba13..aedd7a1 100644 --- a/kernel/src/main.cpp +++ b/kernel/src/main.cpp @@ -11,6 +11,7 @@ #include <drivers/nvme.hpp> #include <drivers/powerbutton.hpp> #include <generic/mp.hpp> +#include <generic/vfs.hpp> #if defined(__x86_64__) #include <arch/x86_64/drivers/pci.hpp> @@ -23,17 +24,17 @@ extern int is_early; extern "C" void main() { utils::cxx::init_constructors(); bootloader::init(); - utils::flanterm::init(); #if defined(__x86_64__) x86_64::serial::init(); #endif pmm::init(); paging::init(); kheap::init(); + utils::flanterm::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); + log("pmm", "total usable memory: %lli bytes", memory_size); + log("paging", "enabled kernel root with %d level paging", arch::level_paging()); + log("kheap", "available memory %lli bytes", KHEAP_SIZE); acpi::init_tables(); arch::init(ARCH_INIT_EARLY); acpi::full_init(); @@ -41,11 +42,12 @@ extern "C" void main() { arch::init(ARCH_INIT_COMMON); mp::init(); mp::sync(); + vfs::init(); drivers::powerbutton::init(); drivers::nvme::init(); #if defined(__x86_64__) x86_64::pci::initworkspace(); - klibc::printf("PCI: launched all drivers\r\n"); + log("pci", "launched all drivers"); #endif klibc::printf("Boot is done\r\n"); mp::sync(); diff --git a/kernel/src/utils/bitmap.hpp b/kernel/src/utils/bitmap.hpp index 0ebbb15..a56fe60 100644 --- a/kernel/src/utils/bitmap.hpp +++ b/kernel/src/utils/bitmap.hpp @@ -7,10 +7,10 @@ namespace utils { class bitmap { private: - std::uint8_t* pool; std::uint32_t pool_size; - public: + std::uint8_t* pool; + bitmap(std::uint32_t size, std::uint8_t* custom_pool = 0) { if (custom_pool) { this->pool = custom_pool; diff --git a/kernel/src/utils/flanterm.cpp b/kernel/src/utils/flanterm.cpp index 1c46922..c132497 100644 --- a/kernel/src/utils/flanterm.cpp +++ b/kernel/src/utils/flanterm.cpp @@ -14,16 +14,12 @@ locks::spinlock flanterm_lock; flanterm_context* ft_ctx0 = 0; -int is_disabled_flanterm = 0; +int is_disabled_flanterm = 1; 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); } @@ -33,152 +29,6 @@ extern "C" void __flanterm_free(void* ptr,size_t 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, @@ -537,91 +387,49 @@ namespace utils { 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 - ); + struct flanterm_context *ft_ctx; + if(bootloader::bootloader->get_flanterm() == nullptr) { + 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 + ); + } else { + + limine_flanterm_fb_init_params_response* flan = bootloader::bootloader->get_flanterm(); + + 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, + flan->entries[0]->canvas, + flan->entries[0]->ansi_colours, flan->entries[0]->ansi_bright_colours, + &flan->entries[0]->default_bg, &flan->entries[0]->default_fg, + &flan->entries[0]->default_bg_bright, &flan->entries[0]->default_fg_bright, + flan->entries[0]->font, flan->entries[0]->font_width, flan->entries[0]->font_height , flan->entries[0]->font_spacing, + flan->entries[0]->font_scale_x, flan->entries[0]->font_scale_y, flan->entries[0]->margin, flan->entries[0]->rotation + ); + } ft_ctx0 = ft_ctx; - const char* msg = "flanterm: Found usable framebuffer\r\n"; + const char* msg = "\033[1;31mflanterm\033[0m: Found usable framebuffer\r\n"; + is_disabled_flanterm = 0; 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 - ); - + return; } void flanterm::write(const char* buffer, std::size_t size) { diff --git a/kernel/src/utils/ringbuffer.hpp b/kernel/src/utils/ringbuffer.hpp new file mode 100644 index 0000000..d6f6c2c --- /dev/null +++ b/kernel/src/utils/ringbuffer.hpp @@ -0,0 +1,91 @@ +#pragma once + +#include <cstdint> +#include <klibc/string.hpp> +#include <generic/lock/spinlock.hpp> + +#include <atomic> + +namespace utils { + template <typename T> + struct buffer_obj_t { + std::uint32_t cycle; + T data; + }; + + template <typename T> + class ring_buffer { + private: + buffer_obj_t<T>* objs; + int tail; + int size; + int cycle; + + locks::preempt_spinlock lock; + + public: + explicit ring_buffer(std::size_t size_elements) { + size = static_cast<int>(size_elements); + objs = new buffer_obj_t<T>[size]; + tail = 0; + cycle = 1; + + klibc::memset(objs, 0, sizeof(buffer_obj_t<T>) * size); + } + + ~ring_buffer() { + delete[] objs; + } + + ring_buffer(const ring_buffer&) = delete; + ring_buffer& operator=(const ring_buffer&) = delete; + + void send(const T& item) { + bool state = lock.lock(); + + objs[tail].cycle = cycle; + objs[tail].data = item; + + write_counter++; + + if (++tail == size) { + tail = 0; + cycle = !cycle; + } + + lock.unlock(state); + } + + bool is_not_empty(int reader_queue, int reader_cycle) const { + return objs[reader_queue].cycle == (std::uint32_t)reader_cycle; + } + + int receive(T* out, int max, int* c_io, int* q_io) { + bool state = lock.lock(); + + int count = 0; + int q = *q_io; + int c = *c_io; + + while (count < max && objs[q].cycle == (std::uint32_t)c) { + out[count] = objs[q].data; + read_counter++; + + if (++q == size) { + q = 0; + c = !c; + } + count += sizeof(T); + } + + *q_io = q; + *c_io = c; + + lock.unlock(state); + return count; + } + + std::uint64_t get_write_count() const { return write_counter; } + }; + +}
\ No newline at end of file diff --git a/limine.conf b/limine.conf index 4fc44ff..7d69f1a 100644 --- a/limine.conf +++ b/limine.conf @@ -1,5 +1,7 @@ # Timeout in seconds that Limine will use before automatically booting. timeout: 2 +term_foreground: EEEEEEEE +term_background: 000011 # The entry name that will be displayed in the boot menu. /Orange @@ -8,3 +10,4 @@ timeout: 2 # Path to the kernel to boot. boot():/ represents the partition on which limine.conf is located. path: boot():/boot/kernel + |
