diff --git a/.config b/.config new file mode 100644 index 0000000..bf7bfb1 --- /dev/null +++ b/.config @@ -0,0 +1,11 @@ +CONFIG_DEBUG_LOGS=y +CONFIG_KERNEL_BASE=0x100000 +CONFIG_HEAP_BASE=0x2000000 +CONFIG_HEAP_SIZE_MB=8 +CONFIG_SCROLL_SPEED=10 +CONFIG_EMERALD_MODE=y +CONFIG_FG_COLOR=0xff88 +CONFIG_BG_COLOR=0x0 +CONFIG_LOAD_SHELL=y +CONFIG_OPTIMIZATION=0 +CONFIG_STRICT_CHECKS=y diff --git a/ARCHITECTURE.md b/ARCHITECTURE.md new file mode 100644 index 0000000..8cd8ae7 --- /dev/null +++ b/ARCHITECTURE.md @@ -0,0 +1,55 @@ +# OSx2 (RTECH dos) Architecture Rules + +## 1. Directory Structure +- `/boot`: UEFI bootloader types and linker scripts. +- `/include`: Public headers and RSL (RTECH Standard Library) definitions. +- `/kernel/unice64`: Core kernel logic and entry points (mains). +- `/kernel/libs`: Internal kernel services and drivers. +- `/programs`: User-space programs (e.g., shell). + +## 2. Kernel Lifecycle (The Ritual) +- `main.c` is strictly an orchestrator. It must NOT contain hardware, filesystem, or memory logic. +- Services are registered via `register_service(InitFunction)`. +- The kernel uses an event-driven flow: + - `EVENT_INIT`: Service initialization and setup. + - `EVENT_MAIN`: Main event loop execution. + - `EVENT_CLEANUP`: Shutdown preparation. + - `EVENT_EXIT`: Final termination. + +## 3. RSL (RTECH Standard Library) +- RSL is the native system language for OSx2. +- Programs must include ONLY `` and never internal kernel headers. +- High-level APIs like `readline()` and `color()` are provided for ease of use. + +## 4. Memory Model (ARC & Managed RAM) +- OSx2 implements an Automatic Reference Counting (ARC) system for managed heap objects. +- High-level RSL functions (e.g., `readline`, `str_create`) return managed pointers with an initial ref-count of 1. +- Developers use `retain()` to increment and `release()` to decrement reference counts. +- **Note:** In the current v0.x implementation, the backing store is a high-speed bump allocator. While ref-counts are tracked, memory is not yet recycled for reuse. Manual `release()` calls are currently required for future-proofing and consistency with the RSL standard. + +## 5. Storage Architecture (/CONNECT & VDISK) +- **Source of Truth**: The `/CONNECT` registry tracks all physical storage (Platters, RAM, USB). +- **Physical nodes**: Each device node has a configuration defining its Sector Size and Total LBA. +- **VDISK Suit**: A Virtual Disk abstraction layer that provides relative LBA access. +- **Signature Handshake**: VDISKs must contain the `0xDEADBEEF` signature at LBA 0 to be considered valid for mounting. +- **Error Handling**: Missing hardware or signature mismatches trigger a `CANNOT FIND DISK` or `Access Denied` error. + +## 5. Console & Input +- Console supports full vertical scrolling and manual 8x8 font rendering to the GOP framebuffer. +- Advanced color selection is supported via `color(fg, bg)`. +- Input uses a freestanding PS/2 keyboard driver with Shift support. + +## 6. Build Rules +- NO precompiled binaries or object files are allowed in the repository. +- The system must be buildable from pure source using the provided `Makefile`. +- Use `make menuconfig` to configure the kernel features and heap settings. + +## 7. Forensic Panic System +- In the event of a fatal loader or kernel error, the system enters an "Autopsy" state. +- CPU registers (RAX-R15) are captured and displayed alongside error messages and status codes. +- Diagnostic data is mirrored to the serial COM1 port (0x3f8) for headless monitoring and logging. + +## 8. Development Tools +- `tools/fontgen.html`: A pro-grade web studio to draw fonts and preview colors. +- `scripts/menuconfig.py`: Terminal-based configuration utility (LFS-style). +- `scripts/rnafs_tool.py`: Host-side tool to manage RNAFS disk images and inject files. diff --git a/CODEBASE.md b/CODEBASE.md new file mode 100644 index 0000000..6c52b6d --- /dev/null +++ b/CODEBASE.md @@ -0,0 +1,79 @@ +# OSx2 (RTECH dos) Technical Implementation Blueprint (CODEBASE.md) + +This document provides an exhaustive, low-level technical specification of the OSx2 codebase. It describes the implementation logic of every file with enough detail to allow for a complete system reconstruction. + +--- + +## 1. Boot & Entry Layer (`/kernel/unice64`) + +### `kernel/unice64/efi_entry.c` (Native UEFI Entry) +- **Purpose**: The "Native Diplomat". Serves as the PE32+ entry point for the firmware. +- **In-Code Logic**: + - **Initialization**: Calls `InitializeLib` (gnu-efi) to setup the UEFI environment. + - **Protocols**: + - Locates `EFI_GRAPHICS_OUTPUT_PROTOCOL` (GOP) to extract the linear framebuffer address, resolution, and scanline width into a `boot_params_t` struct. + - Handles `LOADED_IMAGE_PROTOCOL` and `SIMPLE_FILE_SYSTEM_PROTOCOL` to open the boot volume. + - **File Loading**: Loads `shell.bin` from the ESP into a 48MB fixed memory location (`0x3000000`). + - **Environment Prep**: Allocates memory for the ARC heap and the system ramdisk using `AllocatePages`. + - **The Transition**: Calls `ExitBootServices` to terminate UEFI's control over the hardware, then immediately calls `kernel_main` (passing the populated `boot_params_t`). + +--- + +## 2. Kernel Core Layer (`/kernel/unice64`) + +### `kernel/unice64/main.c` (The Orchestrator) +- **Purpose**: Kernel initialization, service registry, and event loop. +- **In-Code Logic**: + - **GDT Reset**: Calls `gdt_init` to re-establish segment descriptors for 64-bit mode after exiting UEFI services. + - **Service Registry**: Iterates through `registered_services` (Console, Memory, Input, FS, etc.) and calls their init functions. + - **Syscall Bridge**: Populates `rsl_syscall_table_t` with function pointers to kernel services. + - **Execution**: Hands over control to the user-space shell by calling `loader_run_shell`. + - **Event Loop**: Enters a `while(running)` loop that triggers `EVENT_MAIN`, allowing for asynchronous background processing. + +### `kernel/unice64/gdt.c` +- **Purpose**: CPU segmentation for long mode. +- **In-Code Logic**: Defines a static GDT with Null, Code, and Data descriptors. Loads the GDT using the `lgdt` instruction to ensure the kernel runs in a controlled environment. + +--- + +## 3. Kernel Services Layer (`/kernel/libs`) + +### `kernel/libs/connect.c` +- **Purpose**: Physical hardware inventory. Maintains a registry of memory-mapped I/O and RAM regions. + +### `kernel/libs/vdisk.c` +- **Purpose**: Storage virtualization layer. Translates virtual LBA requests to physical offsets on the ramdisk or other hardware. + +### `kernel/libs/memory.c` (ARC System) +- **Purpose**: Reference-counted memory management. +- **In-Code Logic**: Implements a 'Free List' allocator on top of the UEFI-allocated heap. `alloc` returns ref-counted pointers; `release` decrements the count and returns the block to the free list if it hits zero. + +### `kernel/libs/diskman.c` +- **Purpose**: Partition management. Parses GPT (GUID Partition Table) headers and manages VDISK partition mapping. + +### `kernel/libs/rnafs.c` (Proprietary FS) +- **Purpose**: Contiguous filesystem on VDISKs. +- **In-Code Logic**: Uses a bitmap for block management. `rnafs_write` performs contiguous allocation and updates the directory entries. Fixed a critical bug where overwrites leaked blocks; it now deallocates old blocks before re-writing. + +### `kernel/libs/console.c` +- **Purpose**: Graphics-mode text rendering. Draws 8x8 font characters directly to the GOP framebuffer. + +### `kernel/libs/kutils.c` & `kutils.h` +- **Purpose**: Internal utility library. Uses `k_` prefixes (e.g., `k_memcpy`, `k_memset`) to avoid naming collisions with gnu-efi/UEFI symbols. + +--- + +## 4. User Programs Layer (`/programs`) + +### `programs/libsystem.c` +- **Purpose**: RTECH Standard Library (RSL) implementation for user-space. Caches the syscall table passed by the kernel. + +### `programs/shell.c` +- **Purpose**: Native OSx2 Shell. Provides an interactive interface for file management and system commands. + +--- + +## 5. Build System (`Makefile`) + +- **Architecture**: Links all kernel components into a single `kernel.so` shared object, which is then converted to a `BOOTX64.EFI` application using `objcopy`. +- **Emulation**: Uses `qemu-system-x86_64` with the Q35 chipset and OVMF firmware to provide a modern UEFI boot environment. diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..7677cdf --- /dev/null +++ b/Makefile @@ -0,0 +1,127 @@ +# OSx2 (RTECH dos) Root Makefile - Native UEFI Edition + +CC = gcc +LD = ld +OBJCOPY = objcopy + +# Load Configuration +-include .config + +# Set defaults if not configured +CONFIG_KERNEL_BASE ?= 0x100000 +CONFIG_HEAP_BASE ?= 0x2000000 +CONFIG_OPTIMIZATION ?= 0 + +# Paths +BOOT_DIR = boot +EFI_DIR = $(BOOT_DIR)/EFI/BOOT +KERNEL_DIR = kernel/unice64 +LIBS_DIR = kernel/libs + +# GNU-EFI Paths +EFI_LIB = /usr/lib +EFI_LDS = /usr/lib/elf_x86_64_efi.lds +EFI_CRT0 = /usr/lib/crt0-efi-x86_64.o + +# Flags +# Use EFI flags for the entire kernel now +CFLAGS_EFI = -Iinclude -fno-stack-protector -mno-red-zone -Wall -fno-builtin -m64 -O$(CONFIG_OPTIMIZATION) \ + -fpic -fshort-wchar -DEFI_FUNCTION_WRAPPER -I/usr/include/efi -I/usr/include/efi/x86_64 -I/usr/include/efi/protocol + +LDFLAGS_EFI = -nostdlib -znocombreloc -T $(EFI_LDS) -shared -Bsymbolic -L $(EFI_LIB) $(EFI_CRT0) +LDFLAGS_SHELL = -nostdlib -T programs/linker.ld --oformat binary + +LIBS_EFI = -lefi -lgnuefi + +# Source Files +KERNEL_OBJS = $(KERNEL_DIR)/efi_entry.o \ + $(KERNEL_DIR)/main.o \ + $(KERNEL_DIR)/gdt.o \ + $(LIBS_DIR)/kutils.o \ + $(LIBS_DIR)/console.o \ + $(LIBS_DIR)/font_data.o \ + $(LIBS_DIR)/input.o \ + $(LIBS_DIR)/connect.o \ + $(LIBS_DIR)/vdisk.o \ + $(LIBS_DIR)/disk.o \ + $(LIBS_DIR)/diskman.o \ + $(LIBS_DIR)/memory.o \ + $(LIBS_DIR)/fs.o \ + $(LIBS_DIR)/rnafs.o \ + $(LIBS_DIR)/loader.o \ + $(LIBS_DIR)/core/event.o + +SHELL_SRCS = programs/libsystem.c programs/shell.c +SHELL_OBJS = $(SHELL_SRCS:.c=.o) + +HEADERS = $(shell find include kernel -name "*.h") + +# Default Target +all: info prepare $(EFI_DIR)/BOOTX64.EFI $(BOOT_DIR)/shell.bin + +info: + @echo "------------------------------------------------" + @echo " OSx2 / RTECH dos Build System (Native UEFI)" + @echo " Optimization Level: -O$(CONFIG_OPTIMIZATION)" + @echo "------------------------------------------------" + +prepare: + @if [ ! -f .config ]; then \ + python3 scripts/menuconfig.py --save; \ + fi + +menuconfig: + @python3 scripts/menuconfig.py + +# Unified Kernel (Native EFI App) +$(EFI_DIR)/BOOTX64.EFI: kernel.so + @mkdir -p $(EFI_DIR) + $(OBJCOPY) -j .text -j .sdata -j .data -j .dynamic \ + -j .dynsym -j .rel -j .rela -j .reloc \ + -j .rodata* --target=efi-app-x86_64 kernel.so $(EFI_DIR)/BOOTX64.EFI + +kernel.so: $(KERNEL_OBJS) + $(LD) $(LDFLAGS_EFI) $(KERNEL_OBJS) -o kernel.so $(LIBS_EFI) + +$(KERNEL_DIR)/%.o: $(KERNEL_DIR)/%.c $(HEADERS) + $(CC) $(CFLAGS_EFI) -c $< -o $@ + +$(LIBS_DIR)/%.o: $(LIBS_DIR)/%.c $(HEADERS) + $(CC) $(CFLAGS_EFI) -c $< -o $@ + +$(LIBS_DIR)/core/%.o: $(LIBS_DIR)/core/%.c $(HEADERS) + $(CC) $(CFLAGS_EFI) -c $< -o $@ + +# Programs (Still raw binary for simplicity in loading) +$(BOOT_DIR)/shell.bin: $(SHELL_OBJS) + $(LD) $(LDFLAGS_SHELL) $(SHELL_OBJS) -o $(BOOT_DIR)/shell.bin + +programs/%.o: programs/%.c $(HEADERS) + $(CC) -Iinclude -fno-stack-protector -mno-red-zone -Wall -fno-builtin -m64 -ffreestanding -c $< -o $@ + +# Advanced Tools: Create Bootable UEFI Disk Image +disk: all + @echo "Creating bootable UEFI disk image..." + dd if=/dev/zero of=disk.img bs=1M count=64 + mformat -i disk.img -F -v "OSX2" :: + mmd -i disk.img ::/EFI + mmd -i disk.img ::/EFI/BOOT + mcopy -i disk.img $(EFI_DIR)/BOOTX64.EFI ::/EFI/BOOT/BOOTX64.EFI + mcopy -i disk.img $(BOOT_DIR)/shell.bin ::/shell.bin + @echo "OSx2 Pro UEFI Disk Image Ready (disk.img)." + +run: disk + qemu-system-x86_64 -machine q35 -bios /usr/share/ovmf/OVMF.fd -drive format=raw,file=disk.img -m 256M -serial stdio -net none + +setup: + sudo apt-get update + sudo apt-get install -y gnu-efi build-essential qemu-system-x86 ovmf mtools dosfstools + +# Cleanup +clean: + @find . -name "*.o" -delete + @rm -f kernel.so $(BOOT_DIR)/shell.bin disk.img + @rm -rf $(BOOT_DIR)/EFI + @echo "Build artifacts removed." + +.PHONY: all clean disk prepare menuconfig info run diff --git a/README.md b/README.md deleted file mode 100644 index 0dee29e..0000000 --- a/README.md +++ /dev/null @@ -1,2 +0,0 @@ -# osdeving -osdeving diff --git a/include/config.h b/include/config.h new file mode 100644 index 0000000..7ce41dd --- /dev/null +++ b/include/config.h @@ -0,0 +1,18 @@ +#ifndef CONFIG_H +#define CONFIG_H + +/* Auto-generated by OSx2 menuconfig Professional */ + +#define CONFIG_DEBUG_LOGS 1 +#define CONFIG_KERNEL_BASE 0x100000 +#define CONFIG_HEAP_BASE 0x2000000 +#define CONFIG_HEAP_SIZE_MB 8 +#define CONFIG_SCROLL_SPEED 10 +#define CONFIG_EMERALD_MODE 1 +#define CONFIG_FG_COLOR 0xff88 +#define CONFIG_BG_COLOR 0 +#define CONFIG_LOAD_SHELL 1 +#define CONFIG_OPTIMIZATION 0 +#define CONFIG_STRICT_CHECKS 1 + +#endif diff --git a/include/rsl.h b/include/rsl.h new file mode 100644 index 0000000..76e3841 --- /dev/null +++ b/include/rsl.h @@ -0,0 +1,82 @@ +#ifndef RSL_H +#define RSL_H + +#include "types.h" + +/* + * RTECH Standard Library (RSL) + * The ultimate system language for OSx2 / RTECH dos. + */ + +typedef struct { + uint32* framebuffer; + uint32 width; + uint32 height; + uint32 pixels_per_scanline; + void* ramdisk_base; + uint64 ramdisk_size; + void* shell_base; + uint64 shell_size; + void* heap_base; + uint64 heap_size; + void* SystemTable; + void* ImageHandle; +} boot_params_t; + +typedef struct { + void (*print)(const char*); + void (*input)(const char*, char*, uint64); + INTN (*fread)(const char*, void*, uint64); + INTN (*fwrite)(const char*, const void*, uint64); + void* (*alloc)(uint64); + void (*retain)(void*); + void (*release)(void*); + void (*exit)(); + void (*clear)(); + void (*set_color)(uint32 fg, uint32 bg); + + void (*format)(int); + void (*mount)(int); + void (*addpart)(uint64, uint32); + void (*lsfs)(); +} rsl_syscall_table_t; + +/* --- High-Level "Noob-Friendly" API --- */ +void print(const char* str); +char* readline(const char* prompt); +void clear(); +void quit(); +void color(uint32 fg, uint32 bg); + +/* Disk & Partition Management */ +void format(int idx); +void mount(int idx); +void addpart(uint64 start, uint32 count); +void lsfs(); + +/* --- Auto-RAM: Managed Memory API --- */ +void* auto_ram(uint64 size); +void release(void* ptr); +void retain(void* ptr); + +/* --- String Utilities --- */ +char* str_create(const char* init); +int strcmp(const char* s1, const char* s2); +int strncmp(const char* s1, const char* s2, uint64 n); +void strcpy(char* dst, const char* src); +void strncpy(char* dst, const char* src, uint64 n); +uint64 strlen(const char* s); +char* strchr(const char* s, int c); + +/* --- Memory & Files --- */ +void* alloc(uint64 size); +void memcpy(void* dst, const void* src, uint64 n); +void memset(void* s, int c, uint64 n); +INTN read_file(const char* path, void* buffer, uint64 max_size); +INTN write_file(const char* path, const void* buffer, uint64 size); + +/* --- Numeric Utilities --- */ +int atoi(const char* s); +void itoa(int n, char* s, int base); + +#endif diff --git a/include/types.h b/include/types.h new file mode 100644 index 0000000..093a2ec --- /dev/null +++ b/include/types.h @@ -0,0 +1,38 @@ +#ifndef TYPES_H +#define TYPES_H + +/* No stdint.h as per Second category */ + +typedef unsigned long long uint64; +typedef unsigned int uint32; +typedef unsigned short uint16; +typedef unsigned char uint8; + +typedef long long int64; +typedef int int32; +typedef short int16; +typedef signed char int8; + +#ifndef __uintptr_t_defined +typedef unsigned long uintptr_t; +#define __uintptr_t_defined +#endif + +typedef unsigned long size_t; + +#if !defined(_EFI_H) && !defined(_EFI_BIND_H) && !defined(_EFIBIND_H_) && !defined(__EFI_TYPES_H__) && !defined(_EFI_TYPES_H) +typedef unsigned long UINTN; +typedef long INTN; +typedef uint16 CHAR16; +typedef uint8 CHAR8; + +typedef void* EFI_HANDLE; +typedef UINTN EFI_STATUS; +typedef unsigned long EFI_PHYSICAL_ADDRESS; +#endif + +#ifndef NULL +#define NULL ((void*)0) +#endif + +#endif diff --git a/kernel/libs/connect.c b/kernel/libs/connect.c new file mode 100644 index 0000000..b5fb418 --- /dev/null +++ b/kernel/libs/connect.c @@ -0,0 +1,57 @@ +#include "connect.h" +#include "kutils.h" +#include "../unice64/kernel.h" + +typedef struct { + char path[32]; + physical_config_t config; +} connect_entry_t; + +static connect_entry_t registry[MAX_CONNECT_DEVICES]; +static uint32 device_count = 0; + +void connect_init() { + device_count = 0; + memset(registry, 0, sizeof(registry)); + + /* Register System RAM Disk */ + physical_config_t ram0; + ram0.type = DEVICE_TYPE_RAM; + ram0.sector_size = 512; + ram0.total_lba = kboot_params.ramdisk_size / 512; + ram0.base_addr = kboot_params.ramdisk_base; + ram0.is_active = 1; + + /* ARA Collision Check: Ensure ramdisk doesn't overlap low memory or kernel */ + if ((uint64)ram0.base_addr < CONFIG_KERNEL_BASE) { + print("CONNECT: ARA Collision Detected (Low Memory Area).\n"); + } + + connect_register_device("/CONNECT/RAM0/", ram0); + + /* Register Placeholder USB */ + physical_config_t usb0; + usb0.type = DEVICE_TYPE_USB; + usb0.sector_size = 512; + usb0.total_lba = 0; + usb0.base_addr = (void*)0; + usb0.is_active = 0; /* Not connected yet */ + connect_register_device("/CONNECT/USB0/", usb0); +} + +void connect_register_device(const char* path, physical_config_t config) { + if (device_count < MAX_CONNECT_DEVICES) { + strcpy(registry[device_count].path, path); + registry[device_count].config = config; + device_count++; + } +} + +physical_config_t* connect_get_device(const char* path) { + for (uint32 i = 0; i < device_count; i++) { + if (strcmp(registry[i].path, path) == 0) { + return ®istry[i].config; + } + } + return (void*)0; +} diff --git a/kernel/libs/connect.h b/kernel/libs/connect.h new file mode 100644 index 0000000..3f925e8 --- /dev/null +++ b/kernel/libs/connect.h @@ -0,0 +1,26 @@ +#ifndef CONNECT_H +#define CONNECT_H + +#include "../../include/types.h" + +typedef enum { + DEVICE_TYPE_DISK, + DEVICE_TYPE_RAM, + DEVICE_TYPE_USB +} device_type_t; + +typedef struct { + device_type_t type; + uint32 sector_size; + uint64 total_lba; + void* base_addr; /* For RAM disks */ + int is_active; +} physical_config_t; + +#define MAX_CONNECT_DEVICES 8 + +void connect_init(); +physical_config_t* connect_get_device(const char* path); +void connect_register_device(const char* path, physical_config_t config); + +#endif diff --git a/kernel/libs/console.c b/kernel/libs/console.c new file mode 100644 index 0000000..d7df27e --- /dev/null +++ b/kernel/libs/console.c @@ -0,0 +1,97 @@ +#include "console.h" +#include "font.h" +#include "kutils.h" +#include "../unice64/kernel.h" +#include "../../include/rsl.h" + +static uint32 cursor_x = 0; +static uint32 cursor_y = 0; +static uint32 fg_color = 0xFFFFFFFF; +static uint32 bg_color = 0x00000000; + +void console_init() { + cursor_x = 0; + cursor_y = 0; + #ifdef CONFIG_EMERALD_MODE + fg_color = 0x00FF88; + #else + fg_color = CONFIG_FG_COLOR; + #endif + bg_color = CONFIG_BG_COLOR; + if (kboot_params.framebuffer) { + for (uint32 i = 0; i < kboot_params.height * kboot_params.pixels_per_scanline; i++) { + kboot_params.framebuffer[i] = bg_color; + } + } +} + +void console_clear() { + console_init(); +} + +void console_set_color(uint32 fg, uint32 bg) { + fg_color = fg; + bg_color = bg; +} + +static void scroll() { + if (!kboot_params.framebuffer) return; + uint32 row_size = kboot_params.pixels_per_scanline * 4; + uint32 total_rows = kboot_params.height; + uint32 scroll_amount = CONFIG_SCROLL_SPEED; + for (uint32 y = 0; y < total_rows - scroll_amount; y++) { + memcpy((uint8*)kboot_params.framebuffer + y * row_size, + (uint8*)kboot_params.framebuffer + (y + scroll_amount) * row_size, + row_size); + } + for (uint32 y = total_rows - scroll_amount; y < total_rows; y++) { + for (uint32 x = 0; x < kboot_params.pixels_per_scanline; x++) { + kboot_params.framebuffer[y * kboot_params.pixels_per_scanline + x] = bg_color; + } + } + cursor_y -= scroll_amount; +} + +static void draw_char(char c, uint32 x, uint32 y, uint32 color) { + if (!kboot_params.framebuffer) return; + if ((uint8)c >= 128) return; + const uint8* glyph = font8x8_basic[(uint8)c]; + for (int i = 0; i < 8; i++) { + for (int j = 0; j < 8; j++) { + if (glyph[i] & (1 << j)) { + uint32 py = y + i; + uint32 px = x + j; + if (px < kboot_params.width && py < kboot_params.height) { + kboot_params.framebuffer[py * kboot_params.pixels_per_scanline + px] = color; + } + } + } + } +} + +void print(const char* str) { + while (*str) { + if (*str == '\n') { + cursor_x = 0; + cursor_y += 10; + } else if (*str == '\r') { + cursor_x = 0; + } else if (*str == '\b') { + if (cursor_x >= 8) { + cursor_x -= 8; + draw_char(' ', cursor_x, cursor_y, bg_color); + } + } else { + draw_char(*str, cursor_x, cursor_y, fg_color); + cursor_x += 8; + if (cursor_x + 8 > kboot_params.width) { + cursor_x = 0; + cursor_y += 10; + } + } + if (cursor_y + 10 > kboot_params.height) { + scroll(); + } + str++; + } +} diff --git a/kernel/libs/console.h b/kernel/libs/console.h new file mode 100644 index 0000000..7c8a464 --- /dev/null +++ b/kernel/libs/console.h @@ -0,0 +1,10 @@ +#ifndef CONSOLE_H +#define CONSOLE_H + +#include "../unice64/kernel.h" + +void console_init(); +void console_clear(); +void console_set_color(uint32 fg, uint32 bg); + +#endif diff --git a/kernel/libs/core/event.c b/kernel/libs/core/event.c new file mode 100644 index 0000000..010b61b --- /dev/null +++ b/kernel/libs/core/event.c @@ -0,0 +1,21 @@ +#include "event.h" + +#define MAX_HANDLERS 32 +static event_handler_t handlers[MAX_HANDLERS]; +static uint32 handler_count = 0; + +void event_init() { + handler_count = 0; +} + +void register_event_handler(event_handler_t handler) { + if (handler_count < MAX_HANDLERS) { + handlers[handler_count++] = handler; + } +} + +void trigger(event_t event) { + for (uint32 i = 0; i < handler_count; i++) { + handlers[i](event); + } +} diff --git a/kernel/libs/core/event.h b/kernel/libs/core/event.h new file mode 100644 index 0000000..502a47d --- /dev/null +++ b/kernel/libs/core/event.h @@ -0,0 +1,8 @@ +#ifndef EVENT_H +#define EVENT_H + +#include "../../unice64/kernel.h" + +void event_init(); + +#endif diff --git a/kernel/libs/disk.c b/kernel/libs/disk.c new file mode 100644 index 0000000..13b2035 --- /dev/null +++ b/kernel/libs/disk.c @@ -0,0 +1,25 @@ +#include "disk.h" +#include "kutils.h" +#include "../unice64/kernel.h" +#include "../../include/rsl.h" + +void disk_init() { +} + +int read_sectors(uint64 lba, uint32 count, void* buffer) { + if (!kboot_params.ramdisk_base) return 0; + uint64 offset = lba * 512; + uint64 size = (uint64)count * 512; + if (offset + size > kboot_params.ramdisk_size) return 0; + memcpy(buffer, (uint8*)kboot_params.ramdisk_base + offset, size); + return 1; +} + +int write_sectors(uint64 lba, uint32 count, const void* buffer) { + if (!kboot_params.ramdisk_base) return 0; + uint64 offset = lba * 512; + uint64 size = (uint64)count * 512; + if (offset + size > kboot_params.ramdisk_size) return 0; + memcpy((uint8*)kboot_params.ramdisk_base + offset, buffer, size); + return 1; +} diff --git a/kernel/libs/disk.h b/kernel/libs/disk.h new file mode 100644 index 0000000..36b014d --- /dev/null +++ b/kernel/libs/disk.h @@ -0,0 +1,10 @@ +#ifndef DISK_H +#define DISK_H + +#include "../../include/types.h" + +void disk_init(); +int read_sectors(uint64 lba, uint32 count, void* buffer); +int write_sectors(uint64 lba, uint32 count, const void* buffer); + +#endif diff --git a/kernel/libs/diskman.c b/kernel/libs/diskman.c new file mode 100644 index 0000000..8d52490 --- /dev/null +++ b/kernel/libs/diskman.c @@ -0,0 +1,106 @@ +#include "diskman.h" +#include "disk.h" +#include "vdisk.h" +#include "console.h" +#include "rnafs.h" +#include "kutils.h" +#include "../../include/rsl.h" + +static gpt_header_t current_gpt; +static gpt_entry_t entries[128]; + +void diskman_init() { + /* For v0 memory disk, we skip GPT auto-init if signature isn't found to avoid FAT corruption */ + if (read_sectors(1, 1, ¤t_gpt)) { + if (current_gpt.signature == GPT_SIGNATURE) { + read_sectors(current_gpt.partition_entry_lba, + (current_gpt.num_partition_entries * current_gpt.size_partition_entry + 511) / 512, + entries); + } else { + print("Diskman: No GPT found on ramdisk.\n"); + } + } +} + +void diskman_add_partition(uint64 start, uint32 count) { + if (current_gpt.signature != GPT_SIGNATURE) { + /* Initialize Blank GPT on first use */ + memset(¤t_gpt, 0, sizeof(gpt_header_t)); + current_gpt.signature = GPT_SIGNATURE; + current_gpt.revision = 0x00010000; + current_gpt.header_size = sizeof(gpt_header_t); + current_gpt.current_lba = 1; + current_gpt.first_usable_lba = 34; + current_gpt.partition_entry_lba = 2; + current_gpt.num_partition_entries = 128; + current_gpt.size_partition_entry = 128; + memset(entries, 0, sizeof(entries)); + print("Diskman: Initializing new GPT...\n"); + } + for (uint32 i = 0; i < current_gpt.num_partition_entries; i++) { + int unused = 1; + for (int j = 0; j < 16; j++) { + if (entries[i].partition_type_guid.data[j] != 0) { + unused = 0; + break; + } + } + if (unused) { + entries[i].starting_lba = start; + entries[i].ending_lba = start + count - 1; + entries[i].partition_type_guid.data[0] = 0x52; /* RNAFS GUID (Fake) */ + entries[i].partition_type_guid.data[1] = 0x4E; + entries[i].partition_type_guid.data[2] = 0x41; + + /* Update Entry Array CRC */ + current_gpt.partition_entry_array_crc = crc32(entries, (uint64)current_gpt.num_partition_entries * current_gpt.size_partition_entry); + + /* Update Header CRC */ + current_gpt.header_crc = 0; + current_gpt.header_crc = crc32(¤t_gpt, current_gpt.header_size); + + /* Commit to disk */ + write_sectors(current_gpt.partition_entry_lba, + (current_gpt.num_partition_entries * current_gpt.size_partition_entry + 511) / 512, + entries); + write_sectors(1, 1, ¤t_gpt); + + print("Diskman: Added GPT partition "); + char buf[8]; + itoa(i, buf, 10); + print(buf); + print("\n"); + return; + } + } +} + +void diskman_format_rnafs(int idx) { + if (idx < 0 || idx >= 128) return; + if (entries[idx].starting_lba == 0) return; + uint64 size = entries[idx].ending_lba - entries[idx].starting_lba + 1; + + /* VDISK creation for partition */ + char vd_name[16] = "PART"; + itoa(idx, vd_name + 4, 10); + vdisk_t* vd = vdisk_open(vd_name); + if (vd) { + vd->start_lba = entries[idx].starting_lba; + vd->end_lba = entries[idx].ending_lba; + rnafs_format_vdisk(vd_name, (uint32)size); + } +} + +void diskman_mount_rnafs(int idx) { + if (idx < 0 || idx >= 128) return; + if (entries[idx].starting_lba == 0) return; + + char vd_name[16] = "PART"; + itoa(idx, vd_name + 4, 10); + vdisk_t* vd = vdisk_open(vd_name); + if (vd) { + vd->start_lba = entries[idx].starting_lba; + vd->end_lba = entries[idx].ending_lba; + rnafs_mount_vdisk(vd_name); + } +} diff --git a/kernel/libs/diskman.h b/kernel/libs/diskman.h new file mode 100644 index 0000000..6425c8d --- /dev/null +++ b/kernel/libs/diskman.h @@ -0,0 +1,45 @@ +#ifndef DISKMAN_H +#define DISKMAN_H + +#include "../../include/types.h" + +/* GPT (GUID Partition Table) Structures - 64-bit */ + +typedef struct { + uint8 data[16]; +} guid_t; + +typedef struct { + uint64 signature; /* "EFI PART" */ + uint32 revision; + uint32 header_size; + uint32 header_crc; + uint32 reserved; + uint64 current_lba; + uint64 backup_lba; + uint64 first_usable_lba; + uint64 last_usable_lba; + guid_t disk_guid; + uint64 partition_entry_lba; + uint32 num_partition_entries; + uint32 size_partition_entry; + uint32 partition_entry_array_crc; +} __attribute__((packed)) gpt_header_t; + +typedef struct { + guid_t partition_type_guid; + guid_t unique_partition_guid; + uint64 starting_lba; + uint64 ending_lba; + uint64 attributes; + uint16 partition_name[36]; +} __attribute__((packed)) gpt_entry_t; + +#define GPT_SIGNATURE 0x5452415020494645ULL /* "EFI PART" */ + +void diskman_init(); +void diskman_add_partition(uint64 start, uint32 count); +void diskman_format_rnafs(int idx); +void diskman_mount_rnafs(int idx); + +#endif diff --git a/kernel/libs/font.h b/kernel/libs/font.h new file mode 100644 index 0000000..141bff7 --- /dev/null +++ b/kernel/libs/font.h @@ -0,0 +1,8 @@ +#ifndef FONT_H +#define FONT_H + +#include "../../include/types.h" + +extern const uint8 font8x8_basic[128][8]; + +#endif diff --git a/kernel/libs/font_data.c b/kernel/libs/font_data.c new file mode 100644 index 0000000..e8e6a7b --- /dev/null +++ b/kernel/libs/font_data.c @@ -0,0 +1,100 @@ +#include "../../include/types.h" + +const uint8 font8x8_basic[128][8] = { + [0x00] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* (null) */ + [0x20] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* (space) */ + [0x21] = { 0x18, 0x3C, 0x3C, 0x18, 0x18, 0x00, 0x18, 0x00}, /* ! */ + [0x22] = { 0x6C, 0x6C, 0x6C, 0x00, 0x00, 0x00, 0x00, 0x00}, /* " */ + [0x23] = { 0x6C, 0x6C, 0xFE, 0x6C, 0xFE, 0x6C, 0x6C, 0x00}, /* # */ + [0x24] = { 0x18, 0x7E, 0xC0, 0x7C, 0x06, 0xFC, 0x18, 0x00}, /* $ */ + [0x25] = { 0x00, 0xC6, 0xCC, 0x18, 0x30, 0x66, 0xC6, 0x00}, /* % */ + [0x26] = { 0x30, 0x68, 0x30, 0x76, 0xCC, 0xCC, 0x76, 0x00}, /* & */ + [0x27] = { 0x18, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00}, /* ' */ + [0x28] = { 0x0C, 0x18, 0x30, 0x30, 0x30, 0x18, 0x0C, 0x00}, /* ( */ + [0x29] = { 0x30, 0x18, 0x0C, 0x0C, 0x0C, 0x18, 0x30, 0x00}, /* ) */ + [0x2A] = { 0x00, 0x66, 0x3C, 0xFF, 0x3C, 0x66, 0x00, 0x00}, /* * */ + [0x2B] = { 0x00, 0x18, 0x18, 0x7E, 0x18, 0x18, 0x00, 0x00}, /* + */ + [0x2C] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x30}, /* , */ + [0x2D] = { 0x00, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x00, 0x00}, /* - */ + [0x2E] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00}, /* . */ + [0x2F] = { 0x06, 0x0C, 0x18, 0x30, 0x60, 0xC0, 0x80, 0x00}, /* / */ + [0x30] = { 0x7C, 0xC6, 0xCE, 0xD6, 0xE6, 0xC6, 0x7C, 0x00}, /* 0 */ + [0x31] = { 0x18, 0x38, 0x18, 0x18, 0x18, 0x18, 0x7E, 0x00}, /* 1 */ + [0x32] = { 0x7C, 0xC6, 0x06, 0x3C, 0x60, 0xC0, 0xFE, 0x00}, /* 2 */ + [0x33] = { 0x7C, 0xC6, 0x06, 0x3C, 0x06, 0xC6, 0x7C, 0x00}, /* 3 */ + [0x34] = { 0x1C, 0x3C, 0x6C, 0xCC, 0xFE, 0x0C, 0x1E, 0x00}, /* 4 */ + [0x35] = { 0xFE, 0xC0, 0xFC, 0x06, 0x06, 0xC6, 0x7C, 0x00}, /* 5 */ + [0x36] = { 0x3C, 0x60, 0xC0, 0xFC, 0xC6, 0xC6, 0x7C, 0x00}, /* 6 */ + [0x37] = { 0xFE, 0xC6, 0x0C, 0x18, 0x30, 0x30, 0x30, 0x00}, /* 7 */ + [0x38] = { 0x7C, 0xC6, 0xC6, 0x7C, 0xC6, 0xC6, 0x7C, 0x00}, /* 8 */ + [0x39] = { 0x7C, 0xC6, 0xC6, 0x7E, 0x06, 0x0C, 0x78, 0x00}, /* 9 */ + [0x3A] = { 0x00, 0x18, 0x18, 0x00, 0x00, 0x18, 0x18, 0x00}, /* : */ + [0x3B] = { 0x00, 0x18, 0x18, 0x00, 0x00, 0x18, 0x18, 0x30}, /* ; */ + [0x3C] = { 0x0C, 0x18, 0x30, 0x60, 0x30, 0x18, 0x0C, 0x00}, /* < */ + [0x3D] = { 0x00, 0x00, 0x7E, 0x00, 0x7E, 0x00, 0x00, 0x00}, /* = */ + [0x3E] = { 0x30, 0x18, 0x0C, 0x06, 0x0C, 0x18, 0x30, 0x00}, /* > */ + [0x3F] = { 0x7C, 0xC6, 0x06, 0x0C, 0x18, 0x00, 0x18, 0x00}, /* ? */ + [0x40] = { 0x7C, 0xC6, 0x06, 0x5E, 0xD6, 0xD6, 0x7C, 0x00}, /* @ */ + [0x41] = { 0x18, 0x3C, 0x66, 0x66, 0x7E, 0x66, 0x66, 0x00}, /* A */ + [0x42] = { 0xFC, 0x66, 0x66, 0x7C, 0x66, 0x66, 0xFC, 0x00}, /* B */ + [0x43] = { 0x3C, 0x66, 0xC0, 0xC0, 0xC0, 0x66, 0x3C, 0x00}, /* C */ + [0x44] = { 0xF8, 0x6C, 0x66, 0x66, 0x66, 0x6C, 0xF8, 0x00}, /* D */ + [0x45] = { 0xFE, 0x62, 0x68, 0x78, 0x68, 0x62, 0xFE, 0x00}, /* E */ + [0x46] = { 0xFE, 0x62, 0x68, 0x78, 0x68, 0x60, 0xF0, 0x00}, /* F */ + [0x47] = { 0x3C, 0x66, 0xC0, 0xCE, 0xC6, 0x66, 0x3E, 0x00}, /* G */ + [0x48] = { 0x66, 0x66, 0x66, 0x7E, 0x66, 0x66, 0x66, 0x00}, /* H */ + [0x49] = { 0x7E, 0x18, 0x18, 0x18, 0x18, 0x18, 0x7E, 0x00}, /* I */ + [0x4A] = { 0x1E, 0x0C, 0x0C, 0x0C, 0x0C, 0xCC, 0x78, 0x00}, /* J */ + [0x4B] = { 0xE6, 0x66, 0x6C, 0x78, 0x6C, 0x66, 0xE6, 0x00}, /* K */ + [0x4C] = { 0xF0, 0x60, 0x60, 0x60, 0x62, 0x66, 0xFE, 0x00}, /* L */ + [0x4D] = { 0xC6, 0xEE, 0xFE, 0xFE, 0xD6, 0xC6, 0xC6, 0x00}, /* M */ + [0x4E] = { 0xC6, 0xE6, 0xF6, 0xDE, 0xCE, 0xC6, 0xC6, 0x00}, /* N */ + [0x4F] = { 0x38, 0x6C, 0xC6, 0xC6, 0xC6, 0x6C, 0x38, 0x00}, /* O */ + [0x50] = { 0xFC, 0x66, 0x66, 0x7C, 0x60, 0x60, 0xF0, 0x00}, /* P */ + [0x51] = { 0x7C, 0xC6, 0xC6, 0xC6, 0xDA, 0xCC, 0x76, 0x00}, /* Q */ + [0x52] = { 0xFC, 0x66, 0x66, 0x7C, 0x6C, 0x66, 0xE6, 0x00}, /* R */ + [0x53] = { 0x7C, 0xC6, 0x60, 0x38, 0x06, 0xC6, 0x7C, 0x00}, /* S */ + [0x54] = { 0x7E, 0x5A, 0x18, 0x18, 0x18, 0x18, 0x3C, 0x00}, /* T */ + [0x55] = { 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3C, 0x00}, /* U */ + [0x56] = { 0x66, 0x66, 0x66, 0x66, 0x66, 0x3C, 0x18, 0x00}, /* V */ + [0x57] = { 0xC6, 0xC6, 0xD6, 0xFE, 0xFE, 0xEE, 0xC6, 0x00}, /* W */ + [0x58] = { 0x66, 0x66, 0x3C, 0x18, 0x3C, 0x66, 0x66, 0x00}, /* X */ + [0x59] = { 0x66, 0x66, 0x66, 0x3C, 0x18, 0x18, 0x3C, 0x00}, /* Y */ + [0x5A] = { 0xFE, 0xC6, 0x8C, 0x18, 0x32, 0x66, 0xFE, 0x00}, /* Z */ + [0x5B] = { 0x3C, 0x30, 0x30, 0x30, 0x30, 0x30, 0x3C, 0x00}, /* [ */ + [0x5C] = { 0xC0, 0x60, 0x30, 0x18, 0x0C, 0x06, 0x02, 0x00}, /* \ */ + [0x5D] = { 0x3C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x3C, 0x00}, /* ] */ + [0x5E] = { 0x10, 0x38, 0x6C, 0xC6, 0x00, 0x00, 0x00, 0x00}, /* ^ */ + [0x5F] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF}, /* _ */ + [0x60] = { 0x30, 0x18, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00}, /* ` */ + [0x61] = { 0x00, 0x00, 0x78, 0x0C, 0x7C, 0xCC, 0x76, 0x00}, /* a */ + [0x62] = { 0xE0, 0x60, 0x7C, 0x66, 0x66, 0x66, 0x7C, 0x00}, /* b */ + [0x63] = { 0x00, 0x00, 0x7C, 0xC0, 0xC0, 0xC6, 0x7C, 0x00}, /* c */ + [0x64] = { 0x1C, 0x0C, 0x7C, 0xCC, 0xCC, 0xCC, 0x76, 0x00}, /* d */ + [0x65] = { 0x00, 0x00, 0x7C, 0xC6, 0xFE, 0xC0, 0x7C, 0x00}, /* e */ + [0x66] = { 0x1C, 0x36, 0x30, 0x7C, 0x30, 0x30, 0x78, 0x00}, /* f */ + [0x67] = { 0x00, 0x00, 0x76, 0xCC, 0xCC, 0x7C, 0x0C, 0xF8}, /* g */ + [0x68] = { 0xE0, 0x60, 0x6C, 0x76, 0x66, 0x66, 0xE6, 0x00}, /* h */ + [0x69] = { 0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x3C, 0x00}, /* i */ + [0x6A] = { 0x06, 0x00, 0x06, 0x06, 0x06, 0x66, 0x3C, 0x00}, /* j */ + [0x6B] = { 0xE0, 0x60, 0x66, 0x6C, 0x78, 0x6C, 0xE6, 0x00}, /* k */ + [0x6C] = { 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3C, 0x00}, /* l */ + [0x6D] = { 0x00, 0x00, 0xEC, 0xFE, 0xFE, 0xD6, 0xC6, 0x00}, /* m */ + [0x6E] = { 0x00, 0x00, 0xDC, 0x66, 0x66, 0x66, 0x66, 0x00}, /* n */ + [0x6F] = { 0x00, 0x00, 0x7C, 0xC6, 0xC6, 0xC6, 0x7C, 0x00}, /* o */ + [0x70] = { 0x00, 0x00, 0xDC, 0x66, 0x66, 0x7C, 0x60, 0xF0}, /* p */ + [0x71] = { 0x00, 0x00, 0x76, 0xCC, 0xCC, 0x7C, 0x0C, 0x1E}, /* q */ + [0x72] = { 0x00, 0x00, 0xDC, 0x76, 0x60, 0x60, 0xF0, 0x00}, /* r */ + [0x73] = { 0x00, 0x00, 0x7E, 0xC0, 0x7C, 0x06, 0xFC, 0x00}, /* s */ + [0x74] = { 0x30, 0x30, 0xFC, 0x30, 0x30, 0x36, 0x1C, 0x00}, /* t */ + [0x75] = { 0x00, 0x00, 0xCC, 0xCC, 0xCC, 0xCC, 0x76, 0x00}, /* u */ + [0x76] = { 0x00, 0x00, 0x66, 0x66, 0x66, 0x3C, 0x18, 0x00}, /* v */ + [0x77] = { 0x00, 0x00, 0xC6, 0xD6, 0xFE, 0xEE, 0x6C, 0x00}, /* w */ + [0x78] = { 0x00, 0x00, 0xC6, 0x6C, 0x38, 0x6C, 0xC6, 0x00}, /* x */ + [0x79] = { 0x00, 0x00, 0xC6, 0xC6, 0xC6, 0x7E, 0x06, 0xFC}, /* y */ + [0x7A] = { 0x00, 0x00, 0xFE, 0xCC, 0x18, 0x32, 0xFE, 0x00}, /* z */ + [0x7B] = { 0x0C, 0x18, 0x18, 0x70, 0x18, 0x18, 0x0C, 0x00}, /* { */ + [0x7C] = { 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00}, /* | */ + [0x7D] = { 0x30, 0x18, 0x18, 0x0E, 0x18, 0x18, 0x30, 0x00}, /* } */ + [0x7E] = { 0x00, 0x00, 0x00, 0x76, 0xDC, 0x00, 0x00, 0x00}, /* ~ */ +}; diff --git a/kernel/libs/fs.c b/kernel/libs/fs.c new file mode 100644 index 0000000..afeade6 --- /dev/null +++ b/kernel/libs/fs.c @@ -0,0 +1,14 @@ +#include "fs.h" +#include "rnafs.h" + +void fs_init() { + rnafs_init(); +} + +INTN fread(const char* path, void* buffer, uint64 max_size) { + return rnafs_read(path, buffer, max_size); +} + +INTN fwrite(const char* path, const void* buffer, uint64 size) { + return rnafs_write(path, buffer, size); +} diff --git a/kernel/libs/fs.h b/kernel/libs/fs.h new file mode 100644 index 0000000..82a9f10 --- /dev/null +++ b/kernel/libs/fs.h @@ -0,0 +1,10 @@ +#ifndef FS_H +#define FS_H + +#include "../../include/types.h" + +void fs_init(); +INTN fread(const char* path, void* buffer, uint64 max_size); +INTN fwrite(const char* path, const void* buffer, uint64 size); + +#endif diff --git a/kernel/libs/input.c b/kernel/libs/input.c new file mode 100644 index 0000000..24d2803 --- /dev/null +++ b/kernel/libs/input.c @@ -0,0 +1,142 @@ +#include "input.h" +#include "console.h" +#include "../unice64/io.h" + +static const char scancode_map[128] = { + 0, 27, '1', '2', '3', '4', '5', '6', '7', '8', /* 9 */ + '9', '0', '-', '=', '\b', /* Backspace */ + '\t', /* Tab */ + 'q', 'w', 'e', 'r', /* 19 */ + 't', 'y', 'u', 'i', 'o', 'p', '[', ']', '\n', /* Enter key */ + 0, /* 29 - Control */ + 'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', /* 39 */ + '\'', '`', 0, /* Left shift */ + '\\', 'z', 'x', 'c', 'v', 'b', 'n', /* 49 */ + 'm', ',', '.', '/', 0, /* Right shift */ + '*', + 0, /* Alt */ + ' ', /* Space bar */ + 0, /* Caps lock */ +}; + +static const char shift_map[128] = { + 0, 27, '!', '@', '#', '$', '%', '^', '&', '*', /* 9 */ + '(', ')', '_', '+', '\b', /* Backspace */ + '\t', /* Tab */ + 'Q', 'W', 'E', 'R', /* 19 */ + 'T', 'Y', 'U', 'I', 'O', 'P', '{', '}', '\n', /* Enter key */ + 0, /* 29 - Control */ + 'A', 'S', 'D', 'F', 'G', 'H', 'J', 'K', 'L', ':', /* 39 */ + '\"', '~', 0, /* Left shift */ + '|', 'Z', 'X', 'C', 'V', 'B', 'N', /* 49 */ + 'M', '<', '>', '?', 0, /* Right shift */ + '*', + 0, /* Alt */ + ' ', /* Space bar */ + 0, /* Caps lock */ +}; + +static int shift_pressed = 0; + +static void ps2_wait_write() { + while (inb(0x64) & 2); +} + +static void ps2_wait_read() { + while (!(inb(0x64) & 1)); +} + +void input_init() { + shift_pressed = 0; + + /* 1. Disable devices */ + ps2_wait_write(); + outb(0x64, 0xAD); + ps2_wait_write(); + outb(0x64, 0xA7); + + /* 2. Flush buffer */ + while (inb(0x64) & 1) inb(0x60); + + /* 3. Set Controller Config */ + ps2_wait_write(); + outb(0x64, 0x20); + ps2_wait_read(); + uint8 ccb = inb(0x60); + ccb |= 1; + ccb &= ~0x40; + ps2_wait_write(); + outb(0x64, 0x60); + ps2_wait_write(); + outb(0x60, ccb); + + /* 4. Controller self-test */ + ps2_wait_write(); + outb(0x64, 0xAA); + ps2_wait_read(); + if (inb(0x60) != 0x55) return; + + /* 5. Enable P1 */ + ps2_wait_write(); + outb(0x64, 0xAE); + + /* 6. Reset Keyboard */ + ps2_wait_write(); + outb(0x60, 0xFF); + ps2_wait_read(); + if (inb(0x60) != 0xFA) return; + ps2_wait_read(); + if (inb(0x60) != 0xAA) return; + + /* 7. Enable Scanning */ + ps2_wait_write(); + outb(0x60, 0xF4); + ps2_wait_read(); + inb(0x60); +} + +static char get_char() { + while (1) { + if (inb(0x64) & 1) { + uint8 scancode = inb(0x60); + + if (scancode == 0x2A || scancode == 0x36) { + shift_pressed = 1; + continue; + } + if (scancode == 0xAA || scancode == 0xB6) { + shift_pressed = 0; + continue; + } + + if (!(scancode & 0x80)) { + if (scancode < 128) { + return shift_pressed ? shift_map[scancode] : scancode_map[scancode]; + } + } + } + __asm__ volatile("pause"); + } +} + +void input(const char* prompt, char* buffer, uint64 size) { + print(prompt); + uint64 i = 0; + while (i < size - 1) { + char c = get_char(); + if (c == '\n') { + print("\n"); + break; + } else if (c == '\b') { + if (i > 0) { + i--; + print("\b \b"); + } + } else if (c > 0) { + buffer[i++] = c; + char s[2] = {c, 0}; + print(s); + } + } + buffer[i] = 0; +} diff --git a/kernel/libs/input.h b/kernel/libs/input.h new file mode 100644 index 0000000..bab658e --- /dev/null +++ b/kernel/libs/input.h @@ -0,0 +1,9 @@ +#ifndef INPUT_H +#define INPUT_H + +#include "../../include/types.h" + +void input_init(); +void input(const char* prompt, char* buffer, uint64 size); + +#endif diff --git a/kernel/libs/kutils.c b/kernel/libs/kutils.c new file mode 100644 index 0000000..6e3eea3 --- /dev/null +++ b/kernel/libs/kutils.c @@ -0,0 +1,63 @@ +#include "../../include/types.h" + +int strcmp(const char* s1, const char* s2) { + while (*s1 && *s1 == *s2) { s1++; s2++; } + return *(unsigned char*)s1 - *(unsigned char*)s2; +} + +void strcpy(char* dst, const char* src) { + while ((*dst++ = *src++)); +} + +uint64 k_strlen(const char* s) { + uint64 len = 0; + while (*s++) len++; + return len; +} + +void k_memcpy(void* dst, const void* src, uint64 n) { + uint8* d = (uint8*)dst; + const uint8* s = (const uint8*)src; + while (n--) *d++ = *s++; +} + +void k_memset(void* s, int c, uint64 n) { + uint8* p = (uint8*)s; + while (n--) *p++ = (uint8)c; +} + +void itoa(int n, char* s, int base) { + char* p = s; + char* p1, *p2; + unsigned int ud = n; + if (base == 10 && n < 0) { + *p++ = '-'; + s++; + ud = -n; + } + do { + int remainder = ud % base; + *p++ = (remainder < 10) ? remainder + '0' : remainder + 'a' - 10; + } while (ud /= base); + *p = 0; + p1 = s; + p2 = p - 1; + while (p1 < p2) { + char tmp = *p1; + *p1++ = *p2; + *p2-- = tmp; + } +} + +uint32 crc32(const void* data, uint64 len) { + uint32 crc = 0xFFFFFFFF; + const uint8* p = (const uint8*)data; + while (len--) { + crc ^= *p++; + for (int i = 0; i < 8; i++) { + if (crc & 1) crc = (crc >> 1) ^ 0xEDB88320; + else crc >>= 1; + } + } + return ~crc; +} diff --git a/kernel/libs/kutils.h b/kernel/libs/kutils.h new file mode 100644 index 0000000..6235563 --- /dev/null +++ b/kernel/libs/kutils.h @@ -0,0 +1,19 @@ +#ifndef KUTILS_H +#define KUTILS_H + +#include "../../include/types.h" + +int strcmp(const char* s1, const char* s2); +void strcpy(char* dst, const char* src); +uint64 k_strlen(const char* s); +void k_memcpy(void* dst, const void* src, uint64 n); +void k_memset(void* s, int c, uint64 n); +void itoa(int n, char* s, int base); +uint32 crc32(const void* data, uint64 len); + +/* Alias for kernel use if needed, but we'll use k_ prefix to avoid conflicts with gnu-efi */ +#define memcpy k_memcpy +#define memset k_memset +#define strlen k_strlen + +#endif diff --git a/kernel/libs/loader.c b/kernel/libs/loader.c new file mode 100644 index 0000000..8609ad8 --- /dev/null +++ b/kernel/libs/loader.c @@ -0,0 +1,49 @@ +#include "loader.h" +#include "console.h" +#include "vdisk.h" +#include "fs.h" +#include "memory.h" +#include "kutils.h" +#include "../unice64/kernel.h" + +void loader_init() { +} + +void wheres_the_beef() { + print("WHERES_THE_BEEF! Memory corruption or uninitialized jump detected.\n"); + print("Checked: 0xB0000 | Protocol: Triggered\n"); + while(1) { __asm__ volatile("hlt"); } +} + +void debug_kernel_signature() { + uint32* ptr = (uint32*)CONFIG_KERNEL_BASE; + /* Basic check for common uninitialized RAM patterns */ + if (*ptr == 0x00000000 || *ptr == 0xFFFFFFFF) { + wheres_the_beef(); + } + + print("Diagnostic: Kernel Signature at "); + char addr_buf[16]; + itoa(CONFIG_KERNEL_BASE, addr_buf, 16); + print(addr_buf); + print(" = "); + char buf[16]; + itoa((int)*ptr, buf, 16); + print(buf); + print("\n"); +} + +void loader_run_shell(rsl_syscall_table_t* syscalls) { + #ifdef CONFIG_LOAD_SHELL + /* Stage 2 Loader: Run shell.bin already placed in memory by Stage 1 */ + if (kboot_params.shell_base) { + void (*shell_entry)(boot_params_t*, rsl_syscall_table_t*) = + (void (*)(boot_params_t*, rsl_syscall_table_t*))kboot_params.shell_base; + shell_entry(&kboot_params, syscalls); + } else { + print("Loader: shell.bin not found in memory handover.\n"); + } + #else + print("Loader: Auto-load shell disabled by config.\n"); + #endif +} diff --git a/kernel/libs/loader.h b/kernel/libs/loader.h new file mode 100644 index 0000000..9b1bdb2 --- /dev/null +++ b/kernel/libs/loader.h @@ -0,0 +1,10 @@ +#ifndef LOADER_H +#define LOADER_H + +#include "../../include/rsl.h" + +void loader_init(); +void loader_run_shell(rsl_syscall_table_t* syscalls); +void debug_kernel_signature(); + +#endif diff --git a/kernel/libs/memory.c b/kernel/libs/memory.c new file mode 100644 index 0000000..71c9a55 --- /dev/null +++ b/kernel/libs/memory.c @@ -0,0 +1,89 @@ +#include "memory.h" +#include "../unice64/kernel.h" + +static uint64 heap_ptr = 0; + +typedef struct free_block { + uint32 size; + struct free_block* next; +} free_block_t; + +static free_block_t* free_list = (void*)0; + +void memory_init() { + heap_ptr = 0; + free_list = (void*)0; +} + +void* alloc(uint64 size) { + if (!kboot_params.heap_base) { + return (void*)0; + } + + uint64 total_size = sizeof(arc_header_t) + size; + total_size = (total_size + 15) & ~15; + + /* Check free list first */ + free_block_t** curr = &free_list; + while (*curr) { + if ((*curr)->size >= total_size) { + free_block_t* found = *curr; + *curr = found->next; + + arc_header_t* header = (arc_header_t*)found; + header->ref_count = 1; + header->size = (uint32)size; + header->magic = ARC_MAGIC; + return (void*)(header + 1); + } + curr = &((*curr)->next); + } + + /* Use configurable heap size limit from config.h */ + uint64 max_heap = (uint64)CONFIG_HEAP_SIZE_MB * 1024 * 1024; + + if (heap_ptr + total_size > max_heap || heap_ptr + total_size > kboot_params.heap_size) { + return (void*)0; + } + + arc_header_t* header = (arc_header_t*)((uint8*)kboot_params.heap_base + heap_ptr); + header->ref_count = 1; + header->size = (uint32)size; + header->magic = ARC_MAGIC; + + heap_ptr += total_size; + + return (void*)(header + 1); +} + +void retain(void* ptr) { + if (!ptr) { + return; + } + arc_header_t* header = (arc_header_t*)ptr - 1; + if (header->magic == ARC_MAGIC) { + header->ref_count++; + } +} + +void release(void* ptr) { + if (!ptr) { + return; + } + arc_header_t* header = (arc_header_t*)ptr - 1; + if (header->magic == ARC_MAGIC) { + if (header->ref_count > 0) { + header->ref_count--; + if (header->ref_count == 0) { + /* Actual Reclamation */ + uint32 total_size = (sizeof(arc_header_t) + header->size + 15) & ~15; + header->magic = 0; + + free_block_t* free_b = (free_block_t*)header; + free_b->size = total_size; + free_b->next = free_list; + free_list = free_b; + } + } + } +} diff --git a/kernel/libs/memory.h b/kernel/libs/memory.h new file mode 100644 index 0000000..4178ad5 --- /dev/null +++ b/kernel/libs/memory.h @@ -0,0 +1,20 @@ +#ifndef MEMORY_H +#define MEMORY_H + +#include "../../include/types.h" + +/* ARC Header for Python-like memory management */ +typedef struct { + uint32 ref_count; + uint32 size; + uint64 magic; /* To verify ARC pointer */ +} arc_header_t; + +#define ARC_MAGIC 0x4152434D454D3031 /* "ARCMEM01" */ + +void memory_init(); +void* alloc(uint64 size); +void retain(void* ptr); +void release(void* ptr); + +#endif diff --git a/kernel/libs/rnafs.c b/kernel/libs/rnafs.c new file mode 100644 index 0000000..a3c0542 --- /dev/null +++ b/kernel/libs/rnafs.c @@ -0,0 +1,161 @@ +#include "rnafs.h" +#include "vdisk.h" +#include "console.h" +#include "kutils.h" +#include "../unice64/kernel.h" +#include "../../include/rsl.h" + +static vdisk_t* active_vd = (void*)0; +static rnafs_superblock_t active_sb; +static int is_mounted = 0; + +void rnafs_init() { + is_mounted = 0; +} + +void rnafs_format_vdisk(const char* vdisk_name, uint32 size_sectors) { + vdisk_t* vd = vdisk_open(vdisk_name); + if (!vd) return; + + rnafs_superblock_t sb; + sb.magic = RNAFS_MAGIC; + sb.total_blocks = size_sectors; + sb.bitmap_start = 1; + sb.bitmap_blocks = 1; + sb.dir_start = 2; + sb.dir_blocks = 4; + sb.data_start = 6; + vdisk_write(vd, 0, 1, &sb); + + uint8 block[512]; + memset(block, 0, 512); + + /* Bitmap: mark metadata blocks (0-5) as used */ + block[0] = 0x3F; /* 00111111 */ + vdisk_write(vd, (uint32)sb.bitmap_start, 1, block); + + /* Directory & Data Initialization */ + memset(block, 0, 512); + for (int i = (int)sb.dir_start; i < (int)sb.data_start; i++) { + vdisk_write(vd, (uint32)i, 1, block); + } +} + +void rnafs_mount_vdisk(const char* vdisk_name) { + vdisk_t* vd = vdisk_open(vdisk_name); + if (!vd) return; + + if (vdisk_read(vd, 0, 1, &active_sb)) { + if (active_sb.magic == RNAFS_MAGIC) { + active_vd = vd; + is_mounted = 1; + print("RNAFS: Mounted via VDISK Suit.\n"); + } + } +} + +void rnafs_ls() { + if (!is_mounted || !active_vd) return; + rnafs_entry_t entries[RNAFS_MAX_FILES]; + memset(entries, 0, sizeof(entries)); + if (!vdisk_read(active_vd, (uint32)active_sb.dir_start, (uint32)active_sb.dir_blocks, entries)) return; + print("Files:\n"); + for (int i = 0; i < RNAFS_MAX_FILES; i++) { + if (entries[i].name[0] != 0) { + print(" "); + print(entries[i].name); + print("\n"); + } + } +} + +INTN rnafs_read(const char* path, void* buffer, uint64 max_size) { + if (!is_mounted || !active_vd) return -1; + rnafs_entry_t entries[RNAFS_MAX_FILES]; + memset(entries, 0, sizeof(entries)); + if (!vdisk_read(active_vd, (uint32)active_sb.dir_start, (uint32)active_sb.dir_blocks, entries)) return -1; + for (int i = 0; i < RNAFS_MAX_FILES; i++) { + if (entries[i].name[0] != 0 && strcmp(entries[i].name, path) == 0) { + uint64 size = entries[i].size; + if (size > max_size) size = max_size; + uint32 blocks = (uint32)((size + 511) / 512); + if (vdisk_read(active_vd, entries[i].start_block, blocks, buffer)) { + return (INTN)size; + } + } + } + return -1; +} + +INTN rnafs_write(const char* path, const void* buffer, uint64 size) { + if (!is_mounted || !active_vd) return -1; + + rnafs_entry_t entries[RNAFS_MAX_FILES]; + memset(entries, 0, sizeof(entries)); + if (!vdisk_read(active_vd, (uint32)active_sb.dir_start, (uint32)active_sb.dir_blocks, entries)) return -1; + + uint8 bitmap[512]; + if (!vdisk_read(active_vd, (uint32)active_sb.bitmap_start, 1, bitmap)) return -1; + + uint32 blocks_needed = (uint32)((size + 511) / 512); + int entry_idx = -1; + uint64 start_block = 0; + + /* Check if file exists */ + for (int i = 0; i < RNAFS_MAX_FILES; i++) { + if (entries[i].name[0] != 0 && strcmp(entries[i].name, path) == 0) { + /* Clear old bits in bitmap */ + uint32 old_start = entries[i].start_block; + uint32 old_blocks = (uint32)((entries[i].size + 511) / 512); + for (uint32 b = old_start; b < old_start + old_blocks; b++) { + bitmap[b / 8] &= ~(1 << (b % 8)); + } + entry_idx = i; + break; + } + } + + if (entry_idx == -1) { + /* Find new entry */ + for (int i = 0; i < RNAFS_MAX_FILES; i++) { + if (entries[i].name[0] == 0) { + entry_idx = i; + break; + } + } + } + + if (entry_idx == -1) return -1; + + /* Simple Contiguous Allocation */ + uint32 count = 0; + for (uint32 i = (uint32)active_sb.data_start; i < (uint32)active_sb.total_blocks; i++) { + if (!(bitmap[i / 8] & (1 << (i % 8)))) { + if (count == 0) start_block = i; + count++; + if (count == blocks_needed) break; + } else { + count = 0; + } + } + + if (count < blocks_needed) return -1; + + /* Mark Bitmap */ + for (uint32 i = (uint32)start_block; i < (uint32)start_block + blocks_needed; i++) { + bitmap[i / 8] |= (1 << (i % 8)); + } + + /* Write Data */ + if (!vdisk_write(active_vd, (uint32)start_block, blocks_needed, buffer)) return -1; + + /* Update Directory & Bitmap */ + strcpy(entries[entry_idx].name, path); + entries[entry_idx].start_block = start_block; + entries[entry_idx].size = size; + + vdisk_write(active_vd, (uint32)active_sb.bitmap_start, 1, bitmap); + vdisk_write(active_vd, (uint32)active_sb.dir_start, (uint32)active_sb.dir_blocks, entries); + + return (INTN)size; +} diff --git a/kernel/libs/rnafs.h b/kernel/libs/rnafs.h new file mode 100644 index 0000000..f3e83eb --- /dev/null +++ b/kernel/libs/rnafs.h @@ -0,0 +1,37 @@ +#ifndef RNAFS_H +#define RNAFS_H + +#include "../../include/types.h" + +/* RNAFS v1 Structure */ +#define RNAFS_MAGIC 0x5346414E52 /* "RNAFS" */ +#define RNAFS_BLOCK_SIZE 512 + +typedef struct { + uint64 magic; + uint64 total_blocks; + uint64 bitmap_start; + uint64 bitmap_blocks; + uint64 dir_start; + uint64 dir_blocks; + uint64 data_start; +} rnafs_superblock_t; + +typedef struct __attribute__((packed)) { + char name[64]; + uint64 start_block; + uint64 size; + uint32 flags; + uint8 padding[44]; +} rnafs_entry_t; + +#define RNAFS_MAX_FILES 16 + +void rnafs_init(); +void rnafs_format_vdisk(const char* vdisk_name, uint32 size_sectors); +void rnafs_mount_vdisk(const char* vdisk_name); +void rnafs_ls(); +INTN rnafs_read(const char* path, void* buffer, uint64 max_size); +INTN rnafs_write(const char* path, const void* buffer, uint64 size); + +#endif diff --git a/kernel/libs/vdisk.c b/kernel/libs/vdisk.c new file mode 100644 index 0000000..a93817f --- /dev/null +++ b/kernel/libs/vdisk.c @@ -0,0 +1,77 @@ +#include "vdisk.h" +#include "kutils.h" +#include "console.h" + +static vdisk_t vdisk_registry[MAX_VDISKS]; +static uint32 vdisk_count = 0; + +void vdisk_init() { + vdisk_count = 0; + memset(vdisk_registry, 0, sizeof(vdisk_registry)); +} + +vdisk_t* vdisk_open(const char* name) { + for (uint32 i = 0; i < vdisk_count; i++) { + if (strcmp(vdisk_registry[i].name, name) == 0) { + return &vdisk_registry[i]; + } + } + + /* Auto-create VDISK on RAM0 if not found for v0 compatibility */ + if (vdisk_count < MAX_VDISKS) { + strcpy(vdisk_registry[vdisk_count].name, name); + vdisk_registry[vdisk_count].physical = connect_get_device("/CONNECT/RAM0/"); + vdisk_registry[vdisk_count].start_lba = 0; + vdisk_registry[vdisk_count].end_lba = vdisk_registry[vdisk_count].physical ? vdisk_registry[vdisk_count].physical->total_lba - 1 : 0; + vdisk_registry[vdisk_count].is_mounted = 0; + return &vdisk_registry[vdisk_count++]; + } + + return (void*)0; +} + +int vdisk_mount_verify(vdisk_t* vd) { + if (!vd || !vd->physical || !vd->physical->is_active) { + print("VDISK: CANNOT FIND DISK (Hardware Offline)\n"); + return 0; + } + + uint32 signature = 0; + if (vdisk_read(vd, 0, 1, &signature)) { + if (signature == 0xDEADBEEF) { + vd->is_mounted = 1; + return 1; + } + } + + print("VDISK: Signature mismatch. Access denied.\n"); + return 0; +} + +int vdisk_read(vdisk_t* vd, uint64 lba, uint32 count, void* buffer) { + if (!vd || !vd->physical || !vd->physical->is_active) return 0; + uint64 phys_lba = vd->start_lba + lba; + if (phys_lba + count - 1 > vd->end_lba) return 0; + + if (vd->physical->type == DEVICE_TYPE_RAM) { + uint64 offset = phys_lba * vd->physical->sector_size; + uint64 size = (uint64)count * vd->physical->sector_size; + memcpy(buffer, (uint8*)vd->physical->base_addr + offset, size); + return 1; + } + return 0; +} + +int vdisk_write(vdisk_t* vd, uint64 lba, uint32 count, const void* buffer) { + if (!vd || !vd->physical || !vd->physical->is_active) return 0; + uint64 phys_lba = vd->start_lba + lba; + if (phys_lba + count - 1 > vd->end_lba) return 0; + + if (vd->physical->type == DEVICE_TYPE_RAM) { + uint64 offset = phys_lba * vd->physical->sector_size; + uint64 size = (uint64)count * vd->physical->sector_size; + memcpy((uint8*)vd->physical->base_addr + offset, buffer, size); + return 1; + } + return 0; +} diff --git a/kernel/libs/vdisk.h b/kernel/libs/vdisk.h new file mode 100644 index 0000000..7889561 --- /dev/null +++ b/kernel/libs/vdisk.h @@ -0,0 +1,23 @@ +#ifndef VDISK_H +#define VDISK_H + +#include "../../include/types.h" +#include "connect.h" + +typedef struct { + char name[32]; + physical_config_t* physical; + uint64 start_lba; + uint64 end_lba; + int is_mounted; +} vdisk_t; + +#define MAX_VDISKS 8 + +void vdisk_init(); +vdisk_t* vdisk_open(const char* name); +int vdisk_read(vdisk_t* vd, uint64 lba, uint32 count, void* buffer); +int vdisk_write(vdisk_t* vd, uint64 lba, uint32 count, const void* buffer); +int vdisk_mount_verify(vdisk_t* vd); + +#endif diff --git a/kernel/unice64/efi_entry.c b/kernel/unice64/efi_entry.c new file mode 100644 index 0000000..9b89ab6 --- /dev/null +++ b/kernel/unice64/efi_entry.c @@ -0,0 +1,128 @@ +#include +#include +#include "../../include/config.h" +#include "../../include/types.h" +#include "../../include/rsl.h" +#include "kernel.h" + +static EFI_GUID li_g = LOADED_IMAGE_PROTOCOL; +static EFI_GUID fs_g = SIMPLE_FILE_SYSTEM_PROTOCOL; +static EFI_GUID gop_g = EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID; + +static EFI_STATUS load_file(EFI_SYSTEM_TABLE *ST, EFI_FILE_PROTOCOL *root, CHAR16 *name, EFI_PHYSICAL_ADDRESS addr, UINT64 *out_size) { + EFI_FILE_PROTOCOL *file; + EFI_STATUS status = root->Open(root, &file, name, EFI_FILE_MODE_READ, 0); + if (status != EFI_SUCCESS) return status; + + EFI_FILE_INFO *info = LibFileInfo(file); + if (!info) return EFI_LOAD_ERROR; + + UINT64 file_size = info->FileSize; + UINTN pages = (file_size + 4095) / 4096; + EFI_PHYSICAL_ADDRESS load_addr = addr; + + status = ST->BootServices->AllocatePages(AllocateAddress, EfiLoaderData, pages, &load_addr); + if (status != EFI_SUCCESS) return status; + + UINTN read_size = (UINTN)file_size; + status = file->Read(file, &read_size, (void*)load_addr); + if (status == EFI_SUCCESS && out_size) *out_size = (UINT64)read_size; + + FreePool(info); + file->Close(file); + return status; +} + +EFI_STATUS EFIAPI efi_main(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable) { + InitializeLib(ImageHandle, SystemTable); + boot_params_t params = {0}; + EFI_STATUS status; + + Print(L"OSx2 Native EFI Kernel Booting...\n"); + + /* 1. Get Graphics Info */ + EFI_GRAPHICS_OUTPUT_PROTOCOL *gop; + status = SystemTable->BootServices->LocateProtocol(&gop_g, (void*)0, (void**)&gop); + if (status == EFI_SUCCESS) { + params.framebuffer = (UINT32*)gop->Mode->FrameBufferBase; + params.width = gop->Mode->Info->HorizontalResolution; + params.height = gop->Mode->Info->VerticalResolution; + params.pixels_per_scanline = gop->Mode->Info->PixelsPerScanLine; + } + + /* 2. Load Shell */ + EFI_LOADED_IMAGE_PROTOCOL *li; + EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *fs; + EFI_FILE_PROTOCOL *root; + + status = SystemTable->BootServices->HandleProtocol(ImageHandle, &li_g, (void**)&li); + if (status != EFI_SUCCESS) { + Print(L"FATAL: LoadedImage Protocol Failed! %r\n", status); + while(1); + } + + status = SystemTable->BootServices->HandleProtocol(li->DeviceHandle, &fs_g, (void**)&fs); + if (status != EFI_SUCCESS) { + Print(L"FATAL: FileSystem Protocol Failed! %r\n", status); + while(1); + } + + status = fs->OpenVolume(fs, &root); + if (status != EFI_SUCCESS) { + Print(L"FATAL: Could not open root volume! %r\n", status); + while(1); + } + + /* Load Shell at 48MB (or wherever specified) */ + status = load_file(SystemTable, root, L"shell.bin", 0x3000000, ¶ms.shell_size); + if (status == EFI_SUCCESS) { + params.shell_base = (void*)0x3000000; + } else { + Print(L"Warning: shell.bin not found on ESP. %r\n", status); + } + + /* 3. Prepare System Disk (Ramdisk) */ + params.ramdisk_size = 16 * 1024 * 1024; + EFI_PHYSICAL_ADDRESS disk_addr = 0x4000000; + UINTN disk_pages = (params.ramdisk_size + 4095) / 4096; + status = SystemTable->BootServices->AllocatePages(AllocateAddress, EfiLoaderData, disk_pages, &disk_addr); + if (status == EFI_SUCCESS) { + params.ramdisk_base = (void*)disk_addr; + /* Zero the disk */ + UINT8* p = (UINT8*)params.ramdisk_base; + for (UINT64 i = 0; i < params.ramdisk_size; i++) p[i] = 0; + } + + /* 4. Allocate Heap */ + UINTN heap_size = (UINTN)CONFIG_HEAP_SIZE_MB * 1024 * 1024; + EFI_PHYSICAL_ADDRESS heap_addr = CONFIG_HEAP_BASE; + UINTN heap_pages = (heap_size + 4095) / 4096; + status = SystemTable->BootServices->AllocatePages(AllocateAddress, EfiLoaderData, heap_pages, &heap_addr); + if (status == EFI_SUCCESS) { + params.heap_base = (void*)heap_addr; + params.heap_size = (UINT64)heap_size; + } + + params.SystemTable = SystemTable; + params.ImageHandle = ImageHandle; + + Print(L"Exiting Boot Services and jumping to kernel_main...\n"); + + /* 5. Exit Boot Services */ + UINTN map_size = 0, map_key = 0, descriptor_size = 0; + UINT32 descriptor_version = 0; + SystemTable->BootServices->GetMemoryMap(&map_size, (void*)0, &map_key, &descriptor_size, &descriptor_version); + map_size += 2 * descriptor_size; + void* map_buffer; + if (SystemTable->BootServices->AllocatePool(2, map_size, &map_buffer) == EFI_SUCCESS) { + if (SystemTable->BootServices->GetMemoryMap(&map_size, map_buffer, &map_key, &descriptor_size, &descriptor_version) == EFI_SUCCESS) { + if (SystemTable->BootServices->ExitBootServices(ImageHandle, map_key) == EFI_SUCCESS) { + /* Call kernel_main directly */ + kernel_main(¶ms); + } + } + } + + while(1) { __asm__ volatile("hlt"); } + return EFI_SUCCESS; +} diff --git a/kernel/unice64/gdt.c b/kernel/unice64/gdt.c new file mode 100644 index 0000000..9da1cf0 --- /dev/null +++ b/kernel/unice64/gdt.c @@ -0,0 +1,34 @@ +#include "../../include/types.h" + +typedef struct { + uint16 limit_low; + uint16 base_low; + uint8 base_mid; + uint8 access; + uint8 granularity; + uint8 base_high; +} __attribute__((packed)) gdt_entry_t; + +typedef struct { + uint16 limit; + uint64 base; +} __attribute__((packed)) gdt_ptr_t; + +static gdt_entry_t gdt[3]; +static gdt_ptr_t gdt_ptr; + +void gdt_init() { + /* Null descriptor */ + gdt[0] = (gdt_entry_t){0, 0, 0, 0, 0, 0}; + + /* 64-bit Code segment: Access 0x9A (present, ring 0, code, readable), Gran 0x20 (long mode) */ + gdt[1] = (gdt_entry_t){0, 0, 0, 0x9A, 0x20, 0}; + + /* 64-bit Data segment: Access 0x92 (present, ring 0, data, writable) */ + gdt[2] = (gdt_entry_t){0, 0, 0, 0x92, 0, 0}; + + gdt_ptr.limit = sizeof(gdt) - 1; + gdt_ptr.base = (uint64)&gdt; + + __asm__ volatile ("lgdt %0" : : "m"(gdt_ptr)); +} diff --git a/kernel/unice64/io.h b/kernel/unice64/io.h new file mode 100644 index 0000000..f681af9 --- /dev/null +++ b/kernel/unice64/io.h @@ -0,0 +1,16 @@ +#ifndef IO_H +#define IO_H + +#include "../include/types.h" + +static inline uint8 inb(uint16 port) { + uint8 ret; + __asm__ volatile ("inb %1, %0" : "=a"(ret) : "Nd"(port)); + return ret; +} + +static inline void outb(uint16 port, uint8 val) { + __asm__ volatile ("outb %0, %1" : : "a"(val), "Nd"(port)); +} + +#endif diff --git a/kernel/unice64/kernel.h b/kernel/unice64/kernel.h new file mode 100644 index 0000000..e0cdbaa --- /dev/null +++ b/kernel/unice64/kernel.h @@ -0,0 +1,35 @@ +#ifndef KERNEL_H +#define KERNEL_H + +#include "../../include/types.h" +#include "../../include/rsl.h" +#include "../../include/config.h" + +/* Events */ +typedef enum { + EVENT_INIT, + EVENT_MAIN, + EVENT_CLEANUP, + EVENT_EXIT +} event_t; + +/* Service Registry */ +typedef void (*service_init_t)(); +void register_service(service_init_t init_func); + +/* Event System */ +void trigger(event_t event); +typedef void (*event_handler_t)(event_t event); +void register_event_handler(event_handler_t handler); + +/* Global State */ +extern int running; +extern boot_params_t kboot_params; + +/* Entry point defined in main.c */ +void kernel_main(boot_params_t* params); + +/* GDT initialization */ +void gdt_init(void); + +#endif diff --git a/kernel/unice64/main.c b/kernel/unice64/main.c new file mode 100644 index 0000000..72b932b --- /dev/null +++ b/kernel/unice64/main.c @@ -0,0 +1,85 @@ +#include "kernel.h" +#include "../../include/rsl.h" +#include "../libs/console.h" +#include "../libs/kutils.h" +#include "../libs/memory.h" +#include "../libs/input.h" +#include "../libs/connect.h" +#include "../libs/vdisk.h" +#include "../libs/disk.h" +#include "../libs/diskman.h" +#include "../libs/fs.h" +#include "../libs/rnafs.h" +#include "../libs/loader.h" +#include "../libs/core/event.h" + +boot_params_t kboot_params; +int running = 1; + +#define MAX_SERVICES 16 +static service_init_t registered_services[MAX_SERVICES]; +static uint32 service_count = 0; + +void register_service(service_init_t init_func) { + if (service_count < MAX_SERVICES) { + registered_services[service_count++] = init_func; + } +} + +void exit_kernel() { + running = 0; +} + +/* + * The God-Machine Entry Point + */ +void kernel_main(boot_params_t* params) { + kboot_params = *params; + + /* GDT and Interrupts are usually reset after ExitBootServices for full control */ + gdt_init(); + + register_service(console_init); + register_service(memory_init); + register_service(input_init); + register_service(connect_init); + register_service(vdisk_init); + register_service(disk_init); + register_service(diskman_init); + register_service(fs_init); + register_service(loader_init); + + for (uint32 i = 0; i < service_count; i++) { + registered_services[i](); + } + + print("OSx2 God-Mode: Kernel Handover Successful.\n"); + debug_kernel_signature(); + trigger(EVENT_INIT); + + rsl_syscall_table_t syscalls = { + .print = print, + .input = input, + .fread = fread, + .fwrite = fwrite, + .alloc = alloc, + .retain = retain, + .release = release, + .exit = exit_kernel, + .clear = console_clear, + .set_color = console_set_color, + .format = diskman_format_rnafs, + .mount = diskman_mount_rnafs, + .addpart = diskman_add_partition, + .lsfs = rnafs_ls + }; + + loader_run_shell(&syscalls); + + while (running) { + trigger(EVENT_MAIN); + } + + trigger(EVENT_CLEANUP); + trigger(EVENT_EXIT); +} diff --git a/programs/libsystem.c b/programs/libsystem.c new file mode 100644 index 0000000..ec0b933 --- /dev/null +++ b/programs/libsystem.c @@ -0,0 +1,203 @@ +#include "../include/rsl.h" + +/* RTECH Standard Library (RSL) Implementation */ + +static rsl_syscall_table_t* g_syscalls = (void*)0; +boot_params_t kboot_params; + +int program_main(); + +void print(const char* str) { + if (g_syscalls && g_syscalls->print) { + g_syscalls->print(str); + } +} + +void* alloc(uint64 size) { + if (g_syscalls && g_syscalls->alloc) { + return g_syscalls->alloc(size); + } + return (void*)0; +} + +void retain(void* ptr) { + if (g_syscalls && g_syscalls->retain) { + g_syscalls->retain(ptr); + } +} + +void release(void* ptr) { + if (g_syscalls && g_syscalls->release) { + g_syscalls->release(ptr); + } +} + +INTN read_file(const char* path, void* buffer, uint64 max_size) { + if (g_syscalls && g_syscalls->fread) { + return g_syscalls->fread(path, buffer, max_size); + } + return -1; +} + +INTN write_file(const char* path, const void* buffer, uint64 size) { + if (g_syscalls && g_syscalls->fwrite) { + return g_syscalls->fwrite(path, buffer, size); + } + return -1; +} + +void clear() { + if (g_syscalls && g_syscalls->clear) { + g_syscalls->clear(); + } +} + +void quit() { + if (g_syscalls && g_syscalls->exit) { + g_syscalls->exit(); + } +} + +void color(uint32 fg, uint32 bg) { + if (g_syscalls && g_syscalls->set_color) { + g_syscalls->set_color(fg, bg); + } +} + +void lsfs() { + if (g_syscalls && g_syscalls->lsfs) { + g_syscalls->lsfs(); + } +} + +void format(int idx) { + if (g_syscalls && g_syscalls->format) { + g_syscalls->format(idx); + } +} + +void mount(int idx) { + if (g_syscalls && g_syscalls->mount) { + g_syscalls->mount(idx); + } +} + +void addpart(uint64 start, uint32 count) { + if (g_syscalls && g_syscalls->addpart) { + g_syscalls->addpart(start, count); + } +} + +/* --- Auto-RAM: Simplified API --- */ + +void* auto_ram(uint64 size) { + /* Everything in RSL is managed by ARC by default */ + return alloc(size); +} + +char* str_create(const char* init) { + uint64 len = strlen(init); + char* s = (char*)auto_ram(len + 1); + if (s) { + strcpy(s, init); + } + return s; +} + +char* readline(const char* prompt) { + char* buf = (char*)auto_ram(128); + if (!buf) return (void*)0; + + if (g_syscalls && g_syscalls->input) { + g_syscalls->input(prompt, buf, 128); + } + return buf; +} + +/* --- Utilities --- */ + +int strcmp(const char* s1, const char* s2) { + while (*s1 && *s1 == *s2) { s1++; s2++; } + return *(unsigned char*)s1 - *(unsigned char*)s2; +} + +int strncmp(const char* s1, const char* s2, uint64 n) { + for (uint64 i = 0; i < n; i++) { + if (s1[i] != s2[i]) return (unsigned char)s1[i] - (unsigned char)s2[i]; + if (s1[i] == 0) return 0; + } + return 0; +} + +void strcpy(char* dst, const char* src) { + while ((*dst++ = *src++)); +} + +void strncpy(char* dst, const char* src, uint64 n) { + uint64 i; + for (i = 0; i < n && src[i] != '\0'; i++) dst[i] = src[i]; + for (; i < n; i++) dst[i] = '\0'; +} + +uint64 strlen(const char* s) { + uint64 n = 0; + while (s[n]) n++; + return n; +} + +char* strchr(const char* s, int c) { + while (s && *s != (char)c) { + if (!*s++) return (void*)0; + } + return (char*)s; +} + +void memcpy(void* dst, const void* src, uint64 n) { + uint8* d = (uint8*)dst; + const uint8* s = (const uint8*)src; + while (n--) *d++ = *s++; +} + +void memset(void* s, int c, uint64 n) { + uint8* p = (uint8*)s; + while (n--) *p++ = (uint8)c; +} + +int atoi(const char* s) { + int res = 0; + while (s && *s >= '0' && *s <= '9') { + res = res * 10 + (*s - '0'); + s++; + } + return res; +} + +void itoa(int n, char* s, int base) { + char* p = s; + char* p1, *p2; + unsigned int ud = n; + if (base == 10 && n < 0) { + *p++ = '-'; + s++; + ud = -n; + } + do { + int remainder = ud % base; + *p++ = (remainder < 10) ? remainder + '0' : remainder + 'a' - 10; + } while (ud /= base); + *p = 0; + p1 = s; + p2 = p - 1; + while (p1 < p2) { + char tmp = *p1; + *p1++ = *p2; + *p2-- = tmp; + } +} + +__attribute__((section(".text._start"))) +void _start(boot_params_t* params, rsl_syscall_table_t* syscalls) { + if (params) kboot_params = *params; + if (syscalls) g_syscalls = syscalls; + program_main(); +} diff --git a/programs/linker.ld b/programs/linker.ld new file mode 100644 index 0000000..2e73f8f --- /dev/null +++ b/programs/linker.ld @@ -0,0 +1,12 @@ +ENTRY(_start) +SECTIONS +{ + . = 0x3000000; /* Linked to match Stage 1 load address */ + .text : { + KEEP(*(.text._start)) + *(.text*) + } + .rodata : { *(.rodata*) } + .data : { *(.data*) } + .bss : { *(.bss*) } +} diff --git a/programs/shell.c b/programs/shell.c new file mode 100644 index 0000000..296d19f --- /dev/null +++ b/programs/shell.c @@ -0,0 +1,85 @@ +#include "../include/rsl.h" + +/* + * OSx2 Standard Shell + * Powering RTECH dos via the RSL (RTECH Standard Library). + */ + +static void handle_command(char* cmd); + +int program_main() { + clear(); + color(0x00FF88, 0x000000); + print("OSx2 (RTECH dos) - Kernel Expert Mode (64-bit)\n"); + print("Partition Table: GPT (GUID Partition Table)\n"); + print("Permanent Storage: RNAFS (Proprietary)\n\n"); + + while (1) { + char* input_str = readline("> "); + if (input_str) { + handle_command(input_str); + release(input_str); + } + } + return 0; +} + +static void handle_command(char* cmd) { + if (strcmp(cmd, "help") == 0) { + print("Commands:\n"); + print(" lsfs - List files on mounted RNAFS\n"); + print(" cat [file] - Read file content\n"); + print(" write [f] [t] - Write text to file\n"); + print(" addpart [s] [c]- Add GPT partition (Start LBA, Count)\n"); + print(" format [idx] - Format GPT partition with RNAFS\n"); + print(" mount [idx] - Mount RNAFS partition\n"); + print(" clear - Clear screen\n"); + print(" exit - Shutdown\n"); + } else if (strcmp(cmd, "exit") == 0) { + quit(); + } else if (strcmp(cmd, "clear") == 0) { + clear(); + } else if (strncmp(cmd, "lsfs", 4) == 0) { + lsfs(); + } else if (strncmp(cmd, "addpart ", 8) == 0) { + char* start_str = cmd + 8; + char* count_str = strchr(start_str, ' '); + if (start_str && count_str) { + *count_str = 0; + count_str++; + addpart((uint64)atoi(start_str), (uint32)atoi(count_str)); + } + } else if (strncmp(cmd, "format ", 7) == 0) { + format(atoi(cmd + 7)); + } else if (strncmp(cmd, "mount ", 6) == 0) { + mount(atoi(cmd + 6)); + } else if (strncmp(cmd, "cat ", 4) == 0) { + char* buf = (char*)auto_ram(4096); + if (buf) { + memset(buf, 0, 4096); + if (read_file(cmd + 4, buf, 4096) >= 0) { + print(buf); + print("\n"); + } else { + print("Error: File not found or RNAFS not mounted.\n"); + } + release(buf); + } + } else if (strncmp(cmd, "write ", 6) == 0) { + char* arg = cmd + 6; + char* text = strchr(arg, ' '); + if (text) { + *text = 0; + text++; + if (write_file(arg, text, strlen(text)) >= 0) { + print("Write successful.\n"); + } else { + print("Write failed.\n"); + } + } + } else if (cmd[0] != 0) { + print("Unknown command: "); + print(cmd); + print("\n"); + } +} diff --git a/scripts/menuconfig.py b/scripts/menuconfig.py new file mode 100644 index 0000000..620d9f8 --- /dev/null +++ b/scripts/menuconfig.py @@ -0,0 +1,147 @@ +import curses +import os +import sys + +# OSx2 Configuration Options - Professional Suite +OPTIONS = [ + {"id": "CONFIG_DEBUG_LOGS", "label": "Enable Debug Logging", "type": "bool", "default": True}, + {"id": "CONFIG_KERNEL_BASE", "label": "Kernel Base Address (Hex)", "type": "hex", "default": 0x100000}, + {"id": "CONFIG_HEAP_BASE", "label": "ARC Heap Base Address (Hex)", "type": "hex", "default": 0x2000000}, + {"id": "CONFIG_HEAP_SIZE_MB", "label": "Global Heap Size (MB)", "type": "int", "default": 8}, + {"id": "CONFIG_SCROLL_SPEED", "label": "Console Scroll Speed (Pixels)", "type": "int", "default": 10}, + {"id": "CONFIG_EMERALD_MODE", "label": "Enable High-Contrast Emerald Theme", "type": "bool", "default": True}, + {"id": "CONFIG_FG_COLOR", "label": "Default FG Color (RGB Hex)", "type": "hex", "default": 0x00FF88}, + {"id": "CONFIG_BG_COLOR", "label": "Default BG Color (RGB Hex)", "type": "hex", "default": 0x000000}, + {"id": "CONFIG_LOAD_SHELL", "label": "Auto-load shell.bin on boot", "type": "bool", "default": True}, + {"id": "CONFIG_OPTIMIZATION", "label": "Compiler Optimization (-O0, -O1, -O2)", "type": "int", "default": 0}, + {"id": "CONFIG_STRICT_CHECKS", "label": "Enable Strict Memory Bounds Checking", "type": "bool", "default": True}, +] + +class MenuConfig: + def __init__(self, stdscr): + self.stdscr = stdscr + self.cursor = 0 + self.values = {} + self.load_config() + + def load_config(self): + if os.path.exists(".config"): + with open(".config", "r") as f: + for line in f: + if "=" in line: + parts = line.strip().split("=") + if len(parts) == 2: + k, v = parts + if v == "y": self.values[k] = True + elif v == "n": self.values[k] = False + elif v.startswith("0x"): self.values[k] = int(v, 16) + elif v.isdigit(): self.values[k] = int(v) + else: self.values[k] = v + + for opt in OPTIONS: + if opt["id"] not in self.values: + self.values[opt["id"]] = opt["default"] + + def save_config(self): + # Save .config for Makefile + with open(".config", "w") as f: + for k, v in self.values.items(): + if isinstance(v, bool): + f.write(f"{k}={'y' if v else 'n'}\n") + elif isinstance(v, int): + # Check if it was originally hex + is_hex = False + for opt in OPTIONS: + if opt["id"] == k and opt["type"] == "hex": + is_hex = True + break + if is_hex: f.write(f"{k}={hex(v)}\n") + else: f.write(f"{k}={v}\n") + else: + f.write(f"{k}={v}\n") + + # Save include/config.h for C + with open("include/config.h", "w") as f: + f.write("#ifndef CONFIG_H\n#define CONFIG_H\n\n") + f.write("/* Auto-generated by OSx2 menuconfig Professional */\n\n") + for k, v in self.values.items(): + if isinstance(v, bool): + if v: f.write(f"#define {k} 1\n") + else: f.write(f"/* #undef {k} */\n") + elif isinstance(v, int): + f.write(f"#define {k} {hex(v) if v > 1000 else v}\n") + else: + f.write(f"#define {k} {v}\n") + f.write("\n#endif\n") + + def run(self): + curses.curs_set(0) + self.stdscr.nodelay(0) + self.stdscr.keypad(True) + + while True: + self.stdscr.clear() + h, w = self.stdscr.getmaxyx() + + # Draw header + self.stdscr.attron(curses.A_REVERSE) + self.stdscr.addstr(0, 0, " OSx2 / RTECH dos Advanced Configuration Utility ".center(w)) + self.stdscr.attroff(curses.A_REVERSE) + + # Draw options + for i, opt in enumerate(OPTIONS): + val = self.values[opt["id"]] + if isinstance(val, bool): + prefix = "[*]" if val else "[ ]" + elif i == self.cursor: + prefix = f"({hex(val) if isinstance(val, int) and val > 1000 else val})" + else: + prefix = f" {hex(val) if isinstance(val, int) and val > 1000 else val} " + + label = f"{prefix.ljust(12)} {opt['label']}" + + if i == self.cursor: + self.stdscr.attron(curses.A_BOLD | curses.A_REVERSE) + self.stdscr.addstr(i + 2, 2, f" > {label} ") + self.stdscr.attroff(curses.A_BOLD | curses.A_REVERSE) + else: + self.stdscr.addstr(i + 2, 2, f" {label}") + + # Draw footer + self.stdscr.addstr(h - 3, 2, "-" * (w - 4)) + self.stdscr.addstr(h - 2, 2, "Space/Enter: Edit | S: Save & Exit | Q: Discard & Quit") + + key = self.stdscr.getch() + if key == ord('q'): break + if key == ord('s'): + self.save_config() + break + elif key == curses.KEY_UP: + self.cursor = (self.cursor - 1) % len(OPTIONS) + elif key == curses.KEY_DOWN: + self.cursor = (self.cursor + 1) % len(OPTIONS) + elif key in [ord(' '), 10, 13]: + opt = OPTIONS[self.cursor] + if opt["type"] == "bool": + self.values[opt["id"]] = not self.values[opt["id"]] + else: + curses.echo() + self.stdscr.addstr(h - 1, 2, f"Set {opt['id']}: ".ljust(w-4)) + self.stdscr.move(h - 1, len(opt['id']) + 7) + new_val = self.stdscr.getstr().decode() + curses.noecho() + try: + if opt["type"] == "hex": + if new_val.startswith("0x"): self.values[opt["id"]] = int(new_val, 16) + else: self.values[opt["id"]] = int(new_val, 16) + elif opt["type"] == "int": + self.values[opt["id"]] = int(new_val) + except: + pass + +if __name__ == "__main__": + if len(sys.argv) > 1 and sys.argv[1] == "--save": + mc = MenuConfig(None) + mc.save_config() + else: + curses.wrapper(lambda s: MenuConfig(s).run()) diff --git a/scripts/rnafs_tool.py b/scripts/rnafs_tool.py new file mode 100644 index 0000000..349cb80 --- /dev/null +++ b/scripts/rnafs_tool.py @@ -0,0 +1,122 @@ +import struct +import sys +import os + +# RNAFS v1 Structure +BLOCK_SIZE = 512 +MAGIC = b"RNAFS\0\0\0" # Padded to 8 bytes + +# Layout: +# block 0: Superblock +# block 1: Bitmap (1 block = 4096 files/blocks supported) +# block 2-5: Directory Entries (64 entries per block? No, 64 entries total in v0) +# block 6+: Data + +class RNAFSTool: + def __init__(self, filename): + self.filename = filename + + def format(self, size_mb=16): + total_blocks = (size_mb * 1024 * 1024) // BLOCK_SIZE + print(f"Formatting {self.filename} with {total_blocks} blocks...") + + with open(self.filename, "wb") as f: + # Superblock + # magic(8), total(8), bitmap_st(8), bitmap_bl(8), dir_st(8), dir_bl(8), data_st(8) + sb = struct.pack("<8sQQQQQQ", MAGIC, total_blocks, 1, 1, 2, 4, 6) + f.write(sb.ljust(BLOCK_SIZE, b"\0")) + + # Bitmap (mark first 6 blocks used) + bitmap = bytearray(BLOCK_SIZE) + bitmap[0] = 0x3F # binary 00111111 + f.write(bitmap) + + # Directory (4 blocks, all empty) + f.write(b"\0" * (4 * BLOCK_SIZE)) + + # Rest is data + f.write(b"\0" * ((total_blocks - 6) * BLOCK_SIZE)) + + def add_file(self, host_path, guest_name): + if not os.path.exists(host_path): + print(f"Error: {host_path} not found") + return + + with open(host_path, "rb") as src: + data = src.read() + + size = len(data) + blocks_needed = (size + BLOCK_SIZE - 1) // BLOCK_SIZE + + with open(self.filename, "r+b") as f: + # Read SB + f.seek(0) + sb = struct.unpack("<8sQQQQQQ", f.read(56)) + data_start = sb[6] + total_blocks = sb[1] + + # Find free space in bitmap (very simple contiguous find) + f.seek(BLOCK_SIZE) + bitmap = bytearray(f.read(BLOCK_SIZE)) + + start_block = -1 + for i in range(data_start, total_blocks - blocks_needed): + found = True + for j in range(blocks_needed): + byte_idx = (i + j) // 8 + bit_idx = (i + j) % 8 + if bitmap[byte_idx] & (1 << bit_idx): + found = False + break + if found: + start_block = i + break + + if start_block == -1: + print("Error: No contiguous space found") + return + + # Mark bitmap + for i in range(start_block, start_block + blocks_needed): + bitmap[i // 8] |= (1 << (i % 8)) + f.seek(BLOCK_SIZE) + f.write(bitmap) + + # Find empty dir entry + dir_start = sb[4] + f.seek(dir_start * BLOCK_SIZE) + entries = f.read(4 * BLOCK_SIZE) + + entry_size = 128 # name(64), start(8), size(8), flags(4), pad(44) + found_entry = -1 + for i in range(0, len(entries), entry_size): + if entries[i] == 0: + found_entry = i + break + + if found_entry == -1: + print("Error: Directory full") + return + + # Write entry + # name(64s), start(Q), size(Q), flags(I) + name_bytes = guest_name.encode("ascii")[:63] + new_entry = struct.pack("<64sQQI", name_bytes, start_block, size, 0) + f.seek(dir_start * BLOCK_SIZE + found_entry) + f.write(new_entry) + + # Write data + f.seek(start_block * BLOCK_SIZE) + f.write(data) + print(f"Added {guest_name} at block {start_block} ({size} bytes)") + +if __name__ == "__main__": + if len(sys.argv) < 3: + print("Usage: rnafs_tool.py [args]") + print("Commands: format, add ") + sys.exit(1) + + tool = RNAFSTool(sys.argv[1]) + cmd = sys.argv[2] + if cmd == "format": tool.format() + elif cmd == "add": tool.add_file(sys.argv[3], sys.argv[4]) diff --git a/tools/fontgen.html b/tools/fontgen.html new file mode 100644 index 0000000..1727b53 --- /dev/null +++ b/tools/fontgen.html @@ -0,0 +1,211 @@ + + + + + + OSx2 Pro Font & Color Studio + + + +
+

OSx2 / RTECH FONT STUDIO

+
+ +
+ + +
+
+ +
+ +
A
+ +
+
+
+ + + +