diff --git a/Makefile b/Makefile index 567c0902..d9cd5455 100644 --- a/Makefile +++ b/Makefile @@ -1,29 +1,46 @@ -MODE ?= virt -LOAD_ADDR ?= 0x41000000 -XHCI_CTX_SIZE ?= 32 -QEMU ?= true +#top make +ARCH ?= aarch64-none-elf +CC := $(ARCH)-gcc +LD := $(ARCH)-ld +AR := $(ARCH)-ar +OBJCOPY := $(ARCH)-objcopy -OS := $(shell uname) +#common flags +CFLAGS_BASE ?= -g -O0 -std=c17 -nostdlib -ffreestanding \ + -fno-exceptions -fno-unwind-tables -fno-asynchronous-unwind-tables \ + -Wall -Wextra -mcpu=cortex-a72 +LDFLAGS_BASE ?= + +#build vars +LOAD_ADDR ?= 0x41000000 +XHCI_CTX_SIZE ?= 32 +QEMU ?= true +MODE ?= virt + +#export +export ARCH CC LD AR OBJCOPY CFLAGS_BASE LDFLAGS_BASE LOAD_ADDR XHCI_CTX_SIZE QEMU + +#config filesystem +OS := $(shell uname) +FS_DIRS := fs/redos/user ifeq ($(OS),Darwin) -BOOTFS=/Volumes/bootfs +BOOTFS := /Volumes/bootfs else -BOOTFS=/media/bootfs +BOOTFS := /media/bootfs endif -.PHONY: all kernel user shared clean raspi virt run debug dump +#targets +.PHONY: all shared user kernel clean raspi virt run debug dump prepare-fs help install all: shared user kernel @echo "Build complete." ./createfs -dump: - aarch64-none-elf-objdump -D kernel.elf > dump - shared: $(MAKE) -C shared -user: +user: prepare-fs $(MAKE) -C user kernel: @@ -31,8 +48,12 @@ kernel: clean: $(MAKE) -C shared clean + $(MAKE) -C user clean $(MAKE) -C kernel clean - $(MAKE) -C user clean + @echo "removing fs dirs" + rm -rf $(FS_DIRS) + @echo "removing images" + rm -f kernel.img kernel.elf disk.img dump raspi: $(MAKE) LOAD_ADDR=0x80000 XHCI_CTX_SIZE=64 QEMU=true all @@ -40,10 +61,18 @@ raspi: virt: $(MAKE) LOAD_ADDR=0x41000000 XHCI_CTX_SIZE=32 QEMU=true all +run: + $(MAKE) $(MODE) + ./run_$(MODE) + debug: $(MAKE) $(MODE) ./rundebug MODE=$(MODE) $(ARGS) - + +dump: + $(OBJCOPY) -O binary kernel.elf kernel.img + aarch64-none-elf-objdump -D kernel.elf > dump + install: $(MAKE) clean $(MAKE) LOAD_ADDR=0x80000 XHCI_CTX_SIZE=64 QEMU=false all @@ -51,6 +80,18 @@ install: cp kernel.img $(BOOTFS)/kernel_2712.img cp config.txt $(BOOTFS)/config.txt -run: - $(MAKE) $(MODE) - ./run_$(MODE) \ No newline at end of file +prepare-fs: + @echo "creating dirs" + @mkdir -p $(FS_DIRS) + +help: + @printf "usage:\n\ + make all build the os\n\ + make clean remove all build artifacts\n\ + make raspi build for raspberry\n\ + make virt build for qemu virt board\n\ + make run build and run in virt mode\n\ + make debug build and run with debugger\n\ + make dump disassemble kernel.elf\n\ + make install create raspi kernel and mount it on a bootable partition\n\ + make prepare-fs create directories for the filesystem\n\n" diff --git a/kernel/Makefile b/kernel/Makefile index 8ca65871..c6b00990 100644 --- a/kernel/Makefile +++ b/kernel/Makefile @@ -1,39 +1,35 @@ -ARCH= aarch64-none-elf -CC = $(ARCH)-gcc -LD = $(ARCH)-ld -OBJCOPY = $(ARCH)-objcopy - -CFLAGS = -g -O0 -std=c17 -nostdlib -ffreestanding -fno-exceptions -fno-unwind-tables -fno-asynchronous-unwind-tables -Wall -Wextra -DXHCI_CTX_SIZE=$(XHCI_CTX_SIZE) -mcpu=cortex-a72 -I. -I../shared -I../user +#kernel +# toolchain (inherited from top-level) +CFLAGS := $(CFLAGS_BASE) -I. -I../shared -I../user -DXHCI_CTX_SIZE=$(XHCI_CTX_SIZE) ifeq ($(QEMU),true) - CFLAGS += -DQEMU + CFLAGS += -DQEMU endif -LDFLAGS = -T $(shell ls *.ld) --defsym=LOAD_ADDR=$(LOAD_ADDR) +LDFLAGS := $(LDFLAGS_BASE) -T $(shell ls *.ld) --defsym=LOAD_ADDR=$(LOAD_ADDR) -C_SRC = $(shell find . -name '*.c') -ASM_SRC = $(shell find . -name '*.S') -CPP_SRC = $(shell find . -name '*.cpp') -OBJ = $(C_SRC:.c=.o) $(CPP_SRC:.cpp=.o) $(ASM_SRC:.S=.o) -OBJL = $(filter-out ./boot.o, $(OBJ)) +CLEAN_OBJS := $(shell find . -name '*.o') +C_SRC := $(shell find . -name '*.c') +ASM_SRC := $(shell find . -name '*.S') +CPP_SRC := $(shell find . -name '*.cpp') +OBJ := $(C_SRC:.c=.o) $(ASM_SRC:.S=.o) $(CPP_SRC:.cpp=.o) +OBJL := $(filter-out ./boot.o,$(OBJ)) -TARGET = kernel.img -ELF = kernel.elf +ELF := ../kernel.elf +TARGET := ../kernel.img all: $(TARGET) $(TARGET): ../shared/libshared.a $(OBJ) - $(LD) $(LDFLAGS) -o ../$(ELF) $(OBJL) ../shared/libshared.a - $(OBJCOPY) -O binary ../$(ELF) ../$(TARGET) + $(LD) $(LDFLAGS) -o $(ELF) $(OBJL) ../shared/libshared.a + $(OBJCOPY) -O binary $(ELF) $@ %.o: %.S $(CC) $(CFLAGS) -c $< -o $@ - %.o: %.c $(CC) $(CFLAGS) -c $< -o $@ - %.o: %.cpp $(CC) $(CFLAGS) -fno-rtti -c $< -o $@ clean: - rm -f $(shell find . -name '*.o') ../$(ELF) ../$(TARGET) $(TARGET) \ No newline at end of file + rm -f $(CLEAN_OBJS) $(ELF) $(TARGET) diff --git a/kernel/console/kconsole/kconsole.cpp b/kernel/console/kconsole/kconsole.cpp index 948ddf4c..aaefe82d 100644 --- a/kernel/console/kconsole/kconsole.cpp +++ b/kernel/console/kconsole/kconsole.cpp @@ -1,11 +1,7 @@ #include "kconsole.hpp" -#include "memory/kalloc.h" -#include "graph/graphics.h" #include "console/serial/uart.h" -KernelConsole::KernelConsole() - : cursor_x(0), cursor_y(0), scroll_row_offset(0) -{ +KernelConsole::KernelConsole() : cursor_x(0), cursor_y(0), is_initialized(false){ resize(); clear(); } @@ -13,111 +9,109 @@ KernelConsole::KernelConsole() bool KernelConsole::check_ready(){ if (!gpu_ready()) return false; if (!is_initialized){ - is_initialized = true; + is_initialized= true; resize(); clear(); } return true; } -void KernelConsole::resize() { - gpu_size screen = gpu_get_screen_size(); - columns = screen.width / char_width; - rows = screen.height / char_height; +void KernelConsole::resize(){ + gpu_size screen_size = gpu_get_screen_size(); + columns = screen_size.width / char_width; + rows = screen_size.height / char_height; - if (buffer_header_size > 0) - temp_free(buffer,buffer_header_size); - if (buffer_data_size > 0) - temp_free(row_data,buffer_data_size); - - buffer_header_size = rows * sizeof(char*); - buffer = (char**)talloc(rows * sizeof(char*)); - buffer_data_size = rows * columns * sizeof(char); + if (row_data) temp_free(row_data, buffer_data_size); + buffer_data_size = rows * columns; row_data = (char*)talloc(buffer_data_size); - - for (unsigned int i = 0; i < rows; i++) { - buffer[i] = row_data + (i * columns); - } -} - -void KernelConsole::put_char(char c) { - if (!check_ready()) - return; - - if (c == '\n') { - newline(); + if (!row_data){ + rows = columns = 0; + row_ring.clear(); return; } - if (cursor_x >= columns) - newline(); - - buffer[(scroll_row_offset + cursor_y) % rows][cursor_x] = c; - gpu_draw_char({cursor_x * char_width, cursor_y * char_height}, c, 1, 0xFFFFFFFF); - cursor_x++; + row_ring.clear(); + for (uint32_t i = 0; i < rows; i++) row_ring.push(i); } -void KernelConsole::put_string(const char *str) { - if (!check_ready()) +void KernelConsole::put_char(char c){ + if (!check_ready()) return; + if (c == '\n'){ + newline(); return; - for (uint32_t i = 0; str[i] != 0; i++) { - put_char(str[i]); } + if (cursor_x >= columns) newline(); + + uint32_t row_index; + if (row_ring.pop(row_index)){ + row_ring.push(row_index); + char* line = row_data + row_index * columns; + line[cursor_x] = c; + gpu_draw_char({cursor_x * char_width, cursor_y * char_height}, c, 1, 0xFFFFFFFF); + cursor_x++; + } +} + +void KernelConsole::put_string(const char* str){ + if (!check_ready()) return; + for (uint32_t i = 0; str[i]; i++) put_char(str[i]); gpu_flush(); } -void KernelConsole::put_hex(uint64_t value) { - if (!check_ready()) - return; +void KernelConsole::put_hex(uint64_t value){ + if (!check_ready()) return; put_char('0'); put_char('x'); bool started = false; - for (uint32_t i = 60;; i -= 4) { + for (uint32_t i = 60 ;; i -= 4){ uint8_t nibble = (value >> i) & 0xF; - char curr_char = nibble < 10 ? '0' + nibble : 'A' + (nibble - 10); - if (started || curr_char != '0' || i == 0) { + char current_char = nibble < 10 ? '0' + nibble : 'A' + (nibble - 10); + if (started || current_char != '0' || i == 0){ started = true; - put_char(curr_char); + put_char(current_char); } if (i == 0) break; } - gpu_flush(); } -void KernelConsole::newline() { - if (!check_ready()) - return; - for (unsigned x = cursor_x; x < columns; x++){ - buffer[(scroll_row_offset + cursor_y) % rows][x] = 0; +void KernelConsole::newline(){ + if (!check_ready()) return; + uint32_t row_index; + if (row_ring.pop(row_index)){ + char* line = row_data + row_index * columns; + for (uint32_t x = cursor_x; x < columns; x++) line[x] = 0; + row_ring.push(row_index); } cursor_x = 0; cursor_y++; - if (cursor_y >= rows) { + if (cursor_y >= rows){ scroll(); cursor_y = rows - 1; } } -void KernelConsole::scroll() { - if (!check_ready()) - return; - - scroll_row_offset = (scroll_row_offset + 1) % rows; - - for (unsigned int x = 0; x < columns; x++) { - buffer[(scroll_row_offset + rows - 1) % rows][x] = 0; +void KernelConsole::scroll(){ + if (!check_ready()) return; + uint32_t row_index; + if (row_ring.pop(row_index)){ + char* line = row_data + row_index * columns; + for (uint32_t x = 0; x < columns; x++) line[x] = 0; + row_ring.push(row_index); } - redraw(); } void KernelConsole::redraw(){ screen_clear(); - for (unsigned int y = 0; y < rows; y++) { - for (unsigned int x = 0; x < columns; x++) { - char c = buffer[(scroll_row_offset + y) % rows][x]; - gpu_draw_char({x * char_width, y * char_height}, c, 1, 0xFFFFFFFF); + for (uint32_t y = 0; y < rows; y++){ + uint32_t row_index; + if (row_ring.pop(row_index)){ + row_ring.push(row_index); + char* line = row_data + row_index * columns; + for (uint32_t x = 0; x < columns; x++){ + gpu_draw_char({x * char_width, y * char_height}, line[x], 1, 0xFFFFFFFF); + } } } } @@ -126,15 +120,15 @@ void KernelConsole::screen_clear(){ gpu_clear(0x0); } -void KernelConsole::clear() { +void KernelConsole::clear(){ screen_clear(); - for (unsigned int y = 0; y < rows; y++) { - for (unsigned int x = 0; x < columns; x++) { - buffer[y][x] = 0; + for (uint32_t i = 0; i < rows; i++){ + uint32_t row_index; + if (row_ring.pop(row_index)){ + char* line = row_data + row_index * columns; + for (uint32_t x = 0; x < columns; x++) line[x] = 0; + row_ring.push(row_index); } } - cursor_x = 0; - cursor_y = 0; - scroll_row_offset = 0; - gpu_flush(); -} \ No newline at end of file + cursor_x = cursor_y = 0; +} diff --git a/kernel/console/kconsole/kconsole.h b/kernel/console/kconsole/kconsole.h index 84ced522..c381bbc2 100644 --- a/kernel/console/kconsole/kconsole.h +++ b/kernel/console/kconsole/kconsole.h @@ -11,4 +11,4 @@ void kconsole_clear(); #ifdef __cplusplus } -#endif \ No newline at end of file +#endif diff --git a/kernel/console/kconsole/kconsole.hpp b/kernel/console/kconsole/kconsole.hpp index f1556f14..feefa40f 100644 --- a/kernel/console/kconsole/kconsole.hpp +++ b/kernel/console/kconsole/kconsole.hpp @@ -1,14 +1,18 @@ #pragma once #include "types.h" +#include "data_struct/ring_buffer.hpp" +#include "graph/graphics.h" +#include "memory/kalloc.h" -class KernelConsole { +class KernelConsole{ public: KernelConsole(); void put_char(char c); - void put_string(const char *str); + void put_string(const char* str); void put_hex(uint64_t value); + void newline(); void scroll(); void clear(); @@ -19,18 +23,17 @@ class KernelConsole { void screen_clear(); void redraw(); - unsigned int cursor_x; - unsigned int cursor_y; - unsigned int columns; - unsigned int rows; - bool is_initialized = false; - int scroll_row_offset = 0; - static constexpr int char_width = 8; - static constexpr int char_height = 16; - char** buffer; - char* row_data; + uint32_t cursor_x, cursor_y; + uint32_t columns, rows; + bool is_initialized; + + static constexpr uint32_t char_width=8; + static constexpr uint32_t char_height=16; + static constexpr uint32_t max_rows=128; - uint64_t buffer_header_size; - uint64_t buffer_data_size; + RingBuffer row_ring; + char* row_data; + uint32_t buffer_data_size; }; -extern KernelConsole kconsole; \ No newline at end of file + +extern KernelConsole kconsole; diff --git a/kernel/filesystem/fat32.cpp b/kernel/filesystem/fat32.cpp index d871be32..00eca4dd 100644 --- a/kernel/filesystem/fat32.cpp +++ b/kernel/filesystem/fat32.cpp @@ -62,7 +62,6 @@ bool FAT32FS::init(uint32_t partition_sector){ kprintf("FAT32 Volume uses %i cluster size", bytes_per_sector); kprintf("Data start at %x",data_start_sector*512); - read_FAT(mbs->reserved_sectors, mbs->sectors_per_fat, mbs->number_of_fats); return true; @@ -290,4 +289,4 @@ string_list* FAT32FS::list_contents(char *path){ uint32_t count = count_FAT(mbs->first_cluster_of_root_directory); return (string_list*)walk_directory(count, mbs->first_cluster_of_root_directory, path, list_entries_handler); -} \ No newline at end of file +} diff --git a/kernel/input/xhci.cpp b/kernel/input/xhci.cpp index de5154bb..8b1101c9 100644 --- a/kernel/input/xhci.cpp +++ b/kernel/input/xhci.cpp @@ -205,7 +205,6 @@ bool XHCIDriver::init(){ kprintf("[xHCI] Failed to configure device at port %i",i); } } - return true; } diff --git a/kernel/kstring.c b/kernel/kstring.c index 3cfe197b..e4157794 100644 --- a/kernel/kstring.c +++ b/kernel/kstring.c @@ -5,69 +5,87 @@ #include "std/memfunctions.h" //TODO: we can most likely get rid of this class now and use string entirely -static uint32_t compute_length(const char *s, uint32_t max_length) { +static uint32_t compute_length(const char *s, uint32_t max_length){ + if (s == NULL) return 0; + uint32_t len = 0; - while ((max_length == 0 || len < max_length) && s[len] != '\0') { - len++; - } + while ((max_length == 0 || len < max_length) && s[len] != '\0') len++; + return len; } -kstring kstring_l(const char *literal) { +kstring kstring_l(const char *literal){ + + if (literal == NULL) return (kstring){.data = NULL, .length = 0}; + uint32_t len = compute_length(literal, 0); - char *buf = (char*)talloc(len+1); - for (uint32_t i = 0; i < len; i++) - buf[i] = literal[i]; - buf[len] = 0; - return (kstring){ .data = buf, .length = len }; + char *buf = (char*)talloc(len + 1); + if (!buf) return (kstring){ .data = NULL, .length = 0}; + + for (uint32_t i = 0; i < len; i++) buf[i] = literal[i]; + + buf[len] = '\0'; + return (kstring){.data = buf, .length = len}; } kstring kstring_repeat(char symbol, uint32_t amount){ char *buf = (char*)talloc(amount + 1); + if(!buf) return (kstring){ .data = NULL, .length = 0}; + memset(buf, symbol, amount); - buf[amount] = 0; - return (kstring){ .data = buf, .length = amount }; + buf[amount] = '\0'; + return (kstring){.data = buf, .length = amount}; } kstring kstring_tail(const char *array, uint32_t max_length){ + if (array == NULL) return (kstring){.data = NULL, .length = 0}; + uint32_t len = compute_length(array, 0); - int offset = len-max_length; - if (offset < 0) - offset = 0; + int offset = (int)len - (int)max_length; + if (offset < 0) offset = 0; + uint32_t adjusted_len = len - offset; - char *buf = (char*)talloc(adjusted_len + 1); - for (uint32_t i = offset; i < len; i++) - buf[i-offset] = array[i]; - buf[len-offset] = 0; - return (kstring){ .data = buf, .length = adjusted_len }; + char *buf = (char*)talloc(adjusted_len+1); + if (!buf) return (kstring){.data = NULL, .length = 0}; + + for (uint32_t i = 0; i < adjusted_len; i++) buf[i] = array[offset + i]; + + buf[adjusted_len] = '\0'; + return (kstring){ .data = buf, .length = adjusted_len}; } -kstring kstring_ca_max(const char *array, uint32_t max_length) { - uint32_t len = compute_length(array, max_length); - char *buf = (char*)talloc(len + 1); - for (uint32_t i = 0; i < len; i++) - buf[i] = array[i]; - buf[len] = 0; - return (kstring){ .data = buf, .length = len }; +kstring kstring_ca_max(const char *array, uint32_t max_length){ + if(array == NULL) return (kstring){ .data = NULL, .length = 0 }; + + uint32_t len=compute_length(array, max_length); + char *buf = (char*)talloc(len+1); + if(!buf) return (kstring){.data = NULL, .length = 0}; + + for(uint32_t i = 0; i < len; i++) buf[i] = array[i]; + + buf[len] = '\0'; + return (kstring){.data = buf, .length = len}; } kstring kstring_c(const char c){ char *buf = (char*)talloc(2); + if(!buf) return (kstring){ .data = NULL, .length = 0 }; + buf[0] = c; - buf[1] = 0; - return (kstring){ .data = buf, .length = 1 }; + buf[1] = '\0'; + return (kstring){.data = buf, .length = 1}; } -kstring kstring_from_hex(uint64_t value) { +kstring kstring_from_hex(uint64_t value){ char *buf = (char*)talloc(18); uint32_t len = 0; buf[len++] = '0'; buf[len++] = 'x'; bool started = false; - for (uint32_t i = 60;; i -= 4) { - uint8_t nibble = (value >> i) & 0xF; - char curr_char = nibble < 10 ? '0' + nibble : 'A' + (nibble - 10); + for (uint32_t i = 60;; i -= 4){ + uint8_t nibble = (value>>i)&0xF; + char curr_char = nibble < 10 ? '0' + nibble : 'A'+(nibble - 10); if (started || curr_char != '0' || i == 0) { started = true; buf[len++] = curr_char; @@ -76,82 +94,99 @@ kstring kstring_from_hex(uint64_t value) { } buf[len] = 0; - return (kstring){ .data = buf, .length = len }; + return (kstring){.data = buf, .length = len}; } -kstring kstring_from_bin(uint64_t value) { +kstring kstring_from_bin(uint64_t value){ char *buf = (char*)talloc(67); uint32_t len = 0; buf[len++] = '0'; buf[len++] = 'b'; bool started = false; - for (uint32_t i = 60;; i --) { + for (uint32_t i = 60;; i--){ char bit = (value >> i) & 1 ? '1' : '0'; - if (started || bit != '0' || i == 0) { + if (started || bit != '0' || i == 0){ started = true; buf[len++] = bit; } if (i == 0) break; } - buf[len] = 0; return (kstring){ .data = buf, .length = len }; } -bool kstring_equals(kstring a, kstring b) { - return strcmp(a.data,b.data, false) == 0; +bool kstring_equals(kstring a, kstring b){ + return strcmp(a.data, b.data, false) == 0; } -kstring kstring_format_args(const char *fmt, const uint64_t *args, uint32_t arg_count) { +kstring kstring_format_args(const char *fmt, const uint64_t *args, uint32_t arg_count){ + if(fmt == NULL) return (kstring){ .data = NULL, .length = 0 }; + + if(arg_count > 0 && args == NULL) return (kstring){ .data = NULL, .length = 0 }; + char *buf = (char*)talloc(256); + if (!buf) return (kstring){ .data = NULL, .length = 0 }; + uint32_t len = 0; uint32_t arg_index = 0; - - for (uint32_t i = 0; fmt[i] && len < 255; i++) { - if (fmt[i] == '%' && fmt[i+1]) { + for (uint32_t i = 0; fmt[i] && len < 255; i++){ + if (fmt[i] == '%' && fmt[i + 1]) { i++; - if (arg_index >= arg_count) break; - if (fmt[i] == 'x') { + if (arg_index >= arg_count){ + buf[len++] = '%'; + buf[len++] = fmt[i]; + continue; + } + switch(fmt[i]){ + case 'x': { uint64_t val = args[arg_index++]; kstring hex = kstring_from_hex(val); for (uint32_t j = 0; j < hex.length && len < 255; j++) buf[len++] = hex.data[j]; - temp_free(hex.data,hex.length); - } else if (fmt[i] == 'b') { + temp_free(hex.data, hex.length); + break; + } + case 'b': { uint64_t val = args[arg_index++]; kstring bin = kstring_from_bin(val); for (uint32_t j = 0; j < bin.length && len < 255; j++) buf[len++] = bin.data[j]; - temp_free(bin.data,bin.length); - } else if (fmt[i] == 'c') { + temp_free(bin.data, bin.length); + break; + } + case 'c': { uint64_t val = args[arg_index++]; buf[len++] = (char)val; - } else if (fmt[i] == 's') { + break; + } + case 's': { const char *str = (const char *)(uintptr_t)args[arg_index++]; - for (uint32_t j = 0; str[j] && len < 255; j++) buf[len++] = str[j]; - } else if (fmt[i] == 'i') { + if (str){ + for (uint32_t j = 0; str[j] && len < 255; j++) buf[len++] = str[j]; + } + break; + } + case 'i': { uint64_t val = args[arg_index++]; char temp[21]; uint32_t temp_len = 0; bool negative = false; - - if ((int)val < 0) { + if ((int64_t)val < 0){ negative = true; - val = (uint64_t)(-(int)val); + val = (uint64_t)(-(int64_t)val); } - do { temp[temp_len++] = '0' + (val % 10); val /= 10; - } while (val && temp_len < 20); - - if (negative && temp_len < 20) { + } while (val && temp_len < sizeof(temp)-1); + if (negative && temp_len < sizeof(temp)-1){ temp[temp_len++] = '-'; } - - for (int j = temp_len - 1; j >= 0 && len < 255; j--) { + for (int j = temp_len - 1; j >= 0 && len < 255; j--){ buf[len++] = temp[j]; } - } else { + break; + } + default: buf[len++] = '%'; buf[len++] = fmt[i]; } @@ -159,7 +194,6 @@ kstring kstring_format_args(const char *fmt, const uint64_t *args, uint32_t arg_ buf[len++] = fmt[i]; } } - - buf[len] = 0; + buf[len] = '\0'; return (kstring){ .data = buf, .length = len }; -} \ No newline at end of file +} diff --git a/kernel/networking/drivers/virtio_net_pci/virtio_net_pci.cpp b/kernel/networking/drivers/virtio_net_pci/virtio_net_pci.cpp index 4011d439..66f63bb8 100644 --- a/kernel/networking/drivers/virtio_net_pci/virtio_net_pci.cpp +++ b/kernel/networking/drivers/virtio_net_pci/virtio_net_pci.cpp @@ -47,6 +47,8 @@ VirtioNetDriver* VirtioNetDriver::try_init(){ return nullptr; } + + bool VirtioNetDriver::init(){ uint64_t addr = find_pci_device(0x1AF4, 0x1000); if (!addr){ @@ -73,14 +75,12 @@ bool VirtioNetDriver::init(){ kprintf_raw("[VIRTIO_NET] Interrupts setup with MSI %i,%i",NET_IRQ,NET_IRQ+1); break; } - pci_enable_device(addr); if (!virtio_init_device(&vnp_net_dev)) { kprintf("[VIRTIO_NET error] Failed network initialization"); return false; } - kprintf("[VIRTIO_NET] Device set up at %x",(uintptr_t)vnp_net_dev.device_cfg); select_queue(&vnp_net_dev, RECEIVE_QUEUE); @@ -109,6 +109,7 @@ bool VirtioNetDriver::init(){ return true; } + void VirtioNetDriver::get_mac(network_connection_ctx *context){ virtio_net_config* net_config = (virtio_net_config*)vnp_net_dev.device_cfg; kprintfv("[VIRTIO_NET] %x:%x:%x:%x:%x:%x", net_config->mac[0], net_config->mac[1], net_config->mac[2], net_config->mac[3], net_config->mac[4], net_config->mac[5]); @@ -184,4 +185,4 @@ void VirtioNetDriver::send_packet(sizedptr packet){ void VirtioNetDriver::enable_verbose(){ verbose = true; -} \ No newline at end of file +} diff --git a/kernel/networking/processes/net_proc.c b/kernel/networking/processes/net_proc.c index 84b7bfdc..81122989 100644 --- a/kernel/networking/processes/net_proc.c +++ b/kernel/networking/processes/net_proc.c @@ -68,7 +68,6 @@ void test_network(){ unbind_port(8888); } - uint32_t negotiate_dhcp(){ kprintf("Sending DHCP request"); network_connection_ctx *ctx = network_get_context(); @@ -130,9 +129,7 @@ uint32_t negotiate_dhcp(){ //DNS (8 bytes) (6) //TODO: Make subsequent DHCP requests (renewals and requests) directed to the server ctx->ip = local_ip; - test_network(); - return lease_time; } @@ -150,4 +147,4 @@ void dhcp_daemon(){ process_t* launch_net_process(){ return create_kernel_process("dhcp_daemon",dhcp_daemon); -} \ No newline at end of file +} diff --git a/shared/Makefile b/shared/Makefile index fb7390db..4c9fe9cd 100644 --- a/shared/Makefile +++ b/shared/Makefile @@ -1,21 +1,20 @@ -ARCH= aarch64-none-elf -CC = $(ARCH)-gcc -AR = $(ARCH)-ar -OBJCOPY = $(ARCH)-objcopy +#shared +CFLAGS := $(CFLAGS_BASE) -I. -I../kernel -Wno-unused-parameter -CFLAGS = -g -O0 -std=c17 -nostdlib -nolibc -ffreestanding -fno-exceptions -fno-unwind-tables -fno-asynchronous-unwind-tables -Wall -Wextra -mcpu=cortex-a72 -I. -I../kernel -Wno-unused-parameter +CLEAN_OBJS := $(shell find . -name '*.o') +C_SRC := $(shell find . -name '*.c') +CPP_SRC := $(shell find . -name '*.cpp') +ASM_SRC := $(shell find . -name '*.S') +OBJ := $(C_SRC:.c=.o) $(ASM_SRC:.S=.o) $(CPP_SRC:.cpp=.o) -C_SRC = $(shell find . -name '*.c') -CPP_SRC = $(shell find . -name '*.cpp') -ASM_SRC = $(shell find . -name '*.S') -OBJ = $(C_SRC:.c=.o) $(ASM_SRC:.S=.o) $(CPP_SRC:.cpp=.o) +TARGET := libshared.a -TARGET = libshared.a +.PHONY: all clean all: $(TARGET) $(TARGET): $(OBJ) - $(AR) rcs $(TARGET) $(OBJ) + $(AR) rcs $@ $^ %.o: %.S $(CC) $(CFLAGS) -c $< -o $@ @@ -27,4 +26,4 @@ $(TARGET): $(OBJ) $(CC) $(CFLAGS) -fno-rtti -c $< -o $@ clean: - rm -f $(shell find . -name '*.o') $(TARGET) \ No newline at end of file + rm -f $(CLEAN_OBJS) $(TARGET) diff --git a/shared/data_struct/chunked_list.c b/shared/data_struct/chunked_list.c new file mode 100644 index 00000000..376feca5 --- /dev/null +++ b/shared/data_struct/chunked_list.c @@ -0,0 +1,174 @@ +#include "chunked_list.h" +#include "types.h" + +cchunked_list_t* cchunked_list_create(uint64_t chunkSize){ + uintptr_t raw = malloc(sizeof(cchunked_node_t) + chunkSize * sizeof(void*)); + if (!raw) return NULL; + + cchunked_list_t* list = (cchunked_list_t*)malloc(sizeof(cchunked_list_t)); + if (!list) { + free((void*)raw, sizeof(cchunked_node_t) + chunkSize * sizeof(void*)); + return NULL; + } + + list->chunkSize = chunkSize; + list->length = 0; + list->head = (cchunked_node_t*)raw; + list->head->count = 0; + list->head->next = NULL; + list->tail = list->head; + return list; +} + +void cchunked_list_destroy(cchunked_list_t* list){ + if (!list) return; + cchunked_node_t* node = list->head; + while (node) { + cchunked_node_t* next = node->next; + free(node, sizeof(cchunked_node_t) + list->chunkSize * sizeof(void*)); + node = next; + } + free(list, sizeof(cchunked_list_t)); +} + +cchunked_list_t* cchunked_list_clone(const cchunked_list_t* list){ + if (!list) return NULL; + cchunked_list_t* clone = cchunked_list_create(list->chunkSize); + if (!clone) return NULL; + + for (cchunked_node_t* it = list->head; it; it = it->next) { + for (uint64_t i = 0; i < it->count; i++) + cchunked_list_push_back(clone, it->data[i]); + } + return clone; +} + +void cchunked_list_push_back(cchunked_list_t* list, void* data){ + if (!list) return; + + if (!list->tail) { + uintptr_t m = malloc(sizeof(cchunked_node_t) + list->chunkSize * sizeof(void*)); + if (!m) return; + cchunked_node_t* node = (cchunked_node_t*)m; + node->count = 0; + node->next = NULL; + list->head = list->tail = node; + } + + if (list->tail->count == list->chunkSize) { + uintptr_t m = malloc(sizeof(cchunked_node_t) + list->chunkSize * sizeof(void*)); + if (!m) return; + cchunked_node_t* node = (cchunked_node_t*)m; + node->count = 0; + node->next = NULL; + list->tail->next = node; + list->tail = node; + } + + list->tail->data[list->tail->count++] = data; + list->length++; +} + +cchunked_node_t* cchunked_list_insert_after(cchunked_list_t* list, cchunked_node_t* node, void* data){ + if (!list) return NULL; + if (!node) { + cchunked_list_push_back(list, data); + return list->tail; + } + + if (node->count < list->chunkSize) { + node->data[node->count++] = data; + list->length++; + return node; + } + + uintptr_t m = malloc(sizeof(cchunked_node_t) + list->chunkSize * sizeof(void*)); + if (!m) return NULL; + cchunked_node_t* new_node = (cchunked_node_t*)m; + new_node->count = 1; + new_node->next = node->next; + new_node->data[0] = data; + + node->next = new_node; + if (list->tail == node) list->tail = new_node; + list->length++; + return new_node; +} + +void* cchunked_list_pop_front(cchunked_list_t* list){ + if (!list || !list->head || list->length == 0) return NULL; + + void* data = list->head->data[0]; + if (list->head->count > 1) { + for (uint64_t i = 1; i < list->head->count; ++i) + list->head->data[i-1] = list->head->data[i]; + list->head->count--; + } else { + cchunked_node_t* old = list->head; + list->head = old->next; + if (!list->head) list->tail = NULL; + free(old, sizeof(cchunked_node_t) + list->chunkSize * sizeof(void*)); + } + + list->length--; + return data; +} + +void* cchunked_list_remove_node(cchunked_list_t* list, cchunked_node_t* node){ + if (!list || !node || !list->head) return NULL; + + if (node == list->head) + return cchunked_list_pop_front(list); + + cchunked_node_t* prev = list->head; + while (prev->next && prev->next != node) prev = prev->next; + if (prev->next != node) return NULL; + + void* data = node->data[0]; + for (uint64_t i = 1; i < node->count; ++i) + node->data[i - 1] = node->data[i]; + node->count--; + list->length--; + + if (node->count == 0) { + prev->next = node->next; + if (list->tail == node) list->tail = prev; + free(node, sizeof(cchunked_node_t) + list->chunkSize * sizeof(void*)); + } + + return data; +} + +void cchunked_list_update(cchunked_list_t* list, cchunked_node_t* node, void* new_data){ + (void)list; + if (node && node->count) + node->data[0] = new_data; +} + +void cchunked_list_update_at(cchunked_list_t* list, cchunked_node_t* node, uint64_t offset, void* new_data){ + if (!list || !node || offset >= node->count) + return; + node->data[offset] = new_data; +} + +uint64_t cchunked_list_length(const cchunked_list_t* list){ + return list ? list->length : 0; +} + +uint64_t cchunked_list_size_bytes(const cchunked_list_t* list){ + if (!list) return 0; + uint64_t nodes = 0; + for (cchunked_node_t* it = list->head; it; it = it->next) nodes++; + return nodes * (sizeof(cchunked_node_t) + list->chunkSize * sizeof(void*)); +} + +void cchunked_list_for_each(const cchunked_list_t* list, void (*func)(void*)){ + if (!list || !func) return; + for (cchunked_node_t* it = list->head; it; it = it->next) + for (uint64_t i = 0; i < it->count; ++i) + func(it->data[i]); +} + +int cchunked_list_is_empty(const cchunked_list_t* list){ + return (!list || list->length == 0) ? 1 : 0; +} diff --git a/shared/data_struct/chunked_list.h b/shared/data_struct/chunked_list.h new file mode 100644 index 00000000..3d341c96 --- /dev/null +++ b/shared/data_struct/chunked_list.h @@ -0,0 +1,40 @@ +#pragma once +#include "types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct cchunked_node { + uint64_t count; + struct cchunked_node* next; + void* data[]; +} cchunked_node_t; + +typedef struct cchunked_list { + uint64_t chunkSize; + uint64_t length; + cchunked_node_t* head; + cchunked_node_t* tail; +} cchunked_list_t; + +uintptr_t malloc(uint64_t size); +void free(void* ptr, uint64_t size); + +cchunked_list_t* cchunked_list_create(uint64_t chunkSize); +void cchunked_list_destroy(cchunked_list_t* list); +cchunked_list_t* cchunked_list_clone(const cchunked_list_t* list); +void cchunked_list_push_back(cchunked_list_t* list, void* data); +void* cchunked_list_pop_front(cchunked_list_t* list); +cchunked_node_t* cchunked_list_insert_after(cchunked_list_t* list, cchunked_node_t* node, void* data); +void* cchunked_list_remove_node(cchunked_list_t* list, cchunked_node_t* node); +void cchunked_list_update(cchunked_list_t* list, cchunked_node_t* node, void* new_data); +void cchunked_list_update_at(cchunked_list_t* list, cchunked_node_t* node, uint64_t offset, void* new_data); +uint64_t cchunked_list_length(const cchunked_list_t* list); +uint64_t cchunked_list_size_bytes(const cchunked_list_t* list); +void cchunked_list_for_each(const cchunked_list_t* list, void (*func)(void*)); +int cchunked_list_is_empty(const cchunked_list_t* list); + +#ifdef __cplusplus +} +#endif diff --git a/shared/data_struct/chunked_list.hpp b/shared/data_struct/chunked_list.hpp new file mode 100644 index 00000000..df5f04c1 --- /dev/null +++ b/shared/data_struct/chunked_list.hpp @@ -0,0 +1,181 @@ +#pragma once +#include "types.h" +extern "C" { +#include "chunked_list.h" +} + +template +class ChunkedList { +public: + struct Node { + uint64_t count; + Node* next; + T data[]; + }; + + explicit ChunkedList(uint64_t cs) + : head(nullptr), tail(nullptr), length_(0), chunkSize(cs) {} + + ~ChunkedList() { + while (head) { + Node* next = head->next; + ::free(head, sizeof(Node) + chunkSize * sizeof(T)); + head = next; + } + } + + ChunkedList(const ChunkedList& other) + : head(nullptr), tail(nullptr), length_(0), chunkSize(other.chunkSize) { + for (Node* c = other.head; c; c = c->next) { + for (uint64_t i = 0; i < c->count; ++i) { + push_back(c->data[i]); + } + } + } + + ChunkedList& operator=(const ChunkedList& other) { + if (this != &other) { + clear(); + chunkSize = other.chunkSize; + for (Node* c = other.head; c; c = c->next) { + for (uint64_t i = 0; i < c->count; ++i) { + push_back(c->data[i]); + } + } + } + return *this; + } + + void push_back(const T& value) { + if (!tail) allocFirst(); + if (tail->count == chunkSize) allocChunk(); + tail->data[tail->count++] = value; + ++length_; + } + + T pop_front() { + if (!head) return T(); + T val = head->data[0]; + if (head->count > 1) { + for (uint64_t i = 1; i < head->count; ++i) + head->data[i - 1] = head->data[i]; + --head->count; + } else { + Node* old = head; + head = head->next; + ::free(old, sizeof(Node) + chunkSize * sizeof(T)); + if (!head) tail = nullptr; + } + --length_; + return val; + } + + Node* insert_after(Node* node, const T& value) { + if (!node) { + push_back(value); + return tail; + } + if (node->count < chunkSize) { + node->data[node->count++] = value; + ++length_; + return node; + } + Node* n = allocNode(value); + n->next = node->next; + node->next = n; + if (tail == node) tail = n; + ++length_; + return n; + } + + T remove_node(Node* node) { + if (!node || !head) return T(); + if (node == head) { + T val = head->data[0]; + uint64_t removed = head->count; + Node* nxt = head->next; + ::free(head, sizeof(Node) + chunkSize * sizeof(T)); + head = nxt; + if (!head) tail = nullptr; + length_ -= removed; + return val; + } + Node* prev = head; + while (prev->next && prev->next != node) prev = prev->next; + if (prev->next != node) return T(); + T val = node->data[0]; + uint64_t removed = node->count; + prev->next = node->next; + if (tail == node) tail = prev; + ::free(node, sizeof(Node) + chunkSize * sizeof(T)); + length_ -= removed; + return val; + } + + void update(Node* node, const T& value) { + if (node && node->count) node->data[0] = value; + } + + void update_at(Node* node, uint64_t offset, const T& value) { + if (node && offset < node->count) node->data[offset] = value; + } + + uint64_t size() const noexcept { + return length_; + } + + uint64_t size_bytes() const noexcept { + uint64_t nodes = 0; + for (Node* it = head; it; it = it->next) ++nodes; + return nodes * (sizeof(Node) + chunkSize * sizeof(T)); + } + + bool empty() const noexcept { + return length_ == 0; + } + + template + void for_each(Func f) const { + for (Node* it = head; it; it = it->next) { + for (uint64_t i = 0; i < it->count; ++i) { + f(it->data[i]); + } + } + } + +private: + Node* head; + Node* tail; + uint64_t length_; + uint64_t chunkSize; + + Node* allocNode(const T& value) { + uintptr_t raw = ::malloc(sizeof(Node) + chunkSize * sizeof(T)); + Node* n = reinterpret_cast(raw); + n->count = 1; + n->next = nullptr; + n->data[0] = value; + return n; + } + + void allocFirst() { + uintptr_t raw = ::malloc(sizeof(Node) + chunkSize * sizeof(T)); + head = tail = reinterpret_cast(raw); + head->count = 0; + head->next = nullptr; + } + + void allocChunk() { + uintptr_t raw = ::malloc(sizeof(Node) + chunkSize * sizeof(T)); + Node* n = reinterpret_cast(raw); + n->count = 0; + n->next = nullptr; + tail->next = n; + tail = n; + } + + void clear() { + while (head) pop_front(); + } +}; + diff --git a/shared/data_struct/doubly_linked_list.c b/shared/data_struct/doubly_linked_list.c new file mode 100644 index 00000000..d3707a85 --- /dev/null +++ b/shared/data_struct/doubly_linked_list.c @@ -0,0 +1,181 @@ +#include "doubly_linked_list.h" + +cdouble_linked_list_t* cdouble_linked_list_create(void) { + uintptr_t raw = malloc((uint64_t)sizeof(cdouble_linked_list_t)); + if (!raw) return NULL; + cdouble_linked_list_t* list = (cdouble_linked_list_t*)raw; + list->head = list->tail = NULL; + list->length = 0; + return list; +} + +void cdouble_linked_list_destroy(cdouble_linked_list_t* list) { + if (!list) return; + cdouble_linked_list_node_t* node = list->head; + for (uint64_t i = 0; i < list->length; ++i) { + cdouble_linked_list_node_t* next = node->next; + free(node, sizeof(cdouble_linked_list_node_t)); + node = next; + } + free(list, sizeof(cdouble_linked_list_t)); +} + +cdouble_linked_list_t* cdouble_linked_list_clone(const cdouble_linked_list_t* list) { + if (!list) return NULL; + cdouble_linked_list_t* clone = cdouble_linked_list_create(); + if (!clone) return NULL; + cdouble_linked_list_node_t* it = list->head; + for (uint64_t i = 0; i < list->length; ++i) { + uintptr_t raw = malloc(sizeof(cdouble_linked_list_node_t)); + if (raw) { + cdouble_linked_list_node_t* node = (cdouble_linked_list_node_t*)raw; + node->data = it->data; + if (clone->length == 0) { + node->next = node->prev = node; + clone->head = clone->tail = node; + } else { + node->prev = clone->tail; + node->next = clone->head; + clone->tail->next = node; + clone->head->prev = node; + clone->tail = node; + } + ++clone->length; + } + it = it->next; + } + return clone; +} + +void cdouble_linked_list_push_front(cdouble_linked_list_t* list, void* data) { + if (!list) return; + uintptr_t raw = malloc(sizeof(cdouble_linked_list_node_t)); + if (!raw) return; + cdouble_linked_list_node_t* node = (cdouble_linked_list_node_t*)raw; + node->data = data; + if (list->length == 0) { + node->next = node->prev = node; + list->head = list->tail = node; + } else { + node->next = list->head; + node->prev = list->tail; + list->head->prev = node; + list->tail->next = node; + list->head = node; + } + ++list->length; +} + +void cdouble_linked_list_push_back(cdouble_linked_list_t* list, void* data) { + if (!list) return; + uintptr_t raw = malloc(sizeof(cdouble_linked_list_node_t)); + if (!raw) return; + cdouble_linked_list_node_t* node = (cdouble_linked_list_node_t*)raw; + node->data = data; + if (list->length == 0) { + node->next = node->prev = node; + list->head = list->tail = node; + } else { + node->prev = list->tail; + node->next = list->head; + list->tail->next = node; + list->head->prev = node; + list->tail = node; + } + ++list->length; +} + +void* cdouble_linked_list_pop_front(cdouble_linked_list_t* list) { + if (!list || list->length == 0) return NULL; + cdouble_linked_list_node_t* node = list->head; + void* data = node->data; + if (list->length == 1) { + list->head = list->tail = NULL; + } else { + list->head = node->next; + list->head->prev = list->tail; + list->tail->next = list->head; + } + --list->length; + free(node, sizeof(cdouble_linked_list_node_t)); + return data; +} + +void* cdouble_linked_list_pop_back(cdouble_linked_list_t* list) { + if (!list || list->length == 0) return NULL; + cdouble_linked_list_node_t* node = list->tail; + void* data = node->data; + if (list->length == 1) { + list->head = list->tail = NULL; + } else { + list->tail = node->prev; + list->tail->next = list->head; + list->head->prev = list->tail; + } + --list->length; + free(node, sizeof(cdouble_linked_list_node_t)); + return data; +} + +cdouble_linked_list_node_t* cdouble_linked_list_insert_after(cdouble_linked_list_t* list, cdouble_linked_list_node_t* node, void* data) { + if (!list) return NULL; + if (!node) { + cdouble_linked_list_push_front(list, data); + return list->head; + } + uintptr_t raw = malloc(sizeof(cdouble_linked_list_node_t)); + if (!raw) return NULL; + cdouble_linked_list_node_t* new_node = (cdouble_linked_list_node_t*)raw; + new_node->data = data; + new_node->next = node->next; + new_node->prev = node; + node->next->prev = new_node; + node->next = new_node; + if (list->tail == node) list->tail = new_node; + ++list->length; + return new_node; +} + +cdouble_linked_list_node_t* cdouble_linked_list_insert_before(cdouble_linked_list_t* list, cdouble_linked_list_node_t* node, void* data) { + if (!list) return NULL; + if (!node) { + cdouble_linked_list_push_back(list, data); + return list->tail; + } + return cdouble_linked_list_insert_after(list, node->prev, data); +} + +void* cdouble_linked_list_remove(cdouble_linked_list_t* list, cdouble_linked_list_node_t* node) { + if (!list || !node || list->length == 0) return NULL; + if (node == list->head) return cdouble_linked_list_pop_front(list); + if (node == list->tail) return cdouble_linked_list_pop_back(list); + node->prev->next = node->next; + node->next->prev = node->prev; + void* data = node->data; + --list->length; + free(node, sizeof(cdouble_linked_list_node_t)); + return data; +} + +void cdouble_linked_list_update(cdouble_linked_list_t* list, cdouble_linked_list_node_t* node, void* new_data) { + (void)list; + if (node) node->data = new_data; +} + +uint64_t cdouble_linked_list_length(const cdouble_linked_list_t* list) { + return list ? list->length : 0; +} + +uint64_t cdouble_linked_list_size_bytes(const cdouble_linked_list_t* list) { + return list ? list->length * sizeof(cdouble_linked_list_node_t) : 0; +} + +cdouble_linked_list_node_t* cdouble_linked_list_find(cdouble_linked_list_t* list, void* key, int (*cmp)(void*, void*)) { + if (!list || !cmp || list->length == 0) return NULL; + cdouble_linked_list_node_t* it = list->head; + for (uint64_t i = 0; i < list->length; ++i) { + if (cmp(it->data, key) == 0) return it; + it = it->next; + } + return NULL; +} diff --git a/shared/data_struct/doubly_linked_list.h b/shared/data_struct/doubly_linked_list.h new file mode 100644 index 00000000..aee049f5 --- /dev/null +++ b/shared/data_struct/doubly_linked_list.h @@ -0,0 +1,40 @@ +#pragma once +#include "types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct cdouble_linked_list_node { + void* data; + struct cdouble_linked_list_node* next; + struct cdouble_linked_list_node* prev; +} cdouble_linked_list_node_t; + +typedef struct cdouble_linked_list { + cdouble_linked_list_node_t* head; + cdouble_linked_list_node_t* tail; + uint64_t length; +} cdouble_linked_list_t; + +extern uintptr_t malloc(uint64_t size); +extern void free(void* ptr, uint64_t size); + +cdouble_linked_list_t* cdouble_linked_list_create(void); +void cdouble_linked_list_destroy(cdouble_linked_list_t* list); +cdouble_linked_list_t* cdouble_linked_list_clone(const cdouble_linked_list_t* list); +void cdouble_linked_list_push_front(cdouble_linked_list_t* list, void* data); +void cdouble_linked_list_push_back(cdouble_linked_list_t* list, void* data); +void* cdouble_linked_list_pop_front(cdouble_linked_list_t* list); +void* cdouble_linked_list_pop_back(cdouble_linked_list_t* list); +cdouble_linked_list_node_t* cdouble_linked_list_insert_after(cdouble_linked_list_t* list, cdouble_linked_list_node_t* node, void* data); +cdouble_linked_list_node_t* cdouble_linked_list_insert_before(cdouble_linked_list_t* list, cdouble_linked_list_node_t* node, void* data); +void* cdouble_linked_list_remove(cdouble_linked_list_t* list, cdouble_linked_list_node_t* node); +void cdouble_linked_list_update(cdouble_linked_list_t* list, cdouble_linked_list_node_t* node, void* new_data); +uint64_t cdouble_linked_list_length(const cdouble_linked_list_t* list); +uint64_t cdouble_linked_list_size_bytes(const cdouble_linked_list_t* list); +cdouble_linked_list_node_t* cdouble_linked_list_find(cdouble_linked_list_t* list, void* key, int (*cmp)(void*, void*)); + +#ifdef __cplusplus +} +#endif diff --git a/shared/data_struct/doubly_linked_list.hpp b/shared/data_struct/doubly_linked_list.hpp new file mode 100644 index 00000000..2438e01d --- /dev/null +++ b/shared/data_struct/doubly_linked_list.hpp @@ -0,0 +1,207 @@ +#pragma once +#include "types.h" + +extern "C" { +#include "doubly_linked_list.h" +} + +template +class LinkedList { +private: + struct Node { + T data; + Node* next; + Node* prev; + }; + + Node* head; + Node* tail; + uint64_t length; + + Node* alloc_node(const T& value) { + uintptr_t raw = malloc(sizeof(Node)); + if (raw == 0) return nullptr; + Node* n = reinterpret_cast(raw); + n->data = value; + n->next = n->prev = nullptr; + return n; + } + + void free_node(Node* n) { + if (!n) return; + free(n, sizeof(Node)); + } + + static void swap(LinkedList& a, LinkedList& b) noexcept { + std::swap(a.head, b.head); + std::swap(a.tail, b.tail); + std::swap(a.length, b.length); + } + +public: + LinkedList() : head(nullptr), tail(nullptr), length(0) {} + + LinkedList(const LinkedList& other) : head(nullptr), tail(nullptr), length(0) { + if (other.head) { + Node* it = other.head; + do { + push_back(it->data); + it = it->next; + } while (it != other.head); + } + } + + ~LinkedList() { + while (!empty()) pop_front(); + } + + LinkedList& operator=(const LinkedList& other) { + if (this != &other) { + LinkedList tmp(other); + swap(*this, tmp); + } + return *this; + } + + void push_front(const T& value) { + Node* n = alloc_node(value); + if (!n) return; + if (!head) { + head = tail = n; + n->next = n->prev = n; + } else { + n->next = head; + n->prev = tail; + head->prev = n; + tail->next = n; + head = n; + } + ++length; + } + + void push_back(const T& value) { + Node* n = alloc_node(value); + if (!n) return; + if (!tail) { + head = tail = n; + n->next = n->prev = n; + } else { + n->prev = tail; + n->next = head; + tail->next = n; + head->prev = n; + tail = n; + } + ++length; + } + + T pop_front() { + if (!head) return T(); + Node* n = head; + T val = n->data; + if (head == tail) { + head = tail = nullptr; + } else { + head = head->next; + head->prev = tail; + tail->next = head; + } + --length; + free_node(n); + return val; + } + + T pop_back() { + if (!tail) return T(); + Node* n = tail; + T val = n->data; + if (head == tail) { + head = tail = nullptr; + } else { + tail = tail->prev; + tail->next = head; + head->prev = tail; + } + --length; + free_node(n); + return val; + } + + Node* insert_after(Node* node, const T& value) { + if (!node) { + push_front(value); + return head; + } + Node* n = alloc_node(value); + if (!n) return nullptr; + n->next = node->next; + n->prev = node; + node->next->prev = n; + node->next = n; + if (tail == node) tail = n; + ++length; + return n; + } + + Node* insert_before(Node* node, const T& value) { + if (!node) { + push_back(value); + return tail; + } + return insert_after(node->prev, value); + } + + T remove(Node* node) { + if (!node) return T(); + if (node == head) return pop_front(); + if (node == tail) return pop_back(); + node->prev->next = node->next; + node->next->prev = node->prev; + T val = node->data; + --length; + free_node(node); + return val; + } + + void update(Node* node, const T& value) { + if (node) node->data = value; + } + + uint64_t size() const { + return length; + } + + bool empty() const { + return length == 0; + } + + Node* begin() const { + return head; + } + + Node* end() const { + return nullptr; + } + + template + Node* find(Predicate pred) const { + if (!head) return nullptr; + Node* it = head; + do { + if (pred(it->data)) return it; + it = it->next; + } while (it != head); + return nullptr; + } + + template + void for_each(Func func) const { + if (!head) return; + Node* it = head; + do { + func(it->data); + it = it->next; + } while (it != head); + } +}; + diff --git a/shared/data_struct/linked_list.c b/shared/data_struct/linked_list.c new file mode 100644 index 00000000..0ffdd600 --- /dev/null +++ b/shared/data_struct/linked_list.c @@ -0,0 +1,129 @@ +#include "linked_list.h" + +clinkedlist_t *clinkedlist_create(void){ + uintptr_t mem = malloc(sizeof(clinkedlist_t)); + if((void *)mem == NULL) return NULL; + clinkedlist_t *list = (clinkedlist_t *)mem; + list->head = NULL; + list->tail = NULL; + list->length = 0; + return list; +} + +void clinkedlist_destroy(clinkedlist_t *list){ + if(list == NULL) return; + clinkedlist_node_t *node = list->head; + while(node){ + clinkedlist_node_t *next = node->next; + free(node, sizeof(clinkedlist_node_t)); + node = next; + } + free(list, sizeof(clinkedlist_t)); +} + +clinkedlist_t *clinkedlist_clone(const clinkedlist_t *list){ + if(list == NULL) return NULL; + clinkedlist_t *clone = clinkedlist_create(); + if(clone == NULL) return NULL; + clinkedlist_node_t *it = list->head; + while(it){ + if(clone->tail){ + clinkedlist_node_t *new_node = (clinkedlist_node_t *)malloc(sizeof(clinkedlist_node_t)); + new_node->data = it->data; + new_node->next = NULL; + clone->tail->next = new_node; + clone->tail = new_node; + clone->length++; + } else { + clinkedlist_push_front(clone, it->data); + } + it = it->next; + } + return clone; +} + +void clinkedlist_push_front(clinkedlist_t *list, void *data){ + if(list == NULL) return; + clinkedlist_node_t *node = (clinkedlist_node_t *)malloc(sizeof(clinkedlist_node_t)); + node->data = data; + node->next = list->head; + list->head = node; + if(list->tail == NULL) list->tail = node; + list->length++; +} + +void *clinkedlist_pop_front(clinkedlist_t *list){ + if(list == NULL || list->head == NULL) return NULL; + clinkedlist_node_t *node = list->head; + void *data = node->data; + list->head = node->next; + if (list->head == NULL) list->tail = NULL; + list->length--; + free(node, sizeof(clinkedlist_node_t)); + return data; +} + +clinkedlist_node_t *clinkedlist_insert_after(clinkedlist_t *list, clinkedlist_node_t *node, void *data){ + if(list == NULL) return NULL; + if(node == NULL){ + clinkedlist_push_front(list, data); + return list->head; + } + clinkedlist_node_t *new_node = (clinkedlist_node_t *)malloc(sizeof(clinkedlist_node_t)); + new_node->data = data; + new_node->next = node->next; + node->next = new_node; + if(list->tail == node) list->tail = new_node; + list->length++; + return new_node; +} + +void *clinkedlist_remove(clinkedlist_t *list, clinkedlist_node_t *node){ + if(list == NULL || node == NULL || list->head == NULL) return NULL; + if(node == list->head){ + return clinkedlist_pop_front(list); + } + clinkedlist_node_t *prev = list->head; + while(prev->next && prev->next != node){ + prev = prev->next; + } + if(prev->next != node) return NULL; + prev->next = node->next; + if(node == list->tail) list->tail = prev; + void *data = node->data; + list->length--; + free(node, sizeof(clinkedlist_node_t)); + return data; +} + +void clinkedlist_update(clinkedlist_t *list, clinkedlist_node_t *node, void *new_data){ + (void)list; + if(node) node->data = new_data; +} + +uint64_t clinkedlist_length(const clinkedlist_t *list){ + return list ? list->length : 0; +} + +uint64_t clinkedlist_size_bytes(const clinkedlist_t *list){ + return list ? list->length * sizeof(clinkedlist_node_t) : 0; +} + +clinkedlist_node_t *clinkedlist_find(clinkedlist_t *list, void *key, int (*cmp)(void *, void *)){ + if(list == NULL || cmp == NULL) return NULL; + clinkedlist_node_t *it = list->head; + while(it){ + if(cmp(it->data, key) == 0) return it; + it = it->next; + } + return NULL; +} + +void clinkedlist_for_each(const clinkedlist_t *list, void (*func)(void *)){ + if(list == NULL || func == NULL) return; + clinkedlist_node_t *it = list->head; + while(it){ + func(it->data); + it = it->next; + } +} diff --git a/shared/data_struct/linked_list.h b/shared/data_struct/linked_list.h new file mode 100644 index 00000000..4e27a8eb --- /dev/null +++ b/shared/data_struct/linked_list.h @@ -0,0 +1,37 @@ +#pragma once +#include "types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct clinkedlist_node { + void *data; + struct clinkedlist_node *next; +} clinkedlist_node_t; + +typedef struct clinkedlist { + clinkedlist_node_t *head; + clinkedlist_node_t *tail; + uint64_t length; +} clinkedlist_t; + +extern uintptr_t malloc(uint64_t size); +extern void free(void *ptr, uint64_t size); + +clinkedlist_t *clinkedlist_create(void); +void clinkedlist_destroy(clinkedlist_t *list); +clinkedlist_t *clinkedlist_clone(const clinkedlist_t *list); +void clinkedlist_push_front(clinkedlist_t *list, void *data); +void *clinkedlist_pop_front(clinkedlist_t *list); +clinkedlist_node_t *clinkedlist_insert_after(clinkedlist_t *list, clinkedlist_node_t *node, void *data); +void *clinkedlist_remove(clinkedlist_t *list, clinkedlist_node_t *node); +void clinkedlist_update(clinkedlist_t *list, clinkedlist_node_t *node, void *new_data); +uint64_t clinkedlist_length(const clinkedlist_t *list); +uint64_t clinkedlist_size_bytes(const clinkedlist_t *list); +clinkedlist_node_t *clinkedlist_find(clinkedlist_t *list, void *key, int (*cmp)(void *, void *)); +void clinkedlist_for_each(const clinkedlist_t *list, void (*func)(void *)); + +#ifdef __cplusplus +} +#endif diff --git a/shared/data_struct/linked_list.hpp b/shared/data_struct/linked_list.hpp new file mode 100644 index 00000000..b4781fb1 --- /dev/null +++ b/shared/data_struct/linked_list.hpp @@ -0,0 +1,139 @@ +#pragma once +#include "types.h" + +extern "C" { +#include "linked_list.h" +} + +template +class LinkedList { +private: + struct Node { + T data; + Node* next; + }; + + Node* head = nullptr; + Node* tail = nullptr; + uint64_t length = 0; + + Node* alloc_node(const T& value) { + uintptr_t mem = malloc(sizeof(Node)); + Node* n = reinterpret_cast(mem); + n->data = value; + n->next = nullptr; + return n; + } + + void free_node(Node* n) { + free(n, sizeof(Node)); + } + +public: + LinkedList() = default; + + LinkedList(const LinkedList& other) { + for (Node* it = other.head; it; it = it->next) { + push_front(it->data); + } + LinkedList tmp; + while (!empty()) tmp.push_front(pop_front()); + *this = tmp; + } + + ~LinkedList() { + while (!empty()) pop_front(); + } + + LinkedList& operator=(const LinkedList& other) { + if (this != &other) { + while (!empty()) pop_front(); + for (Node* it = other.head; it; it = it->next) { + push_front(it->data); + } + LinkedList tmp; + while (!empty()) tmp.push_front(pop_front()); + head = tmp.head; + tail = tmp.tail; + length = tmp.length; + tmp.head = tmp.tail = nullptr; + tmp.length = 0; + } + return *this; + } + + void push_front(const T& value) { + Node* n = alloc_node(value); + n->next = head; + head = n; + if (!tail) tail = n; + ++length; + } + + T pop_front() { + if (!head) return T(); + Node* n = head; + head = head->next; + if (!head) tail = nullptr; + T val = n->data; + free_node(n); + --length; + return val; + } + + Node* insert_after(Node* node, const T& value) { + if (!node) { + push_front(value); + return head; + } + Node* n = alloc_node(value); + n->next = node->next; + node->next = n; + if (tail == node) tail = n; + ++length; + return n; + } + + T remove(Node* node) { + if (!node) return T(); + if (node == head) return pop_front(); + Node* prev = head; + while (prev && prev->next != node) prev = prev->next; + if (!prev) return T(); + prev->next = node->next; + if (node == tail) tail = prev; + T val = node->data; + free_node(node); + --length; + return val; + } + + void update(Node* node, const T& value) { + if (node) node->data = value; + } + + uint64_t size() const { + return length; + } + + bool empty() const { + return length == 0; + } + + Node* begin() const { + return head; + } + + Node* end() const { + return nullptr; + } + + template + Node* find(Predicate pred) const { + for (Node* it = head; it; it = it->next) { + if (pred(it->data)) return it; + } + return nullptr; + } +}; + diff --git a/shared/data_struct/queue.c b/shared/data_struct/queue.c new file mode 100644 index 00000000..957ea22d --- /dev/null +++ b/shared/data_struct/queue.c @@ -0,0 +1,69 @@ +#include "queue.h" +#include "std/memfunctions.h" + +void cqueue_init(CQueue* q, uint64_t max_capacity, uint64_t elem_size) { + q->buffer = NULL; + q->capacity = max_capacity; + q->max_capacity = max_capacity; + q->elem_size = elem_size; + q->head = q->tail = q->length = 0; + if (max_capacity > 0) { + uintptr_t b = malloc(max_capacity * elem_size); + if (b) q->buffer = (void*)b; + } +} + +int32_t cqueue_enqueue(CQueue* q, const void* item) { + if (!q) return 0; + if (q->max_capacity > 0) { + if (q->length == q->capacity) return 0; + } else { + if (q->length == q->capacity) { + uint64_t nc = q->capacity > 0 ? q->capacity * 2 : 4; + uintptr_t nb = malloc(nc * q->elem_size); + if (!nb) return 0; + void* newb = (void*)nb; + for (uint64_t i = 0; i < q->length; ++i) { + uint64_t idx = (q->tail + i) % q->capacity; + memcpy((uint8_t*)newb + i * q->elem_size, + (uint8_t*)q->buffer + idx * q->elem_size, + q->elem_size); + } + if (q->buffer) free(q->buffer, q->capacity * q->elem_size); + q->buffer = newb; + q->capacity = nc; + q->head = q->length; + q->tail = 0; + } + } + memcpy((uint8_t*)q->buffer + q->head * q->elem_size, item, q->elem_size); + q->head = (q->head + 1) % q->capacity; + q->length++; + return 1; +} + +int32_t cqueue_dequeue(CQueue* q, void* out) { + if (!q || q->length == 0) return 0; + memcpy(out, (uint8_t*)q->buffer + q->tail * q->elem_size, q->elem_size); + q->tail = (q->tail + 1) % q->capacity; + q->length--; + return 1; +} + +int32_t cqueue_is_empty(const CQueue* q) { + return (!q || q->length == 0) ? 1 : 0; +} + +uint64_t cqueue_size(const CQueue* q) { + return q ? q->length : 0; +} + +void cqueue_clear(CQueue* q) { + if (!q) return; + q->head = q->tail = q->length = 0; +} + +void cqueue_destroy(CQueue* q) { + if (!q) return; + if (q->buffer) free(q->buffer, q->capacity * q->elem_size); +} diff --git a/shared/data_struct/queue.h b/shared/data_struct/queue.h new file mode 100644 index 00000000..531d3089 --- /dev/null +++ b/shared/data_struct/queue.h @@ -0,0 +1,31 @@ +#pragma once +#include "types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct CQueue { + void* buffer; + uint64_t capacity; // current queue size + uint64_t max_capacity; // 0 = infinite + uint64_t elem_size; + uint64_t head; + uint64_t tail; + uint64_t length; +} CQueue; + +extern uintptr_t malloc(uint64_t); +extern void free(void*, uint64_t); + +void cqueue_init(CQueue* q, uint64_t max_capacity, uint64_t elem_size); +int32_t cqueue_enqueue(CQueue* q, const void* item); +int32_t cqueue_dequeue(CQueue* q, void* out); +int32_t cqueue_is_empty(const CQueue* q); +uint64_t cqueue_size(const CQueue* q); +void cqueue_clear(CQueue* q); +void cqueue_destroy(CQueue* q); + +#ifdef __cplusplus +} +#endif diff --git a/shared/data_struct/queue.hpp b/shared/data_struct/queue.hpp new file mode 100644 index 00000000..fe02fb9c --- /dev/null +++ b/shared/data_struct/queue.hpp @@ -0,0 +1,87 @@ +#pragma once +#include "types.h" +#include "std/string.h" +#include "std/memfunctions.h" +#include "queue.h" + +template +class Queue { +public: + explicit Queue(uint64_t capacity = 0) { + max_capacity = capacity; + this->capacity = capacity; + if (capacity > 0) { + uintptr_t mem = malloc(capacity * sizeof(T)); + if (mem) { + buffer = reinterpret_cast(mem); + } + } + } + + ~Queue() { + if (buffer) { + free(buffer, capacity * sizeof(T)); + } + } + + bool enqueue(const T& value) { + if (max_capacity > 0 && length == capacity) return false; + if (max_capacity == 0 && length == capacity) grow_if_needed(); + if (!buffer) return false; + + buffer[head] = value; + head = (head + 1) % capacity; + ++length; + return true; + } + + bool dequeue(T& out) { + if (length == 0 || !buffer) return false; + out = buffer[tail]; + tail = (tail + 1) % capacity; + --length; + return true; + } + + bool is_empty() const { + return length == 0; + } + + uint64_t size() const { + return length; + } + + void clear() { + head = tail = length = 0; + } + +private: + T* buffer = nullptr; + uint64_t capacity = 0; + uint64_t max_capacity = 0; // 0 infinite + uint64_t head = 0; + uint64_t tail = 0; + uint64_t length = 0; + + void grow_if_needed() { + uint64_t new_cap = (capacity > 0) ? capacity * 2 : 4; + uintptr_t new_mem = malloc(new_cap * sizeof(T)); + if (!new_mem) return; + + T* new_buf = reinterpret_cast(new_mem); + for (uint64_t i = 0; i < length; ++i) { + uint64_t idx = (tail + i) % capacity; + new_buf[i] = buffer[idx]; + } + + if (buffer) { + free(buffer, capacity * sizeof(T)); + } + + buffer = new_buf; + capacity = new_cap; + tail = 0; + head = length; + } +}; + diff --git a/shared/data_struct/ring_buffer.c b/shared/data_struct/ring_buffer.c new file mode 100644 index 00000000..67429799 --- /dev/null +++ b/shared/data_struct/ring_buffer.c @@ -0,0 +1,57 @@ +#include "ring_buffer.h" +#include "std/memfunctions.h" + +void cring_init(CRingBuffer* rb, void* storage, uint64_t capacity, uint64_t elem_size) { + rb->buffer = storage; + rb->capacity = capacity; + rb->element_size = elem_size; + rb->head = rb->tail = 0; + rb->full = 0; +} + +uint64_t cring_capacity(const CRingBuffer* rb) { + return rb->capacity; +} + +int32_t cring_push(CRingBuffer* rb, const void* item) { + if (rb->full) return 0; + + uint8_t* base = (uint8_t*)rb->buffer; + void* dest = base + (rb->head * rb->element_size); + + for (uint64_t i = 0; i < rb->element_size; ++i) { + ((uint8_t*)dest)[i] = ((const uint8_t*)item)[i]; + } + + rb->head = (rb->head + 1) % rb->capacity; + rb->full = (rb->head == rb->tail); + return 1; +} + +int32_t cring_pop(CRingBuffer* rb, void* out) { + if (!rb->full && (rb->head == rb->tail)) return 0; + + uint8_t* base = (uint8_t*)rb->buffer; + void* src = base + (rb->tail * rb->element_size); + + for (uint64_t i = 0; i < rb->element_size; ++i) { + ((uint8_t*)out)[i] = ((uint8_t*)src)[i]; + } + + rb->tail = (rb->tail + 1) % rb->capacity; + rb->full = 0; + return 1; +} + +int32_t cring_is_empty(const CRingBuffer* rb) { + return (!rb->full && (rb->head == rb->tail)); +} + +int32_t cring_is_full(const CRingBuffer* rb) { + return rb->full; +} + +void cring_clear(CRingBuffer* rb) { + rb->head = rb->tail = 0; + rb->full = 0; +} diff --git a/shared/data_struct/ring_buffer.h b/shared/data_struct/ring_buffer.h new file mode 100644 index 00000000..958b9da5 --- /dev/null +++ b/shared/data_struct/ring_buffer.h @@ -0,0 +1,27 @@ +#pragma once +#include "types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct CRingBuffer { + void* buffer; + uint64_t capacity; + uint64_t element_size; + uint64_t head; + uint64_t tail; + int32_t full; +} CRingBuffer; + +void cring_init(CRingBuffer* rb, void* storage, uint64_t capacity, uint64_t elem_size); +int32_t cring_push(CRingBuffer* rb, const void* item); +int32_t cring_pop(CRingBuffer* rb, void* out); +int32_t cring_is_empty(const CRingBuffer* rb); +int32_t cring_is_full(const CRingBuffer* rb); +void cring_clear(CRingBuffer* rb); +uint64_t cring_capacity(const CRingBuffer* rb); + +#ifdef __cplusplus +} +#endif diff --git a/shared/data_struct/ring_buffer.hpp b/shared/data_struct/ring_buffer.hpp new file mode 100644 index 00000000..c798f23f --- /dev/null +++ b/shared/data_struct/ring_buffer.hpp @@ -0,0 +1,66 @@ +#pragma once +#include "types.h" + +template +class RingBuffer { +private: + T data[Capacity]; + uint64_t head = 0; + uint64_t tail = 0; + int32_t full = 0; + +public: + RingBuffer() : head(0), tail(0), full(0) {} + + int32_t push(const T& item) { + if (full) return 0; + data[head] = item; + head = (head + 1) % Capacity; + full = (head == tail); + return 1; + } + + int32_t pop(T& out) { + if (is_empty()) return 0; + out = data[tail]; + tail = (tail + 1) % Capacity; + full = 0; + return 1; + } + + int32_t is_empty() const { + return (!full && head == tail); + } + + int32_t is_full() const { + return full; + } + + void clear() { + head = tail = 0; + full = 0; + } + + uint64_t size() const { + if (full) return Capacity; + if (head >= tail) return head - tail; + return Capacity + head - tail; + } + + static constexpr uint64_t capacity() { + return Capacity; + } + + const T& peek() const { + return data[tail]; + } + + const T& at(uint32_t index) const { + return data[(tail + index) % Capacity]; + } + + T& at(uint32_t index) { + return data[(tail + index) % Capacity]; + } +}; + diff --git a/shared/std/string.c b/shared/std/string.c index b0ee1623..f67fbe0a 100644 --- a/shared/std/string.c +++ b/shared/std/string.c @@ -3,21 +3,26 @@ #include "memory/memory_access.h" #include "std/memfunctions.h" -static uint32_t compute_length( char *s, uint32_t max_length) { +static uint32_t compute_length(char *s, uint32_t max_length){ + if (s == NULL) return 0; + uint32_t len = 0; - while ((max_length == 0 || len < max_length) && s[len] != '\0') { - len++; - } + while ((max_length == 0 || len < max_length) && s[len] != '\0') len++; + return len; } -string string_l( char *literal) { +string string_l(char *literal){ + if (literal == NULL) return (string){ .data = NULL, .length = 0, .mem_length = 0}; + uint32_t len = compute_length(literal, 0); - char *buf = (char*)malloc(len+1); - for (uint32_t i = 0; i < len; i++) - buf[i] = literal[i]; - buf[len] = 0; - return (string){ .data = buf, .length = len, .mem_length = len+1 }; + char *buf = (char*)malloc(len + 1); + if (!buf) return (string){ .data = NULL, .length = 0, .mem_length = 0 }; + + for (uint32_t i = 0; i < len; i++) buf[i] = literal[i]; + + buf[len] = '\0'; + return (string){ .data = buf, .length = len, .mem_length = len + 1 }; } string string_repeat(char symbol, uint32_t amount){ @@ -27,33 +32,42 @@ string string_repeat(char symbol, uint32_t amount){ return (string){ .data = buf, .length = amount, .mem_length = amount+1 }; } -string string_tail( char *array, uint32_t max_length){ +string string_tail(char *array, uint32_t max_length){ + + if (array == NULL) return (string){ .data = NULL, .length = 0, .mem_length = 0 }; + uint32_t len = compute_length(array, 0); - int offset = len-max_length; - if (offset < 0) - offset = 0; + int offset = (int)len - (int)max_length; + if (offset < 0) offset = 0; + uint32_t adjusted_len = len - offset; char *buf = (char*)malloc(adjusted_len + 1); - for (uint32_t i = offset; i < len; i++) - buf[i-offset] = array[i]; - buf[len-offset] = 0; - return (string){ .data = buf, .length = adjusted_len }; + if (!buf) return (string){ .data = NULL, .length = 0, .mem_length = 0 }; + + for (uint32_t i = 0; i < adjusted_len; i++) buf[i] = array[offset + i]; + + buf[adjusted_len] = '\0'; + return (string){.data = buf, .length = adjusted_len, .mem_length = adjusted_len + 1 }; } -string string_ca_max( char *array, uint32_t max_length) { +string string_ca_max(char *array, uint32_t max_length){ + if (array == NULL) return (string){.data = NULL, .length = 0, .mem_length= 0 }; + uint32_t len = compute_length(array, max_length); char *buf = (char*)malloc(len + 1); - for (uint32_t i = 0; i < len; i++) - buf[i] = array[i]; - buf[len] = 0; - return (string){ .data = buf, .length = len }; + if(!buf) return (string){ .data = NULL, .length = 0, .mem_length=0 }; + + for (uint32_t i = 0; i < len; i++) buf[i] = array[i]; + + buf[len] = '\0'; + return (string){ .data = buf, .length = len, .mem_length = len+1}; } string string_c( char c){ char *buf = (char*)malloc(2); buf[0] = c; buf[1] = 0; - return (string){ .data = buf, .length = 1, .mem_length = 2 }; + return (string){.data = buf, .length = 1, .mem_length = 2}; } uint32_t parse_hex(uint64_t value, char* buf){ @@ -68,6 +82,7 @@ uint32_t parse_hex(uint64_t value, char* buf){ started = true; buf[len++] = curr_char; } + if (i == 0) break; } @@ -75,7 +90,7 @@ uint32_t parse_hex(uint64_t value, char* buf){ return len; } -string string_from_hex(uint64_t value) { +string string_from_hex(uint64_t value){ char *buf = (char*)malloc(18); uint32_t len = parse_hex(value, buf); return (string){ .data = buf, .length = len, .mem_length = 18 }; @@ -86,12 +101,13 @@ uint32_t parse_bin(uint64_t value, char* buf){ buf[len++] = '0'; buf[len++] = 'b'; bool started = false; - for (uint32_t i = 63;; i --) { + for (uint32_t i = 63;; i --){ char bit = (value >> i) & 1 ? '1' : '0'; - if (started || bit != '0' || i == 0) { + if (started || bit != '0' || i == 0){ started = true; buf[len++] = bit; } + if (i == 0) break; } @@ -99,45 +115,51 @@ uint32_t parse_bin(uint64_t value, char* buf){ return len; } -string string_from_bin(uint64_t value) { +string string_from_bin(uint64_t value){ char *buf = (char*)malloc(66); uint32_t len = parse_bin(value, buf); return (string){ .data = buf, .length = len, .mem_length = 66 }; } -bool string_equals(string a, string b) { +bool string_equals(string a, string b){ return strcmp(a.data,b.data, false) == 0; } -string string_format( char *fmt, ...) { +string string_format(char *fmt, ...){ + if (fmt == NULL) return (string){ .data = NULL, .length = 0, .mem_length = 0}; + va_list args; va_start(args, fmt); - string_format_va(fmt, args); + string result = string_format_va(fmt, args); va_end(args); + return result; } -string string_format_va( char *fmt, va_list args){ +string string_format_va(char *fmt, va_list args){ char *buf = (char*)malloc(256); uint32_t len = 0; uint32_t arg_index = 0; - - for (uint32_t i = 0; fmt[i] && len < 255; i++) { - if (fmt[i] == '%' && fmt[i+1]) { + for (uint32_t i = 0; fmt[i] && len < 255; i++){ + if (fmt[i] == '%' && fmt[i+1]){ i++; - if (fmt[i] == 'x') { + if (fmt[i] == 'x'){ uint64_t val = va_arg(args, uint64_t); len += parse_hex(val,(char*)(buf + len)); + } else if (fmt[i] == 'b') { uint64_t val = va_arg(args, uint64_t); string bin = string_from_bin(val); - for (uint32_t j = 0; j < bin.length && len < 255; j++) buf[len++] = bin.data[j]; + for(uint32_t j = 0; j < bin.length && len < 255; j++) buf[len++] = bin.data[j]; free(bin.data,bin.mem_length); + } else if (fmt[i] == 'c') { uint64_t val = va_arg(args, uint64_t); buf[len++] = (char)val; + } else if (fmt[i] == 's') { char *str = ( char *)va_arg(args, uintptr_t); for (uint32_t j = 0; str[j] && len < 255; j++) buf[len++] = str[j]; + } else if (fmt[i] == 'i') { uint64_t val = va_arg(args, long int); char temp[21]; @@ -149,38 +171,36 @@ string string_format_va( char *fmt, va_list args){ buf[len++] = '-'; val = (uint64_t)(-(int)val); } - + do { temp[temp_len++] = '0' + (val % 10); val /= 10; } while (val && temp_len < 20); - for (int j = temp_len - 1; j >= 0 && len < 255; j--) { + for (int j = temp_len - 1; j >= 0 && len < 255; j--){ buf[len++] = temp[j]; } - }else if (fmt[i] == 'f' || fmt[i] == 'd') { + } else if (fmt[i] == 'f' || fmt[i] == 'd') { double val = va_arg(args, double); - if (val < 0) { + if (val < 0){ buf[len++] = '-'; val = -val; } - uint64_t whole = (uint64_t)val; double frac = val - (double)whole; char temp[21]; uint32_t temp_len = 0; do { - temp[temp_len++] = '0' + (whole % 10); + temp[temp_len++] = '0' +(whole % 10); whole /= 10; - } while (whole && temp_len < 20); + } while(whole && temp_len < 20); - for (int j = temp_len - 1; j >= 0 && len < 255; j--) { + for (int j = temp_len - 1; j >= 0 && len < 255; j--){ buf[len++] = temp[j]; } - if (len < 255) buf[len++] = '.'; - + for (int d = 0; d < 6 && len < 255; d++) { frac *= 10; int digit = (int)frac; @@ -196,7 +216,7 @@ string string_format_va( char *fmt, va_list args){ } } - buf[len] = 0; + buf[len]=0; return (string){ .data = buf, .length = len, .mem_length = 256 }; } @@ -205,31 +225,33 @@ char tolower(char c){ return c; } -int strcmp(char *a, char *b, bool case_insensitive) { - while (*a && *b) { +int strcmp(char *a, char *b, bool case_insensitive){ + if (a == NULL && b == NULL)return 0; //i guess + if (a == NULL) return -1; + if (b == NULL) return 1; + + while (*a && *b){ char ca = *a; char cb = *b; - - if (case_insensitive) { + if (case_insensitive){ ca = tolower((unsigned char)ca); cb = tolower((unsigned char)cb); } - - if (ca != cb) return ca - cb; - + if (ca != cb) return ca - cb; a++; b++; } - if (case_insensitive) return tolower(*a) - tolower(*b); - return *a - *b; + if (case_insensitive) return tolower((unsigned char)*a) - tolower((unsigned char)*b); + + return (unsigned char)*a - (unsigned char)*b; } -int strstart(char *a, char *b, bool case_insensitive) { +int strstart(char *a, char *b, bool case_insensitive){ int index = 0; - while (*a && *b) { + while (*a && *b){ char ca = *a; char cb = *b; - if (case_insensitive) { + if (case_insensitive){ ca = tolower(ca); cb = tolower(cb); } @@ -240,8 +262,8 @@ int strstart(char *a, char *b, bool case_insensitive) { return 0; } -int strindex( char *a, char *b) { - for (int i = 0; a[i]; i++) { +int strindex( char *a, char *b){ + for (int i = 0; a[i]; i++){ int j = 0; while (b[j] && a[i + j] == b[j]) j++; if (!b[j]) return i; @@ -249,14 +271,14 @@ int strindex( char *a, char *b) { return -1; } -int strend(char *a, char *b, bool case_insensitive) { - while (*a && *b) { +int strend(char *a, char *b, bool case_insensitive){ + while (*a && *b){ char ca = case_insensitive ? tolower((unsigned char)*a) : *a; char cb = case_insensitive ? tolower((unsigned char)*b) : *b; - if (ca == cb) { + if (ca == cb){ char *pa = a, *pb = b; - while (1) { + while (1){ char cpa = case_insensitive ? tolower((unsigned char)*pa) : *pa; char cpb = case_insensitive ? tolower((unsigned char)*pb) : *pb; @@ -271,10 +293,10 @@ int strend(char *a, char *b, bool case_insensitive) { return 1; } -bool strcont( char *a, char *b) { - while (*a) { +bool strcont( char *a, char *b){ + while (*a){ char *p = a, *q = b; - while (*p && *q && *p == *q) { + while (*p && *q && *p == *q){ p++; q++; } if (*q == 0) return 1; @@ -283,7 +305,7 @@ bool strcont( char *a, char *b) { return 0; } -bool utf16tochar( uint16_t* str_in, char* out_str, size_t max_len) { +bool utf16tochar(uint16_t* str_in, char* out_str, size_t max_len){ size_t out_i = 0; for (int i = 0; i < max_len && str_in[i]; i++){ uint16_t wc = str_in[i]; @@ -293,9 +315,9 @@ bool utf16tochar( uint16_t* str_in, char* out_str, size_t max_len) { return true; } -uint64_t parse_hex_u64(char* str, size_t size) { +uint64_t parse_hex_u64(char* str, size_t size){ uint64_t result = 0; - for (uint32_t i = 0; i < size; i++) { + for (uint32_t i = 0; i < size; i++){ char c = str[i]; uint8_t digit = 0; if (c >= '0' && c <= '9') digit = c - '0'; @@ -305,4 +327,4 @@ uint64_t parse_hex_u64(char* str, size_t size) { result = (result << 4) | digit; } return result; -} \ No newline at end of file +} diff --git a/user/Makefile b/user/Makefile index fb6b8328..a9799437 100644 --- a/user/Makefile +++ b/user/Makefile @@ -1,25 +1,24 @@ -ARCH= aarch64-none-elf -CC = $(ARCH)-gcc -LD = $(ARCH)-ld -OBJCOPY = $(ARCH)-objcopy +#user +CFLAGS := $(CFLAGS_BASE) -I. -I../shared -Wno-unused-parameter +LDFLAGS := -T $(shell ls *.ld) -CFLAGS = -g -O0 -std=c17 -nostdlib -ffreestanding -Wall -Wextra -mcpu=cortex-a72 -I. -I../shared -Wno-unused-parameter -LDFLAGS = -T $(shell ls *.ld) +CLEAN_OBJS := $(shell find . -name '*.o') +C_SRC := $(shell find . -name '*.c') +CPP_SRC := $(shell find . -name '*.cpp') +OBJ := $(C_SRC:.c=.o) $(CPP_SRC:.cpp=.o) -C_SRC = $(shell find . -name '*.c') -CPP_SRC = $(shell find . -name '*.cpp') -OBJ = $(C_SRC:.c=.o) $(CPP_SRC:.cpp=.o) +NAME := $(notdir $(CURDIR)) +ELF := $(NAME).elf +TARGET := $(NAME).bin +LOCATION := ../fs/redos/user/ -NAME = $(shell basename "$$PWD") -TARGET = $(NAME).bin -ELF = $(NAME).elf -LOCATION = ../fs/redos/user/ +.PHONY: all clean -all: $(TARGET) +all: $(LOCATION)$(TARGET) -$(TARGET): $(OBJ) +$(LOCATION)$(TARGET): $(OBJ) $(LD) $(LDFLAGS) -o $(LOCATION)$(ELF) $(OBJ) ../shared/libshared.a - $(OBJCOPY) -O binary $(LOCATION)$(ELF) $(LOCATION)$(TARGET) + $(OBJCOPY) -O binary $(LOCATION)$(ELF) $@ %.o: %.S $(CC) $(CFLAGS) -c $< -o $@ @@ -28,7 +27,7 @@ $(TARGET): $(OBJ) $(CC) $(CFLAGS) -c $< -o $@ %.o: %.cpp - $(CC) $(CFLAGS) -c $< -o $@ + $(CC) $(CFLAGS) -fno-rtti -c $< -o $@ clean: - rm -f $(shell find . -name '*.o') $(TARGET) \ No newline at end of file + rm -f $(CLEAN_OBJS) $(TARGET)