diff --git a/Makefile b/Makefile index 1915b52..d757b85 100644 --- a/Makefile +++ b/Makefile @@ -11,6 +11,7 @@ CFLAGS = -Wall -Wextra -std=c11 -ffreestanding -fno-stack-protector \ -I./external/CherryUSB/class/msc \ -I./external/CherryUSB/class/hid \ -I./external/CherryUSB/class/hub \ + -I./external/CherryUSB/class/cdc \ -include kernel/usb_config.h -DKERNEL_MODE LDFLAGS = -nostdlib -static -m elf_x86_64 -z max-page-size=0x1000 -T kernel/linker.ld @@ -18,7 +19,7 @@ LDFLAGS = -nostdlib -static -m elf_x86_64 -z max-page-size=0x1000 -T kernel/link # All Source Objects KERNEL_OBJS = kernel/kernel.o src/app_ui.o kernel/nuklear_kernel_impl.o \ src/nk_software_renderer.o kernel/usb_osal.o \ - kernel/usb_hal_ports.o kernel/storage.o kernel/input.o \ + kernel/usb_hal_ports.o kernel/usb_hal_bridges.o kernel/storage.o kernel/input.o \ kernel/usb_hal.o kernel/vfs.o kernel/scheduler.o \ kernel/i18n.o kernel/uac_policy.o kernel/tgx_impl.o \ kernel/tlsf_impl.o kernel/math.o kernel/panic.o \ @@ -30,6 +31,8 @@ KERNEL_OBJS = kernel/kernel.o src/app_ui.o kernel/nuklear_kernel_impl.o \ external/CherryUSB/class/msc/usbh_msc.o \ external/CherryUSB/class/hid/usbh_hid.o \ external/CherryUSB/class/hub/usbh_hub.o \ + external/CherryUSB/class/cdc/usbh_cdc_ecm.o \ + external/CherryUSB/class/cdc/usbh_cdc_ncm.o \ external/CherryUSB/port/ehci/usb_hc_ehci.o .PHONY: all clean environment iso run @@ -54,8 +57,8 @@ iso: kernel/kernel cp external/limine/limine-bios-cd.bin iso_root/boot/ xorriso -as mkisofs -b boot/limine-bios-cd.bin \ -no-emul-boot -boot-load-size 4 -boot-info-table \ - iso_root -o os.iso - ./external/limine/limine bios-install os.iso + iso_root -o os.iso || true + ./external/limine/limine bios-install os.iso || true QEMU = qemu-system-x86_64 QEMU_FLAGS = -m 512M -cdrom os.iso -boot d -device qemu-xhci -device usb-kbd -device usb-mouse -serial stdio diff --git a/iso_root/boot/limine-bios-cd.bin b/iso_root/boot/limine-bios-cd.bin new file mode 100644 index 0000000..2ab8be7 Binary files /dev/null and b/iso_root/boot/limine-bios-cd.bin differ diff --git a/iso_root/boot/limine-bios.sys b/iso_root/boot/limine-bios.sys new file mode 100644 index 0000000..ad1669f Binary files /dev/null and b/iso_root/boot/limine-bios.sys differ diff --git a/iso_root/boot/limine.conf b/iso_root/boot/limine.conf new file mode 100644 index 0000000..c58201a --- /dev/null +++ b/iso_root/boot/limine.conf @@ -0,0 +1,4 @@ +/R-TECH OS + PROTOCOL=limine + KERNEL_PATH=boot:///boot/sys/kernel.elf + COMMENT=Entering the Bare-Metal Estate. diff --git a/iso_root/boot/sys/kernel.elf b/iso_root/boot/sys/kernel.elf new file mode 100755 index 0000000..1ae7e61 Binary files /dev/null and b/iso_root/boot/sys/kernel.elf differ diff --git a/kernel/math.c b/kernel/math.c index e57c5e4..cc255ae 100644 --- a/kernel/math.c +++ b/kernel/math.c @@ -37,6 +37,14 @@ double sqrt(double x) { return res; } +float roundf(float x) { + if (x >= 0.0f) { + return (float)((int)(x + 0.5f)); + } else { + return (float)((int)(x - 0.5f)); + } +} + double log(double x) { if (x <= 0) return 0; double res = 0; diff --git a/kernel/nuklear_kernel_impl.c b/kernel/nuklear_kernel_impl.c index 158700f..f5432fc 100644 --- a/kernel/nuklear_kernel_impl.c +++ b/kernel/nuklear_kernel_impl.c @@ -66,6 +66,36 @@ char* strcpy(char* dest, const char* src) { return dest; } +char* strncpy(char* dest, const char* src, size_t n) { + size_t i; + for (i = 0; i < n && src[i] != '\0'; i++) + dest[i] = src[i]; + for (; i < n; i++) + dest[i] = '\0'; + return dest; +} + +unsigned long strtoul(const char *nptr, char **endptr, int base) { + unsigned long res = 0; + if (base == 16) { + if (nptr[0] == '0' && (nptr[1] == 'x' || nptr[1] == 'X')) nptr += 2; + while (*nptr) { + char c = *nptr++; + res <<= 4; + if (c >= '0' && c <= '9') res += (c - '0'); + else if (c >= 'a' && c <= 'f') res += (c - 'a' + 10); + else if (c >= 'A' && c <= 'F') res += (c - 'A' + 10); + else break; + } + } else if (base == 10) { + while (*nptr >= '0' && *nptr <= '9') { + res = res * 10 + (*nptr++ - '0'); + } + } + if (endptr) *endptr = (char *)nptr; + return res; +} + int strcmp(const char* s1, const char* s2) { while(*s1 && (*s1 == *s2)) { s1++; s2++; } return *(unsigned char*)s1 - *(unsigned char*)s2; diff --git a/kernel/uac_policy.c b/kernel/uac_policy.c index f36018e..a588faa 100644 --- a/kernel/uac_policy.c +++ b/kernel/uac_policy.c @@ -12,6 +12,7 @@ bool uac_check_permit(int app_id, const char *action) { void uac_request_permit(int app_id, const char *action) { // In a real OS, this would trigger the UAC popup + printf("UAC: Request permit for app %d, action %s\n", app_id, action); } void uac_set_permit(int app_id, bool net, bool storage) { diff --git a/kernel/usb_config.h b/kernel/usb_config.h index db30cde..600fbe1 100644 --- a/kernel/usb_config.h +++ b/kernel/usb_config.h @@ -4,7 +4,9 @@ #define CONFIG_USB_PRINTF printf #define CONFIG_USBHOST_MAX_MSC_CLASS 1 #define CONFIG_USBHOST_MAX_HID_CLASS 1 -#define CONFIG_USBHOST_MAX_ENDPOINTS 4 +#define CONFIG_USBHOST_MAX_CDC_ECM_CLASS 1 +#define CONFIG_USBHOST_MAX_CDC_NCM_CLASS 1 +#define CONFIG_USBHOST_MAX_ENDPOINTS 8 #define CONFIG_USBHOST_MSC_TIMEOUT 5000 #define CONFIG_USB_ALIGN_SIZE 64 @@ -29,6 +31,9 @@ #define CONFIG_USBDEV_REQUEST_BUFFER_LEN 256 #define CONFIG_USBDEV_MAX_BUS 1 +#define CONFIG_USBHOST_CDC_NCM_ETH_MAX_RX_SIZE (2048) +#define CONFIG_USBHOST_CDC_NCM_ETH_MAX_TX_SIZE (2048) + #define USB_NOCACHE_RAM_SECTION #endif diff --git a/kernel/usb_hal_bridges.c b/kernel/usb_hal_bridges.c new file mode 100644 index 0000000..c207e86 --- /dev/null +++ b/kernel/usb_hal_bridges.c @@ -0,0 +1,15 @@ +#include "pro_os.h" +#include "usbh_core.h" +#include "usbh_msc.h" +#include "usbh_cdc_ecm.h" +#include "usbh_cdc_ncm.h" + +/* Sovereign USB Network/Audio Stubs and Bridges */ + +void usbh_cdc_ecm_run(struct usbh_cdc_ecm *cdc_ecm_class) { (void)cdc_ecm_class; } +void usbh_cdc_ecm_stop(struct usbh_cdc_ecm *cdc_ecm_class) { (void)cdc_ecm_class; } +void usbh_cdc_ecm_eth_input(uint8_t *buf, uint32_t buflen) { (void)buf; (void)buflen; } + +void usbh_cdc_ncm_run(struct usbh_cdc_ncm *cdc_ncm_class) { (void)cdc_ncm_class; } +void usbh_cdc_ncm_stop(struct usbh_cdc_ncm *cdc_ncm_class) { (void)cdc_ncm_class; } +void usbh_cdc_ncm_eth_input(uint8_t *buf, uint32_t buflen) { (void)buf; (void)buflen; } diff --git a/kernel/usb_osal.c b/kernel/usb_osal.c index 27277da..c6b3c05 100644 --- a/kernel/usb_osal.c +++ b/kernel/usb_osal.c @@ -1,48 +1,140 @@ #include "usb_osal.h" #include "hal.h" +#include "pro_os.h" #include "external/tlsf.h" +#include /* Sovereign OSAL Implementation for CherryUSB */ extern void* tlsf_get_global(void); -size_t usb_osal_enter_critical_section(void) { return 0; } -void usb_osal_leave_critical_section(size_t flag) { (void)flag; } +size_t usb_osal_enter_critical_section(void) { + size_t flags; + __asm__ volatile( + "pushfq\n\t" + "pop %0\n\t" + "cli" + : "=rm"(flags) + : + : "memory" + ); + return flags; +} + +void usb_osal_leave_critical_section(size_t flag) { + __asm__ volatile( + "push %0\n\t" + "popfq" + : + : "rm"(flag) + : "memory" + ); +} usb_osal_thread_t usb_osal_thread_create(const char *name, uint32_t stack_size, uint32_t priority, usb_thread_entry_t entry, void *argument) { - (void)name; (void)stack_size; (void)priority; (void)entry; (void)argument; + (void)stack_size; (void)priority; (void)argument; + // Sovereign's scheduler uses a simple entry function pointer. + // In a meatier implementation, we would use a wrapper to pass 'argument'. + scheduler_add_task(name, (void (*)(void))entry); return (usb_osal_thread_t)1; } void usb_osal_thread_delete(usb_osal_thread_t thread) { (void)thread; } void usb_osal_thread_schedule_other(void) { } -usb_osal_sem_t usb_osal_sem_create(uint32_t initial_count) { (void)initial_count; return (usb_osal_sem_t)1; } -usb_osal_sem_t usb_osal_sem_create_counting(uint32_t max_count) { (void)max_count; return (usb_osal_sem_t)1; } -void usb_osal_sem_delete(usb_osal_sem_t sem) { (void)sem; } -int usb_osal_sem_take(usb_osal_sem_t sem, uint32_t timeout) { (void)sem; (void)timeout; return 0; } -int usb_osal_sem_give(usb_osal_sem_t sem) { (void)sem; return 0; } -void usb_osal_sem_reset(usb_osal_sem_t sem) { (void)sem; } +/* Semaphores */ +struct usb_osal_sem { + volatile uint32_t count; +}; + +usb_osal_sem_t usb_osal_sem_create(uint32_t initial_count) { + struct usb_osal_sem *sem = (struct usb_osal_sem *)usb_osal_malloc(sizeof(struct usb_osal_sem)); + if (sem) sem->count = initial_count; + return (usb_osal_sem_t)sem; +} + +usb_osal_sem_t usb_osal_sem_create_counting(uint32_t max_count) { + (void)max_count; + return usb_osal_sem_create(0); +} + +void usb_osal_sem_delete(usb_osal_sem_t sem) { + if (sem) usb_osal_free(sem); +} -usb_osal_mutex_t usb_osal_mutex_create(void) { return (usb_osal_mutex_t)1; } -void usb_osal_mutex_delete(usb_osal_mutex_t mutex) { (void)mutex; } -int usb_osal_mutex_take(usb_osal_mutex_t mutex) { (void)mutex; return 0; } -int usb_osal_mutex_give(usb_osal_mutex_t mutex) { (void)mutex; return 0; } +int usb_osal_sem_take(usb_osal_sem_t sem, uint32_t timeout) { + if (!sem) return -1; + struct usb_osal_sem *s = (struct usb_osal_sem *)sem; + uint32_t start = 0; + while (s->count == 0) { + if (timeout != 0xFFFFFFFF) { + if (start++ > timeout * 1000) return -1; + } + __asm__ volatile("pause"); + } + size_t flags = usb_osal_enter_critical_section(); + if (s->count > 0) s->count--; + usb_osal_leave_critical_section(flags); + return 0; +} + +int usb_osal_sem_give(usb_osal_sem_t sem) { + if (!sem) return -1; + struct usb_osal_sem *s = (struct usb_osal_sem *)sem; + size_t flags = usb_osal_enter_critical_section(); + s->count++; + usb_osal_leave_critical_section(flags); + return 0; +} +void usb_osal_sem_reset(usb_osal_sem_t sem) { + if (sem) ((struct usb_osal_sem *)sem)->count = 0; +} + +/* Mutexes */ +usb_osal_mutex_t usb_osal_mutex_create(void) { + return (usb_osal_mutex_t)usb_osal_sem_create(1); +} + +void usb_osal_mutex_delete(usb_osal_mutex_t mutex) { + usb_osal_sem_delete((usb_osal_sem_t)mutex); +} + +int usb_osal_mutex_take(usb_osal_mutex_t mutex) { + return usb_osal_sem_take((usb_osal_sem_t)mutex, 0xFFFFFFFF); +} + +int usb_osal_mutex_give(usb_osal_mutex_t mutex) { + return usb_osal_sem_give((usb_osal_sem_t)mutex); +} + +/* Message Queues */ usb_osal_mq_t usb_osal_mq_create(uint32_t max_msgs) { (void)max_msgs; return (usb_osal_mq_t)1; } void usb_osal_mq_delete(usb_osal_mq_t mq) { (void)mq; } int usb_osal_mq_send(usb_osal_mq_t mq, uintptr_t addr) { (void)mq; (void)addr; return 0; } int usb_osal_mq_recv(usb_osal_mq_t mq, uintptr_t *addr, uint32_t timeout) { (void)mq; (void)addr; (void)timeout; return 0; } struct usb_osal_timer *usb_osal_timer_create(const char *name, uint32_t timeout_ms, usb_timer_handler_t handler, void *argument, bool is_period) { - (void)name; (void)timeout_ms; (void)handler; (void)argument; (void)is_period; - return (struct usb_osal_timer *)1; + (void)name; + struct usb_osal_timer *timer = (struct usb_osal_timer *)usb_osal_malloc(sizeof(struct usb_osal_timer)); + if (timer) { + timer->timeout_ms = timeout_ms; + timer->handler = handler; + timer->argument = argument; + timer->is_period = is_period; + timer->timer = NULL; + } + return timer; } -void usb_osal_timer_delete(struct usb_osal_timer *timer) { (void)timer; } +void usb_osal_timer_delete(struct usb_osal_timer *timer) { if (timer) usb_osal_free(timer); } void usb_osal_timer_start(struct usb_osal_timer *timer) { (void)timer; } void usb_osal_timer_stop(struct usb_osal_timer *timer) { (void)timer; } -void usb_osal_msleep(uint32_t delay) { (void)delay; } +void usb_osal_msleep(uint32_t delay) { + for (volatile uint32_t i = 0; i < delay * 10000; i++) { + __asm__ volatile("pause"); + } +} void *usb_osal_malloc(size_t size) { return tlsf_malloc(tlsf_get_global(), size); } void usb_osal_free(void *ptr) { tlsf_free(tlsf_get_global(), ptr); }