├── arch ├── SUBSYSTEM.md ├── x86-64 │ ├── sources │ │ ├── user_mode.h │ │ ├── arch_x64.h │ │ ├── arch_x64.c │ │ ├── tss_x64.h │ │ ├── idt_arch_x64.c │ │ ├── tss_x64.c │ │ ├── idt_arch_x64.h │ │ ├── gdt.h │ │ ├── user_mode.c │ │ ├── gdt.c │ │ └── fault.c │ ├── grub.cfg │ ├── linker.ld │ ├── Makefile │ └── asm │ │ └── syscall_entry_64.asm └── common │ ├── common_paging.h │ ├── arch_interface.h │ └── idt.h ├── scripts ├── cloc.sh ├── test_userspace.sh ├── unibuild-clean.sh └── create_disk.sh ├── fs ├── libir0fs.a ├── libvfs.a ├── ramfs.h ├── Makefile ├── vfs_simple.h ├── vfs_simple_wrappers.c └── chmod.c ├── kernel ├── init.h ├── errno.h ├── shell.h ├── user.h ├── syscall_wrappers.h ├── rr_sched.h ├── kernel.h ├── Makefile ├── user.c ├── syscalls.h ├── scheduler │ ├── Makefile │ ├── scheduler_types.h │ ├── scheduler.h │ └── switch │ │ └── debug.asm ├── syscall_wrappers.c ├── rr_sched.c ├── fs │ └── file.c ├── init.c ├── syscalls_internal.h ├── kernel_config.h ├── main.c ├── elf_loader.h └── SUBSYSTEM.md ├── tools └── kconfig │ ├── assets │ └── black_hole_logo.png │ ├── __pycache__ │ └── tkconfig.cpython-312.pyc │ └── Makefile ├── drivers ├── timer │ ├── lapic │ │ ├── lapic.h │ │ └── lapic.c │ ├── pit │ │ ├── pit.h │ │ └── pit.c │ ├── hpet │ │ ├── hpet.h │ │ ├── find_hpet.h │ │ ├── hpet.c │ │ └── find_hpet.c │ ├── acpi │ │ └── acpi.h │ ├── Makefile │ ├── rtc │ │ └── rtc.h │ └── clock_system.h ├── storage │ ├── fs_types.h │ ├── Makefile │ ├── fs_types.c │ ├── ata_helpers.c │ └── ata.h ├── dma │ ├── dma.h │ └── dma.c ├── IO │ └── Makefile ├── audio │ └── Makefile ├── serial │ ├── serial.h │ └── serial.c ├── video │ ├── vbe.h │ └── typewriter.h ├── disk │ └── partition.h ├── net │ └── rtl8139.h └── SUBSYSTEM.md ├── interrupt ├── arch │ ├── lidt_32.c │ ├── x86-32 │ │ ├── lidt_32.asm │ │ ├── isr_stubs_32.asm │ │ └── interrupt.asm │ ├── keyboard.h │ ├── io.h │ ├── pic.h │ ├── isr_handlers.c │ ├── idt_32.h │ ├── x86-64 │ │ └── interrupt.asm │ ├── idt.h │ ├── pic.c │ └── idt_32.c ├── isr_handlers.h ├── isr_handlers.c └── Makefile ├── includes ├── ir0 │ ├── keyboard.h │ ├── kernel.h │ ├── serial.h │ ├── context.h │ ├── config.h │ ├── user.h │ ├── stdlib.h │ ├── compat.h │ ├── fcntl.h │ ├── stdbool.h │ ├── Makefile │ ├── path.h │ ├── init.h │ ├── memory │ │ ├── allocator.h │ │ └── kmem.h │ ├── chmod.h │ ├── types.h │ ├── oops.h │ ├── stat.h │ ├── net.h │ ├── common.h │ ├── logging.h │ └── validation.h ├── Makefile ├── stdarg.h ├── stddef.h ├── errno.h ├── stdint.h └── string.h ├── .gitignore ├── rust ├── Cargo.toml ├── ffi │ └── README.md └── x86_64-ir0-kernel.json ├── include ├── generated │ └── autoconf.h └── kernel │ └── fs │ └── file.h ├── setup ├── Makefile.menuconfig └── Makefile ├── cpp ├── README.md └── runtime │ └── compat.cpp ├── userspace ├── bin │ ├── echo.c │ ├── hello.c │ └── libctest.c └── Makefile ├── menuconfig └── .github └── workflows └── loc-update.yml /arch/SUBSYSTEM.md: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /scripts/cloc.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | cloc --json . > loc.json 3 | -------------------------------------------------------------------------------- /fs/libir0fs.a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IRodriguez13/IR0/HEAD/fs/libir0fs.a -------------------------------------------------------------------------------- /fs/libvfs.a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IRodriguez13/IR0/HEAD/fs/libvfs.a -------------------------------------------------------------------------------- /kernel/init.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | int start_init_process(void); 4 | void init_1(void); -------------------------------------------------------------------------------- /tools/kconfig/assets/black_hole_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IRodriguez13/IR0/HEAD/tools/kconfig/assets/black_hole_logo.png -------------------------------------------------------------------------------- /kernel/errno.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #define ERRNO_MAX EHWPOISON 6 | 7 | const char *strerror(int errnum); 8 | 9 | -------------------------------------------------------------------------------- /arch/x86-64/sources/user_mode.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | void jmp_ring3(void *entry_point); 5 | void syscall_handler_c(void); 6 | -------------------------------------------------------------------------------- /tools/kconfig/__pycache__/tkconfig.cpython-312.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IRodriguez13/IR0/HEAD/tools/kconfig/__pycache__/tkconfig.cpython-312.pyc -------------------------------------------------------------------------------- /drivers/timer/lapic/lapic.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | void lapic_init_timer(); 5 | int lapic_available(); 6 | void lapic_send_eoi(); 7 | -------------------------------------------------------------------------------- /drivers/timer/pit/pit.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | void init_PIT(uint32_t frequency); 5 | void init_pic(void); 6 | uint32_t get_pit_ticks(void); 7 | void increment_pit_ticks(void); 8 | 9 | -------------------------------------------------------------------------------- /drivers/timer/hpet/hpet.h: -------------------------------------------------------------------------------- 1 | #ifndef HPET_H 2 | #define HPET_H 3 | 4 | #include 5 | #include 6 | 7 | void hpet_init(); 8 | void hpet_set_address(void* addr); 9 | 10 | #endif 11 | -------------------------------------------------------------------------------- /drivers/storage/fs_types.h: -------------------------------------------------------------------------------- 1 | #ifndef _FS_TYPES_H 2 | #define _FS_TYPES_H 3 | 4 | #include 5 | 6 | // Filesystem type identification 7 | const char* get_fs_type(uint8_t system_id); 8 | 9 | #endif /* _FS_TYPES_H */ -------------------------------------------------------------------------------- /interrupt/arch/lidt_32.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | extern void idt_load32_asm(uint32_t idt_ptr_addr); 5 | 6 | void idt_load32(void) 7 | { 8 | idt_load32_asm((uint32_t)&idt_ptr); 9 | } 10 | -------------------------------------------------------------------------------- /fs/ramfs.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-only 2 | /** 3 | * IR0 Kernel - RAMFS Header 4 | * Copyright (C) 2025 Iván Rodriguez 5 | */ 6 | 7 | #pragma once 8 | 9 | int ramfs_register(void); 10 | int ramfs_init_boot_files(void); 11 | 12 | 13 | -------------------------------------------------------------------------------- /interrupt/arch/x86-32/lidt_32.asm: -------------------------------------------------------------------------------- 1 | ; idt_load32.s 2 | section .text 3 | 4 | [bits 32] 5 | global idt_load32_asm 6 | idt_load32_asm: 7 | mov eax, [esp+4] ; recibir puntero a idt_ptr desde C 8 | lidt [eax] ; cargar IDT 9 | ret 10 | -------------------------------------------------------------------------------- /includes/ir0/keyboard.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: GPL-3.0-only */ 2 | #ifndef _IR0_KEYBOARD_H 3 | #define _IR0_KEYBOARD_H 4 | 5 | /* Keyboard buffer functions */ 6 | extern char keyboard_buffer_get(void); 7 | extern int keyboard_buffer_has_data(void); 8 | 9 | #endif /* _IR0_KEYBOARD_H */ -------------------------------------------------------------------------------- /includes/ir0/kernel.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | // Prototipos de funciones 8 | void init_paging_x86(void); 9 | void init_paging_x64(void); 10 | void dump_scheduler_state(void); 11 | void ShutDown(void); -------------------------------------------------------------------------------- /arch/x86-64/sources/arch_x64.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | void outb(uint16_t port, uint8_t value); 5 | uint8_t inb(uint16_t port); 6 | 7 | const char* arch_get_name(void); 8 | 9 | void arch_enable_interrupts(void); 10 | 11 | void kmain_x32(void); 12 | 13 | uintptr_t read_fault_address(); 14 | -------------------------------------------------------------------------------- /includes/ir0/serial.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: GPL-3.0-only */ 2 | #ifndef _IR0_SERIAL_H 3 | #define _IR0_SERIAL_H 4 | 5 | #include 6 | 7 | /* Serial port functions */ 8 | extern void serial_print(const char *str); 9 | extern void serial_print_hex32(uint32_t num); 10 | 11 | #endif /* _IR0_SERIAL_H */ -------------------------------------------------------------------------------- /drivers/timer/hpet/find_hpet.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | 6 | #define ACPI_RSDP_SIGNATURE "RSD PTR " 7 | #define ACPI_HPET_SIGNATURE 0x54455048 8 | #define RSDP_SEARCH_START 0x000E0000 9 | #define RSDP_SEARCH_END 0x000FFFFF 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /.vscode 2 | *.o 3 | *.P 4 | *.so 5 | *.dll 6 | *.d 7 | *.patch 8 | *.bin 9 | *.log 10 | *.iso 11 | *.elf 12 | *.raw 13 | *iso-x86-64/boot 14 | *iso-x86-64/boot 15 | *.txt 16 | 17 | .aider* 18 | disk.img 19 | iso-x86-64-desktop/boot/grub/grub.cfg 20 | *memory-wip 21 | iso/boot/grub/grub.cfg 22 | userspace/build/echo 23 | .config 24 | -------------------------------------------------------------------------------- /includes/ir0/context.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: GPL-3.0-only */ 2 | #ifndef _IR0_CONTEXT_H 3 | #define _IR0_CONTEXT_H 4 | 5 | #include 6 | 7 | /* Context switching functions */ 8 | extern void switch_context_x64(task_t *prev, task_t *next); 9 | extern uint64_t get_current_page_directory(void); 10 | 11 | #endif /* _IR0_CONTEXT_H */ -------------------------------------------------------------------------------- /interrupt/isr_handlers.h: -------------------------------------------------------------------------------- 1 | // interrupt/isr_handlers.h - IMPLEMENTACIÓN MÍNIMA 2 | #pragma once 3 | 4 | #include 5 | 6 | // Handler principal de interrupciones (definido en idt.c) 7 | void isr_handler(uint8_t int_no); 8 | 9 | // Función para enviar EOI 10 | void isr_send_eoi(uint8_t irq); 11 | 12 | // Handler de timer simple 13 | void time_handler(void); -------------------------------------------------------------------------------- /kernel/shell.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: GPL-3.0-only */ 2 | /* 3 | * IR0 Kernel - Built-in Shell 4 | * Copyright (C) 2025 Iván Rodriguez 5 | * 6 | * Public interface for kernel shell 7 | */ 8 | 9 | #pragma once 10 | #include 11 | 12 | 13 | void shell_entry(void); 14 | void cmd_clear(void); 15 | void vga_print(const char *str, uint8_t color); 16 | -------------------------------------------------------------------------------- /drivers/dma/dma.h: -------------------------------------------------------------------------------- 1 | // dma.h - DMA controller header 2 | #ifndef DMA_H 3 | #define DMA_H 4 | 5 | #include 6 | #include 7 | 8 | // DMA functions 9 | void dma_setup_channel(uint8_t channel, uint32_t addr, uint16_t length, bool is_16bit); 10 | void dma_enable_channel(uint8_t channel); 11 | void dma_disable_channel(uint8_t channel); 12 | 13 | #endif // DMA_H -------------------------------------------------------------------------------- /includes/Makefile: -------------------------------------------------------------------------------- 1 | # includes/Makefile - builds common include-side objects (e.g., string.o) 2 | 3 | CC ?= gcc 4 | ASM ?= nasm 5 | CFLAGS ?= -Wall -Wextra -O1 -MMD -MP 6 | ASMFLAGS ?= 7 | 8 | OBJS = string.o 9 | 10 | all: $(OBJS) 11 | 12 | %.o: %.c 13 | $(CC) $(CFLAGS) -c $< -o $@ 14 | 15 | .PHONY: clean 16 | clean: 17 | rm -f $(OBJS) 18 | rm -f *.d 19 | 20 | -include $(OBJS:.o=.d) 21 | 22 | 23 | -------------------------------------------------------------------------------- /drivers/IO/Makefile: -------------------------------------------------------------------------------- 1 | # IO Drivers Makefile 2 | IO_SOURCES = ps2.c ps2_mouse.c 3 | IO_OBJECTS = $(IO_SOURCES:.c=.o) 4 | 5 | # Compiler flags 6 | CFLAGS += -I../../includes -I../../includes/ir0 -I../../arch/common -I../../setup 7 | 8 | # Default target 9 | all: $(IO_OBJECTS) 10 | 11 | # Compile C files 12 | %.o: %.c 13 | $(CC) $(CFLAGS) -c $< -o $@ 14 | 15 | # Clean 16 | clean: 17 | rm -f *.o 18 | 19 | .PHONY: all clean 20 | -------------------------------------------------------------------------------- /kernel/user.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #define MAX_PATH_LEN 256 6 | 7 | typedef struct { 8 | uint32_t uid; 9 | uint32_t gid; 10 | char name[32]; 11 | char home[MAX_PATH_LEN]; 12 | char shell[MAX_PATH_LEN]; 13 | } user_info_t; 14 | 15 | // Initialize user subsystem 16 | void user_init(void); 17 | 18 | // Get current user information 19 | int get_current_user(user_info_t *user); 20 | -------------------------------------------------------------------------------- /includes/ir0/config.h: -------------------------------------------------------------------------------- 1 | #ifndef _IR0_CONFIG_H 2 | #define _IR0_CONFIG_H 3 | 4 | /* 5 | * KERNEL_DEBUG_SHELL 6 | * 1: Use the built-in kernel shell (init_1) 7 | * 0: Load and execute /bin/init from the filesystem 8 | */ 9 | 10 | /* In 1 the kernel will use the built-in kernel shell (init_1), in 0 it will load and execute /bin/init from the filesystem */ 11 | #define KERNEL_DEBUG_SHELL 1 12 | 13 | #endif /* _IR0_CONFIG_H */ 14 | -------------------------------------------------------------------------------- /drivers/storage/Makefile: -------------------------------------------------------------------------------- 1 | # Storage Drivers Makefile 2 | STORAGE_SOURCES = ata.c ata_helpers.c 3 | STORAGE_OBJECTS = $(STORAGE_SOURCES:.c=.o) 4 | 5 | # Compiler flags 6 | CFLAGS += -I../../includes -I../../includes/ir0 -I../../arch/common -I../../setup 7 | 8 | # Default target 9 | all: $(STORAGE_OBJECTS) 10 | 11 | # Compile C files 12 | %.o: %.c 13 | $(CC) $(CFLAGS) -c $< -o $@ 14 | 15 | # Clean 16 | clean: 17 | rm -f *.o 18 | 19 | .PHONY: all clean 20 | -------------------------------------------------------------------------------- /arch/x86-64/grub.cfg: -------------------------------------------------------------------------------- 1 | set timeout=5 2 | set default=0 3 | 4 | menuentry "IR0 Kernel v0.0.1" { 5 | multiboot /boot/kernel-x64.bin 6 | set gfxpayload=text 7 | boot 8 | } 9 | 10 | menuentry "IR0 Kernel - Debug" { 11 | multiboot /boot/kernel-x64.bin debug=1 12 | set gfxpayload=text 13 | boot 14 | } 15 | 16 | menuentry "IR0 Kernel - Safe Mode" { 17 | multiboot /boot/kernel-x64.bin --safe 18 | set gfxpayload=text 19 | boot 20 | } 21 | -------------------------------------------------------------------------------- /scripts/test_userspace.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # IR0 Kernel - Userspace Testing Script 4 | 5 | set -e 6 | 7 | echo "🔧 Building userspace programs..." 8 | cd userspace/programs 9 | make clean 10 | make all 11 | cd ../.. 12 | 13 | echo "📦 Building kernel..." 14 | make clean 15 | make ir0 16 | 17 | echo "🚀 Testing kernel with userspace programs..." 18 | echo "Starting QEMU - press Ctrl+C to stop" 19 | echo "In the shell, try: exec /bin/hello" 20 | 21 | make run-debug -------------------------------------------------------------------------------- /includes/stdarg.h: -------------------------------------------------------------------------------- 1 | #ifndef STDARG_H 2 | #define STDARG_H 3 | 4 | // Use GCC builtins for variable arguments 5 | // This is required for x86-64 System V ABI which passes arguments in registers 6 | typedef __builtin_va_list va_list; 7 | 8 | #define va_start(ap, last) __builtin_va_start(ap, last) 9 | #define va_arg(ap, type) __builtin_va_arg(ap, type) 10 | #define va_end(ap) __builtin_va_end(ap) 11 | #define va_copy(dest, src) __builtin_va_copy(dest, src) 12 | 13 | #endif // STDARG_H 14 | -------------------------------------------------------------------------------- /arch/common/common_paging.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | // Declaraciones comunes de paginación 5 | // Las implementaciones específicas están en los archivos de cada arquitectura 6 | 7 | // Esta función le dice a la CPU que empiece a paginar configurando el directorio. -- 32 bit -- 8 | void paging_set_cpu(uint32_t page_directory); 9 | 10 | // Esta función le dice a la CPU que empiece a paginar configurando el directorio. -- 64 bit -- 11 | void paging_set_cpu_x64(uint64_t page_directory); 12 | -------------------------------------------------------------------------------- /rust/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "ir0-rust-ffi" 3 | version = "1.0.0" 4 | authors = ["IR0 Kernel Team"] 5 | edition = "2021" 6 | description = "Rust FFI bindings for IR0 kernel" 7 | 8 | [lib] 9 | name = "ir0_ffi" 10 | path = "ffi/kernel.rs" 11 | crate-type = ["staticlib", "rlib"] 12 | 13 | [profile.dev] 14 | panic = "abort" 15 | opt-level = 2 16 | 17 | [profile.release] 18 | panic = "abort" 19 | opt-level = 2 20 | lto = true 21 | codegen-units = 1 22 | 23 | [dependencies] 24 | # No dependencies - bare metal kernel environment 25 | -------------------------------------------------------------------------------- /drivers/audio/Makefile: -------------------------------------------------------------------------------- 1 | CC = gcc 2 | CFLAGS = -Wall -Wextra -std=c99 -ffreestanding -O2 -nostdlib -nostartfiles -nodefaultlibs 3 | CFLAGS += -I../../includes -I../../ 4 | CFLAGS += -mcmodel=large -mno-red-zone -mno-mmx -mno-sse -mno-sse2 5 | 6 | OBJECTS = sound_blaster.o 7 | 8 | all: libaudio.a 9 | 10 | libaudio.a: $(OBJECTS) 11 | ar rcs libaudio.a $(OBJECTS) 12 | 13 | sound_blaster.o: sound_blaster.c sound_blaster.h 14 | $(CC) $(CFLAGS) -c sound_blaster.c -o sound_blaster.o 15 | 16 | clean: 17 | rm -f *.o *.a *.d 18 | 19 | .PHONY: all clean -------------------------------------------------------------------------------- /rust/ffi/README.md: -------------------------------------------------------------------------------- 1 | # IR0 Kernel - Rust FFI Bindings 2 | 3 | This directory contains Rust Foreign Function Interface (FFI) bindings for the IR0 kernel. 4 | 5 | ## Files 6 | 7 | - `kernel.rs` - Core kernel API bindings for Rust drivers 8 | 9 | ## Usage 10 | 11 | Include this in your Rust driver: 12 | 13 | ```rust 14 | use ir0::ffi::kernel::*; 15 | ``` 16 | 17 | ## Building 18 | 19 | Rust drivers are compiled with: 20 | 21 | ```bash 22 | make unibuild -rust drivers/your_driver.rs 23 | ``` 24 | 25 | See `CONTRIBUTING.md` for full development guide. 26 | -------------------------------------------------------------------------------- /includes/ir0/user.h: -------------------------------------------------------------------------------- 1 | #ifndef _IR0_USER_H 2 | #define _IR0_USER_H 3 | 4 | #include 5 | 6 | // User ID type 7 | typedef uint32_t uid_t; 8 | 9 | // Structure to hold user information 10 | typedef struct { 11 | uid_t uid; // User ID 12 | char name[32]; // Username 13 | char home[256]; // Home directory 14 | char shell[64]; // Login shell 15 | } user_info_t; 16 | 17 | // Get information about the current user 18 | int get_current_user(user_info_t *user); 19 | 20 | // Initialize the user subsystem 21 | void user_init(void); 22 | 23 | #endif /* _IR0_USER_H */ -------------------------------------------------------------------------------- /rust/x86_64-ir0-kernel.json: -------------------------------------------------------------------------------- 1 | { 2 | "llvm-target": "x86_64-unknown-none", 3 | "data-layout": "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128", 4 | "arch": "x86_64", 5 | "target-endian": "little", 6 | "target-pointer-width": 64, 7 | "target-c-int-width": 32, 8 | "os": "none", 9 | "executables": true, 10 | "linker-flavor": "ld.lld", 11 | "linker": "rust-lld", 12 | "panic-strategy": "abort", 13 | "disable-redzone": true, 14 | "features": "-mmx", 15 | "code-model": "kernel", 16 | "relocation-model": "static" 17 | } -------------------------------------------------------------------------------- /include/generated/autoconf.h: -------------------------------------------------------------------------------- 1 | /* AUTOGENERATED BY KCONFIG - DO NOT EDIT */ 2 | #ifndef __AUTOCONF_H__ 3 | #define __AUTOCONF_H__ 4 | 5 | #define SUBSYSTEM_ARCH 1 6 | #undef SUBSYSTEM_AUDIO 7 | #undef SUBSYSTEM_DISK 8 | #undef SUBSYSTEM_DMA 9 | #define SUBSYSTEM_FILESYSTEM 1 10 | #define SUBSYSTEM_INTERRUPT 1 11 | #define SUBSYSTEM_KERNEL 1 12 | #define SUBSYSTEM_KEYBOARD 1 13 | #define SUBSYSTEM_LIBRARIES 1 14 | #define SUBSYSTEM_MEMORY 1 15 | #define SUBSYSTEM_SCHEDULER 1 16 | #define SUBSYSTEM_SERIAL 1 17 | #define SUBSYSTEM_STORAGE 1 18 | #define SUBSYSTEM_TIMER 1 19 | #define SUBSYSTEM_VIDEO 1 20 | #undef SUBSYSTEM_DRIVERS 21 | 22 | #endif /* __AUTOCONF_H__ */ 23 | -------------------------------------------------------------------------------- /includes/ir0/stdlib.h: -------------------------------------------------------------------------------- 1 | #ifndef IR0_STDLIB_H 2 | #define IR0_STDLIB_H 3 | 4 | #include 5 | #include 6 | 7 | // IR0 kernel-provided utility functions (not standard C) 8 | // Use: #include 9 | 10 | // Memory management (kernel helpers, not userland malloc) 11 | void *ir0_kmalloc(size_t size); 12 | void ir0_kfree(void *ptr); 13 | 14 | // String conversion (kernel helpers) 15 | int ir0_atoi(const char *str); 16 | long ir0_atol(const char *str); 17 | 18 | // Process control (kernel helpers) 19 | void ir0_panic(const char *msg); 20 | void ir0_reboot(void); 21 | 22 | // Add more kernel-specific helpers as needed 23 | 24 | #endif // IR0_STDLIB_H 25 | -------------------------------------------------------------------------------- /arch/x86-64/sources/arch_x64.c: -------------------------------------------------------------------------------- 1 | // arch/x86-64/sources/arch_x64.c - Architecture setup functions 2 | #include 3 | #include 4 | #include 5 | #include "tss_x64.h" 6 | #include "arch_x64.h" 7 | #include "gdt.h" 8 | 9 | // I/O functions are now in arch_interface.h 10 | 11 | // Architecture-specific initialization (called from kernel_start.c) 12 | void arch_x64_init(void) 13 | { 14 | // Setup mínimo específico de x86-64 15 | __asm__ volatile("cli"); // Deshabilitar interrupciones al arrancar 16 | 17 | // Initialize GDT 18 | gdt_install(); 19 | 20 | // Initialize TSS for user mode support 21 | setup_tss(); 22 | } 23 | 24 | 25 | -------------------------------------------------------------------------------- /setup/Makefile.menuconfig: -------------------------------------------------------------------------------- 1 | # =============================================================================== 2 | # MENUCONFIG MAKEFILE 3 | # =============================================================================== 4 | 5 | # Menu-based configuration 6 | menuconfig: 7 | @if [ ! -f "$(KERNEL_ROOT)/menuconfig" ]; then \ 8 | echo "Error: menuconfig script not found in the root directory."; \ 9 | exit 1; \ 10 | fi 11 | @chmod +x "$(KERNEL_ROOT)/menuconfig" 12 | @"$(KERNEL_ROOT)/menuconfig" 13 | 14 | # Help target for menuconfig 15 | help-menuconfig: 16 | @echo "Menu Configuration Targets:" 17 | @echo " make menuconfig Configure kernel build options" 18 | 19 | .PHONY: menuconfig help-menuconfig 20 | -------------------------------------------------------------------------------- /cpp/README.md: -------------------------------------------------------------------------------- 1 | # IR0 Kernel - C++ Support 2 | 3 | This directory contains C++ runtime and compatibility headers for kernel development. 4 | 5 | ## Structure 6 | 7 | - `include/` - C++ compatibility headers 8 | - `runtime/` - C++ runtime implementation (new/delete, etc.) 9 | 10 | ## Files 11 | 12 | - `include/compat.h` - C++/Rust interoperability header 13 | - `runtime/compat.cpp` - C++ runtime for kernel 14 | 15 | ## Usage 16 | 17 | Include in C++ kernel components: 18 | 19 | ```cpp 20 | #include 21 | ``` 22 | 23 | ## Building 24 | 25 | C++ components are compiled with: 26 | 27 | ```bash 28 | make unibuild -cpp kernel/component.cpp 29 | ``` 30 | 31 | See `CONTRIBUTING.md` for full development guide. 32 | -------------------------------------------------------------------------------- /scripts/unibuild-clean.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | if [ $# -lt 1 ]; then 4 | echo "Usage: $0 " 5 | exit 1 6 | fi 7 | 8 | SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" 9 | KERNEL_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)" 10 | cd "$KERNEL_ROOT" || exit 1 11 | 12 | SOURCE_FILE="$1" 13 | 14 | if [ ! -f "$SOURCE_FILE" ]; then 15 | echo "Error: File not found: $SOURCE_FILE" 16 | exit 1 17 | fi 18 | 19 | EXT="${SOURCE_FILE##*.}" 20 | BASENAME=$(basename "$SOURCE_FILE" ".$EXT") 21 | DIRNAME=$(dirname "$SOURCE_FILE") 22 | OUTPUT_FILE="$DIRNAME/$BASENAME.o" 23 | 24 | if [ -f "$OUTPUT_FILE" ]; then 25 | rm -f "$OUTPUT_FILE" 26 | echo " CLEAN $OUTPUT_FILE" 27 | else 28 | echo " CLEAN $OUTPUT_FILE (not found)" 29 | fi 30 | 31 | -------------------------------------------------------------------------------- /interrupt/arch/keyboard.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | // Constantes del buffer de teclado 6 | #define KEYBOARD_BUFFER_SIZE 256 7 | 8 | // Funciones del buffer de teclado 9 | void keyboard_buffer_add(char c); 10 | char keyboard_buffer_get(void); 11 | int keyboard_buffer_has_data(void); 12 | void keyboard_buffer_clear(void); 13 | 14 | // Handlers de interrupciones 15 | void keyboard_handler64(void); 16 | void keyboard_handler32(void); 17 | 18 | // Inicialización 19 | void keyboard_init(void); 20 | 21 | // Función de traducción de scancodes 22 | char translate_scancode(uint8_t sc); 23 | 24 | // Sistema de despertar del idle 25 | void set_idle_mode(int is_idle); 26 | int is_in_idle_mode(void); 27 | void wakeup_from_idle(void); 28 | 29 | -------------------------------------------------------------------------------- /drivers/serial/serial.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: GPL-3.0-only */ 2 | /* 3 | * IR0 Kernel - Serial Port Driver 4 | * Copyright (C) 2025 Iván Rodriguez 5 | * 6 | * Public interface for COM1 serial port (0x3F8) 7 | */ 8 | 9 | #pragma once 10 | 11 | #include 12 | 13 | /* ========================================================================== */ 14 | /* PUBLIC API */ 15 | /* ========================================================================== */ 16 | 17 | void serial_init(void); 18 | void serial_putchar(char c); 19 | void serial_print(const char *str); 20 | void serial_print_hex32(uint32_t num); 21 | void serial_print_hex64(uint64_t num); 22 | char serial_read_char(void); 23 | -------------------------------------------------------------------------------- /tools/kconfig/Makefile: -------------------------------------------------------------------------------- 1 | # =============================================================================== 2 | # KCONFIG MAKEFILE - Configuration system for IR0 Kernel 3 | # =============================================================================== 4 | 5 | # Python interpreter 6 | PYTHON = python3 7 | 8 | # Source files 9 | TKCONFIG = tkconfig.py 10 | 11 | # Default target 12 | all: menuconfig 13 | 14 | # Run the configuration tool 15 | menuconfig: 16 | @echo " CONFIG Starting configuration tool..." 17 | @$(PYTHON) $(TKCONFIG) || (echo " ERROR Failed to run configuration tool"; exit 1) 18 | 19 | # Clean generated files 20 | clean: 21 | @echo " CLEAN Configuration files" 22 | @rm -f ../../.config ../../include/generated/autoconf.h 23 | 24 | .PHONY: all menuconfig clean 25 | -------------------------------------------------------------------------------- /scripts/create_disk.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # create_disk.sh - Create virtual disk for IR0 MINIX filesystem 4 | 5 | DISK_SIZE="100M" 6 | DISK_FILE="disk.img" 7 | 8 | echo "🔧 Creating virtual disk for MINIX filesystem..." 9 | 10 | # Create empty disk image 11 | if [ -f "$DISK_FILE" ]; then 12 | echo "⚠️ Disk $DISK_FILE already exists. Backing up..." 13 | mv "$DISK_FILE" "${DISK_FILE}.backup.$(date +%s)" 14 | fi 15 | 16 | # Create 100MB disk 17 | dd if=/dev/zero of="$DISK_FILE" bs=1M count=100 2>/dev/null 18 | 19 | if [ $? -eq 0 ]; then 20 | echo "✅ Virtual disk created: $DISK_FILE ($DISK_SIZE)" 21 | echo "📝 Note: The kernel will automatically format this as MINIX filesystem on first boot" 22 | echo "" 23 | echo "🚀 Ready to run: make run" 24 | else 25 | echo "❌ Failed to create disk image" 26 | exit 1 27 | fi -------------------------------------------------------------------------------- /drivers/storage/fs_types.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "fs_types.h" 3 | 4 | // Get filesystem type string from partition system ID 5 | const char* get_fs_type(uint8_t system_id) { 6 | switch(system_id) { 7 | case 0x00: return "Empty"; 8 | case 0x01: return "FAT12"; 9 | case 0x04: return "FAT16 <32M"; 10 | case 0x05: return "Extended"; 11 | case 0x06: return "FAT16"; 12 | case 0x07: return "NTFS/HPFS"; 13 | case 0x0B: return "FAT32"; 14 | case 0x0C: return "FAT32 LBA"; 15 | case 0x0E: return "FAT16 LBA"; 16 | case 0x0F: return "Extended LBA"; 17 | case 0x82: return "Linux Swap"; 18 | case 0x83: return "Linux"; 19 | case 0x8E: return "Linux LVM"; 20 | case 0xEE: return "GPT"; 21 | default: return "Unknown"; 22 | } 23 | } -------------------------------------------------------------------------------- /includes/ir0/compat.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | 5 | #ifdef __cplusplus 6 | // Global new/delete operators 7 | void* operator_new(size_t size); 8 | void operator_delete(void* ptr) noexcept; 9 | void operator_delete(void* ptr, size_t size) noexcept; 10 | 11 | 12 | // Array new/delete operators 13 | void* operator_new_array(size_t size); 14 | void operator_delete_array(void* ptr) noexcept; 15 | void operator_delete_array(void* ptr, size_t size) noexcept; 16 | 17 | // C++ runtime support functions 18 | extern "C" void __cxa_pure_virtual(void); 19 | extern "C" int __cxa_guard_acquire(unsigned long long *guard); 20 | extern "C" void __cxa_guard_release(unsigned long long *guard); 21 | extern "C" void __cxa_guard_abort(unsigned long long *guard); 22 | 23 | #else 24 | // C linkage declarations (no operators) 25 | #endif 26 | -------------------------------------------------------------------------------- /includes/ir0/fcntl.h: -------------------------------------------------------------------------------- 1 | #ifndef _IR0_FCNTL_H 2 | #define _IR0_FCNTL_H 3 | 4 | /* File access modes */ 5 | #define O_RDONLY 0x0000 /* Read only */ 6 | #define O_WRONLY 0x0001 /* Write only */ 7 | #define O_RDWR 0x0002 /* Read and write */ 8 | #define O_ACCMODE 0x0003 /* Mask for file access modes */ 9 | 10 | /* File status flags */ 11 | #define O_APPEND 0x0008 /* Append mode */ 12 | #define O_CREAT 0x0100 /* Create if nonexistent */ 13 | #define O_EXCL 0x0200 /* Error if file exists */ 14 | #define O_TRUNC 0x0400 /* Truncate to zero length */ 15 | 16 | /* Seek types */ 17 | #define SEEK_SET 0 /* Set file offset to offset */ 18 | #define SEEK_CUR 1 /* Set file offset to current plus offset */ 19 | #define SEEK_END 2 /* Set file offset to EOF plus offset */ 20 | 21 | #endif /* _IR0_FCNTL_H */ -------------------------------------------------------------------------------- /includes/ir0/stdbool.h: -------------------------------------------------------------------------------- 1 | #ifndef _STDBOOL_H 2 | #define _STDBOOL_H 3 | 4 | /* Boolean type and values for IR0 Kernel - Freestanding implementation */ 5 | 6 | /* C99 boolean type support */ 7 | #ifndef __cplusplus 8 | 9 | /* Define the boolean type */ 10 | #if !defined(__STDC_VERSION__) || __STDC_VERSION__ < 199901L 11 | /* Pre-C99 compilers */ 12 | typedef unsigned char _Bool; 13 | #define bool _Bool 14 | #else 15 | /* C99 and later - _Bool is a keyword */ 16 | #define bool _Bool 17 | #endif 18 | 19 | /* Boolean constants */ 20 | #define true 1 21 | #define false 0 22 | 23 | /* Indicate that bool, true, false are available */ 24 | #define __bool_true_false_are_defined 1 25 | 26 | #else 27 | /* C++ has built-in bool, true, false */ 28 | /* No need to define anything */ 29 | #endif 30 | 31 | #endif /* _STDBOOL_H */ -------------------------------------------------------------------------------- /kernel/syscall_wrappers.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: GPL-3.0-only */ 2 | /* 3 | * IR0 Kernel - System Call Wrappers 4 | * Copyright (C) 2025 Iván Rodriguez 5 | * 6 | * Public interface for safe syscall wrappers 7 | */ 8 | 9 | #pragma once 10 | 11 | #include 12 | #include 13 | 14 | typedef uint32_t mode_t; 15 | 16 | /* ========================================================================== */ 17 | /* SAFE WRAPPERS */ 18 | /* ========================================================================== */ 19 | 20 | int64_t safe_sys_write(int fd, const void *buf, size_t count); 21 | int64_t safe_sys_read(int fd, void *buf, size_t count); 22 | int64_t safe_sys_open(const char *pathname, int flags, mode_t mode); 23 | int64_t safe_sys_mkdir(const char *pathname, mode_t mode); 24 | void *safe_kmalloc(size_t size); 25 | -------------------------------------------------------------------------------- /userspace/bin/echo.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | // Minimal strlen implementation 4 | static int strlen(const char *str) { 5 | int len = 0; 6 | while (str[len]) len++; 7 | return len; 8 | } 9 | 10 | void _start(int argc, char *argv[]) { 11 | // Note: Arguments might not be passed correctly yet depending on kernel implementation. 12 | // However, we follow the standard ABI convention for _start. 13 | 14 | if (argc > 1) { 15 | for (int i = 1; i < argc; i++) { 16 | if (i > 1) { 17 | ir0_write(1, " ", 1); 18 | } 19 | ir0_write(1, argv[i], strlen(argv[i])); 20 | } 21 | } else { 22 | // Default message if no args 23 | const char *msg = "echo: no arguments provided"; 24 | ir0_write(1, msg, strlen(msg)); 25 | } 26 | 27 | ir0_write(1, "\n", 1); 28 | ir0_exit(0); 29 | } 30 | -------------------------------------------------------------------------------- /drivers/storage/ata_helpers.c: -------------------------------------------------------------------------------- 1 | #include "ata.h" 2 | #include 3 | 4 | // Global variables 5 | extern bool ata_drives_present[4]; 6 | extern ata_device_info_t ata_devices[4]; 7 | 8 | bool ata_drive_present(uint8_t drive) { 9 | if (drive >= 4) return false; 10 | return ata_drives_present[drive]; 11 | } 12 | 13 | uint64_t ata_get_size(uint8_t drive) { 14 | if (drive >= 4 || !ata_drives_present[drive]) return 0; 15 | return ata_devices[drive].size; 16 | } 17 | 18 | const char* ata_get_model(uint8_t drive) { 19 | static const char* unknown = "UNKNOWN"; 20 | if (drive >= 4 || !ata_drives_present[drive]) return unknown; 21 | return ata_devices[drive].model; 22 | } 23 | 24 | const char* ata_get_serial(uint8_t drive) { 25 | static const char* unknown = "UNKNOWN"; 26 | if (drive >= 4 || !ata_drives_present[drive]) return unknown; 27 | return ata_devices[drive].serial; 28 | } 29 | -------------------------------------------------------------------------------- /interrupt/arch/io.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | // Funciones de I/O 7 | // Using I/O functions from arch_interface.h 8 | 9 | static inline uint16_t inw(uint16_t port) 10 | { 11 | uint16_t ret; 12 | __asm__ volatile("inw %1, %0" : "=a"(ret) : "Nd"(port)); 13 | return ret; 14 | } 15 | 16 | static inline void outw(uint16_t port, uint16_t val) 17 | { 18 | __asm__ volatile("outw %0, %1" : : "a"(val), "Nd"(port)); 19 | } 20 | 21 | static inline uint32_t inl(uint16_t port) 22 | { 23 | uint32_t ret; 24 | __asm__ volatile("inl %1, %0" : "=a"(ret) : "Nd"(port)); 25 | return ret; 26 | } 27 | 28 | static inline void outl(uint16_t port, uint32_t val) 29 | { 30 | __asm__ volatile("outl %0, %1" : : "a"(val), "Nd"(port)); 31 | } 32 | 33 | // Funciones de espera 34 | static inline void io_wait(void) 35 | { 36 | outb(0x80, 0); 37 | } 38 | 39 | -------------------------------------------------------------------------------- /includes/ir0/Makefile: -------------------------------------------------------------------------------- 1 | # Makefile para includes/ir0 2 | 3 | # Usar variables pasadas desde el Makefile principal (no fijar -m32 aquí) 4 | CC ?= gcc 5 | CFLAGS ?= -Wall -Wextra -O1 -MMD -MP 6 | 7 | # Detectar arquitectura desde CFLAGS 8 | ifneq (,$(findstring -m64,$(CFLAGS))) 9 | ARCH_DETECTED = x86-64 10 | else 11 | ARCH_DETECTED = x86-32 12 | endif 13 | 14 | # Incluir directorios 15 | CFLAGS += -I../.. -I. 16 | 17 | # Objetos 18 | OBJS = print.o logging.o validation.o oops.o 19 | 20 | all: $(OBJS) 21 | @echo "\033[1;32m============================================================\033[0m" 22 | @echo "\033[1;32m IR0 includes compilado correctamente para $(ARCH_DETECTED)\033[0m" 23 | @echo "\033[1;32m============================================================\033[0m" 24 | 25 | %.o: %.c 26 | $(CC) $(CFLAGS) -c $< -o $@ 27 | 28 | clean: 29 | rm -f $(OBJS) 30 | rm -f *.d 31 | 32 | .PHONY: all clean 33 | 34 | -include $(OBJS:.o=.d) 35 | -------------------------------------------------------------------------------- /includes/ir0/path.h: -------------------------------------------------------------------------------- 1 | #ifndef _IR0_PATH_H 2 | #define _IR0_PATH_H 3 | 4 | #include 5 | 6 | // Normalize a path, handling ".." and "." components 7 | // Returns the normalized path in dest 8 | // dest must be at least as large as src 9 | // Returns 0 on success, -1 on error 10 | int normalize_path(const char *src, char *dest, size_t size); 11 | 12 | // Join two paths together, handling ".." and "." components 13 | // Returns the joined path in dest 14 | // dest must be large enough to hold both paths plus a separator 15 | // Returns 0 on success, -1 on error 16 | int join_paths(const char *base, const char *rel, char *dest, size_t size); 17 | 18 | // Test if a path is absolute 19 | int is_absolute_path(const char *path); 20 | 21 | // Get parent directory path 22 | // Returns the parent directory path in dest 23 | // Returns 0 on success, -1 on error 24 | int get_parent_path(const char *path, char *dest, size_t size); 25 | 26 | #endif /* _IR0_PATH_H */ -------------------------------------------------------------------------------- /setup/Makefile: -------------------------------------------------------------------------------- 1 | # Makefile para el subsistema de configuración 2 | 3 | # Usar variables pasadas desde el Makefile principal 4 | CC ?= gcc 5 | CFLAGS ?= -m32 -march=i686 -nostdlib -nostdinc -fno-builtin -fno-stack-protector -fno-pic -nodefaultlibs -ffreestanding 6 | 7 | # Detectar arquitectura desde CFLAGS 8 | ifneq (,$(findstring -m64,$(CFLAGS))) 9 | ARCH_DETECTED = x86-64 10 | else 11 | ARCH_DETECTED = x86-32 12 | endif 13 | 14 | # Incluir directorios 15 | CFLAGS += -I../includes -I../includes/ir0 16 | 17 | # Objetos 18 | OBJS = kernel_config.o 19 | 20 | all: $(OBJS) 21 | @echo "\033[1;32m============================================================\033[0m" 22 | @echo "\033[1;32m Setup subsystem compilado correctamente para $(ARCH_DETECTED)\033[0m" 23 | @echo "\033[1;32m============================================================\033[0m" 24 | 25 | %.o: %.c 26 | $(CC) $(CFLAGS) -c $< -o $@ 27 | 28 | clean: 29 | rm -f $(OBJS) 30 | 31 | .PHONY: all clean 32 | -------------------------------------------------------------------------------- /kernel/rr_sched.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: GPL-3.0-only */ 2 | /* 3 | * IR0 Kernel - Round-Robin Scheduler 4 | * Copyright (C) 2025 Iván Rodriguez 5 | * 6 | * Public interface for round-robin scheduler 7 | */ 8 | 9 | #pragma once 10 | 11 | #include "process.h" 12 | 13 | /* ========================================================================== */ 14 | /* TYPES */ 15 | /* ========================================================================== */ 16 | 17 | typedef struct rr_task 18 | { 19 | process_t *process; 20 | struct rr_task *next; 21 | } rr_task_t; 22 | 23 | /* ========================================================================== */ 24 | /* PUBLIC API */ 25 | /* ========================================================================== */ 26 | 27 | void rr_add_process(process_t *proc); 28 | void rr_schedule_next(void); 29 | -------------------------------------------------------------------------------- /arch/x86-64/linker.ld: -------------------------------------------------------------------------------- 1 | ENTRY(_start) 2 | OUTPUT_FORMAT(elf64-x86-64) 3 | OUTPUT_ARCH(i386:x86-64) 4 | 5 | SECTIONS 6 | { 7 | . = 0x100000; 8 | 9 | .multiboot : ALIGN(4K) 10 | { 11 | *(.multiboot) 12 | } 13 | 14 | .text : ALIGN(4K) 15 | { 16 | *(.text) 17 | *(.text.*) 18 | } 19 | 20 | .rodata : ALIGN(4K) 21 | { 22 | *(.rodata) 23 | *(.rodata.*) 24 | } 25 | 26 | .data : ALIGN(4K) 27 | { 28 | *(.data) 29 | *(.data.*) 30 | } 31 | 32 | /* Sección específica para tablas de páginas - dentro del rango mapeado */ 33 | .paging : ALIGN(4K) 34 | { 35 | *(.paging) 36 | } 37 | 38 | .bss : ALIGN(4K) 39 | { 40 | *(COMMON) 41 | *(.bss) 42 | *(.bss.*) 43 | } 44 | 45 | /* Definir símbolo _end para el bump_allocator */ 46 | _end = .; 47 | 48 | /DISCARD/ : 49 | { 50 | *(.comment) 51 | *(.note.*) 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /drivers/timer/acpi/acpi.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | 7 | /* 8 | Bueno, esta es una función que me sirve para encontrar la firma ASCII de la tabla HPET (High Precission Event Timer) 9 | se buca a través de memo mapeada y, según la BIOS, anda por algún lugar de la memoria RAM entre 0x000E0000 – 0x000FFFFF. 10 | Hay que llegar a esa región, iterar y leer la HPET 11 | */ 12 | void* find_hpet_table(); 13 | 14 | typedef struct 15 | { 16 | char signature[8]; 17 | uint8_t checksum; 18 | char oem_id[6]; 19 | uint8_t revision; 20 | uint32_t rsdt_address; 21 | } __attribute__((packed)) rsdp_t; 22 | 23 | typedef struct 24 | { 25 | char signature[4]; 26 | uint32_t length; 27 | uint8_t revision; 28 | uint8_t checksum; 29 | char oem_id[6]; 30 | char oem_table_id[8]; 31 | uint32_t oem_revision; 32 | uint32_t creator_id; 33 | uint32_t creator_revision; 34 | } __attribute__((packed)) acpi_sdt_header_t; 35 | -------------------------------------------------------------------------------- /includes/ir0/init.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: GPL-3.0-only */ 2 | #ifndef _IR0_INIT_H 3 | #define _IR0_INIT_H 4 | 5 | #include 6 | 7 | /* Architecture initialization */ 8 | extern void gdt_install(void); 9 | extern void setup_tss(void); 10 | extern void idt_init64(void); 11 | extern void idt_load64(void); 12 | 13 | /* Interrupt controller */ 14 | extern void pic_remap64(void); 15 | extern void pic_unmask_irq(uint8_t irq); 16 | 17 | /* Subsystem initialization */ 18 | extern void logging_init(void); 19 | extern void serial_init(void); 20 | extern void ps2_init(void); 21 | extern void keyboard_init(void); 22 | extern void simple_alloc_init(void); 23 | extern void ata_init(void); 24 | extern void process_init(void); 25 | extern void syscalls_init(void); 26 | 27 | /* Complex subsystems */ 28 | extern int vfs_init_with_minix(void); 29 | extern int clock_system_init(void); 30 | extern int scheduler_cascade_init(void); 31 | extern int start_init_process(void); 32 | 33 | #endif /* _IR0_INIT_H */ -------------------------------------------------------------------------------- /arch/x86-64/sources/tss_x64.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | // TSS structure for x86-64 5 | typedef struct 6 | { 7 | uint32_t reserved0; 8 | uint64_t rsp0; // Kernel stack pointer for Ring 0 9 | uint64_t rsp1; // Kernel stack pointer for Ring 1 10 | uint64_t rsp2; // Kernel stack pointer for Ring 2 11 | uint64_t reserved1; 12 | uint64_t ist1; // Interrupt stack table 1 13 | uint64_t ist2; // Interrupt stack table 2 14 | uint64_t ist3; // Interrupt stack table 3 15 | uint64_t ist4; // Interrupt stack table 4 16 | uint64_t ist5; // Interrupt stack table 5 17 | uint64_t ist6; // Interrupt stack table 6 18 | uint64_t ist7; // Interrupt stack table 7 19 | uint64_t reserved2; 20 | uint16_t reserved3; 21 | uint16_t iopb_offset; // I/O permission bitmap offset 22 | } __attribute__((packed)) tss_t; 23 | 24 | void tss_init_x64(void); 25 | void tss_load_x64(void); 26 | void setup_tss(); 27 | uint64_t tss_get_address(void); 28 | uint32_t tss_get_size(void); 29 | -------------------------------------------------------------------------------- /kernel/kernel.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | /** 4 | * IR0 Kernel — Core system software 5 | * Copyright (C) 2025 Iván Rodriguez 6 | * 7 | * File: kernel.h 8 | * Description: Main kernel entry point and core function declarations 9 | */ 10 | 11 | #include 12 | #include 13 | #include 14 | 15 | // Main kernel entry point 16 | void kmain(void); 17 | 18 | // Core subsystem initialization functions 19 | void gdt_install(void); 20 | void setup_tss(void); 21 | void logging_init(void); 22 | void ps2_init(void); 23 | void keyboard_init(void); 24 | void simple_alloc_init(void); 25 | void ata_init(void); 26 | int vfs_init_with_minix(void); 27 | void process_init(void); 28 | int clock_system_init(void); 29 | int scheduler_cascade_init(void); 30 | void syscalls_init(void); 31 | void idt_init64(void); 32 | void idt_load64(void); 33 | void pic_remap64(void); 34 | void pic_unmask_irq(uint8_t irq); 35 | int start_init_process(void); 36 | void serial_init(void); 37 | void heap_init(void); 38 | bool sb16_init(void); -------------------------------------------------------------------------------- /kernel/Makefile: -------------------------------------------------------------------------------- 1 | # kernel/Makefile - Compilación del kernel 2 | 3 | # Variables 4 | KERNEL_OBJS = kernel.o init.o process.o scheduler.o task.o syscalls.o shell.o elf_loader.o typewriter.o 5 | KERNEL_TARGET = kernel.a 6 | 7 | # Reglas 8 | all: $(KERNEL_TARGET) 9 | 10 | $(KERNEL_TARGET): $(KERNEL_OBJS) 11 | $(AR) rcs $@ $^ 12 | 13 | kernel.o: kernel.c 14 | $(CC) $(CFLAGS) -c $< -o $@ 15 | 16 | init.o: init.c 17 | $(CC) $(CFLAGS) -c $< -o $@ 18 | 19 | process.o: process.c process.h 20 | $(CC) $(CFLAGS) -c $< -o $@ 21 | 22 | scheduler.o: scheduler.c scheduler.h 23 | $(CC) $(CFLAGS) -c $< -o $@ 24 | 25 | task.o: task.c task.h 26 | $(CC) $(CFLAGS) -c $< -o $@ 27 | 28 | syscalls.o: syscalls.c syscalls.h 29 | $(CC) $(CFLAGS) -c $< -o $@ 30 | 31 | shell.o: shell.c 32 | $(CC) $(CFLAGS) -c $< -o $@ 33 | 34 | elf_loader.o: elf_loader.c elf_loader.h 35 | $(CC) $(CFLAGS) -c $< -o $@ 36 | 37 | typewriter.o: typewriter.c typewriter.h 38 | $(CC) $(CFLAGS) -c $< -o $@ 39 | 40 | clean: 41 | rm -f *.o *.a 42 | 43 | .PHONY: all clean 44 | -------------------------------------------------------------------------------- /arch/x86-64/sources/idt_arch_x64.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | extern idt_entry_t idt[256]; 4 | 5 | // Implementación específica para 64-bit 6 | void idt_arch_set_gate_64(int n, uintptr_t handler, uint8_t flags) 7 | { 8 | idt[n].offset_low = handler & 0xFFFF; // Bits 0-15 9 | idt[n].selector = 0x08; // Código del kernel 10 | idt[n].ist = 0; // No usar IST 11 | idt[n].type_attr = flags; // Tipo y privilegios 12 | idt[n].offset_mid = (handler >> 16) & 0xFFFF; // Bits 16-31 13 | idt[n].offset_high = (handler >> 32) & 0xFFFFFFFF; // Bits 32-63 14 | idt[n].zero = 0; // Reservado 15 | } 16 | 17 | // Función de paginación para 64-bit (cuando la implementes) 18 | void paging_set_cpu_64(uint64_t page_directory) 19 | { 20 | // Para 64-bit: usar PML4 en lugar de page directory 21 | asm volatile("mov %0, %%cr3" ::"r"(page_directory)); 22 | } -------------------------------------------------------------------------------- /kernel/user.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | // For now, we'll have a single root user 5 | static user_info_t root_user = { 6 | .uid = 0, 7 | .name = "root", 8 | .home = "/root", 9 | .shell = "/bin/sh" 10 | }; 11 | 12 | // Current user info 13 | static user_info_t *current_user = NULL; 14 | 15 | void user_init(void) { 16 | // Initialize with root user 17 | current_user = &root_user; 18 | } 19 | 20 | int get_current_user(user_info_t *user) { 21 | if (!user || !current_user) 22 | return -1; 23 | 24 | // Copy current user info 25 | user->uid = current_user->uid; 26 | strncpy(user->name, current_user->name, sizeof(user->name) - 1); 27 | user->name[sizeof(user->name) - 1] = '\0'; 28 | 29 | strncpy(user->home, current_user->home, sizeof(user->home) - 1); 30 | user->home[sizeof(user->home) - 1] = '\0'; 31 | 32 | strncpy(user->shell, current_user->shell, sizeof(user->shell) - 1); 33 | user->shell[sizeof(user->shell) - 1] = '\0'; 34 | 35 | return 0; 36 | } -------------------------------------------------------------------------------- /arch/x86-64/sources/tss_x64.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include "gdt.h" 6 | #include "tss_x64.h" 7 | 8 | 9 | // Global TSS instance 10 | tss_t kernel_tss __attribute__((aligned(4096))); 11 | 12 | // Kernel stack for Ring 0 - 32KB for safety 13 | static uint8_t kernel_stack[32768] __attribute__((aligned(4096))); 14 | 15 | void setup_tss() 16 | { 17 | // Clear TSS structure 18 | memset(&kernel_tss, 0, sizeof(tss_t)); 19 | 20 | // Set up kernel stack pointer for Ring 0 21 | kernel_tss.rsp0 = (uint64_t)(kernel_stack + sizeof(kernel_stack) - 16); 22 | 23 | // IST not used - set to 0 24 | kernel_tss.ist1 = 0; 25 | kernel_tss.ist2 = 0; 26 | kernel_tss.ist3 = 0; 27 | kernel_tss.ist4 = 0; 28 | kernel_tss.ist5 = 0; 29 | kernel_tss.ist6 = 0; 30 | kernel_tss.ist7 = 0; 31 | 32 | // I/O permission bitmap 33 | kernel_tss.iopb_offset = sizeof(tss_t); 34 | 35 | // Update GDT TSS descriptor 36 | update_gdt_tss((uint64_t)&kernel_tss); 37 | } 38 | 39 | -------------------------------------------------------------------------------- /includes/ir0/memory/allocator.h: -------------------------------------------------------------------------------- 1 | // Simple unified memory allocator 2 | #pragma once 3 | 4 | #include 5 | #include 6 | 7 | // Memory layout (from boot: 0-32MB mapped) 8 | // 0x000000 - 0x100000 : Reserved (BIOS, boot) 9 | // 0x100000 - 0x800000 : Kernel code/data (1MB-8MB) 10 | // 0x800000 - 0x2000000: Heap (8MB-32MB = 24MB heap) 11 | 12 | #define SIMPLE_HEAP_START 0x800000 13 | #define SIMPLE_HEAP_SIZE 0x1800000 // 24MB 14 | #define SIMPLE_HEAP_END (SIMPLE_HEAP_START + SIMPLE_HEAP_SIZE) 15 | 16 | typedef struct 17 | { 18 | void *start; 19 | void *end; 20 | void *current; 21 | size_t total_size; 22 | size_t used; 23 | size_t allocations; 24 | } simple_allocator_t; 25 | 26 | // Initialize the allocator 27 | void alloc_init(void); 28 | 29 | // Allocate memory 30 | void *alloc(size_t size); 31 | 32 | // Free memory (no-op for now, we use bump allocation) 33 | void alloc_free(void *ptr); 34 | 35 | // Get stats 36 | void alloc_stats(size_t *total, size_t *used, size_t *allocs); 37 | 38 | // Reallocate memory 39 | void *all_realloc(void *ptr, size_t new_size); 40 | -------------------------------------------------------------------------------- /includes/ir0/chmod.h: -------------------------------------------------------------------------------- 1 | #ifndef _CHMOD_H 2 | #define _CHMOD_H 3 | 4 | #include 5 | #include // For mode_t 6 | 7 | // File permission bits 8 | #define S_ISUID 0004000 /* Set user ID on execution */ 9 | #define S_ISGID 0002000 /* Set group ID on execution */ 10 | #define S_ISVTX 0001000 /* Save swapped text after use (sticky) */ 11 | 12 | #define S_IRWXU 0000700 /* RWX mask for owner */ 13 | #define S_IRUSR 0000400 /* R for owner */ 14 | #define S_IWUSR 0000200 /* W for owner */ 15 | #define S_IXUSR 0000100 /* X for owner */ 16 | 17 | #define S_IRWXG 0000070 /* RWX mask for group */ 18 | #define S_IRGRP 0000040 /* R for group */ 19 | #define S_IWGRP 0000020 /* W for group */ 20 | #define S_IXGRP 0000010 /* X for group */ 21 | 22 | #define S_IRWXO 0000007 /* RWX mask for other */ 23 | #define S_IROTH 0000004 /* R for other */ 24 | #define S_IWOTH 0000002 /* W for other */ 25 | #define S_IXOTH 0000001 /* X for other */ 26 | 27 | // Function declarations 28 | int chmod(const char *path, mode_t mode); 29 | int parse_mode(const char *mode_str); 30 | 31 | #endif -------------------------------------------------------------------------------- /interrupt/isr_handlers.c: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-only 2 | /** 3 | * IR0 Kernel — Core system software 4 | * Copyright (C) 2025 Iván Rodriguez 5 | * 6 | * This file is part of the IR0 Operating System. 7 | * Distributed under the terms of the GNU General Public License v3.0. 8 | * See the LICENSE file in the project root for full license information. 9 | * 10 | * File: isr_handlers.c 11 | * Description: Interrupt service routine handlers for x86 architecture 12 | */ 13 | 14 | #include "isr_handlers.h" 15 | #include 16 | 17 | // Handler mínimo ya definido en idt.c 18 | // void isr_handler(uint8_t int_no) está en idt.c 19 | 20 | // Función simple para enviar EOI 21 | void isr_send_eoi(uint8_t irq) 22 | { 23 | if (irq >= 8) 24 | { 25 | // Send EOI to slave PIC 26 | __asm__ volatile("outb %%al, %%dx" : : "a"(0x20), "d"(0xA0)); 27 | } 28 | // Send EOI to master PIC 29 | __asm__ volatile("outb %%al, %%dx" : : "a"(0x20), "d"(0x20)); 30 | } 31 | 32 | // Handler de timer simple 33 | void time_handler(void) 34 | { 35 | // Solo enviar EOI 36 | isr_send_eoi(0); 37 | } -------------------------------------------------------------------------------- /menuconfig: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Check if Python 3 is installed 4 | if ! command -v python3 &> /dev/null; then 5 | echo "Error: Python 3 is not installed. Please install it to continue." 6 | echo "You can install it with: sudo apt update && sudo apt install python3 python3-tk" 7 | exit 1 8 | fi 9 | 10 | # Check if tkinter is installed 11 | if ! python3 -c "import tkinter" 2>/dev/null; then 12 | echo "Installing required dependencies..." 13 | if command -v apt-get &> /dev/null; then 14 | sudo apt-get update && sudo apt-get install -y python3-tk 15 | elif command -v yum &> /dev/null; then 16 | sudo yum install -y python3-tk 17 | else 18 | echo "Could not determine package manager." 19 | echo "Please install 'python3-tk' or 'python-tk' manually." 20 | exit 1 21 | fi 22 | fi 23 | 24 | # Run the configuration menu 25 | echo "Starting configuration menu..." 26 | python3 tools/kconfig/tkconfig.py 27 | 28 | # Show confirmation message 29 | echo "" 30 | echo "Configuration saved to .config" 31 | echo "You can review the generated .config file" 32 | echo "" 33 | 34 | exit 0 35 | -------------------------------------------------------------------------------- /arch/x86-64/sources/idt_arch_x64.h: -------------------------------------------------------------------------------- 1 | // arch/x86-64/sources/idt_arch_x64.c - ACTUALIZADO 2 | #include // Solo incluir el header común 3 | 4 | // Array externo del IDT (definido en idt.c) 5 | extern idt_entry_t idt[256]; 6 | 7 | // Implementación específica para 64-bit 8 | void idt_arch_set_gate_64(int n, uintptr_t handler, uint8_t flags) 9 | { 10 | idt[n].offset_low = handler & 0xFFFF; // Bits 0-15 11 | idt[n].selector = 0x08; // Código del kernel 12 | idt[n].ist = 0; // No usar IST 13 | idt[n].type_attr = flags; // Tipo y privilegios 14 | idt[n].offset_mid = (handler >> 16) & 0xFFFF; // Bits 16-31 15 | idt[n].offset_high = (handler >> 32) & 0xFFFFFFFF; // Bits 32-63 16 | idt[n].zero = 0; // Reservado 17 | } 18 | 19 | // Función de paginación para 64-bit (cuando la implementes) 20 | void paging_set_cpu_64(uint64_t page_directory) 21 | { 22 | // Para 64-bit: usar PML4 en lugar de page directory 23 | asm volatile("mov %0, %%cr3" ::"r"(page_directory)); 24 | } -------------------------------------------------------------------------------- /drivers/video/vbe.h: -------------------------------------------------------------------------------- 1 | // VBE (VESA BIOS Extensions) Framebuffer Driver Header 2 | #pragma once 3 | 4 | #include 5 | #include 6 | 7 | // Initialize VBE framebuffer 8 | int vbe_init(void); 9 | 10 | // Clear screen with color 11 | void vbe_clear(uint32_t color); 12 | 13 | // Put pixel at coordinates (for graphics mode) 14 | void vbe_putpixel(uint32_t x, uint32_t y, uint32_t color); 15 | 16 | // Put character at coordinates 17 | void vbe_putchar(uint32_t x, uint32_t y, char c, uint32_t fg, uint32_t bg); 18 | 19 | // Print string at coordinates 20 | void vbe_print_at(uint32_t x, uint32_t y, const char *str, uint32_t fg, uint32_t bg); 21 | 22 | // Get framebuffer information 23 | bool vbe_get_info(uint32_t *width, uint32_t *height, uint32_t *bpp); 24 | 25 | // Check if VBE is available 26 | bool vbe_is_available(void); 27 | 28 | // Color macros (RGB) 29 | #define VBE_RGB(r, g, b) (((r) << 16) | ((g) << 8) | (b)) 30 | #define VBE_BLACK 0x000000 31 | #define VBE_WHITE 0xFFFFFF 32 | #define VBE_RED 0xFF0000 33 | #define VBE_GREEN 0x00FF00 34 | #define VBE_BLUE 0x0000FF 35 | #define VBE_CYAN 0x00FFFF 36 | #define VBE_YELLOW 0xFFFF00 37 | #define VBE_MAGENTA 0xFF00FF 38 | -------------------------------------------------------------------------------- /kernel/syscalls.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: GPL-3.0-only */ 2 | /* 3 | * IR0 Kernel - System Calls 4 | * Copyright (C) 2025 Iván Rodriguez 5 | * 6 | * Public interface for system call subsystem 7 | */ 8 | 9 | #pragma once 10 | 11 | #include // For standard types 12 | #include 13 | 14 | /* Forward declarations */ 15 | struct stat; 16 | typedef struct stat stat_t; 17 | 18 | 19 | /* Syscall implementations */ 20 | int64_t sys_read(int fd, void *buf, size_t count); 21 | int64_t sys_write(int fd, const void *buf, size_t count); 22 | int64_t sys_open(const char *pathname, int flags, mode_t mode); 23 | int64_t sys_lseek(int fd, off_t offset, int whence); 24 | int64_t sys_dup2(int oldfd, int newfd); 25 | int64_t sys_mkdir(const char *pathname, mode_t mode); 26 | int64_t sys_mount(const char *dev, const char *mountpoint, const char *fstype); 27 | int64_t sys_df(void); 28 | int64_t sys_get_block_devices(int fd, void *buf, size_t count); 29 | 30 | /* System functions */ 31 | void syscalls_init(void); 32 | int64_t syscall_dispatch(uint64_t syscall_num, uint64_t arg1, uint64_t arg2, 33 | uint64_t arg3, uint64_t arg4, uint64_t arg5); 34 | 35 | #define SYS_GET_BLOCK_DEVICES 92 36 | -------------------------------------------------------------------------------- /arch/x86-64/sources/gdt.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | // GDT entry (8 bytes) 3 | struct gdt_entry 4 | { 5 | uint16_t limit; 6 | uint16_t base_low; 7 | uint8_t base_mid; 8 | uint8_t access; 9 | uint8_t gran; 10 | uint8_t base_high; 11 | } __attribute__((packed)); 12 | 13 | // TSS descriptor (16 bytes + 8 extra) 14 | struct gdt_tss_entry 15 | { 16 | uint16_t limit; 17 | uint16_t base_low; 18 | uint8_t base_mid; 19 | uint8_t access; 20 | uint8_t gran; 21 | uint8_t base_high; 22 | uint32_t base_long; 23 | uint32_t reserved; 24 | } __attribute__((packed)); 25 | 26 | // GDTR structure 27 | struct gdtr 28 | { 29 | uint16_t size; 30 | uint64_t offset; 31 | } __attribute__((packed)); 32 | 33 | // GDT table 34 | struct gdt_table_struct 35 | { 36 | struct gdt_entry entries[5]; 37 | struct gdt_tss_entry tss_entry; 38 | } __attribute__((packed)); 39 | 40 | extern struct gdt_table_struct gdt_table; 41 | 42 | extern struct gdtr gdt_descriptor; 43 | 44 | void update_gdt_tss(uint64_t tss_addr); 45 | 46 | void gdt_set_entry(int index, uint32_t base, uint32_t limit, uint8_t access, uint8_t gran); 47 | 48 | void gdt_install(); 49 | 50 | void gdt_set_tss(uint64_t base, uint16_t limit); 51 | -------------------------------------------------------------------------------- /drivers/timer/Makefile: -------------------------------------------------------------------------------- 1 | # Makefile para el subsistema de timer 2 | 3 | # Usar variables pasadas desde el Makefile principal 4 | CC ?= gcc 5 | ASM ?= nasm 6 | CFLAGS ?= -m32 -march=i686 -nostdlib -nostdinc -fno-builtin -fno-stack-protector -fno-pic -nodefaultlibs -ffreestanding 7 | ASMFLAGS ?= -f elf32 8 | 9 | # Detectar arquitectura desde CFLAGS 10 | ifneq (,$(findstring -m64,$(CFLAGS))) 11 | ARCH_DETECTED = x86-64 12 | ASMFLAGS = -f elf64 13 | else 14 | ARCH_DETECTED = x86-32 15 | ASMFLAGS = -f elf32 16 | endif 17 | 18 | # Incluir directorios 19 | INCLUDES = -I../../includes -I../../includes/ir0 -I../../arch/common 20 | 21 | # Objetos 22 | OBJS = pit/pit.o lapic/lapic.o hpet/hpet.o hpet/find_hpet.o rtc/rtc.o clock_system.o best_clock.o 23 | 24 | all: $(OBJS) 25 | @echo "\033[1;32m============================================================\033[0m" 26 | @echo "\033[1;32m Timer compilado correctamente para $(ARCH_DETECTED)\033[0m" 27 | @echo "\033[1;32m============================================================\033[0m" 28 | 29 | %.o: %.c 30 | $(CC) $(CFLAGS) $(INCLUDES) -c $< -o $@ 31 | 32 | %.o: %.asm 33 | $(ASM) $(ASMFLAGS) $< -o $@ 34 | 35 | clean: 36 | rm -f $(OBJS) 37 | 38 | .PHONY: all clean 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /arch/x86-64/Makefile: -------------------------------------------------------------------------------- 1 | # Makefile para x64. 2 | 3 | # Configuración específica para x64 4 | ARCH_NAME = x64 5 | 6 | # Usar variables pasadas desde el Makefile principal 7 | CC ?= gcc 8 | ASM ?= nasm 9 | CFLAGS ?= -m64 -mcmodel=large -mno-red-zone -mno-mmx -mno-sse -mno-sse2 10 | ASMFLAGS ?= -f elf64 11 | 12 | # Fuentes específicas de esta arquitectura 13 | ARCH_SOURCES = sources/arch_x64.c sources/fault.c sources/idt_arch_x64.c sources/tss_x64.c sources/gdt.c sources/user_mode.o 14 | BOOT_SOURCES = asm/boot_x64.asm asm/syscall_entry_64.asm 15 | 16 | # Objetos generados 17 | ARCH_OBJECTS = $(ARCH_SOURCES:.c=.o) 18 | BOOT_OBJECTS = $(BOOT_SOURCES:.asm=.o) 19 | ALL_OBJECTS = $(ARCH_OBJECTS) $(BOOT_OBJECTS) 20 | 21 | # Reglas de compilación 22 | %.o: %.c 23 | $(CC) $(CFLAGS) -c $< -o $@ 24 | 25 | %.o: %.asm 26 | $(ASM) $(ASMFLAGS) $< -o $@ 27 | 28 | all: $(ALL_OBJECTS) 29 | @echo "\033[1;32m============================================================\033[0m" 30 | @echo "\033[1;32m Boot subsystem compilado correctamente para $(ARCH_NAME)\033[0m" 31 | @echo "\033[1;32m============================================================\033[0m" 32 | 33 | clean: 34 | rm -f $(ALL_OBJECTS) 35 | @echo "Limpieza de $(ARCH_NAME) completada" 36 | 37 | .PHONY: all clean -------------------------------------------------------------------------------- /drivers/timer/rtc/rtc.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | // RTC register addresses 7 | #define RTC_ADDRESS_REG 0x70 8 | #define RTC_DATA_REG 0x71 9 | 10 | // RTC register indices 11 | #define RTC_SECONDS 0x00 12 | #define RTC_MINUTES 0x02 13 | #define RTC_HOURS 0x04 14 | #define RTC_DAY 0x07 15 | #define RTC_MONTH 0x08 16 | #define RTC_YEAR 0x09 17 | #define RTC_CENTURY 0x32 18 | 19 | // RTC status registers 20 | #define RTC_STATUS_A 0x0A 21 | #define RTC_STATUS_B 0x0B 22 | #define RTC_STATUS_C 0x0C 23 | 24 | // RTC status bits 25 | #define RTC_STATUS_B_24HOUR 0x02 26 | #define RTC_STATUS_B_BINARY 0x04 27 | 28 | // Time structure 29 | typedef struct 30 | { 31 | uint8_t second; 32 | uint8_t minute; 33 | uint8_t hour; 34 | uint8_t day; 35 | uint8_t month; 36 | uint16_t year; 37 | uint8_t century; 38 | } rtc_time_t; 39 | 40 | // Function declarations 41 | int rtc_init(void); 42 | int rtc_read_time(rtc_time_t *time); 43 | uint8_t rtc_read_register(uint8_t reg); 44 | void rtc_write_register(uint8_t reg, uint8_t value); 45 | uint8_t rtc_bcd_to_binary(uint8_t bcd); 46 | void rtc_get_time_string(char *buffer, size_t buffer_size); 47 | void rtc_get_date_string(char *buffer, size_t buffer_size); 48 | -------------------------------------------------------------------------------- /includes/stddef.h: -------------------------------------------------------------------------------- 1 | // Por ahora las repito antes de hacer refactor por cuestiones de economía y ver qué necesito de las libs std. 2 | 3 | #ifndef _STDDEF_H 4 | #define _STDDEF_H 5 | 6 | /* Standard definitions for IR0 Kernel - Freestanding implementation */ 7 | /* Architecture-aware definitions */ 8 | 9 | /* NULL pointer constant */ 10 | #ifndef NULL 11 | #ifdef __cplusplus 12 | #define NULL 0 13 | #else 14 | #define NULL ((void*)0) 15 | #endif 16 | #endif 17 | 18 | /* Architecture-dependent size and pointer difference types */ 19 | #if defined(__x86_64__) || defined(__amd64__) || defined(_M_X64) 20 | /* 64-bit architecture */ 21 | typedef unsigned long size_t; 22 | typedef long ptrdiff_t; 23 | #elif defined(__i386__) || defined(_M_IX86) 24 | /* 32-bit architecture */ 25 | typedef unsigned int size_t; 26 | typedef int ptrdiff_t; 27 | #else 28 | #error "Unsupported architecture for size_t and ptrdiff_t" 29 | #endif 30 | 31 | /* wchar_t - wide character type */ 32 | #ifndef __cplusplus 33 | typedef int wchar_t; 34 | #endif 35 | 36 | /* offsetof macro - offset of member in structure */ 37 | #define offsetof(type, member) __builtin_offsetof(type, member) 38 | 39 | /* max_align_t - type with strictest alignment requirement */ 40 | typedef struct 41 | { 42 | long long __ll; 43 | long double __ld; 44 | } max_align_t; 45 | 46 | #endif /* _STDDEF_H */ 47 | -------------------------------------------------------------------------------- /userspace/bin/hello.c: -------------------------------------------------------------------------------- 1 | // hello.c - Simple test program for IR0 ELF loader 2 | // This program will test basic ELF loading and execution 3 | 4 | // Minimal syscall interface 5 | static inline long syscall1(long number, long arg1) 6 | { 7 | long result; 8 | __asm__ volatile("int $0x80" 9 | : "=a"(result) 10 | : "a"(number), "b"(arg1) 11 | : "memory"); 12 | return result; 13 | } 14 | 15 | static inline long syscall3(long number, long arg1, long arg2, long arg3) { 16 | long result; 17 | __asm__ volatile("int $0x80" 18 | : "=a"(result) 19 | : "a"(number), "b"(arg1), "c"(arg2), "d"(arg3) 20 | : "memory"); 21 | return result; 22 | } 23 | 24 | // Syscall numbers (must match kernel) 25 | #define SYS_EXIT 0 26 | #define SYS_WRITE 1 27 | 28 | // Simple write function 29 | void write_string(const char *str) { 30 | int len = 0; 31 | while (str[len]) 32 | len++; // Calculate length 33 | syscall3(SYS_WRITE, 1, (long)str, len); // fd=1 (stdout) 34 | } 35 | 36 | // Program entry point 37 | void _start(void) { 38 | write_string("Hello from userspace ELF program!\n"); 39 | write_string("ELF loader is working!\n"); 40 | write_string("This is running in Ring 3 user mode.\n"); 41 | 42 | // Exit with code 42 43 | syscall1(SYS_EXIT, 42); 44 | 45 | // Should never reach here 46 | while (1) 47 | ; 48 | } -------------------------------------------------------------------------------- /fs/Makefile: -------------------------------------------------------------------------------- 1 | # fs/Makefile - Filesystem Makefile 2 | 3 | CC = gcc 4 | CFLAGS = -Wall -Wextra -O2 -std=c99 5 | INCLUDES = -I../includes -I../includes/ir0 -I../memory 6 | 7 | # Source files 8 | VFS_SOURCES = vfs.c vfs_simple_wrappers.c 9 | IR0FS_SOURCES = ir0fs.c 10 | SOURCES = $(VFS_SOURCES) $(IR0FS_SOURCES) 11 | 12 | # Object files 13 | VFS_OBJECTS = $(VFS_SOURCES:.c=.o) 14 | IR0FS_OBJECTS = $(IR0FS_SOURCES:.c=.o) 15 | OBJECTS = $(SOURCES:.c=.o) 16 | 17 | # Libraries 18 | VFS_LIB = libvfs.a 19 | IR0FS_LIB = libir0fs.a 20 | 21 | # Default target 22 | all: $(VFS_LIB) $(IR0FS_LIB) 23 | 24 | # VFS library 25 | $(VFS_LIB): $(VFS_OBJECTS) 26 | @echo "Creating VFS library..." 27 | ar rcs $@ $^ 28 | 29 | # IR0FS library 30 | $(IR0FS_LIB): $(IR0FS_OBJECTS) 31 | @echo "Creating IR0FS library..." 32 | ar rcs $@ $^ 33 | 34 | # Compile source files 35 | %.o: %.c 36 | @echo "Compiling $<..." 37 | $(CC) $(CFLAGS) $(INCLUDES) -c $< -o $@ 38 | 39 | # Clean 40 | clean: 41 | @echo "Cleaning filesystem objects..." 42 | rm -f $(OBJECTS) $(VFS_LIB) $(IR0FS_LIB) 43 | 44 | # Install 45 | install: all 46 | @echo "Installing filesystem libraries..." 47 | cp $(VFS_LIB) ../lib/ 48 | cp $(IR0FS_LIB) ../lib/ 49 | 50 | # Dependencies 51 | vfs.o: vfs.c vfs.h ../includes/ir0/print.h ../includes/string.h ../memory/memo_interface.h 52 | ir0fs.o: ir0fs.c ir0fs.h vfs.h ../includes/ir0/print.h ../includes/ir0/panic/panic.h ../includes/string.h ../memory/memo_interface.h 53 | 54 | .PHONY: all clean install 55 | -------------------------------------------------------------------------------- /includes/ir0/types.h: -------------------------------------------------------------------------------- 1 | #ifndef _IR0_TYPES_H 2 | #define _IR0_TYPES_H 3 | 4 | #include // Para tipos estándar 5 | 6 | // Standard types 7 | typedef int32_t pid_t; 8 | typedef int64_t time_t; 9 | typedef int64_t off_t; // Definición centralizada de off_t 10 | typedef uint32_t mode_t; 11 | typedef uint32_t dev_t; 12 | typedef uint32_t ino_t; 13 | typedef uint32_t nlink_t; 14 | typedef uint32_t uid_t; 15 | typedef uint32_t gid_t; 16 | typedef int64_t blksize_t; 17 | typedef int64_t blkcnt_t; 18 | 19 | // File type and permission bits (from stat.h) 20 | #define S_IFMT 0170000 // File type mask 21 | #define S_IFREG 0100000 // Regular file 22 | #define S_IFDIR 0040000 // Directory 23 | #define S_IFCHR 0020000 // Character device 24 | #define S_IFBLK 0060000 // Block device 25 | #define S_IFLNK 0120000 // Symbolic link 26 | #define S_IFSOCK 0140000 // Socket 27 | 28 | // File mode bits (from stat.h) 29 | #define S_IRWXU 0000700 // User: read, write, execute 30 | #define S_IRUSR 0000400 // User: read 31 | #define S_IWUSR 0000200 // User: write 32 | #define S_IXUSR 0000100 // User: execute 33 | 34 | #define S_IRWXG 0000070 // Group: read, write, execute 35 | #define S_IRGRP 0000040 // Group: read 36 | #define S_IWGRP 0000020 // Group: write 37 | #define S_IXGRP 0000010 // Group: execute 38 | 39 | #define S_IRWXO 0000007 // Others: read, write, execute 40 | #define S_IROTH 0000004 // Others: read 41 | #define S_IWOTH 0000002 // Others: write 42 | #define S_IXOTH 0000001 // Others: execute 43 | 44 | #endif /* _IR0_TYPES_H */ 45 | -------------------------------------------------------------------------------- /drivers/video/typewriter.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: GPL-3.0-only */ 2 | /* 3 | * IR0 Kernel - Typewriter Effect 4 | * Copyright (C) 2025 Iván Rodriguez 5 | * 6 | * Typewriter/Teletype effect for console output 7 | */ 8 | 9 | #ifndef TYPEWRITER_H 10 | #define TYPEWRITER_H 11 | 12 | #include 13 | #include 14 | 15 | /* Typewriter configuration */ 16 | #define TYPEWRITER_DELAY_FAST 2000 /* Fast typing (microseconds per char) */ 17 | #define TYPEWRITER_DELAY_NORMAL 5000 /* Normal typing */ 18 | #define TYPEWRITER_DELAY_SLOW 8000 /* Slow typing */ 19 | 20 | /* Typewriter modes */ 21 | typedef enum { 22 | TYPEWRITER_DISABLED = 0, 23 | TYPEWRITER_FAST, 24 | TYPEWRITER_NORMAL, 25 | TYPEWRITER_SLOW 26 | } typewriter_mode_t; 27 | 28 | /* Initialize typewriter system */ 29 | void typewriter_init(void); 30 | 31 | /* Set typewriter mode */ 32 | void typewriter_set_mode(typewriter_mode_t mode); 33 | 34 | /* Get current mode */ 35 | typewriter_mode_t typewriter_get_mode(void); 36 | 37 | /* Typewriter print functions */ 38 | void typewriter_print(const char *str); 39 | void typewriter_print_char(char c); 40 | void typewriter_print_uint32(uint32_t num); 41 | 42 | /* VGA typewriter functions for shell */ 43 | void typewriter_vga_print(const char *str, uint8_t color); 44 | void typewriter_vga_print_char(char c, uint8_t color); 45 | 46 | /* Enable/disable for specific contexts */ 47 | void typewriter_enable_for_commands(int enable); 48 | int typewriter_is_enabled_for_commands(void); 49 | 50 | #endif /* TYPEWRITER_H */ -------------------------------------------------------------------------------- /userspace/Makefile: -------------------------------------------------------------------------------- 1 | # Makefile for IR0 userspace programs 2 | CC = gcc 3 | CFLAGS = -m64 -nostdlib -nostartfiles -nodefaultlibs -fno-builtin -fno-stack-protector 4 | CFLAGS += -Ilibc/include -I../includes -static -fPIC 5 | LDFLAGS = -nostdlib -static 6 | 7 | # Directories 8 | LIBC_SRC = libc/src 9 | LIBC_INC = libc/include 10 | BIN_SRC = bin 11 | BUILD_DIR = build 12 | 13 | # Libc object files 14 | LIBC_OBJS = $(BUILD_DIR)/syscalls.o $(BUILD_DIR)/stdio.o $(BUILD_DIR)/malloc.o \ 15 | $(BUILD_DIR)/unistd.o $(BUILD_DIR)/strtok.o $(BUILD_DIR)/atoi.o $(BUILD_DIR)/strtod.o \ 16 | $(BUILD_DIR)/string.o $(BUILD_DIR)/math.o $(BUILD_DIR)/time.o 17 | 18 | 19 | # Programs 20 | PROGRAMS = $(BUILD_DIR)/echo $(BUILD_DIR)/libctest 21 | 22 | 23 | .PHONY: all clean 24 | 25 | all: $(BUILD_DIR) $(PROGRAMS) 26 | 27 | $(BUILD_DIR): 28 | mkdir -p $(BUILD_DIR) 29 | 30 | # Build libc objects 31 | $(BUILD_DIR)/%.o: $(LIBC_SRC)/%.c 32 | $(CC) $(CFLAGS) -c $< -o $@ 33 | 34 | # Build echo program 35 | $(BUILD_DIR)/echo: $(BIN_SRC)/echo.c $(LIBC_OBJS) 36 | $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $^ 37 | 38 | # Build libctest program 39 | $(BUILD_DIR)/libctest: $(BIN_SRC)/libctest.c $(LIBC_OBJS) 40 | $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $^ 41 | 42 | 43 | clean: 44 | rm -rf $(BUILD_DIR) 45 | disk: 46 | dd if=/dev/zero of=/home/ivanr013/Escritorio/ir0-kernel/disk.img bs=1M count=10 47 | 48 | rmdisk: 49 | rm /home/ivanr013/Escritorio/ir0-kernel/disk.img 50 | 51 | install: all 52 | # Copy programs to filesystem (when we have one) 53 | @echo "Programs built in $(BUILD_DIR)/" -------------------------------------------------------------------------------- /includes/ir0/oops.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | 4 | // Niveles de panic semánticos 5 | typedef enum 6 | { 7 | PANIC_KERNEL_BUG = 0, // Bug en kernel code 8 | PANIC_HARDWARE_FAULT = 1, // Hardware malfunction 9 | PANIC_OUT_OF_MEMORY = 2, // System out of memory 10 | PANIC_STACK_OVERFLOW = 3, // Stack corruption 11 | PANIC_ASSERT_FAILED= 4, // Assertion failure 12 | PANIC_MEM = 5, // Memory operation error (null ptr, invalid access, etc.) 13 | TESTING = 6, 14 | RUNNING_OUT_PROCESS = 7 15 | } panic_level_t; 16 | 17 | #ifdef __cplusplus 18 | extern "C" { 19 | #endif 20 | 21 | void panic(const char *message); 22 | void panicex(const char *message, panic_level_t level, const char *file, int line, const char *caller); /*Panic with more detailed logs*/ 23 | void cpu_relax(); 24 | void dump_stack_trace(); 25 | void dump_registers(); 26 | 27 | #ifdef __cplusplus 28 | } 29 | #endif 30 | 31 | 32 | // Macros for better panic message tunning 33 | #define BUG_ON(condition) \ 34 | do { \ 35 | if (unlikely(condition)) \ 36 | { \ 37 | panicex("BUG_ON: " #condition, PANIC_KERNEL_BUG, __FILE__, __LINE__, __func__); \ 38 | } \ 39 | } while(0) 40 | 41 | /* For testing */ 42 | #define ASSERT(condition) \ 43 | do { \ 44 | if (unlikely(!(condition))) \ 45 | { \ 46 | panicex("ASSERT failed: " #condition, PANIC_ASSERT_FAILED, __FILE__, __LINE__, __func__); \ 47 | } \ 48 | } while(0) 49 | 50 | #define likely(x) __builtin_expect(!!(x), 1) 51 | #define unlikely(x) __builtin_expect(!!(x), 0) 52 | 53 | -------------------------------------------------------------------------------- /interrupt/Makefile: -------------------------------------------------------------------------------- 1 | # Makefile para el sistema de interrupciones 2 | 3 | # Variables 4 | CC = gcc 5 | NASM = nasm 6 | CFLAGS = -Wall -Wextra -O1 -MMD -MP 7 | INCLUDES = -I../../includes -I../../includes/ir0 -I../../arch/common -I../../setup 8 | 9 | # Objetos comunes 10 | COMMON_OBJS = arch/idt.o arch/pic.o arch/isr_handlers.o arch/keyboard.o 11 | 12 | # Objetos específicos por arquitectura 13 | X86_32_OBJS = arch/x86-32/isr_stubs_32.o 14 | X86_64_OBJS = arch/x86-64/isr_stubs_64.o 15 | 16 | # Objetos finales 17 | INTERRUPT_OBJS = $(COMMON_OBJS) 18 | 19 | # Reglas principales 20 | all: $(INTERRUPT_OBJS) 21 | 22 | # Compilar archivos C 23 | arch/idt.o: arch/idt.c arch/idt.h arch/io.h 24 | $(CC) $(CFLAGS) $(INCLUDES) -c $< -o $@ 25 | 26 | arch/pic.o: arch/pic.c arch/pic.h arch/io.h 27 | $(CC) $(CFLAGS) $(INCLUDES) -c $< -o $@ 28 | 29 | arch/isr_handlers.o: arch/isr_handlers.c arch/idt.h arch/pic.h arch/io.h 30 | $(CC) $(CFLAGS) $(INCLUDES) -c $< -o $@ 31 | 32 | arch/keyboard.o: arch/keyboard.c arch/idt.h arch/pic.h arch/io.h 33 | $(CC) $(CFLAGS) $(INCLUDES) -c $< -o $@ 34 | 35 | # Compilar stubs de 32-bit 36 | arch/x86-32/isr_stubs_32.o: arch/x86-32/isr_stubs_32.asm 37 | $(NASM) -f elf32 $< -o $@ 38 | 39 | # Compilar stubs de 64-bit 40 | arch/x86-64/isr_stubs_64.o: arch/x86-64/isr_stubs_64.asm 41 | $(NASM) -f elf64 $< -o $@ 42 | 43 | # Limpiar 44 | clean: 45 | rm -f $(COMMON_OBJS) $(X86_32_OBJS) $(X86_64_OBJS) *.d 46 | 47 | # Información 48 | info: 49 | @echo "Sistema de Interrupciones - Objetos:" 50 | @echo " Comunes: $(COMMON_OBJS)" 51 | @echo " 32-bit: $(X86_32_OBJS)" 52 | @echo " 64-bit: $(X86_64_OBJS)" 53 | 54 | .PHONY: all clean info -------------------------------------------------------------------------------- /includes/ir0/stat.h: -------------------------------------------------------------------------------- 1 | #ifndef _IR0_STAT_H 2 | #define _IR0_STAT_H 3 | 4 | #include // For standard types and mode bits 5 | #include // Incluir types.h para off_t 6 | 7 | typedef struct stat stat_t; 8 | 9 | /* Structure describing file characteristics */ 10 | struct stat { 11 | dev_t st_dev; /* ID of device containing file */ 12 | ino_t st_ino; /* Inode number */ 13 | mode_t st_mode; /* File type and mode */ 14 | nlink_t st_nlink; /* Number of hard links */ 15 | uid_t st_uid; /* User ID of owner */ 16 | gid_t st_gid; /* Group ID of owner */ 17 | dev_t st_rdev; /* Device ID (if special file) */ 18 | off_t st_size; /* Total size, in bytes */ 19 | blksize_t st_blksize; /* Block size for filesystem I/O */ 20 | blkcnt_t st_blocks; /* Number of 512B blocks allocated */ 21 | time_t st_atime; /* Time of last access */ 22 | time_t st_mtime; /* Time of last modification */ 23 | time_t st_ctime; /* Time of last status change */ 24 | }; 25 | 26 | 27 | /* Test macros for file types */ 28 | #define S_ISREG(m) (((m) & S_IFMT) == S_IFREG) /* Regular file */ 29 | #define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR) /* Directory */ 30 | #define S_ISCHR(m) (((m) & S_IFMT) == S_IFCHR) /* Character device */ 31 | #define S_ISBLK(m) (((m) & S_IFMT) == S_IFBLK) /* Block device */ 32 | #define S_ISFIFO(m) (((m) & S_IFMT) == S_IFIFO) /* FIFO/pipe */ 33 | #define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK) /* Symbolic link */ 34 | #define S_ISSOCK(m) (((m) & S_IFMT) == S_IFSOCK) /* Socket */ 35 | 36 | #endif /* _IR0_STAT_H */ -------------------------------------------------------------------------------- /includes/ir0/net.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: GPL-3.0-only */ 2 | /** 3 | * IR0 Kernel — Core system software 4 | * Copyright (C) 2025 Iván Rodriguez 5 | * 6 | * This file is part of the IR0 Operating System. 7 | * Distributed under the terms of the GNU General Public License v3.0. 8 | * See the LICENSE file in the project root for full license information. 9 | * 10 | * File: net.h 11 | * Description: Common networking types and macros for IR0. 12 | */ 13 | 14 | #pragma once 15 | 16 | #include 17 | 18 | /* Byte order conversion macros (Big Endian <-> Little Endian) */ 19 | /* IR0 is x86-64 (Little Endian) */ 20 | 21 | #define htons(n) (((((uint16_t)(n) & 0xFF)) << 8) | (((uint16_t)(n) & 0xFF00) >> 8)) 22 | #define ntohs(n) htons(n) 23 | 24 | #define htonl(n) (((((uint32_t)(n) & 0x000000FF)) << 24) | \ 25 | ((((uint32_t)(n) & 0x0000FF00)) << 8) | \ 26 | ((((uint32_t)(n) & 0x00FF0000)) >> 8) | \ 27 | ((((uint32_t)(n) & 0xFF000000)) >> 24)) 28 | #define ntohl(n) htonl(n) 29 | 30 | /* Common Ethernet Types */ 31 | #define ETHERTYPE_IP 0x0800 32 | #define ETHERTYPE_ARP 0x0806 33 | #define ETHERTYPE_IPV6 0x86DD 34 | 35 | /* Ethernet header (14 bytes) */ 36 | struct eth_header { 37 | uint8_t dest[6]; 38 | uint8_t src[6]; 39 | uint16_t type; 40 | } __attribute__((packed)); 41 | 42 | /* IPv4 Address type */ 43 | typedef uint32_t ip4_addr_t; 44 | 45 | /* MAC Address type */ 46 | typedef uint8_t mac_addr_t[6]; 47 | 48 | /* Function to create an IP address from 4 octets */ 49 | static inline ip4_addr_t make_ip4_addr(uint8_t a, uint8_t b, uint8_t c, uint8_t d) { 50 | return (a << 24) | (b << 16) | (c << 8) | d; 51 | } 52 | -------------------------------------------------------------------------------- /kernel/scheduler/Makefile: -------------------------------------------------------------------------------- 1 | # Makefile para el subsistema de scheduler 2 | 3 | # Usar variables pasadas desde el Makefile principal 4 | CC ?= gcc 5 | ASM ?= nasm 6 | CFLAGS ?= -m32 -march=i686 -nostdlib -nostdinc -fno-builtin -fno-stack-protector -fno-pic -nodefaultlibs -ffreestanding 7 | ASMFLAGS ?= -f elf32 8 | 9 | # Detectar arquitectura desde CFLAGS 10 | ifneq (,$(findstring -m64,$(CFLAGS))) 11 | ARCH_DETECTED = x86-64 12 | ASMFLAGS = -f elf64 13 | else 14 | ARCH_DETECTED = x86-32 15 | ASMFLAGS = -f elf32 16 | endif 17 | 18 | # Incluir directorios 19 | CFLAGS += -I../../includes -I../../includes/ir0 -I../../arch/common 20 | 21 | # Objetos comunes 22 | OBJS = priority_scheduler.o round-robin_scheduler.o sched_central.o scheduler_detection.o cfs_scheduler.o task_impl.o 23 | 24 | # Objetos específicos de arquitectura 25 | ifeq ($(ARCH_DETECTED),x86-64) 26 | OBJS += switch/switch_x64.o 27 | else 28 | OBJS += switch/switch_x86.o 29 | endif 30 | 31 | all: $(OBJS) 32 | @echo "\033[1;32m============================================================\033[0m" 33 | @echo "\033[1;32m Scheduler subsystem compilado correctamente para $(ARCH_DETECTED)\033[0m" 34 | @echo "\033[1;32m============================================================\033[0m" 35 | 36 | %.o: %.c 37 | @echo "Compilando $< para $(ARCH_DETECTED)..." 38 | $(CC) $(CFLAGS) -c $< -o $@ 39 | 40 | %.o: %.asm 41 | @echo "Compilando context switch para $(ARCH_DETECTED)..." 42 | $(ASM) $(ASMFLAGS) $< -o $@ 43 | 44 | clean: 45 | @echo "Limpiando scheduler subsystem..." 46 | rm -f $(OBJS) 47 | @echo "Limpiando archivos de dependencias (.d)..." 48 | rm -f *.d switch/*.d 49 | @echo "Limpieza del scheduler completada." 50 | 51 | .PHONY: all clean -------------------------------------------------------------------------------- /interrupt/arch/pic.h: -------------------------------------------------------------------------------- 1 | #ifndef PIC_H 2 | #define PIC_H 3 | 4 | #include 5 | 6 | // Puertos del PIC 7 | #define PIC1_COMMAND 0x20 8 | #define PIC1_DATA 0x21 9 | #define PIC2_COMMAND 0xA0 10 | #define PIC2_DATA 0xA1 11 | 12 | // Comandos PIC 13 | #define ICW1_ICW4 0x01 // ICW4 needed 14 | #define ICW1_SINGLE 0x02 // Single (cascade) mode 15 | #define ICW1_INTERVAL4 0x04 // Call address interval 4 (8) 16 | #define ICW1_LEVEL 0x08 // Level triggered (edge) mode 17 | #define ICW1_INIT 0x10 // Initialization - required! 18 | 19 | #define ICW4_8086 0x01 // 8086/88 (MCS-80/85) mode 20 | #define ICW4_AUTO 0x02 // Auto (normal) EOI 21 | #define ICW4_BUF_SLAVE 0x08 // Buffered mode/slave 22 | #define ICW4_BUF_MASTER 0x0C // Buffered mode/master 23 | #define ICW4_SFNM 0x10 // Special fully nested (not) 24 | 25 | // EOI (End of Interrupt) 26 | #define PIC_EOI 0x20 27 | 28 | // Máscaras de IRQ 29 | #define IRQ_TIMER 0 30 | #define IRQ_KEYBOARD 1 31 | #define IRQ_CASCADE 2 32 | #define IRQ_COM2 3 33 | #define IRQ_COM1 4 34 | #define IRQ_LPT2 5 35 | #define IRQ_FLOPPY 6 36 | #define IRQ_LPT1 7 37 | #define IRQ_CMOS 8 38 | #define IRQ_FREE1 9 39 | #define IRQ_FREE2 10 40 | #define IRQ_FREE3 11 41 | #define IRQ_PS2 12 42 | #define IRQ_FPU 13 43 | #define IRQ_ATA1 14 44 | #define IRQ_ATA2 15 45 | 46 | // Funciones 47 | void pic_remap32(void); 48 | void pic_remap64(void); 49 | void pic_send_eoi32(uint8_t irq); 50 | void pic_send_eoi64(uint8_t irq); 51 | void pic_mask_irq(uint8_t irq); 52 | void pic_unmask_irq(uint8_t irq); 53 | 54 | #endif // PIC_H 55 | -------------------------------------------------------------------------------- /drivers/disk/partition.h: -------------------------------------------------------------------------------- 1 | #ifndef _PARTITION_H 2 | #define _PARTITION_H 3 | 4 | #include 5 | 6 | // MBR Partition Entry Structure 7 | typedef struct { 8 | uint8_t boot_indicator; 9 | uint8_t start_head; 10 | uint8_t start_sector; 11 | uint8_t start_cylinder; 12 | uint8_t system_id; 13 | uint8_t end_head; 14 | uint8_t end_sector; 15 | uint8_t end_cylinder; 16 | uint32_t start_lba; 17 | uint32_t total_sectors; 18 | } __attribute__((packed)) mbr_partition_entry_t; 19 | 20 | // MBR Structure 21 | typedef struct { 22 | uint8_t bootstrap[446]; 23 | mbr_partition_entry_t partitions[4]; 24 | uint16_t signature; 25 | } __attribute__((packed)) mbr_t; 26 | 27 | // GPT Header 28 | typedef struct { 29 | uint8_t signature[8]; 30 | uint32_t revision; 31 | uint32_t header_size; 32 | uint32_t header_crc32; 33 | uint32_t reserved; 34 | uint64_t current_lba; 35 | uint64_t backup_lba; 36 | uint64_t first_usable_lba; 37 | uint64_t last_usable_lba; 38 | uint8_t disk_guid[16]; 39 | uint64_t partition_entry_lba; 40 | uint32_t num_partition_entries; 41 | uint32_t size_of_partition_entry; 42 | uint32_t partition_entry_array_crc32; 43 | } __attribute__((packed)) gpt_header_t; 44 | 45 | // GPT Partition Entry 46 | typedef struct { 47 | uint8_t type_guid[16]; 48 | uint8_t unique_guid[16]; 49 | uint64_t first_lba; 50 | uint64_t last_lba; 51 | uint64_t attributes; 52 | uint16_t name[36]; // UTF-16LE 53 | } __attribute__((packed)) gpt_partition_entry_t; 54 | 55 | // Function declarations 56 | int read_partition_table(uint8_t disk_id); 57 | int is_gpt_disk(uint8_t disk_id); 58 | const char* get_partition_type(uint8_t system_id); 59 | 60 | #endif -------------------------------------------------------------------------------- /drivers/timer/lapic/lapic.c: -------------------------------------------------------------------------------- 1 | #include "lapic.h" 2 | #include 3 | #include 4 | 5 | #define LAPIC_BASE ((uintptr_t)0xFEE00000) 6 | #define LAPIC_TIMER_REG 0x320 7 | #define LAPIC_TIMER_DIV 0x3E0 8 | #define LAPIC_TIMER_INIT_COUNT 0x380 9 | #define LAPIC_TIMER_CURR_COUNT 0x390 10 | #define LAPIC_EOI_REG 0xB0 11 | 12 | // Registra valor en MMIO del LAPIC 13 | static inline void lapic_write(uint32_t reg, uint32_t value) 14 | { 15 | *((volatile uint32_t *)(LAPIC_BASE + reg)) = value; 16 | } 17 | 18 | // Lee valor actual del LAPIC MMIO 19 | static inline uint32_t lapic_read(uint32_t reg) 20 | { 21 | return *((volatile uint32_t *)(LAPIC_BASE + reg)); 22 | } 23 | 24 | void lapic_init_timer() 25 | { 26 | print_colored("[LAPIC] Inicializando temporizador local...\n", VGA_COLOR_CYAN, VGA_COLOR_BLACK); 27 | 28 | // Configurar divisor del reloj del LAPIC → /16 por ejemplo 29 | lapic_write(LAPIC_TIMER_DIV, 0x3); // divisor 16 (ver tabla del datasheet Intel) 30 | 31 | // Modo de interrupción: 0x20020 = periodic mode, IRQ 32 32 | lapic_write(LAPIC_TIMER_REG, 0x20020); // vector 32, periodic 33 | 34 | // Cargar el contador inicial 35 | lapic_write(LAPIC_TIMER_INIT_COUNT, 10000000); // este valor define frecuencia 36 | 37 | print_success("[LAPIC] Temporizador local configurado.\n"); 38 | } 39 | 40 | int lapic_available() 41 | { 42 | // Check CPUID for LAPIC support 43 | uint32_t eax, ebx, ecx, edx; 44 | asm volatile("cpuid" : "=a"(eax), "=b"(ebx), "=c"(ecx), "=d"(edx) : "a"(1)); 45 | return (edx & (1 << 9)) != 0; // APIC bit 46 | } 47 | 48 | // Agregar esta función 49 | void lapic_send_eoi() 50 | { 51 | // Escribir cualquier valor al registro EOI (típicamente 0) 52 | lapic_write(LAPIC_EOI_REG, 0); 53 | } -------------------------------------------------------------------------------- /includes/ir0/memory/kmem.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | 5 | 6 | #ifdef __cplusplus 7 | extern "C" { 8 | #endif 9 | 10 | // Internal implementations (pure logic, no validation) 11 | void *__kmalloc_impl(size_t size); 12 | void __kfree_impl(void *ptr); 13 | void *__krealloc_impl(void *ptr, size_t new_size); 14 | void *__kmalloc_aligned_impl(size_t size, size_t alignment); 15 | void __kfree_aligned_impl(void *ptr); 16 | 17 | // Checked wrappers with debug info 18 | void *__kmalloc_checked(size_t size, const char *file, int line, const char *caller); 19 | void __kfree_checked(void *ptr, const char *file, int line, const char *caller); 20 | void *__krealloc_checked(void *ptr, size_t new_size, 21 | const char *file, int line, const char *caller); 22 | void *__kmalloc_aligned_checked(size_t size, size_t alignment, 23 | const char *file, int line, const char *caller); 24 | void __kfree_aligned_checked(void *ptr, const char *file, int line, const char *caller); 25 | 26 | void heap_init(void); 27 | 28 | 29 | #ifdef __cplusplus 30 | } 31 | #endif 32 | 33 | // Automatic debug tracking macros - capture caller location transparently 34 | #define kmalloc(size) \ 35 | __kmalloc_checked((size), __FILE__, __LINE__, __func__) 36 | 37 | #define kfree(ptr) \ 38 | __kfree_checked((ptr), __FILE__, __LINE__, __func__) 39 | 40 | #define krealloc(ptr, new_size) \ 41 | __krealloc_checked((ptr), (new_size), __FILE__, __LINE__, __func__) 42 | 43 | #define kmalloc_aligned(size, alignment) \ 44 | __kmalloc_aligned_checked((size), (alignment), __FILE__, __LINE__, __func__) 45 | 46 | #define kfree_aligned(ptr) \ 47 | __kfree_aligned_checked((ptr), __FILE__, __LINE__, __func__) 48 | 49 | 50 | -------------------------------------------------------------------------------- /kernel/syscall_wrappers.c: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: GPL-3.0-only */ 2 | /* 3 | * IR0 Kernel - System Call Wrappers 4 | * Copyright (C) 2025 Iván Rodriguez 5 | * 6 | * Safe wrappers for system calls with parameter validation 7 | */ 8 | 9 | #include "syscalls.h" 10 | #include "syscalls_internal.h" 11 | #include "process.h" 12 | #include 13 | #include 14 | 15 | /* Error codes */ 16 | #define EINVAL 22 17 | #define EBADF 9 18 | #define ENAMETOOLONG 36 19 | 20 | typedef uint32_t mode_t; 21 | 22 | int64_t safe_sys_write(int fd, const void *buf, size_t count) 23 | { 24 | if (!buf || count == 0) 25 | return -EINVAL; 26 | 27 | if (fd < 0 || fd >= MAX_FDS_PER_PROCESS) 28 | return -EBADF; 29 | 30 | return sys_write(fd, buf, count); 31 | } 32 | 33 | int64_t safe_sys_read(int fd, void *buf, size_t count) 34 | { 35 | if (!buf || count == 0) 36 | return -EINVAL; 37 | 38 | if (fd < 0 || fd >= MAX_FDS_PER_PROCESS) 39 | return -EBADF; 40 | 41 | return sys_read(fd, buf, count); 42 | } 43 | 44 | int64_t safe_sys_open(const char *pathname, int flags, mode_t mode) 45 | { 46 | if (!pathname || strlen(pathname) == 0) 47 | return -EINVAL; 48 | 49 | if (strlen(pathname) > 255) 50 | return -ENAMETOOLONG; 51 | 52 | return sys_open(pathname, flags, mode); 53 | } 54 | 55 | 56 | int64_t safe_sys_mkdir(const char *pathname, mode_t mode) 57 | { 58 | if (!pathname || strlen(pathname) == 0) 59 | return -EINVAL; 60 | 61 | if (strlen(pathname) > 255) 62 | return -ENAMETOOLONG; 63 | 64 | /* Ensure reasonable permissions */ 65 | mode &= 0777; 66 | 67 | return sys_mkdir(pathname, mode); 68 | } 69 | 70 | void *safe_kmalloc(size_t size) 71 | { 72 | /* Max 1MB allocation */ 73 | if (size == 0 || size > (1024 * 1024)) 74 | return NULL; 75 | 76 | return kmalloc(size); 77 | } 78 | -------------------------------------------------------------------------------- /includes/errno.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: GPL-3.0-only */ 2 | #ifndef _ERRNO_H 3 | #define _ERRNO_H 4 | 5 | /* Error codes - compatible with POSIX */ 6 | #define EPERM 1 /* Operation not permitted */ 7 | #define ENOENT 2 /* No such file or directory */ 8 | #define ESRCH 3 /* No such process */ 9 | #define EINTR 4 /* Interrupted system call */ 10 | #define EIO 5 /* I/O error */ 11 | #define ENXIO 6 /* No such device or address */ 12 | #define E2BIG 7 /* Argument list too long */ 13 | #define ENOEXEC 8 /* Exec format error */ 14 | #define EBADF 9 /* Bad file number */ 15 | #define ECHILD 10 /* No child processes */ 16 | #define EAGAIN 11 /* Try again */ 17 | #define ENOMEM 12 /* Out of memory */ 18 | #define EACCES 13 /* Permission denied */ 19 | #define EFAULT 14 /* Bad address */ 20 | #define ENOTBLK 15 /* Block device required */ 21 | #define EBUSY 16 /* Device or resource busy */ 22 | #define EEXIST 17 /* File exists */ 23 | #define EXDEV 18 /* Cross-device link */ 24 | #define ENODEV 19 /* No such device */ 25 | #define ENOTDIR 20 /* Not a directory */ 26 | #define EISDIR 21 /* Is a directory */ 27 | #define EINVAL 22 /* Invalid argument */ 28 | #define ENFILE 23 /* File table overflow */ 29 | #define EMFILE 24 /* Too many open files */ 30 | #define ENOTTY 25 /* Not a typewriter */ 31 | #define ETXTBSY 26 /* Text file busy */ 32 | #define EFBIG 27 /* File too large */ 33 | #define ENOSPC 28 /* No space left on device */ 34 | #define ESPIPE 29 /* Illegal seek */ 35 | #define EROFS 30 /* Read-only file system */ 36 | #define EMLINK 31 /* Too many links */ 37 | #define EPIPE 32 /* Broken pipe */ 38 | #define EDOM 33 /* Math argument out of domain of func */ 39 | #define ERANGE 34 /* Math result not representable */ 40 | #define ENOSYS 38 /* Invalid system call number */ 41 | 42 | #endif /* _ERRNO_H */ -------------------------------------------------------------------------------- /fs/vfs_simple.h: -------------------------------------------------------------------------------- 1 | // fs/vfs_simple.h - Simplified Virtual File System Interface 2 | #pragma once 3 | 4 | #include 5 | #include 6 | 7 | 8 | /** 9 | * Inicializa el sistema de archivos simple 10 | */ 11 | void vfs_simple_init(void); 12 | 13 | /** 14 | * Crea un directorio 15 | * @param path Nombre del directorio a crear 16 | * @return 0 en éxito, -1 en error 17 | */ 18 | int vfs_simple_mkdir(const char* path); 19 | 20 | /** 21 | * Lista el contenido de un directorio 22 | * @param path Ruta del directorio a listar 23 | * @return 0 en éxito, -1 en error 24 | */ 25 | int vfs_simple_ls(const char* path); 26 | 27 | /** 28 | * Crea un archivo en un directorio 29 | * @param path Ruta del directorio 30 | * @param filename Nombre del archivo 31 | * @param size Tamaño del archivo 32 | * @return 0 en éxito, -1 en error 33 | */ 34 | int vfs_simple_create_file(const char* path, const char* filename, uint32_t size); 35 | 36 | /** 37 | * Obtiene el número de directorios creados 38 | * @return Número de directorios 39 | */ 40 | int vfs_simple_get_directory_count(void); 41 | 42 | /** 43 | * Obtiene el nombre de un directorio por índice 44 | * @param index Índice del directorio 45 | * @return Nombre del directorio o NULL si no existe 46 | */ 47 | const char* vfs_simple_get_directory_name(int index); 48 | 49 | /** 50 | * Verifica si un archivo existe 51 | * @param pathname Ruta del archivo 52 | * @return 1 si existe, 0 si no existe 53 | */ 54 | int vfs_file_exists(const char *pathname); 55 | 56 | /** 57 | * Verifica si un directorio existe 58 | * @param pathname Ruta del directorio 59 | * @return 1 si existe, 0 si no existe 60 | */ 61 | int vfs_directory_exists(const char *pathname); 62 | 63 | // Funciones de compatibilidad 64 | int vfs_allocate_sectors(int count); 65 | int vfs_remove_directory(const char *path); 66 | -------------------------------------------------------------------------------- /kernel/scheduler/scheduler_types.h: -------------------------------------------------------------------------------- 1 | // kernel/scheduler/scheduler_types.h 2 | #pragma once 3 | #include 4 | #include "task.h" 5 | 6 | // Scheduler Types - similar a Clocktype 7 | typedef enum 8 | { 9 | SCHEDULER_CFS, // Only CFS supported 10 | SCHEDULER_NONE 11 | } scheduler_type_t; 12 | 13 | typedef enum 14 | { 15 | RB_RED = 0, 16 | RB_BLACK = 1 17 | } rb_color_t; 18 | 19 | typedef struct rb_node 20 | { 21 | struct rb_node *parent; 22 | struct rb_node *left; 23 | struct rb_node *right; 24 | rb_color_t color; 25 | uint64_t key; // vruntime 26 | task_t *task; // puntero a la tarea 27 | } rb_node_t; 28 | 29 | typedef struct cfs_runqueue 30 | { 31 | rb_node_t *root; 32 | rb_node_t *leftmost; 33 | uint64_t clock; 34 | uint64_t exec_clock; 35 | uint64_t min_vruntime; 36 | uint64_t avg_vruntime; 37 | uint32_t nr_running; 38 | uint32_t total_weight; 39 | uint64_t targeted_latency; 40 | uint64_t min_granularity; 41 | uint32_t load_avg; 42 | uint32_t runnable_avg; 43 | } cfs_runqueue_t; 44 | 45 | // Scheduler interface - Similar a tu timer interface 46 | typedef struct 47 | { 48 | scheduler_type_t type; 49 | const char *name; 50 | 51 | // Function pointers for scheduler operations 52 | void (*init)(void); 53 | void (*add_task)(task_t *task); 54 | task_t *(*pick_next_task)(void); 55 | void (*task_tick)(void); 56 | void (*cleanup)(void); 57 | 58 | // Scheduler-specific data 59 | void *private_data; 60 | } scheduler_ops_t; 61 | 62 | // Global scheduler state 63 | extern scheduler_ops_t current_scheduler; 64 | extern scheduler_type_t active_scheduler_type; 65 | 66 | // Detection and fallback functions 67 | scheduler_type_t detect_best_scheduler(void); 68 | int scheduler_cascade_init(void); 69 | void scheduler_fallback_to_next(void); 70 | -------------------------------------------------------------------------------- /arch/common/arch_interface.h: -------------------------------------------------------------------------------- 1 | // arch/common/arch_interface.h - ARREGLADO 2 | #pragma once 3 | #include 4 | 5 | // =============================================================================== 6 | // Interfaz común para todas las arquitecturas 7 | // =============================================================================== 8 | 9 | /** 10 | * Habilita interrupciones en la CPU ("sti" en x86) 11 | */ 12 | void arch_enable_interrupts(void); 13 | 14 | /** 15 | * Función INB para leer de puertos I/O (solo x86) 16 | * En ARM esto sería MMIO reads 17 | */ 18 | uint8_t inb(uint16_t port); 19 | 20 | /** 21 | * Función OUTB para escribir a puertos I/O (solo x86) 22 | * En ARM esto sería MMIO writes 23 | */ 24 | void outb(uint16_t port, uint8_t value); 25 | 26 | /** 27 | * Lee la dirección que causó un page fault desde CR2 (x86) 28 | * Implementación específica por arquitectura 29 | */ 30 | uintptr_t read_fault_address(void); 31 | 32 | /** 33 | * Obtiene el nombre de la arquitectura actual 34 | * Útil para debugging y logs 35 | */ 36 | const char *arch_get_name(void); 37 | 38 | /** 39 | * Función de espera de CPU (HLT instruction en x86) 40 | * Permite que la CPU entre en estado de bajo consumo 41 | */ 42 | void cpu_wait(void); 43 | 44 | 45 | // =============================================================================== 46 | // Macros de detección de arquitectura (para uso interno) 47 | // =============================================================================== 48 | 49 | #if defined(__x86_64__) || defined(__amd64__) 50 | #define ARCH_X86_64 51 | #elif defined(__i386__) || defined(__i486__) || defined(__i586__) || defined(__i686__) 52 | #define ARCH_X86_32 53 | #elif defined(__aarch64__) 54 | #define ARCH_ARM64 55 | #elif defined(__arm__) 56 | #define ARCH_ARM32 57 | #else 58 | #error "Arquitectura no soportada en arch_interface.h" 59 | #endif -------------------------------------------------------------------------------- /kernel/rr_sched.c: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: GPL-3.0-only */ 2 | /* 3 | * IR0 Kernel - Round-Robin Scheduler 4 | * Copyright (C) 2025 Iván Rodriguez 5 | * 6 | * Simple round-robin process scheduler 7 | */ 8 | 9 | #include "process.h" 10 | #include "rr_sched.h" 11 | #include 12 | #include 13 | #include 14 | 15 | 16 | static rr_task_t *rr_head = NULL; 17 | static rr_task_t *rr_tail = NULL; 18 | static rr_task_t *rr_current = NULL; 19 | 20 | 21 | void rr_add_process(process_t *proc) 22 | { 23 | rr_task_t *node; 24 | 25 | if (!proc) 26 | return; 27 | 28 | node = kmalloc(sizeof(rr_task_t)); 29 | if (!node) 30 | return; 31 | 32 | node->process = proc; 33 | node->next = NULL; 34 | 35 | if (!rr_head) 36 | { 37 | rr_head = rr_tail = node; 38 | } 39 | else 40 | { 41 | rr_tail->next = node; 42 | rr_tail = node; 43 | } 44 | 45 | proc->state = PROCESS_READY; 46 | } 47 | 48 | 49 | void rr_schedule_next(void) 50 | { 51 | static int first = 1; 52 | process_t *prev; 53 | process_t *next; 54 | 55 | if (!rr_head) 56 | return; 57 | 58 | prev = current_process; 59 | 60 | /* Select next process in round-robin fashion */ 61 | if (!rr_current) 62 | rr_current = rr_head; 63 | else 64 | rr_current = rr_current->next ? rr_current->next : rr_head; 65 | 66 | next = rr_current->process; 67 | if (!next) 68 | return; 69 | 70 | /* Avoid unnecessary context switch */ 71 | if (!first && prev == next) 72 | return; 73 | 74 | /* Update process states */ 75 | if (prev && prev->state == PROCESS_RUNNING) 76 | prev->state = PROCESS_READY; 77 | 78 | next->state = PROCESS_RUNNING; 79 | current_process = next; 80 | 81 | /* First context switch - jump to ring3 */ 82 | if (first) 83 | { 84 | first = 0; 85 | jmp_ring3((void *)next->task.rip); 86 | panic("Returned from jmp_ring3"); 87 | } 88 | 89 | /* Normal context switch - TODO: implement switch_context */ 90 | } 91 | -------------------------------------------------------------------------------- /arch/x86-64/sources/user_mode.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | // Detect MinGW-w64 cross-compilation 6 | #if defined(__MINGW32__) || defined(__MINGW64__) || defined(_WIN32) 7 | #define MINGW_BUILD 1 8 | #else 9 | #define MINGW_BUILD 0 10 | #endif 11 | 12 | // User mode transition function - WITH INTERRUPTS ENABLED 13 | void jmp_ring3(void *entry_point) 14 | { 15 | #if MINGW_BUILD 16 | // MinGW-w64 stub - this function cannot work in Windows PE format 17 | // as it requires kernel mode execution 18 | (void)entry_point; 19 | panic("jmp_ring3 not supported in Windows build"); 20 | #else 21 | // Use stack within mapped 32MB region (safe area at 16MB) 22 | uintptr_t stack_top = 0x1000000 - 0x1000; // 16MB - 4KB 23 | 24 | // Switch to user mode - ENABLE INTERRUPTS for keyboard 25 | __asm__ volatile( 26 | "cli\n" // Disable interrupts temporarily during transition 27 | "mov $0x23, %%ax\n" // User data segment (GDT entry 4, RPL=3) 28 | "mov %%ax, %%ds\n" 29 | "mov %%ax, %%es\n" 30 | "mov %%ax, %%fs\n" 31 | "mov %%ax, %%gs\n" 32 | "pushq $0x23\n" // SS (user stack segment) 33 | "pushq %0\n" // RSP (user stack pointer) 34 | "pushfq\n" // Get current RFLAGS 35 | "pop %%rax\n" 36 | "or $0x200, %%rax\n" // Set IF=1 - ENABLE interrupts in user mode 37 | "push %%rax\n" // Push modified RFLAGS 38 | "pushq $0x1B\n" // CS (user code segment, GDT entry 3, RPL=3) 39 | "pushq %1\n" // RIP (entry point) 40 | "iretq\n" // Return to Ring 3 with interrupts enabled 41 | : 42 | : "r"(stack_top), "r"((uintptr_t)entry_point) 43 | : "rax", "memory"); 44 | 45 | panic("Returned from user mode unexpectedly"); 46 | #endif 47 | } 48 | 49 | 50 | 51 | [[maybe_unused]]void syscall_handler_c(void) 52 | { 53 | // Syscall received 54 | } -------------------------------------------------------------------------------- /arch/x86-64/asm/syscall_entry_64.asm: -------------------------------------------------------------------------------- 1 | ; System call entry point for int 0x80 2 | [BITS 64] 3 | 4 | global syscall_entry_asm 5 | extern syscall_dispatch 6 | 7 | section .text 8 | 9 | syscall_entry_asm: 10 | ; Save all registers 11 | push rax 12 | push rbx 13 | push rcx 14 | push rdx 15 | push rsi 16 | push rdi 17 | push rbp 18 | push r8 19 | push r9 20 | push r10 21 | push r11 22 | push r12 23 | push r13 24 | push r14 25 | push r15 26 | 27 | ; Save syscall arguments BEFORE overwriting anything 28 | ; Shell passes: rax=syscall_num, rbx=arg1, rcx=arg2, rdx=arg3, rsi=arg4, rdi=arg5 29 | mov r10, rax ; Save syscall number 30 | mov r11, rbx ; Save arg1 31 | mov r12, rcx ; Save arg2 32 | mov r13, rdx ; Save arg3 33 | mov r14, rsi ; Save arg4 34 | mov r15, rdi ; Save arg5 35 | 36 | ; Switch to kernel segments (this overwrites ax/rax!) 37 | mov ax, 0x10 38 | mov ds, ax 39 | mov es, ax 40 | 41 | ; Setup syscall arguments for C function 42 | ; C function expects: (rdi=syscall_num, rsi=arg1, rdx=arg2, rcx=arg3, r8=arg4, r9=arg5) 43 | mov rdi, r10 ; syscall number 44 | mov rsi, r11 ; arg1 45 | mov rdx, r12 ; arg2 46 | mov rcx, r13 ; arg3 47 | mov r8, r14 ; arg4 48 | mov r9, r15 ; arg5 49 | 50 | ; Call C dispatcher 51 | call syscall_dispatch 52 | 53 | ; Return value in rax (already set by syscall_dispatch) 54 | 55 | ; Restore registers 56 | pop r15 57 | pop r14 58 | pop r13 59 | pop r12 60 | pop r11 61 | pop r10 62 | pop r9 63 | pop r8 64 | pop rbp 65 | pop rdi 66 | pop rsi 67 | pop rdx 68 | pop rcx 69 | pop rbx 70 | add rsp, 8 ; Skip saved rax, use return value instead 71 | 72 | ; No need to send EOI for syscalls (they are software interrupts) 73 | 74 | ; Return to user mode 75 | iretq 76 | 77 | 78 | section .note.GNU-stack noalloc noexec nowrite progbits -------------------------------------------------------------------------------- /fs/vfs_simple_wrappers.c: -------------------------------------------------------------------------------- 1 | // Thin compatibility wrappers for previous vfs_simple API 2 | // These forward to the unified VFS/minix implementations. 3 | #include "vfs.h" 4 | #include "minix_fs.h" 5 | #include 6 | #include 7 | #include 8 | 9 | void vfs_simple_init(void) { vfs_init(); } 10 | 11 | int vfs_simple_mkdir(const char *path) 12 | { 13 | if (!path) 14 | return -1; 15 | return vfs_mkdir(path, 0755); 16 | } 17 | 18 | int vfs_simple_ls(const char *path) 19 | { 20 | const char *p = path ? path : "/"; 21 | return vfs_ls(p); 22 | } 23 | 24 | int vfs_simple_create_file(const char *path, const char *filename, uint32_t size) 25 | { 26 | (void)size; // size ignored for simple wrapper 27 | if (!path || !filename) 28 | return -1; 29 | // Build full path 30 | char full[512]; 31 | if (path[0] == '\0' || strcmp(path, "/") == 0) 32 | { 33 | snprintf(full, sizeof(full), "/%s", filename); 34 | } 35 | else 36 | { 37 | snprintf(full, sizeof(full), "%s/%s", path, filename); 38 | } 39 | extern int minix_fs_touch(const char *path, mode_t mode); 40 | return minix_fs_touch(full, 0644); 41 | } 42 | 43 | int vfs_simple_get_directory_count(void) 44 | { 45 | (void)0; 46 | return 0; 47 | } 48 | 49 | const char *vfs_simple_get_directory_name(int index) 50 | { 51 | (void)index; 52 | return NULL; 53 | } 54 | 55 | int vfs_file_exists(const char *pathname) 56 | { 57 | if (!pathname) 58 | return 0; 59 | stat_t st; 60 | if (vfs_stat(pathname, &st) == 0) 61 | return 1; 62 | return 0; 63 | } 64 | 65 | int vfs_directory_exists(const char *pathname) 66 | { 67 | if (!pathname) 68 | return 0; 69 | stat_t st; 70 | if (vfs_stat(pathname, &st) == 0) 71 | { 72 | return S_ISDIR(st.st_mode) ? 1 : 0; 73 | } 74 | return 0; 75 | } 76 | 77 | int vfs_allocate_sectors(int count) 78 | { 79 | (void)count; 80 | return 0; 81 | } 82 | int vfs_remove_directory(const char *path) { return vfs_rmdir_recursive(path); } 83 | -------------------------------------------------------------------------------- /kernel/fs/file.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | // Global file system list 8 | static filesystem_type_t *filesystems = NULL; 9 | 10 | // File operations for MINIX 11 | extern file_operations_t minix_file_ops; 12 | 13 | int register_filesystem(filesystem_type_t *fs) 14 | { 15 | if (!fs || !fs->name || !fs->fops) 16 | { 17 | return -EINVAL; 18 | } 19 | 20 | // Add to the beginning of the list 21 | fs->next = filesystems; 22 | filesystems = fs; 23 | 24 | return 0; 25 | } 26 | 27 | file_descriptor_t *get_file_descriptor(int fd) 28 | { 29 | if (fd < 0 || fd >= 16 || !current_process) 30 | { 31 | return NULL; 32 | } 33 | return current_process->fd_table[fd]; 34 | } 35 | 36 | int alloc_fd(void) 37 | { 38 | if (!current_process) 39 | { 40 | return -ESRCH; 41 | } 42 | 43 | // Find first available file descriptor (starting from 3) 44 | for (int i = 3; i < 16; i++) 45 | { 46 | if (!current_process->fd_table[i]) 47 | { 48 | return i; 49 | } 50 | } 51 | 52 | return -EMFILE; // Too many open files 53 | } 54 | 55 | void free_fd(int fd) 56 | { 57 | if (fd < 0 || fd >= 16 || !current_process) 58 | { 59 | return; 60 | } 61 | 62 | file_descriptor_t *fdesc = current_process->fd_table[fd]; 63 | if (fdesc) 64 | { 65 | fdesc->refcount--; 66 | if (fdesc->refcount <= 0) 67 | { 68 | if (fdesc->close) 69 | { 70 | fdesc->close(fdesc); 71 | } 72 | kfree(fdesc); 73 | } 74 | current_process->fd_table[fd] = NULL; 75 | } 76 | } 77 | 78 | // Initialize the file system 79 | void fs_init(void) 80 | { 81 | // Register MINIX file system 82 | static filesystem_type_t minix_fs = { 83 | .name = "minix", 84 | .fops = &minix_file_ops, 85 | .next = NULL}; 86 | 87 | if (register_filesystem(&minix_fs) < 0) 88 | { 89 | print("Failed to register MINIX file system\n"); 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /includes/ir0/common.h: -------------------------------------------------------------------------------- 1 | #ifndef _IR0_COMMON_H 2 | #define _IR0_COMMON_H 3 | 4 | #include 5 | 6 | // File types 7 | #define S_IFMT 00170000 8 | #define S_IFSOCK 0140000 9 | #define S_IFLNK 0120000 10 | #define S_IFREG 0100000 11 | #define S_IFBLK 0060000 12 | #define S_IFDIR 0040000 13 | #define S_IFCHR 0020000 14 | #define S_IFIFO 0010000 15 | 16 | // File mode bits 17 | #define S_ISUID 0004000 18 | #define S_ISGID 0002000 19 | #define S_ISVTX 0001000 20 | 21 | #define S_IRWXU 0000700 22 | #define S_IRUSR 0000400 23 | #define S_IWUSR 0000200 24 | #define S_IXUSR 0000100 25 | 26 | #define S_IRWXG 0000070 27 | #define S_IRGRP 0000040 28 | #define S_IWGRP 0000020 29 | #define S_IXGRP 0000010 30 | 31 | #define S_IRWXO 0000007 32 | #define S_IROTH 0000004 33 | #define S_IWOTH 0000002 34 | #define S_IXOTH 0000001 35 | 36 | // File type macros 37 | #define S_ISREG(m) (((m) & S_IFMT) == S_IFREG) 38 | #define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR) 39 | #define S_ISCHR(m) (((m) & S_IFMT) == S_IFCHR) 40 | #define S_ISBLK(m) (((m) & S_IFMT) == S_IFBLK) 41 | #define S_ISFIFO(m) (((m) & S_IFMT) == S_IFIFO) 42 | #define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK) 43 | #define S_ISSOCK(m) (((m) & S_IFMT) == S_IFSOCK) 44 | 45 | // File open flags 46 | #define O_RDONLY 00000000 47 | #define O_WRONLY 00000001 48 | #define O_RDWR 00000002 49 | #define O_CREAT 00000100 50 | #define O_EXCL 00000200 51 | #define O_TRUNC 00001000 52 | #define O_APPEND 00002000 53 | #define O_NONBLOCK 00004000 54 | #define O_SYNC 00010000 55 | 56 | // Standard file descriptors 57 | #define STDIN_FILENO 0 58 | #define STDOUT_FILENO 1 59 | #define STDERR_FILENO 2 60 | 61 | // Maximum path length 62 | #define PATH_MAX 256 63 | 64 | // Error codes 65 | #define EPERM 1 66 | #define ENOENT 2 67 | #define ESRCH 3 68 | #define EIO 5 69 | #define EBADF 9 70 | #define EAGAIN 11 71 | #define ENOMEM 12 72 | #define EACCES 13 73 | #define EFAULT 14 74 | #define EEXIST 17 75 | #define ENOTDIR 20 76 | #define EISDIR 21 77 | #define EINVAL 22 78 | #define ENFILE 23 79 | #define EMFILE 24 80 | #define EFBIG 27 81 | #define ENOSPC 28 82 | #define EROFS 30 83 | #define EPIPE 32 84 | 85 | #endif /* _IR0_COMMON_H */ -------------------------------------------------------------------------------- /kernel/init.c: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: GPL-3.0-only */ 2 | /* 3 | * IR0 Kernel - Init Process (PID 1) 4 | * Copyright (C) 2025 Iván Rodriguez 5 | * 6 | * This file is part of the IR0 Operating System. 7 | * Distributed under the terms of the GNU General Public License v3.0. 8 | * See the LICENSE file in the project root for full license information. 9 | * 10 | * First userspace process, runs the shell 11 | */ 12 | 13 | #include "process.h" 14 | #include "shell.h" 15 | #include "rr_sched.h" 16 | #include 17 | #include 18 | #include 19 | #include 20 | 21 | 22 | 23 | void init_1(void) 24 | { 25 | /* Initialize typewriter effect */ 26 | typewriter_init(); 27 | 28 | shell_entry(); 29 | 30 | /* If shell exits, restart it */ 31 | for (;;) 32 | shell_entry(); 33 | } 34 | 35 | /* START INIT 1 PROCESS */ 36 | 37 | int start_init_process(void) 38 | { 39 | process_t *init; 40 | 41 | init = kmalloc(sizeof(process_t)); 42 | if (!init) 43 | return -1; 44 | 45 | memset(init, 0, sizeof(process_t)); 46 | 47 | /* Setup init process */ 48 | init->task.pid = 1; 49 | init->task.rip = (uint64_t)init_1; 50 | init->task.rsp = 0x1000000 + 0x1000 - 8; 51 | init->task.rbp = 0x1000000 + 0x1000; 52 | init->task.rflags = 0x202; 53 | init->task.cs = 0x1B; 54 | init->task.ss = 0x23; 55 | init->task.ds = 0x23; 56 | init->task.es = 0x23; 57 | init->task.fs = 0x23; 58 | init->task.gs = 0x23; 59 | init->task.cr3 = create_process_page_directory(); 60 | 61 | if (!init->task.cr3) 62 | { 63 | kfree(init); 64 | return -1; 65 | } 66 | 67 | init->ppid = 1; 68 | init->state = PROCESS_READY; 69 | init->stack_start = 0x1000000; 70 | init->stack_size = 0x1000; 71 | init->page_directory = (uint64_t *)init->task.cr3; 72 | 73 | /* Initialize current working directory */ 74 | strcpy(init->cwd, "/"); 75 | 76 | /* Set process command name */ 77 | strncpy(init->comm, "init_1", sizeof(init->comm) - 1); 78 | init->comm[sizeof(init->comm) - 1] = '\0'; 79 | 80 | /* Add to scheduler and start */ 81 | rr_add_process(init); 82 | rr_schedule_next(); 83 | 84 | return 0; 85 | } 86 | -------------------------------------------------------------------------------- /drivers/timer/pit/pit.c: -------------------------------------------------------------------------------- 1 | // drivers/timer/pit/pit.c 2 | #include "pit.h" 3 | 4 | // Variable global para ticks del PIT 5 | uint64_t pit_ticks = 0; 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #define PIT_FREC 1193180 14 | 15 | extern void timer_stub(); 16 | 17 | static uint32_t ticks = 0; 18 | 19 | uint32_t get_pit_ticks(void) 20 | { 21 | return ticks; 22 | } 23 | 24 | void increment_pit_ticks(void) 25 | { 26 | ticks++; 27 | } 28 | 29 | // Inicializar PIC (Programmable Interrupt Controller) 30 | void init_pic(void) 31 | { 32 | 33 | // Guardar máscaras actuales (no utilizadas por ahora) 34 | (void)inb(0x21); // Read current mask1 35 | (void)inb(0xA1); // Read current mask2 36 | 37 | 38 | outb(0x21, 0xFF); 39 | outb(0xA1, 0xFF); 40 | 41 | // ICW1: Inicialización 42 | outb(0x20, 0x11); // ICW1 para PIC1 43 | outb(0xA0, 0x11); // ICW1 para PIC2 44 | 45 | // ICW2: Vector offset 46 | outb(0x21, 0x20); // PIC1: IRQ 0-7 -> INT 0x20-0x27 47 | outb(0xA1, 0x28); // PIC2: IRQ 8-15 -> INT 0x28-0x2F 48 | 49 | // ICW3: Cascada 50 | outb(0x21, 0x04); // PIC1: IRQ2 conectado a PIC2 51 | outb(0xA1, 0x02); // PIC2: Cascada a IRQ2 de PIC1 52 | 53 | // ICW4: Modo 8086 54 | outb(0x21, 0x01); // PIC1: Modo 8086 55 | outb(0xA1, 0x01); // PIC2: Modo 8086 56 | 57 | // MODO ESTABLE: Mantener todas las interrupciones deshabilitadas 58 | outb(0x21, 0xFF); // PIC1: Todas deshabilitadas 59 | outb(0xA1, 0xFF); // PIC2: Todas deshabilitadas 60 | 61 | 62 | } 63 | 64 | void init_PIT(uint32_t frequency) 65 | { 66 | 67 | // Inicializar PIC primero 68 | init_pic(); 69 | 70 | // Calcular divisor para la frecuencia deseada 71 | uint32_t divisor = PIT_FREC / frequency; 72 | 73 | 74 | // Configurar PIT 75 | outb(0x43, 0x36); // Comando: canal 0, lohi, modo 3 76 | outb(0x40, divisor & 0xFF); // Byte bajo del divisor 77 | outb(0x40, (divisor >> 8) & 0xFF); // Byte alto del divisor 78 | 79 | // Habilitar interrupción del timer (IRQ 0) 80 | uint8_t mask = inb(0x21); 81 | mask &= ~(1 << 0); // Habilitar IRQ 0 (timer) 82 | outb(0x21, mask); 83 | 84 | } 85 | -------------------------------------------------------------------------------- /.github/workflows/loc-update.yml: -------------------------------------------------------------------------------- 1 | name: Update LOC 2 | 3 | on: 4 | push: 5 | branches: [mainline] 6 | 7 | jobs: 8 | contar-lineas: 9 | runs-on: ubuntu-latest 10 | steps: 11 | - uses: actions/checkout@v3 12 | 13 | - run: sudo apt-get install -y cloc 14 | 15 | # Count lines including Rust (.rs) and C++ (.cpp) files for multi-language kernel 16 | - run: | 17 | echo "Counting lines of code (C, C++, Rust, ASM)..." 18 | cloc --json \ 19 | --include-lang=C,C++,Rust,"Assembly" \ 20 | --by-file-by-lang \ 21 | . > loc.json 22 | echo "LOC count complete" 23 | 24 | 25 | # 🔹 Paso de ping para despertar la API 26 | - run: | 27 | echo "Ping a la API para despertar el server..." 28 | curl -s https://ir0-loc.onrender.com/ || true 29 | sleep 14 30 | 31 | # 🔹 Paso de POST del loc.json 32 | - run: | 33 | echo "Enviando loc.json a la API..." 34 | curl -X POST https://ir0-loc.onrender.com/api/loc \ 35 | -H "Content-Type: application/json" \ 36 | -d @loc.json 37 | 38 | # 🔹 Obtener contribuidores del repositorio 39 | - name: Fetch and send contributors 40 | env: 41 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 42 | run: | 43 | echo "Obteniendo contribuidores del repositorio..." 44 | 45 | # Obtener owner y repo del contexto de GitHub 46 | OWNER="${{ github.repository_owner }}" 47 | REPO="${{ github.event.repository.name }}" 48 | 49 | # Hacer GET a la API de GitHub para obtener contribuidores 50 | curl -s -H "Authorization: token $GITHUB_TOKEN" \ 51 | -H "Accept: application/vnd.github.v3+json" \ 52 | "https://api.github.com/repos/IRodriguez13/IR0/contributors" \ 53 | > contributors.json 54 | 55 | echo "Contribuidores obtenidos, enviando al endpoint Flask..." 56 | 57 | # Enviar JSON de contribuidores al endpoint Flask 58 | curl -X POST https://ir0-loc.onrender.com/api/contributors \ 59 | -H "Content-Type: application/json" \ 60 | -d @contributors.json 61 | 62 | echo "✓ Contribuidores enviados exitosamente" 63 | -------------------------------------------------------------------------------- /arch/x86-64/sources/gdt.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "tss_x64.h" 4 | #include "gdt.h" 5 | 6 | extern tss_t kernel_tss; 7 | 8 | struct gdt_table_struct gdt_table; 9 | 10 | struct gdtr gdt_descriptor; 11 | 12 | void gdt_flush(struct gdtr *gdtr) 13 | { 14 | asm volatile( 15 | "lgdt (%0)\n" 16 | "mov $0x28, %%ax\n" // TSS selector (index 5 << 3) 17 | "ltr %%ax\n" 18 | : 19 | : "r"(gdtr) 20 | : "rax", "memory"); 21 | } 22 | 23 | void update_gdt_tss(uint64_t tss_addr) 24 | { 25 | struct gdt_tss_entry *e = &gdt_table.tss_entry; 26 | 27 | uint16_t limit = sizeof(tss_t) - 1; 28 | 29 | e->limit = limit; 30 | e->base_low = tss_addr & 0xFFFF; 31 | e->base_mid = (tss_addr >> 16) & 0xFF; 32 | e->access = 0x89; // Present, Available TSS 33 | e->gran = 0x00; 34 | e->base_high = (tss_addr >> 24) & 0xFF; 35 | e->base_long = (tss_addr >> 32) & 0xFFFFFFFF; 36 | e->reserved = 0; 37 | } 38 | 39 | void gdt_set_entry(int index, uint32_t base, uint32_t limit, uint8_t access, uint8_t gran) 40 | { 41 | struct gdt_entry *e = &gdt_table.entries[index]; 42 | e->limit = limit & 0xFFFF; 43 | e->base_low = base & 0xFFFF; 44 | e->base_mid = (base >> 16) & 0xFF; 45 | e->access = access; 46 | e->gran = ((limit >> 16) & 0x0F) | (gran & 0xF0); 47 | e->base_high = (base >> 24) & 0xFF; 48 | } 49 | 50 | void gdt_set_tss(uint64_t base, uint16_t limit) 51 | { 52 | struct gdt_tss_entry *e = &gdt_table.tss_entry; 53 | e->limit = limit; 54 | e->base_low = base & 0xFFFF; 55 | e->base_mid = (base >> 16) & 0xFF; 56 | e->access = 0x89; // Present, Available TSS 57 | e->gran = 0x00; 58 | e->base_high = (base >> 24) & 0xFF; 59 | e->base_long = (base >> 32) & 0xFFFFFFFF; 60 | e->reserved = 0; 61 | } 62 | 63 | void gdt_install() 64 | { 65 | gdt_set_entry(0, 0, 0, 0x00, 0x00); // Null 66 | gdt_set_entry(1, 0, 0, 0x9A, 0x20); // Kernel code 67 | gdt_set_entry(2, 0, 0, 0x92, 0x00); // Kernel data 68 | gdt_set_entry(3, 0, 0, 0xFA, 0x20); // User code 69 | gdt_set_entry(4, 0, 0, 0xF2, 0x00); // User data 70 | gdt_set_tss((uint64_t)&kernel_tss, sizeof(tss_t) - 1); 71 | 72 | gdt_descriptor.size = sizeof(gdt_table) - 1; 73 | gdt_descriptor.offset = (uint64_t)&gdt_table; 74 | 75 | gdt_flush(&gdt_descriptor); 76 | } 77 | -------------------------------------------------------------------------------- /kernel/scheduler/scheduler.h: -------------------------------------------------------------------------------- 1 | // kernel/scheduler/scheduler.h - VERSIÓN CORREGIDA 2 | #pragma once 3 | #include "scheduler_types.h" 4 | 5 | // =============================================================================== 6 | // API PÚBLICA UNIFICADA (compatible con código existente) 7 | // =============================================================================== 8 | 9 | void scheduler_init(void); // Inicializar sistema de schedulers 10 | void scheduler_tick(void); // Llamado desde timer interrupt 11 | void add_task(task_t *task); // Agregar tarea al scheduler activo 12 | void scheduler_start(void); // Iniciar ejecución de tareas 13 | void scheduler_main_loop(void); // Loop principal del scheduler - NUNCA RETORNA 14 | 15 | // =============================================================================== 16 | // NUEVAS FUNCIONES DE GESTIÓN 17 | // =============================================================================== 18 | 19 | void scheduler_dispatch_loop(void); // Loop principal del dispatcher 20 | void scheduler_yield(void); // Yield del proceso actual 21 | scheduler_type_t get_active_scheduler(void); // Obtener tipo de scheduler activo 22 | task_t *get_current_task(void); // Obtener tarea actual 23 | void set_current_task_null(void); // Limpiar referencia de tarea actual 24 | void terminate_current_task(void); // Terminar tarea actual y cambiar a siguiente 25 | const char *get_scheduler_name(void); // Obtener nombre del scheduler 26 | void force_scheduler_fallback(void); // Forzar fallback manual 27 | 28 | // =============================================================================== 29 | // FUNCIONES DE DEBUG Y COMPATIBILIDAD 30 | // =============================================================================== 31 | 32 | void dump_scheduler_state(void); // Mostrar estado del scheduler 33 | int scheduler_ready(void); // Verificar si scheduler está listo 34 | 35 | // =============================================================================== 36 | // PARCHE 4: Actualizar task.h - AGREGAR DEFINE FALTANTE 37 | // =============================================================================== 38 | 39 | // kernel/scheduler/task.h - AGREGAR ESTA LÍNEA AL FINAL 40 | #ifndef MAX_TASKS 41 | #define MAX_TASKS 256 // Máximo número de tareas para evitar loops infinitos 42 | #endif -------------------------------------------------------------------------------- /interrupt/arch/isr_handlers.c: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-only 2 | /** 3 | * IR0 Kernel — Core system software 4 | * Copyright (C) 2025 Iván Rodriguez 5 | * 6 | * This file is part of the IR0 Operating System. 7 | * Distributed under the terms of the GNU General Public License v3.0. 8 | * See the LICENSE file in the project root for full license information. 9 | * 10 | * File: isr_handlers.c 11 | * Description: Interrupt Service Routine handlers for exceptions, hardware interrupts, and system calls 12 | */ 13 | 14 | #include "idt.h" 15 | #include "pic.h" 16 | #include "io.h" 17 | #include 18 | #include 19 | 20 | // Declaraciones externas para el nuevo driver de teclado 21 | extern void keyboard_handler64(void); 22 | extern void keyboard_handler32(void); 23 | extern void increment_pit_ticks(void); 24 | #ifdef __x86_64__ 25 | 26 | // Handler de interrupciones para 64-bit 27 | void isr_handler64(uint64_t interrupt_number) 28 | { 29 | // Manejar excepciones del CPU (0-31) 30 | if (interrupt_number < 32) 31 | { 32 | print("Excepción CPU #"); 33 | print_int32(interrupt_number); 34 | print("\n"); 35 | 36 | // Para excepciones, NO enviar EOI 37 | return; 38 | } 39 | 40 | // Manejar syscall (0x80) 41 | if (interrupt_number == 128) 42 | { 43 | print("SYSCALL: Interrupción 0x80 recibida\n"); 44 | return; 45 | } 46 | 47 | // Manejar IRQs del PIC (32-47) 48 | if (interrupt_number >= 32 && interrupt_number <= 47) 49 | { 50 | uint8_t irq = interrupt_number - 32; 51 | 52 | switch (irq) 53 | { 54 | case 0: // Timer 55 | { 56 | 57 | increment_pit_ticks(); 58 | 59 | static int tick_counter = 0; 60 | tick_counter++; 61 | 62 | // Cada 10 ticks (~10ms si PIT=1kHz), hacer cambio de proceso 63 | if (tick_counter >= 10) 64 | { 65 | tick_counter = 0; 66 | rr_schedule_next(); 67 | } 68 | 69 | break; 70 | } 71 | 72 | case 1: // Keyboard 73 | keyboard_handler64(); 74 | break; 75 | 76 | default: 77 | break; 78 | } 79 | 80 | // Enviar EOI para IRQs 81 | pic_send_eoi64(irq); 82 | return; 83 | } 84 | 85 | } 86 | 87 | #endif 88 | -------------------------------------------------------------------------------- /kernel/scheduler/switch/debug.asm: -------------------------------------------------------------------------------- 1 | ; Debug utilities for context switching 2 | 3 | extern serial_print 4 | extern serial_print_hex64 5 | 6 | ; Save all registers to stack 7 | %macro SAVE_REGS 0 8 | push rax 9 | push rbx 10 | push rcx 11 | push rdx 12 | push rsi 13 | push rdi 14 | push rbp 15 | push r8 16 | push r9 17 | push r10 18 | push r11 19 | push r12 20 | push r13 21 | push r14 22 | push r15 23 | pushfq 24 | %endmacro 25 | 26 | ; Restore all registers from stack 27 | %macro RESTORE_REGS 0 28 | popfq 29 | pop r15 30 | pop r14 31 | pop r13 32 | pop r12 33 | pop r11 34 | pop r10 35 | pop r9 36 | pop r8 37 | pop rbp 38 | pop rdi 39 | pop rsi 40 | pop rdx 41 | pop rcx 42 | pop rbx 43 | pop rax 44 | %endmacro 45 | 46 | ; Print register value 47 | %macro PRINT_REG 2 48 | push rdi 49 | push rsi 50 | push rdx 51 | push rcx 52 | push rax 53 | 54 | lea rdi, [%1_msg] 55 | call serial_print 56 | 57 | mov rdi, %2 58 | call serial_print_hex64 59 | 60 | lea rdi, [newline] 61 | call serial_print 62 | 63 | pop rax 64 | pop rcx 65 | pop rdx 66 | pop rsi 67 | pop rdi 68 | %endmacro 69 | 70 | section .rodata 71 | cr3_msg: db "CR3: ", 0 72 | rip_msg: db "RIP: ", 0 73 | rsp_msg: db "RSP: ", 0 74 | rbp_msg: db "RBP: ", 0 75 | newline: db 0x0A, 0x00 76 | 77 | section .text 78 | 79 | ; void debug_print_context(const char* msg, task_t* task) 80 | global debug_print_context 81 | debug_print_context: 82 | SAVE_REGS 83 | 84 | ; Save message 85 | mov r15, rdi ; message 86 | mov r14, rsi ; task 87 | 88 | ; Print message 89 | mov rdi, r15 90 | call serial_print 91 | 92 | ; Print PID if available 93 | test r14, r14 94 | jz .no_task 95 | 96 | mov rdi, [r14 + 0x28] ; task.pid 97 | call serial_print_hex64 98 | 99 | mov rdi, newline 100 | call serial_print 101 | 102 | ; Print important registers 103 | PRINT_REG cr3, [r14 + 0xB0] ; task.cr3 104 | PRINT_REG rip, [r14 + 0x80] ; task.rip 105 | PRINT_REG rsp, [r14 + 0x70] ; task.rsp 106 | PRINT_REG rbp, [r14 + 0x78] ; task.rbp 107 | 108 | .no_task: 109 | RESTORE_REGS 110 | ret 111 | -------------------------------------------------------------------------------- /interrupt/arch/x86-32/isr_stubs_32.asm: -------------------------------------------------------------------------------- 1 | ; Stubs de interrupción completos para x86-32 2 | ; Implementación desde cero - limpia y funcional 3 | 4 | extern isr_handler32 5 | 6 | ; Macro para stubs sin código de error 7 | %macro ISR_NOERRCODE 1 8 | global isr%1_32 9 | isr%1_32: 10 | cli 11 | push byte 0 12 | push byte %1 13 | jmp isr_common_stub_32 14 | %endmacro 15 | 16 | ; Macro para stubs con código de error 17 | %macro ISR_ERRCODE 1 18 | global isr%1_32 19 | isr%1_32: 20 | cli 21 | push byte %1 22 | jmp isr_common_stub_32 23 | %endmacro 24 | 25 | ; Generar stubs para excepciones (0-31) 26 | ISR_NOERRCODE 0 27 | ISR_NOERRCODE 1 28 | ISR_NOERRCODE 2 29 | ISR_NOERRCODE 3 30 | ISR_NOERRCODE 4 31 | ISR_NOERRCODE 5 32 | ISR_NOERRCODE 6 33 | ISR_NOERRCODE 7 34 | ISR_ERRCODE 8 35 | ISR_NOERRCODE 9 36 | ISR_ERRCODE 10 37 | ISR_ERRCODE 11 38 | ISR_ERRCODE 12 39 | ISR_ERRCODE 13 40 | ISR_ERRCODE 14 41 | ISR_NOERRCODE 15 42 | ISR_NOERRCODE 16 43 | ISR_ERRCODE 17 44 | ISR_NOERRCODE 18 45 | ISR_NOERRCODE 19 46 | ISR_NOERRCODE 20 47 | ISR_NOERRCODE 21 48 | ISR_NOERRCODE 22 49 | ISR_NOERRCODE 23 50 | ISR_NOERRCODE 24 51 | ISR_NOERRCODE 25 52 | ISR_NOERRCODE 26 53 | ISR_NOERRCODE 27 54 | ISR_NOERRCODE 28 55 | ISR_NOERRCODE 29 56 | ISR_NOERRCODE 30 57 | ISR_NOERRCODE 31 58 | 59 | ; Generar stubs para IRQs (32-47) 60 | ISR_NOERRCODE 32 61 | ISR_NOERRCODE 33 62 | ISR_NOERRCODE 34 63 | ISR_NOERRCODE 35 64 | ISR_NOERRCODE 36 65 | ISR_NOERRCODE 37 66 | ISR_NOERRCODE 38 67 | ISR_NOERRCODE 39 68 | ISR_NOERRCODE 40 69 | ISR_NOERRCODE 41 70 | ISR_NOERRCODE 42 71 | ISR_NOERRCODE 43 72 | ISR_NOERRCODE 44 73 | ISR_NOERRCODE 45 74 | ISR_NOERRCODE 46 75 | ISR_NOERRCODE 47 76 | 77 | ; Handler común completo 78 | isr_common_stub_32: 79 | ; Guardar todos los registros 80 | push eax 81 | push ecx 82 | push edx 83 | push ebx 84 | push ebp 85 | push esi 86 | push edi 87 | 88 | ; Llamar al handler C 89 | ; El número de interrupción está en [esp + 28] 90 | mov eax, [esp + 28] 91 | push eax 92 | call isr_handler32 93 | add esp, 4 94 | 95 | ; Restaurar todos los registros 96 | pop edi 97 | pop esi 98 | pop ebp 99 | pop ebx 100 | pop edx 101 | pop ecx 102 | pop eax 103 | 104 | ; Limpiar stack (código de error y número de interrupción) 105 | add esp, 8 106 | 107 | ; Habilitar interrupciones y retornar 108 | sti 109 | iret 110 | -------------------------------------------------------------------------------- /kernel/syscalls_internal.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: GPL-3.0-only */ 2 | /* 3 | * IR0 Kernel - System Call Implementations 4 | * Copyright (C) 2025 Iván Rodriguez 5 | * 6 | * Internal syscall implementation functions 7 | * These are called by the syscall dispatcher 8 | */ 9 | 10 | #pragma once 11 | 12 | #include 13 | #include 14 | #include 15 | 16 | /* Type definitions */ 17 | typedef uint32_t mode_t; 18 | 19 | /* ========================================================================== */ 20 | /* PROCESS MANAGEMENT */ 21 | /* ========================================================================== */ 22 | 23 | int64_t sys_exit(int exit_code); 24 | int64_t sys_fork(void); 25 | int64_t sys_wait4(int pid, int *status, int options, void *rusage); 26 | int64_t sys_getpid(void); 27 | int64_t sys_getppid(void); 28 | 29 | /* ========================================================================== */ 30 | /* FILE OPERATIONS */ 31 | /* ========================================================================== */ 32 | 33 | int64_t sys_read(int fd, void *buf, size_t count); 34 | int64_t sys_write(int fd, const void *buf, size_t count); 35 | int64_t sys_open(const char *pathname, int flags, mode_t mode); 36 | int64_t sys_close(int fd); 37 | int64_t sys_lseek(int fd, off_t offset, int whence); 38 | 39 | /* ========================================================================== */ 40 | /* FILE SYSTEM */ 41 | /* ========================================================================== */ 42 | 43 | int64_t sys_stat(const char *pathname, stat_t *buf); 44 | int64_t sys_fstat(int fd, stat_t *buf); 45 | int64_t sys_mkdir(const char *pathname, mode_t mode); 46 | int64_t sys_rmdir(const char *pathname); 47 | int64_t sys_ls(const char *pathname); 48 | int64_t sys_chdir(const char *pathname); 49 | int64_t sys_getcwd(char *buf, size_t size); 50 | int64_t sys_unlink(const char *pathname); 51 | 52 | /* ========================================================================== */ 53 | /* MEMORY MANAGEMENT */ 54 | /* ========================================================================== */ 55 | 56 | int64_t sys_brk(void *addr); 57 | int64_t sys_mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset); 58 | int64_t sys_munmap(void *addr, size_t length); 59 | -------------------------------------------------------------------------------- /include/kernel/fs/file.h: -------------------------------------------------------------------------------- 1 | #ifndef KERNEL_FS_FILE_H 2 | #define KERNEL_FS_FILE_H 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | // File descriptor flags 9 | #define FD_CLOEXEC 0x0001 // Close on exec 10 | 11 | // File status flags (compatibles con O_*) 12 | #define O_RDONLY 0x0000 // Open for reading only 13 | #define O_WRONLY 0x0001 // Open for writing only 14 | #define O_RDWR 0x0002 // Open for reading and writing 15 | #define O_ACCMODE 0x0003 // Mask for access modes 16 | #define O_CREAT 0x0040 // Create file if it doesn't exist 17 | #define O_EXCL 0x0080 // Fail if file already exists (with O_CREAT) 18 | #define O_TRUNC 0x0200 // Truncate file to zero length if it exists 19 | #define O_APPEND 0x0400 // Append to the end of file on each write 20 | 21 | // File types 22 | #define FT_NONE 0 // No file 23 | #define FT_REGULAR 1 // Regular file 24 | #define FT_DIR 2 // Directory 25 | #define FT_DEVICE 3 // Character/block device 26 | 27 | // File descriptor structure 28 | typedef struct file_descriptor { 29 | int fd; // File descriptor number 30 | int flags; // File status flags 31 | off_t offset; // Current file offset 32 | int refcount; // Reference count 33 | int type; // File type (FT_*) 34 | void *data; // File-specific data (e.g., inode) 35 | 36 | // File operations 37 | ssize_t (*read)(struct file_descriptor *fd, void *buf, size_t count); 38 | ssize_t (*write)(struct file_descriptor *fd, const void *buf, size_t count); 39 | off_t (*lseek)(struct file_descriptor *fd, off_t offset, int whence); 40 | int (*close)(struct file_descriptor *fd); 41 | } file_descriptor_t; 42 | 43 | // File system operations 44 | typedef struct file_operations { 45 | ssize_t (*read)(file_descriptor_t *fd, void *buf, size_t count); 46 | ssize_t (*write)(file_descriptor_t *fd, const void *buf, size_t count); 47 | off_t (*lseek)(file_descriptor_t *fd, off_t offset, int whence); 48 | int (*open)(file_descriptor_t *fd, const char *path, int flags, mode_t mode); 49 | int (*close)(file_descriptor_t *fd); 50 | } file_operations_t; 51 | 52 | // File system type 53 | typedef struct filesystem_type { 54 | const char *name; 55 | file_operations_t *fops; 56 | struct filesystem_type *next; 57 | } filesystem_type_t; 58 | 59 | // File system operations for MINIX 60 | extern file_operations_t minix_file_ops; 61 | 62 | // File system functions 63 | int register_filesystem(filesystem_type_t *fs); 64 | file_descriptor_t *get_file_descriptor(int fd); 65 | int alloc_fd(void); 66 | void free_fd(int fd); 67 | 68 | #endif // KERNEL_FS_FILE_H 69 | -------------------------------------------------------------------------------- /arch/common/idt.h: -------------------------------------------------------------------------------- 1 | // arch/common/idt.h - REFACTORIZADO (detección automática) 2 | #pragma once 3 | #include 4 | 5 | #define IDT_ENTRIES 256 6 | #define IDT_INTERRUPT_GATE_KERNEL 0x8E 7 | #define IDT_INTERRUPT_GATE_USER 0xEE 8 | #define IDT_TRAP_GATE_KERNEL 0x8F 9 | 10 | // =============================================================================== 11 | // DETECCIÓN AUTOMÁTICA DE ARQUITECTURA Y DEFINICIONES ESPECÍFICAS 12 | // =============================================================================== 13 | 14 | #if defined(__x86_64__) || defined(__amd64__) 15 | // ===== ARQUITECTURA 64-BIT ===== 16 | typedef struct 17 | { 18 | uint16_t offset_low; // Bits 0-15 del offset 19 | uint16_t selector; // Selector de segmento 20 | uint8_t ist; // Interrupt Stack Table (solo 64-bit) 21 | uint8_t type_attr; // Tipo y atributos 22 | uint16_t offset_mid; // Bits 16-31 del offset 23 | uint32_t offset_high; // Bits 32-63 del offset (solo 64-bit) 24 | uint32_t zero; // Reservado (debe ser 0) 25 | } __attribute__((packed)) idt_entry_t; 26 | 27 | typedef struct 28 | { 29 | uint16_t limit; 30 | uintptr_t base; // 64-bit address 31 | } __attribute__((packed)) idt_ptr_t; 32 | 33 | // Función específica para 64-bit 34 | void idt_arch_set_gate_64(int n, uintptr_t handler, uint8_t flags); 35 | #define idt_set_gate(n, handler, flags) idt_arch_set_gate_64(n, handler, flags) 36 | 37 | #elif defined(__i386__) || defined(__i486__) || defined(__i586__) || defined(__i686__) 38 | // ===== ARQUITECTURA 32-BIT ===== 39 | typedef struct 40 | { 41 | uint16_t offset_low; // Bits 0-15 del offset 42 | uint16_t selector; // Selector de segmento 43 | uint8_t zero; // Siempre 0 en x86-32 44 | uint8_t type_attr; // Tipo y atributos 45 | uint16_t offset_high; // Bits 16-31 del offset 46 | } __attribute__((packed)) idt_entry_t; 47 | 48 | typedef struct 49 | { 50 | uint16_t limit; 51 | uint32_t base; // 32-bit address 52 | } __attribute__((packed)) idt_ptr_t; 53 | 54 | // Función específica para 32-bit 55 | void idt_arch_set_gate_32(int n, uintptr_t handler, uint8_t flags); 56 | #define idt_set_gate(n, handler, flags) idt_arch_set_gate_32(n, handler, flags) 57 | 58 | #else 59 | #error "Arquitectura no soportada para IDT" 60 | #endif 61 | 62 | // =============================================================================== 63 | // FUNCIONES COMUNES (independientes de arquitectura) 64 | // =============================================================================== 65 | 66 | void idt_init(); 67 | 68 | // Funciones ASM específicas (declaradas extern) 69 | extern void idt_flush(uintptr_t); 70 | extern void isr_default(void); 71 | extern void isr_page_fault(void); 72 | extern void timer_stub(void); -------------------------------------------------------------------------------- /interrupt/arch/idt_32.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | // Estructura de entrada IDT para 32-bit 5 | struct idt_entry32 6 | { 7 | uint16_t offset_low; // Bits 0-15 del offset 8 | uint16_t selector; // Selector del segmento 9 | uint8_t zero; // Siempre 0 en 32-bit 10 | uint8_t flags; // Tipo y privilegios 11 | uint16_t offset_high; // Bits 16-31 del offset 12 | } __attribute__((packed)); 13 | 14 | // Puntero IDT para 32-bit 15 | struct idt_ptr32 16 | { 17 | uint16_t limit; 18 | uint32_t base; 19 | } __attribute__((packed)); 20 | 21 | // Declaraciones de funciones específicas para 32-bit 22 | void idt_init32(void); 23 | void idt_load32(void); 24 | void idt_set_gate32(uint8_t num, uint32_t base, uint16_t sel, uint8_t flags); 25 | 26 | // Handler de interrupciones para 32-bit 27 | void isr_handler32(uint32_t interrupt_number); 28 | 29 | // Funciones PIC para 32-bit 30 | void pic_remap32(void); 31 | void pic_send_eoi32(uint8_t irq); 32 | 33 | // Funciones de teclado para 32-bit 34 | void keyboard_handler32(void); 35 | 36 | // Declaraciones de stubs de interrupción para 32-bit 37 | extern void isr0_32(void); 38 | extern void isr1_32(void); 39 | extern void isr2_32(void); 40 | extern void isr3_32(void); 41 | extern void isr4_32(void); 42 | extern void isr5_32(void); 43 | extern void isr6_32(void); 44 | extern void isr7_32(void); 45 | extern void isr8_32(void); 46 | extern void isr9_32(void); 47 | extern void isr10_32(void); 48 | extern void isr11_32(void); 49 | extern void isr12_32(void); 50 | extern void isr13_32(void); 51 | extern void isr14_32(void); 52 | extern void isr15_32(void); 53 | extern void isr16_32(void); 54 | extern void isr17_32(void); 55 | extern void isr18_32(void); 56 | extern void isr19_32(void); 57 | extern void isr20_32(void); 58 | extern void isr21_32(void); 59 | extern void isr22_32(void); 60 | extern void isr23_32(void); 61 | extern void isr24_32(void); 62 | extern void isr25_32(void); 63 | extern void isr26_32(void); 64 | extern void isr27_32(void); 65 | extern void isr28_32(void); 66 | extern void isr29_32(void); 67 | extern void isr30_32(void); 68 | extern void isr31_32(void); 69 | extern void isr32_32(void); 70 | extern void isr33_32(void); 71 | extern void isr34_32(void); 72 | extern void isr35_32(void); 73 | extern void isr36_32(void); 74 | extern void isr37_32(void); 75 | extern void isr38_32(void); 76 | extern void isr39_32(void); 77 | extern void isr40_32(void); 78 | extern void isr41_32(void); 79 | extern void isr42_32(void); 80 | extern void isr43_32(void); 81 | extern void isr44_32(void); 82 | extern void isr45_32(void); 83 | extern void isr46_32(void); 84 | extern void isr47_32(void); 85 | 86 | // Variables globales para 32-bit 87 | extern struct idt_entry32 idt[256]; 88 | extern struct idt_ptr32 idt_ptr; 89 | 90 | -------------------------------------------------------------------------------- /drivers/storage/ata.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | // ATA I/O ports 7 | #define ATA_PRIMARY_DATA 0x1F0 8 | #define ATA_PRIMARY_ERROR 0x1F1 9 | #define ATA_PRIMARY_FEATURES 0x1F1 10 | #define ATA_PRIMARY_SECTOR_COUNT 0x1F2 11 | #define ATA_PRIMARY_LBA_LOW 0x1F3 12 | #define ATA_PRIMARY_LBA_MID 0x1F4 13 | #define ATA_PRIMARY_LBA_HIGH 0x1F5 14 | #define ATA_PRIMARY_DRIVE_HEAD 0x1F6 15 | #define ATA_PRIMARY_STATUS 0x1F7 16 | #define ATA_PRIMARY_COMMAND 0x1F7 17 | 18 | #define ATA_SECONDARY_DATA 0x170 19 | #define ATA_SECONDARY_ERROR 0x171 20 | #define ATA_SECONDARY_FEATURES 0x171 21 | #define ATA_SECONDARY_SECTOR_COUNT 0x172 22 | #define ATA_SECONDARY_LBA_LOW 0x173 23 | #define ATA_SECONDARY_LBA_MID 0x174 24 | #define ATA_SECONDARY_LBA_HIGH 0x175 25 | #define ATA_SECONDARY_DRIVE_HEAD 0x176 26 | #define ATA_SECONDARY_STATUS 0x177 27 | #define ATA_SECONDARY_COMMAND 0x177 28 | 29 | // ATA Commands 30 | #define ATA_CMD_READ_SECTORS 0x20 31 | #define ATA_CMD_WRITE_SECTORS 0x30 32 | #define ATA_CMD_IDENTIFY 0xEC 33 | #define ATA_CMD_FLUSH_CACHE 0xE7 34 | 35 | // ATA Status register bits 36 | #define ATA_STATUS_ERR 0x01 37 | #define ATA_STATUS_IDX 0x02 38 | #define ATA_STATUS_CORR 0x04 39 | #define ATA_STATUS_DRQ 0x08 40 | #define ATA_STATUS_SRV 0x10 41 | #define ATA_STATUS_DF 0x20 42 | #define ATA_STATUS_RDY 0x40 43 | #define ATA_STATUS_BSY 0x80 44 | 45 | // Drive selection 46 | #define ATA_DRIVE_MASTER 0xA0 47 | #define ATA_DRIVE_SLAVE 0xB0 48 | 49 | // Sector size 50 | #define ATA_SECTOR_SIZE 512 51 | 52 | // ATA device information structure 53 | typedef struct { 54 | bool present; 55 | bool is_atapi; 56 | uint64_t size; // Size in sectors 57 | uint64_t capacity_bytes; // Device capacity in bytes 58 | char model[41]; // NUL-terminated model string 59 | char serial[21]; // NUL-terminated serial number string 60 | uint16_t sectors_per_intr; // Sectors per interrupt (for multi-sector transfers) 61 | } ata_device_info_t; 62 | 63 | // Global variables 64 | extern bool ata_drives_present[4]; // Primary master, primary slave, secondary master, secondary slave 65 | extern ata_device_info_t ata_devices[4]; 66 | 67 | // Core ATA functions 68 | void ata_init(void); 69 | bool ata_is_available(void); 70 | bool ata_drive_present(uint8_t drive); 71 | bool ata_identify_drive(uint8_t drive); 72 | bool ata_read_sectors(uint8_t drive, uint32_t lba, uint8_t num_sectors, void* buffer); 73 | bool ata_write_sectors(uint8_t drive, uint32_t lba, uint8_t num_sectors, const void* buffer); 74 | bool ata_wait_ready(uint8_t drive); 75 | bool ata_wait_drq(uint8_t drive); 76 | void ata_reset_drive(uint8_t drive); 77 | bool ata_get_device_info(uint8_t drive, ata_device_info_t *out); 78 | 79 | // Helper functions 80 | uint64_t ata_get_size(uint8_t drive); 81 | const char* ata_get_model(uint8_t drive); 82 | const char* ata_get_serial(uint8_t drive); 83 | 84 | 85 | -------------------------------------------------------------------------------- /interrupt/arch/x86-32/interrupt.asm: -------------------------------------------------------------------------------- 1 | ; interrupt/arch/x86-32/interrupt.asm - IMPLEMENTACIÓN MÍNIMA Y FUNCIONAL 2 | BITS 32 3 | 4 | ; Variables globales 5 | extern isr_handler 6 | 7 | ; Macro para crear stubs sin error code 8 | %macro ISR_NOERRCODE 1 9 | global isr_stub_%1 10 | isr_stub_%1: 11 | cli ; Deshabilitar interrupciones 12 | push dword 0 ; Error code dummy 13 | push dword %1 ; Número de interrupción 14 | jmp isr_common_stub 15 | %endmacro 16 | 17 | ; Macro para crear stubs con error code 18 | %macro ISR_ERRCODE 1 19 | global isr_stub_%1 20 | isr_stub_%1: 21 | cli ; Deshabilitar interrupciones 22 | push dword %1 ; Número de interrupción 23 | jmp isr_common_stub 24 | %endmacro 25 | 26 | ; Crear todos los stubs 27 | ISR_NOERRCODE 0 ; Divide by zero 28 | ISR_NOERRCODE 1 ; Debug 29 | ISR_NOERRCODE 2 ; Non-maskable interrupt 30 | ISR_NOERRCODE 3 ; Breakpoint 31 | ISR_NOERRCODE 4 ; Overflow 32 | ISR_NOERRCODE 5 ; Bound range exceeded 33 | ISR_NOERRCODE 6 ; Invalid opcode 34 | ISR_NOERRCODE 7 ; Device not available 35 | ISR_ERRCODE 8 ; Double fault 36 | ISR_NOERRCODE 9 ; Coprocessor segment overrun 37 | ISR_ERRCODE 10 ; Invalid TSS 38 | ISR_ERRCODE 11 ; Segment not present 39 | ISR_ERRCODE 12 ; Stack segment fault 40 | ISR_ERRCODE 13 ; General protection fault 41 | ISR_ERRCODE 14 ; Page fault 42 | ISR_NOERRCODE 15 ; Reserved 43 | ISR_NOERRCODE 16 ; x87 FPU error 44 | ISR_ERRCODE 17 ; Alignment check 45 | ISR_NOERRCODE 18 ; Machine check 46 | ISR_NOERRCODE 19 ; SIMD FPU error 47 | ISR_NOERRCODE 20 ; Virtualization error 48 | ISR_NOERRCODE 21 ; Reserved 49 | ISR_NOERRCODE 22 ; Reserved 50 | ISR_NOERRCODE 23 ; Reserved 51 | ISR_NOERRCODE 24 ; Reserved 52 | ISR_NOERRCODE 25 ; Reserved 53 | ISR_NOERRCODE 26 ; Reserved 54 | ISR_NOERRCODE 27 ; Reserved 55 | ISR_NOERRCODE 28 ; Reserved 56 | ISR_NOERRCODE 29 ; Reserved 57 | ISR_NOERRCODE 30 ; Security exception 58 | ISR_NOERRCODE 31 ; Reserved 59 | 60 | ; IRQs 61 | ISR_NOERRCODE 32 ; Timer 62 | ISR_NOERRCODE 33 ; Keyboard 63 | 64 | ; Stub común para todas las interrupciones 65 | isr_common_stub: 66 | ; Guardar todos los registros 67 | push eax 68 | push ecx 69 | push edx 70 | push ebx 71 | push ebp 72 | push esi 73 | push edi 74 | 75 | ; Llamar al handler C 76 | mov eax, [esp + 28] ; Obtener número de interrupción 77 | push eax 78 | call isr_handler 79 | add esp, 4 80 | 81 | ; Restaurar registros 82 | pop edi 83 | pop esi 84 | pop ebp 85 | pop ebx 86 | pop edx 87 | pop ecx 88 | pop eax 89 | 90 | ; Limpiar error code y número de interrupción 91 | add esp, 8 92 | 93 | ; Restaurar interrupciones y retornar 94 | sti 95 | iret 96 | 97 | ; Función para cargar IDT 98 | global idt_load 99 | idt_load: 100 | mov eax, [esp + 4] ; Parámetro pasado en stack 101 | lidt [eax] ; Cargar IDT 102 | ret -------------------------------------------------------------------------------- /drivers/net/rtl8139.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: GPL-3.0-only */ 2 | /** 3 | * IR0 Kernel — Core system software 4 | * Copyright (C) 2025 Iván Rodriguez 5 | * 6 | * This file is part of the IR0 Operating System. 7 | * Distributed under the terms of the GNU General Public License v3.0. 8 | * See the LICENSE file in the project root for full license information. 9 | * 10 | * File: rtl8139.h 11 | * Description: RTL8139 network card driver definitions 12 | */ 13 | 14 | #pragma once 15 | 16 | #include 17 | #include 18 | 19 | /* PCI definitions for RTL8139 */ 20 | #define RTL8139_VENDOR_ID 0x10EC 21 | #define RTL8139_DEVICE_ID 0x8139 22 | 23 | /* RTL8139 Registers */ 24 | #define RTL8139_REG_MAC0 0x00 /* MAC Address */ 25 | #define RTL8139_REG_MAR0 0x08 /* Multicast Filter */ 26 | #define RTL8139_REG_TSD0 0x10 /* Transmit Status Descriptor 0 */ 27 | #define RTL8139_REG_TSAD0 0x20 /* Transmit Start Address Descriptor 0 */ 28 | #define RTL8139_REG_RBSTART 0x30 /* Receive Buffer Start Address */ 29 | #define RTL8139_REG_CR 0x37 /* Command Register */ 30 | #define RTL8139_REG_CAPR 0x38 /* Current Address of Packet Read */ 31 | #define RTL8139_REG_IMR 0x3C /* Interrupt Mask Register */ 32 | #define RTL8139_REG_ISR 0x3E /* Interrupt Status Register */ 33 | #define RTL8139_REG_TCR 0x40 /* Transmit Configuration Register */ 34 | #define RTL8139_REG_RCR 0x44 /* Receive Configuration Register */ 35 | #define RTL8139_REG_CONFIG1 0x52 /* Configuration Register 1 */ 36 | 37 | /* Command Register bits */ 38 | #define RTL8139_CR_BUFE (1 << 0) /* Buffer Empty */ 39 | #define RTL8139_CR_TE (1 << 2) /* Transmitter Enable */ 40 | #define RTL8139_CR_RE (1 << 3) /* Receiver Enable */ 41 | #define RTL8139_CR_RST (1 << 4) /* Software Reset */ 42 | 43 | /* Interrupt Status/Mask Register bits */ 44 | #define RTL8139_INT_ROK (1 << 0) /* Receive OK */ 45 | #define RTL8139_INT_RER (1 << 1) /* Receive Error */ 46 | #define RTL8139_INT_TOK (1 << 2) /* Transmit OK */ 47 | #define RTL8139_INT_TER (1 << 3) /* Transmit Error */ 48 | 49 | /* Receive Configuration Register bits */ 50 | #define RTL8139_RCR_AAP (1 << 0) /* Accept All Packets */ 51 | #define RTL8139_RCR_APM (1 << 1) /* Accept Physical Match */ 52 | #define RTL8139_RCR_AM (1 << 2) /* Accept Multicast */ 53 | #define RTL8139_RCR_AB (1 << 3) /* Accept Broadcast */ 54 | #define RTL8139_RCR_WRAP (1 << 7) /* Wrap around */ 55 | 56 | /* Transmit Status Descriptor bits */ 57 | #define RTL8139_TSD_SIZE_MASK 0x1FFF /* Packet size mask */ 58 | #define RTL8139_TSD_OWN (1 << 13) /* DMA operation completed */ 59 | 60 | /* Public API */ 61 | int rtl8139_init(void); 62 | void rtl8139_send(void *data, size_t len); 63 | void rtl8139_handle_interrupt(void); 64 | void rtl8139_get_mac(uint8_t mac[6]); 65 | -------------------------------------------------------------------------------- /userspace/bin/libctest.c: -------------------------------------------------------------------------------- 1 | // libctest.c - Test program for new libc functions 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | void test_strtok() { 8 | printf("Testing strtok...\n"); 9 | char str[] = "Hello,World,IR0"; 10 | const char *delim = ","; 11 | char *token; 12 | 13 | token = strtok(str, delim); 14 | while (token != NULL) { 15 | printf("Token: %s\n", token); 16 | token = strtok(NULL, delim); 17 | } 18 | } 19 | 20 | void test_atoi() { 21 | printf("Testing atoi...\n"); 22 | const char *s1 = "123"; 23 | const char *s2 = "-456"; 24 | const char *s3 = " 789"; 25 | 26 | printf("atoi('%s') = %d\n", s1, atoi(s1)); 27 | printf("atoi('%s') = %d\n", s2, atoi(s2)); 28 | printf("atoi('%s') = %d\n", s3, atoi(s3)); 29 | } 30 | 31 | void test_strtod() { 32 | printf("Testing strtod...\n"); 33 | const char *s1 = "123.456"; 34 | const char *s2 = "-78.90"; 35 | const char *s3 = "1.23e2"; 36 | char *endptr; 37 | 38 | // Note: printf %f might not be fully supported if I didn't verify it, 39 | // but let's try. If not, we can print parts. 40 | // Looking at stdio.c, printf only supports %d, %s, %c, %. 41 | // So I can't print doubles with printf yet! 42 | // I should probably implement a simple print_double or just cast to int for verification. 43 | 44 | double d1 = strtod(s1, &endptr); 45 | double d2 = strtod(s2, &endptr); 46 | double d3 = strtod(s3, &endptr); 47 | 48 | printf("strtod('%s') = %d (approx)\n", s1, (int)d1); 49 | printf("strtod('%s') = %d (approx)\n", s2, (int)d2); 50 | printf("strtod('%s') = %d (approx)\n", s3, (int)d3); 51 | } 52 | 53 | void test_malloc_free() { 54 | printf("Testing malloc/free...\n"); 55 | 56 | // Test 1: Simple allocation 57 | int *p1 = (int*)malloc(sizeof(int) * 10); 58 | if (!p1) { 59 | printf("malloc failed\n"); 60 | return; 61 | } 62 | for (int i = 0; i < 10; i++) p1[i] = i; 63 | printf("p1[5] = %d\n", p1[5]); 64 | 65 | // Test 2: Another allocation 66 | char *p2 = (char*)malloc(100); 67 | if (!p2) { 68 | printf("malloc p2 failed\n"); 69 | return; 70 | } 71 | strcpy(p2, "Hello Malloc"); 72 | printf("p2: %s\n", p2); 73 | 74 | // Test 3: Free and reuse 75 | free(p1); 76 | 77 | int *p3 = (int*)malloc(sizeof(int) * 5); // Should fit in p1's old spot 78 | if (!p3) { 79 | printf("malloc p3 failed\n"); 80 | return; 81 | } 82 | p3[0] = 999; 83 | printf("p3[0] = %d\n", p3[0]); 84 | 85 | // Check if p3 is same address as p1 (reuse) 86 | if (p3 == p1) { 87 | printf("Memory reused successfully!\n"); 88 | } else { 89 | printf("Memory not reused (might be split or new block)\n"); 90 | } 91 | 92 | free(p2); 93 | free(p3); 94 | printf("Malloc/Free tests done\n"); 95 | } 96 | 97 | int main() { 98 | printf("Starting libc tests\n"); 99 | 100 | test_strtok(); 101 | test_atoi(); 102 | test_strtod(); 103 | test_malloc_free(); 104 | 105 | printf("Tests finished\n"); 106 | return 0; 107 | } 108 | -------------------------------------------------------------------------------- /interrupt/arch/x86-64/interrupt.asm: -------------------------------------------------------------------------------- 1 | ; interrupt/arch/x86-64/interrupt.asm - IMPLEMENTACIÓN MÍNIMA Y FUNCIONAL 2 | BITS 64 3 | 4 | ; Variables globales 5 | extern isr_handler 6 | 7 | ; Macro para crear stubs sin error code 8 | %macro ISR_NOERRCODE 1 9 | global isr_stub_%1 10 | isr_stub_%1: 11 | cli ; Deshabilitar interrupciones 12 | push qword 0 ; Error code dummy 13 | push qword %1 ; Número de interrupción 14 | jmp isr_common_stub 15 | %endmacro 16 | 17 | ; Macro para crear stubs con error code 18 | %macro ISR_ERRCODE 1 19 | global isr_stub_%1 20 | isr_stub_%1: 21 | cli ; Deshabilitar interrupciones 22 | push qword %1 ; Número de interrupción 23 | jmp isr_common_stub 24 | %endmacro 25 | 26 | ; Crear todos los stubs 27 | ISR_NOERRCODE 0 ; Divide by zero 28 | ISR_NOERRCODE 1 ; Debug 29 | ISR_NOERRCODE 2 ; Non-maskable interrupt 30 | ISR_NOERRCODE 3 ; Breakpoint 31 | ISR_NOERRCODE 4 ; Overflow 32 | ISR_NOERRCODE 5 ; Bound range exceeded 33 | ISR_NOERRCODE 6 ; Invalid opcode 34 | ISR_NOERRCODE 7 ; Device not available 35 | ISR_ERRCODE 8 ; Double fault 36 | ISR_NOERRCODE 9 ; Coprocessor segment overrun 37 | ISR_ERRCODE 10 ; Invalid TSS 38 | ISR_ERRCODE 11 ; Segment not present 39 | ISR_ERRCODE 12 ; Stack segment fault 40 | ISR_ERRCODE 13 ; General protection fault 41 | ISR_ERRCODE 14 ; Page fault 42 | ISR_NOERRCODE 15 ; Reserved 43 | ISR_NOERRCODE 16 ; x87 FPU error 44 | ISR_ERRCODE 17 ; Alignment check 45 | ISR_NOERRCODE 18 ; Machine check 46 | ISR_NOERRCODE 19 ; SIMD FPU error 47 | ISR_NOERRCODE 20 ; Virtualization error 48 | ISR_NOERRCODE 21 ; Reserved 49 | ISR_NOERRCODE 22 ; Reserved 50 | ISR_NOERRCODE 23 ; Reserved 51 | ISR_NOERRCODE 24 ; Reserved 52 | ISR_NOERRCODE 25 ; Reserved 53 | ISR_NOERRCODE 26 ; Reserved 54 | ISR_NOERRCODE 27 ; Reserved 55 | ISR_NOERRCODE 28 ; Reserved 56 | ISR_NOERRCODE 29 ; Reserved 57 | ISR_NOERRCODE 30 ; Security exception 58 | ISR_NOERRCODE 31 ; Reserved 59 | 60 | ; IRQs 61 | ISR_NOERRCODE 32 ; Timer 62 | ISR_NOERRCODE 33 ; Keyboard 63 | 64 | ; Stub común para todas las interrupciones 65 | isr_common_stub: 66 | ; Guardar todos los registros 67 | push rax 68 | push rcx 69 | push rdx 70 | push rbx 71 | push rbp 72 | push rsi 73 | push rdi 74 | push r8 75 | push r9 76 | push r10 77 | push r11 78 | push r12 79 | push r13 80 | push r14 81 | push r15 82 | 83 | ; Llamar al handler C 84 | mov rdi, [rsp + 120] ; Obtener número de interrupción 85 | call isr_handler 86 | 87 | ; Restaurar registros 88 | pop r15 89 | pop r14 90 | pop r13 91 | pop r12 92 | pop r11 93 | pop r10 94 | pop r9 95 | pop r8 96 | pop rdi 97 | pop rsi 98 | pop rbp 99 | pop rbx 100 | pop rdx 101 | pop rcx 102 | pop rax 103 | 104 | ; Limpiar error code y número de interrupción 105 | add rsp, 16 106 | 107 | ; Restaurar interrupciones y retornar 108 | sti 109 | iretq 110 | 111 | ; Función para cargar IDT 112 | global idt_load 113 | idt_load: 114 | lidt [rdi] ; RDI contiene el puntero al IDT 115 | ret -------------------------------------------------------------------------------- /arch/x86-64/sources/fault.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | 8 | void page_fault_handler_x64(uint64_t *stack) 9 | { 10 | uint64_t fault_addr; 11 | asm volatile("mov %%cr2, %0" : "=r"(fault_addr)); 12 | 13 | uint64_t errcode = stack[1]; 14 | 15 | int not_present = !(errcode & 1); 16 | int write = errcode & 2; 17 | int user = errcode & 4; 18 | 19 | if (user && not_present) 20 | { 21 | void *phys_page = kmalloc(0x1000); 22 | if (!phys_page) 23 | { 24 | panic("[PF] No hay memoria física para usuario"); 25 | } 26 | 27 | uint64_t flags = PAGE_USER; 28 | if (write) 29 | flags |= PAGE_RW; 30 | 31 | map_user_page(fault_addr & ~0xFFF, (uintptr_t)phys_page, flags); 32 | 33 | return; 34 | } 35 | 36 | // Kernel fault o violación de permisos 37 | print("[PF] Kernel page fault en "); 38 | print_hex(fault_addr); 39 | print(" - código: "); 40 | print_hex(errcode); 41 | print("\n"); 42 | panic("Unhandled kernel page fault"); 43 | } 44 | 45 | // Double Fault 46 | void double_fault_x64(uint64_t error_code, uint64_t rip) 47 | { 48 | print_colored("DOUBLE FAULT!\n", 0x0C, 0x00); 49 | print("Error code: "); 50 | print_hex(error_code); 51 | print("\n"); 52 | print("RIP: "); 53 | print_hex(rip); 54 | print("\n"); 55 | panic("Double fault - Kernel halted"); 56 | } 57 | 58 | // Triple Fault 59 | void triple_fault_x64() 60 | { 61 | print_colored("TRIPLE FAULT!\n", 0x0C, 0x00); 62 | print("FATAL: CPU reset imminent\n"); 63 | panic("Triple fault - System halted"); 64 | } 65 | 66 | // ------------------------------------------------------------------- 67 | // General Protection Fault 68 | // ------------------------------------------------------------------- 69 | void general_protection_fault_x64(uint64_t error_code, uint64_t rip, uint64_t cs, uint64_t rsp) 70 | { 71 | print_colored("GENERAL PROTECTION FAULT!\n", 0x0C, 0x00); 72 | print("Error code: "); 73 | print_hex(error_code); 74 | print("\n"); 75 | print("RIP: "); 76 | print_hex(rip); 77 | print("\n"); 78 | print("CS: "); 79 | print_hex(cs); 80 | print("\n"); 81 | print("RSP: "); 82 | print_hex(rsp); 83 | print("\n"); 84 | panic("GPF - Kernel halted"); 85 | } 86 | 87 | // ------------------------------------------------------------------- 88 | // Invalid Opcode 89 | // ------------------------------------------------------------------- 90 | void invalid_opcode_x64(uint64_t rip) 91 | { 92 | print_colored("INVALID OPCODE!\n", 0x0C, 0x00); 93 | print("RIP: "); 94 | print_hex(rip); 95 | print("\n"); 96 | panic("Invalid instruction - Kernel halted"); 97 | } 98 | 99 | // ------------------------------------------------------------------- 100 | // Divide by Zero 101 | // ------------------------------------------------------------------- 102 | void divide_by_zero_x64(uint64_t rip) 103 | { 104 | print_colored("DIVIDE BY ZERO!\n", 0x0C, 0x00); 105 | print("RIP: "); 106 | print_hex(rip); 107 | print("\n"); 108 | panic("Divide by zero - Kernel halted"); 109 | } 110 | -------------------------------------------------------------------------------- /kernel/kernel_config.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-only 2 | /** 3 | * IR0 Kernel — Core system software 4 | * Copyright (C) 2025 Iván Rodriguez 5 | * 6 | * File: kernel_config.h 7 | * Description: Kernel configuration constants and limits 8 | */ 9 | 10 | #pragma once 11 | 12 | // =============================================================================== 13 | // KERNEL VERSION AND BUILD INFO 14 | // =============================================================================== 15 | #define IR0_VERSION_MAJOR 0 16 | #define IR0_VERSION_MINOR 0 17 | #define IR0_VERSION_PATCH 1 18 | #define IR0_VERSION_STRING "0.0.1-pre-rc1" 19 | 20 | // =============================================================================== 21 | // MEMORY CONFIGURATION 22 | // =============================================================================== 23 | #define DEFAULT_STACK_SIZE (4 * 1024) // 4KB stack per process 24 | #define KERNEL_HEAP_SIZE (16 * 1024 * 1024) // 16MB kernel heap 25 | #define USER_HEAP_MAX_SIZE (256 * 1024 * 1024) // 256MB max per process 26 | 27 | // =============================================================================== 28 | // PROCESS LIMITS 29 | // =============================================================================== 30 | #define MAX_PROCESSES 256 31 | #define MAX_FDS_PER_PROCESS 32 32 | #define MAX_NICE 19 33 | #define MIN_NICE -20 34 | #define DEFAULT_NICE 0 35 | 36 | // =============================================================================== 37 | // SCHEDULER CONFIGURATION 38 | // =============================================================================== 39 | #define CFS_TARGETED_LATENCY 20000000ULL // 20ms in nanoseconds 40 | #define CFS_MIN_GRANULARITY 4000000ULL // 4ms minimum per process 41 | #define CFS_NICE_0_LOAD 1024 // Weight of nice 0 42 | #define MAX_RB_NODES 1024 // RB-tree node pool size 43 | 44 | // =============================================================================== 45 | // FILESYSTEM CONFIGURATION 46 | // =============================================================================== 47 | #define MAX_PATH_LENGTH 256 48 | #define MAX_FILENAME_LENGTH 64 49 | #define VFS_MAX_OPEN_FILES 128 50 | 51 | // =============================================================================== 52 | // HARDWARE LIMITS 53 | // =============================================================================== 54 | #define MAX_CPUS 8 55 | #define MAX_IRQ_HANDLERS 256 56 | #define TIMER_FREQUENCY 1000 // 1000 Hz timer 57 | 58 | // =============================================================================== 59 | // DEBUG AND LOGGING 60 | // =============================================================================== 61 | #ifdef DEBUG 62 | #define KERNEL_DEBUG 1 63 | #define VERBOSE_LOGGING 1 64 | #else 65 | #define KERNEL_DEBUG 0 66 | #define VERBOSE_LOGGING 0 67 | #endif 68 | 69 | // =============================================================================== 70 | // FEATURE FLAGS 71 | // =============================================================================== 72 | #define ENABLE_SMP 0 // Symmetric multiprocessing (not implemented) 73 | #define ENABLE_NETWORKING 0 // Network stack (not implemented) 74 | #define ENABLE_GRAPHICS 0 // Graphics subsystem (basic VGA only) 75 | #define ENABLE_SOUND 1 // Sound Blaster support 76 | #define ENABLE_USB 0 // USB support (not implemented) -------------------------------------------------------------------------------- /drivers/timer/hpet/hpet.c: -------------------------------------------------------------------------------- 1 | #include "hpet.h" 2 | #include 3 | #include 4 | #include // para outb, inb 5 | #include 6 | 7 | #define HPET_GENERAL_CAPABILITY 0x00 8 | #define HPET_GENERAL_CONFIGURATION 0x10 9 | #define HPET_MAIN_COUNTER 0xF0 10 | 11 | #define HPET_TIMER0_CONFIG 0x100 12 | #define HPET_TIMER0_COMPARATOR 0x108 13 | #define HPET_TIMER0_FSB_ROUTE 0x110 // para MSI (a futuro) 14 | 15 | #define HPET_ENABLE_CNF (1 << 0) // Habilita el contador general 16 | #define HPET_LEGACY_REPLACEMENT (1 << 1) // Usa IRQ0 para HPET (reemplaza PIT) 17 | #define HPET_TN_INT_ENB_CNF (1 << 2) // Habilita interrupciones en el timer 18 | #define HPET_TN_TYPE_CNF (1 << 3) // 1 = periódica, 0 = una sola vez 19 | #define HPET_TN_VAL_SET_CNF (1 << 6) // Usar valor inmediato en comparador 20 | #define HPET_TN_32MODE_CNF (1 << 8) // Usar modo 32-bit si querés 21 | 22 | volatile uint64_t* hpet_base = 0; // Puntero base mapeado a la tabla HPET 23 | 24 | static void* hpet_mmio_base = NULL; 25 | 26 | void hpet_set_address(void* addr) 27 | { 28 | hpet_mmio_base = addr; 29 | } 30 | 31 | void hpet_init() 32 | { 33 | if (hpet_mmio_base == NULL) 34 | 35 | panic("HPET address not set before hpet_init"); 36 | 37 | // Guardamos la dirección base (mapeada por ACPI) 38 | hpet_base = (volatile uint64_t*)hpet_mmio_base; 39 | 40 | // 1. Deshabilitamos el contador general antes de modificarlo 41 | *((volatile uint64_t*)((uint8_t*)hpet_base + HPET_GENERAL_CONFIGURATION)) = 0; 42 | 43 | // 2. Resetear el contador principal 44 | *((volatile uint64_t*)((uint8_t*)hpet_base + HPET_MAIN_COUNTER)) = 0; 45 | 46 | // 3. Leer las capacidades de HPET 47 | uint64_t capabilities = *((volatile uint64_t*)((uint8_t*)hpet_base + HPET_GENERAL_CAPABILITY)); 48 | 49 | // Extraer la resolución en femtosegundos por tick 50 | uint32_t clock_period_fs = (uint32_t)(capabilities >> 32); 51 | 52 | // Convertir a Hz: (1e15 fs / periodo en fs = Hz) 53 | uint64_t freq_hz = 1000000000000000ULL / clock_period_fs; 54 | 55 | print("HPET Frequency: "); 56 | print_hex_compact(freq_hz); 57 | print("\n"); 58 | 59 | // 4. Configurar el Timer 0 como periódico, con interrupciones habilitadas 60 | uint64_t config = 0; 61 | config |= HPET_TN_TYPE_CNF; // Periodic mode 62 | config |= HPET_TN_INT_ENB_CNF; // Enable IRQ 63 | config |= HPET_TN_VAL_SET_CNF; // Usar valor inmediato 64 | 65 | *((volatile uint64_t*)((uint8_t*)hpet_base + HPET_TIMER0_CONFIG)) = config; 66 | 67 | // 5. Setear comparador (cada cuánto lanzar interrupción) 68 | // Frecuencia deseada: 100 Hz → cada 10ms → equivalente en ticks HPET 69 | uint64_t ticks_per_irq = freq_hz / 100; 70 | 71 | *((volatile uint64_t*)((uint8_t*)hpet_base + HPET_TIMER0_COMPARATOR)) = ticks_per_irq; 72 | 73 | // 6. Habilitar modo legacy (usa IRQ 0, el mismo que el PIT) 74 | uint64_t gen_config = 0; 75 | gen_config |= HPET_ENABLE_CNF; // Enable HPET 76 | gen_config |= HPET_LEGACY_REPLACEMENT; // Reemplaza PIT en IRQ0 77 | 78 | *((volatile uint64_t*)((uint8_t*)hpet_base + HPET_GENERAL_CONFIGURATION)) = gen_config; 79 | 80 | LOG_OK("[HPET] Inicializado con interrupciones periódicas en IRQ0.\n"); 81 | } 82 | -------------------------------------------------------------------------------- /kernel/main.c: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-only 2 | /** 3 | * IR0 Kernel — Core system software 4 | * Copyright (C) 2025 Iván Rodriguez 5 | * 6 | * This file is part of the IR0 Operating System. 7 | * Distributed under the terms of the GNU General Public License v3.0. 8 | * See the LICENSE file in the project root for full license information. 9 | * 10 | * File: main.c 11 | * Description: Kernel initialization and user-space transition routines 12 | */ 13 | 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | 27 | // Include kernel header with all function declarations 28 | #include "kernel.h" 29 | 30 | void kmain(void) 31 | { 32 | // Initialize GDT and TSS first 33 | gdt_install(); 34 | setup_tss(); 35 | 36 | // Banner 37 | print("IR0 Kernel v0.0.1 Boot\n"); 38 | delay_ms(2500); 39 | 40 | // Initialize logging 41 | logging_init(); 42 | log_subsystem_ok("INIT"); 43 | 44 | // Initialize serial for debugging 45 | serial_init(); 46 | log_subsystem_ok("SERIAL"); 47 | 48 | // Initialize PS/2 controller and keyboard 49 | ps2_init(); 50 | keyboard_init(); 51 | pic_unmask_irq(1); // Enable keyboard IRQ 52 | log_subsystem_ok("PS2_KEYBOARD"); 53 | 54 | // Initialize PS/2 mouse 55 | ps2_mouse_init(); 56 | log_subsystem_ok("PS2_MOUSE"); 57 | 58 | // Initialize memory allocator 59 | heap_init(); 60 | log_subsystem_ok("MEMORY"); 61 | 62 | // Initialize Sound Blaster audio 63 | sb16_init(); 64 | log_subsystem_ok("AUDIO_SB16"); 65 | 66 | // Initialize storage 67 | ata_init(); 68 | log_subsystem_ok("STORAGE"); 69 | 70 | // Initialize network card 71 | rtl8139_init(); 72 | log_subsystem_ok("NET_RTL8139"); 73 | 74 | // Initialize filesystem 75 | vfs_init_with_minix(); 76 | log_subsystem_ok("FILESYSTEM"); 77 | 78 | // Initialize process management 79 | process_init(); 80 | log_subsystem_ok("PROCESSES"); 81 | 82 | // Initialize scheduler (using Round Robin for now) 83 | clock_system_init(); 84 | 85 | // Initialize system calls 86 | syscalls_init(); 87 | log_subsystem_ok("SYSCALLS"); 88 | 89 | // Set up interrupts 90 | idt_init64(); 91 | idt_load64(); 92 | pic_remap64(); 93 | 94 | #include 95 | #include 96 | 97 | log_subsystem_ok("INTERRUPTS"); 98 | 99 | // panic("Test"); Just for testing 100 | 101 | #if KERNEL_DEBUG_SHELL 102 | start_init_process(); 103 | log_subsystem_ok("DEBUG_SHELL"); 104 | #else 105 | serial_print("SERIAL: kmain: Loading userspace init...\n"); 106 | if (elf_load_and_execute("/bin/init") < 0) 107 | { 108 | serial_print("SERIAL: kmain: FAILED to load /bin/init, falling back to debug shell\n"); 109 | panic("Failed to load /bin/init"); 110 | } 111 | #endif 112 | 113 | 114 | for (;;) 115 | { 116 | __asm__ volatile("hlt"); // fallback if something goes wrong 117 | } 118 | } -------------------------------------------------------------------------------- /includes/stdint.h: -------------------------------------------------------------------------------- 1 | #ifndef _STDINT_H 2 | #define _STDINT_H 3 | 4 | /* Integer types for IR0 Kernel - Freestanding implementation */ 5 | /* Architecture-aware definitions */ 6 | 7 | /* Exact-width integer types */ 8 | typedef signed char int8_t; 9 | typedef short int16_t; 10 | typedef int int32_t; 11 | typedef long long int64_t; 12 | 13 | typedef unsigned char uint8_t; 14 | typedef unsigned short uint16_t; 15 | typedef unsigned int uint32_t; 16 | typedef unsigned long long uint64_t; 17 | 18 | /* Minimum-width integer types */ 19 | typedef int8_t int_least8_t; 20 | typedef int16_t int_least16_t; 21 | typedef int32_t int_least32_t; 22 | typedef int64_t int_least64_t; 23 | 24 | typedef uint8_t uint_least8_t; 25 | typedef uint16_t uint_least16_t; 26 | typedef uint32_t uint_least32_t; 27 | typedef uint64_t uint_least64_t; 28 | 29 | /* Fastest minimum-width integer types */ 30 | typedef int8_t int_fast8_t; 31 | typedef int32_t int_fast16_t; 32 | typedef int32_t int_fast32_t; 33 | typedef int64_t int_fast64_t; 34 | 35 | typedef uint8_t uint_fast8_t; 36 | typedef uint32_t uint_fast16_t; 37 | typedef uint32_t uint_fast32_t; 38 | typedef uint64_t uint_fast64_t; 39 | 40 | /* Architecture-dependent pointer types */ 41 | #if defined(__x86_64__) || defined(__amd64__) || defined(_M_X64) 42 | /* 64-bit architecture */ 43 | typedef long intptr_t; 44 | typedef unsigned long uintptr_t; 45 | #define INTPTR_MIN (-9223372036854775807L - 1) 46 | #define INTPTR_MAX (9223372036854775807L) 47 | #define UINTPTR_MAX (18446744073709551615UL) 48 | #elif defined(__i386__) || defined(_M_IX86) 49 | /* 32-bit architecture */ 50 | typedef int intptr_t; 51 | typedef unsigned int uintptr_t; 52 | #define INTPTR_MIN (-2147483647 - 1) 53 | #define INTPTR_MAX (2147483647) 54 | #define UINTPTR_MAX (4294967295U) 55 | #else 56 | #error "Unsupported architecture for pointer types" 57 | #endif 58 | 59 | /* Greatest-width integer types */ 60 | typedef long long intmax_t; 61 | typedef unsigned long long uintmax_t; 62 | 63 | /* Limits of exact-width integer types */ 64 | #define INT8_MIN (-128) 65 | #define INT8_MAX (127) 66 | #define INT16_MIN (-32768) 67 | #define INT16_MAX (32767) 68 | #define INT32_MIN (-2147483647 - 1) 69 | #define INT32_MAX (2147483647) 70 | #define INT64_MIN (-9223372036854775807LL - 1) 71 | #define INT64_MAX (9223372036854775807LL) 72 | 73 | #define UINT8_MAX (255) 74 | #define UINT16_MAX (65535) 75 | #define UINT32_MAX (4294967295U) 76 | #define UINT64_MAX (18446744073709551615ULL) 77 | 78 | /* Limits of other integer types */ 79 | #define PTRDIFF_MIN INTPTR_MIN 80 | #define PTRDIFF_MAX INTPTR_MAX 81 | #define SIZE_MAX UINTPTR_MAX 82 | 83 | /* Limits of greatest-width integer types */ 84 | #define INTMAX_MIN INT64_MIN 85 | #define INTMAX_MAX INT64_MAX 86 | #define UINTMAX_MAX UINT64_MAX 87 | 88 | /* Macros for integer constants */ 89 | #define INT8_C(c) c 90 | #define INT16_C(c) c 91 | #define INT32_C(c) c 92 | #define INT64_C(c) c ## LL 93 | 94 | #define UINT8_C(c) c 95 | #define UINT16_C(c) c 96 | #define UINT32_C(c) c ## U 97 | #define UINT64_C(c) c ## ULL 98 | 99 | #define INTMAX_C(c) INT64_C(c) 100 | #define UINTMAX_C(c) UINT64_C(c) 101 | 102 | #endif /* _STDINT_H */ -------------------------------------------------------------------------------- /drivers/dma/dma.c: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-only 2 | /** 3 | * IR0 Kernel — Core system software 4 | * Copyright (C) 2025 Iván Rodriguez 5 | * 6 | * This file is part of the IR0 Operating System. 7 | * Distributed under the terms of the GNU General Public License v3.0. 8 | * See the LICENSE file in the project root for full license information. 9 | * 10 | * File: dma.c 11 | * Description: DMA controller driver for 8-channel DMA with Sound Blaster integration 12 | */ 13 | 14 | #include "dma.h" 15 | #include 16 | 17 | // DMA controller ports 18 | #define DMA1_COMMAND_REG 0x08 19 | #define DMA1_STATUS_REG 0x08 20 | #define DMA1_REQUEST_REG 0x09 21 | #define DMA1_SINGLE_MASK 0x0A 22 | #define DMA1_MODE_REG 0x0B 23 | #define DMA1_CLEAR_FF 0x0C 24 | #define DMA1_MASTER_CLEAR 0x0D 25 | #define DMA1_CLEAR_MASK 0x0E 26 | #define DMA1_ALL_MASK 0x0F 27 | 28 | #define DMA2_COMMAND_REG 0xD0 29 | #define DMA2_STATUS_REG 0xD0 30 | #define DMA2_REQUEST_REG 0xD2 31 | #define DMA2_SINGLE_MASK 0xD4 32 | #define DMA2_MODE_REG 0xD6 33 | #define DMA2_CLEAR_FF 0xD8 34 | #define DMA2_MASTER_CLEAR 0xDA 35 | #define DMA2_CLEAR_MASK 0xDC 36 | #define DMA2_ALL_MASK 0xDE 37 | 38 | // DMA channel ports 39 | static const uint16_t dma_addr_ports[] = {0x00, 0x02, 0x04, 0x06, 0xC0, 0xC4, 0xC8, 0xCC}; 40 | static const uint16_t dma_count_ports[] = {0x01, 0x03, 0x05, 0x07, 0xC2, 0xC6, 0xCA, 0xCE}; 41 | static const uint16_t dma_page_ports[] = {0x87, 0x83, 0x81, 0x82, 0x8F, 0x8B, 0x89, 0x8A}; 42 | 43 | void dma_setup_channel(uint8_t channel, uint32_t addr, uint16_t length, bool is_16bit) 44 | { 45 | if (channel > 7) return; 46 | 47 | // Disable the channel 48 | dma_disable_channel(channel); 49 | 50 | // Clear flip-flop 51 | if (channel < 4) { 52 | outb(DMA1_CLEAR_FF, 0); 53 | } else { 54 | outb(DMA2_CLEAR_FF, 0); 55 | } 56 | 57 | // Set mode (single transfer, read from memory) 58 | uint8_t mode = 0x48 | (channel & 3); // Single transfer, read 59 | if (channel < 4) { 60 | outb(DMA1_MODE_REG, mode); 61 | } else { 62 | outb(DMA2_MODE_REG, mode); 63 | } 64 | 65 | // Set address 66 | if (is_16bit && channel >= 4) { 67 | // 16-bit channels use word addresses 68 | addr >>= 1; 69 | length >>= 1; 70 | } 71 | 72 | outb(dma_addr_ports[channel], addr & 0xFF); 73 | outb(dma_addr_ports[channel], (addr >> 8) & 0xFF); 74 | 75 | // Set page 76 | outb(dma_page_ports[channel], (addr >> 16) & 0xFF); 77 | 78 | // Set count 79 | length--; // DMA uses length-1 80 | outb(dma_count_ports[channel], length & 0xFF); 81 | outb(dma_count_ports[channel], (length >> 8) & 0xFF); 82 | } 83 | 84 | void dma_enable_channel(uint8_t channel) 85 | { 86 | if (channel > 7) return; 87 | 88 | if (channel < 4) { 89 | outb(DMA1_SINGLE_MASK, channel); 90 | } else { 91 | outb(DMA2_SINGLE_MASK, channel & 3); 92 | } 93 | } 94 | 95 | void dma_disable_channel(uint8_t channel) 96 | { 97 | if (channel > 7) return; 98 | 99 | if (channel < 4) { 100 | outb(DMA1_SINGLE_MASK, 0x04 | channel); 101 | } else { 102 | outb(DMA2_SINGLE_MASK, 0x04 | (channel & 3)); 103 | } 104 | } -------------------------------------------------------------------------------- /drivers/timer/hpet/find_hpet.c: -------------------------------------------------------------------------------- 1 | #include "find_hpet.h" 2 | #include 3 | 4 | static int memcmp(const void *s1, const void *s2, size_t n) 5 | { 6 | const unsigned char *p1 = (const unsigned char *)s1; 7 | const unsigned char *p2 = (const unsigned char *)s2; 8 | 9 | for (size_t i = 0; i < n; i++) 10 | { 11 | if (p1[i] != p2[i]) 12 | { 13 | return p1[i] - p2[i]; 14 | } 15 | } 16 | return 0; 17 | } 18 | 19 | // Validar si una dirección parece válida para ACPI 20 | static int is_valid_acpi_address(uintptr_t addr) 21 | { 22 | // Verificar que esté en rangos válidos de memoria 23 | if (addr < 0x100000) // Menor a 1MB 24 | return 0; 25 | if (addr > 0xFFFFFFFF) // Mayor a 4GB (en 32-bit) 26 | return 0; 27 | if (addr & 0xF) // No alineado a 16 bytes 28 | return 0; 29 | return 1; 30 | } 31 | 32 | // Validar checksum de RSDP 33 | static int validate_rsdp_checksum(rsdp_t *rsdp) 34 | { 35 | uint8_t *bytes = (uint8_t *)rsdp; 36 | uint8_t sum = 0; 37 | 38 | for (int i = 0; i < 20; i++) 39 | { // RSDP v1.0 tiene 20 bytes 40 | sum += bytes[i]; 41 | } 42 | 43 | return sum == 0; // Checksum válido si suma es 0 44 | } 45 | 46 | void *find_hpet_table() 47 | { 48 | for (uint32_t addr = RSDP_SEARCH_START; addr < RSDP_SEARCH_END; addr += 16) 49 | { 50 | char *sig = (char *)(uintptr_t)addr; 51 | 52 | // Usar implementación propia de memcmp 53 | if (memcmp(sig, ACPI_RSDP_SIGNATURE, 8) == 0) 54 | { 55 | rsdp_t *rsdp = (rsdp_t *)(uintptr_t)addr; 56 | 57 | // Validar checksum de RSDP 58 | if (!validate_rsdp_checksum(rsdp)) 59 | continue; // RSDP corrupto, seguir buscando 60 | 61 | // Validar que rsdt_address sea válido 62 | if (!is_valid_acpi_address(rsdp->rsdt_address)) 63 | continue; 64 | 65 | acpi_sdt_header_t *rsdt = (acpi_sdt_header_t *)(uintptr_t)rsdp->rsdt_address; 66 | 67 | // Validar longitud de RSDT 68 | if (rsdt->length < sizeof(acpi_sdt_header_t)) 69 | continue; 70 | 71 | // Verificar signature de RSDT 72 | if (memcmp(rsdt->signature, "RSDT", 4) != 0) 73 | continue; 74 | 75 | int entries = (rsdt->length - sizeof(acpi_sdt_header_t)) / 4; 76 | 77 | // Limitar número de entradas para evitar loops infinitos 78 | if (entries > 64) 79 | continue; 80 | 81 | uint32_t *table_ptrs = (uint32_t *)((uint8_t *)rsdt + sizeof(acpi_sdt_header_t)); 82 | 83 | for (int i = 0; i < entries; i++) 84 | { 85 | // Validar cada puntero de tabla 86 | if (!is_valid_acpi_address(table_ptrs[i])) 87 | continue; 88 | 89 | acpi_sdt_header_t *table = (acpi_sdt_header_t *)(uintptr_t)table_ptrs[i]; 90 | 91 | // Verificar que el puntero no sea NULL 92 | if (table == NULL) 93 | continue; 94 | 95 | // Comparar signature completa, no solo el primer uint32_t 96 | if (memcmp(table->signature, "HPET", 4) == 0) 97 | return table; 98 | } 99 | } 100 | } 101 | 102 | return NULL; 103 | } -------------------------------------------------------------------------------- /drivers/timer/clock_system.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include // For time_t 5 | 6 | // =============================================================================== 7 | // CLOCK SYSTEM TYPES AND CONSTANTS 8 | // =============================================================================== 9 | 10 | // Timer types 11 | typedef enum 12 | { 13 | CLOCK_TIMER_NONE = 0, 14 | CLOCK_TIMER_PIT, 15 | CLOCK_TIMER_HPET, 16 | CLOCK_TIMER_LAPIC, 17 | CLOCK_TIMER_RTC 18 | } clock_timer_t; 19 | 20 | // Clock resolution 21 | #define CLOCK_RESOLUTION_MS 1 22 | 23 | // Clock state structure 24 | typedef struct 25 | { 26 | int initialized; 27 | uint64_t tick_count; 28 | uint64_t uptime_seconds; 29 | uint32_t uptime_milliseconds; 30 | uint32_t time_resolution; 31 | uint32_t timer_frequency; 32 | uint32_t timer_ticks_per_second; 33 | 34 | // Time tracking 35 | time_t boot_time; 36 | time_t current_time; 37 | int32_t timezone_offset; 38 | 39 | // Timer source flags 40 | int pit_enabled; 41 | int hpet_enabled; 42 | int lapic_enabled; 43 | clock_timer_t active_timer; 44 | 45 | // PIT specific 46 | uint32_t pit_divisor; 47 | uint32_t pit_frequency; 48 | 49 | // HPET specific 50 | uint64_t hpet_frequency; 51 | uint64_t hpet_ticks_per_ms; 52 | 53 | // LAPIC specific 54 | uint32_t lapic_frequency; 55 | uint32_t lapic_ticks_per_ms; 56 | } clock_state_t; 57 | 58 | // Alarm callback function type 59 | typedef void (*clock_alarm_callback_t)(void *data); 60 | 61 | // Clock statistics structure 62 | typedef struct 63 | { 64 | int initialized; 65 | clock_timer_t active_timer; 66 | uint32_t timer_frequency; 67 | uint64_t tick_count; 68 | uint64_t uptime_seconds; 69 | uint32_t uptime_milliseconds; 70 | time_t current_time; 71 | int32_t timezone_offset; 72 | } clock_stats_t; 73 | 74 | // =============================================================================== 75 | // CLOCK SYSTEM FUNCTIONS 76 | // =============================================================================== 77 | 78 | // Main initialization 79 | int clock_system_init(void); 80 | void init_clock(void); 81 | 82 | // Timer detection 83 | clock_timer_t detect_best_clock(void); 84 | clock_timer_t get_current_timer_type(void); 85 | 86 | // Time functions 87 | uint64_t clock_get_uptime_seconds(void); 88 | uint64_t clock_get_uptime_milliseconds(void); 89 | uint64_t clock_get_tick_count(void); 90 | time_t clock_get_current_time(void); 91 | int clock_set_current_time(time_t time); 92 | 93 | // Timezone functions 94 | int clock_set_timezone_offset(int32_t offset_seconds); 95 | int32_t clock_get_timezone_offset(void); 96 | 97 | // Timer information 98 | clock_timer_t clock_get_active_timer(void); 99 | uint32_t clock_get_timer_frequency(void); 100 | 101 | // Sleep functions 102 | int clock_sleep(uint32_t milliseconds); 103 | int clock_sleep_ticks(uint32_t ticks); 104 | 105 | // Alarm functions 106 | int clock_set_alarm(uint32_t seconds, clock_alarm_callback_t callback, void *data); 107 | 108 | // Statistics 109 | int clock_get_stats(clock_stats_t *stats); 110 | void clock_print_stats(void); 111 | 112 | // Tick handler (called from interrupt) 113 | void clock_tick(void); 114 | 115 | // System time function 116 | uint64_t get_system_time(void); -------------------------------------------------------------------------------- /includes/string.h: -------------------------------------------------------------------------------- 1 | #ifndef STRING_H 2 | #define STRING_H 3 | 4 | #include 5 | #include 6 | #include "stdarg.h" 7 | 8 | // =============================================================================== 9 | // STRING FUNCTIONS 10 | // =============================================================================== 11 | 12 | // Basic string functions 13 | size_t strlen(const char *str); 14 | 15 | // Kernel-specific string functions 16 | size_t kstrlen(const char *s); 17 | int kstrcmp(const char *s1, const char *s2); 18 | int kstrncmp(const char *s1, const char *s2, size_t n); 19 | int strcmp(const char *s1, const char *s2); 20 | int strncmp(const char *s1, const char *s2, size_t n); 21 | char *strcpy(char *dest, const char *src); 22 | char *strncpy(char *dest, const char *src, size_t n); 23 | char *strcat(char *dest, const char *src); 24 | char *strncat(char *dest, const char *src, size_t n); 25 | 26 | // String search functions 27 | char *strchr(const char *str, int c); 28 | char *strrchr(const char *str, int c); 29 | char *strstr(const char *haystack, const char *needle); 30 | 31 | // Memory functions 32 | void *memset(void *ptr, int value, size_t num); 33 | void *memcpy(void *dest, const void *src, size_t num); 34 | void *memmove(void *dest, const void *src, size_t num); 35 | int memcmp(const void *ptr1, const void *ptr2, size_t num); 36 | 37 | // Kernel-specific memory functions - Internal implementations 38 | void *__kmemset_impl(void *s, int c, size_t n); 39 | void *__kmemcpy_impl(void *dest, const void *src, size_t n); 40 | char *__kstrncpy_impl(char *dest, const char *src, size_t n); 41 | 42 | // Kernel-specific memory functions - Checked wrappers with debug info 43 | void *__kmemset_checked(void *dst, int c, size_t n, 44 | const char *file, int line, const char *caller); 45 | void *__kmemcpy_checked(void *dst, const void *src, size_t n, 46 | const char *file, int line, const char *caller); 47 | char *__kstrncpy_checked(char *dst, const char *src, size_t n, 48 | const char *file, int line, const char *caller); 49 | 50 | // Automatic debug tracking macros - capture caller location transparently 51 | #define kmemset(dst, c, n) \ 52 | __kmemset_checked((dst), (c), (n), __FILE__, __LINE__, __func__) 53 | 54 | #define kmemcpy(dst, src, n) \ 55 | __kmemcpy_checked((dst), (src), (n), __FILE__, __LINE__, __func__) 56 | 57 | #define kstrncpy(dst, src, n) \ 58 | __kstrncpy_checked((dst), (src), (n), __FILE__, __LINE__, __func__) 59 | 60 | // String tokenization 61 | char *strtok(char *str, const char *delim); 62 | char *strtok_r(char *str, const char *delim, char **saveptr); 63 | 64 | // String conversion functions 65 | int atoi(const char *str); 66 | long atol(const char *str); 67 | unsigned long strtoul(const char *str, char **endptr, int base); 68 | long strtol(const char *str, char **endptr, int base); 69 | char *itoa(int value, char *str, int base); 70 | 71 | // String formatting 72 | int snprintf(char *str, size_t size, const char *format, ...); 73 | int sprintf(char *str, const char *format, ...); 74 | int vsnprintf(char *str, size_t size, const char *format, va_list ap); 75 | 76 | // Character classification 77 | int isdigit(int c); 78 | int isalpha(int c); 79 | int isalnum(int c); 80 | int isspace(int c); 81 | int isupper(int c); 82 | int islower(int c); 83 | 84 | // Character conversion 85 | int toupper(int c); 86 | int tolower(int c); 87 | 88 | #endif // STRING_H 89 | -------------------------------------------------------------------------------- /includes/ir0/logging.h: -------------------------------------------------------------------------------- 1 | #ifndef IR0_LOGGING_H 2 | #define IR0_LOGGING_H 3 | 4 | #include 5 | #include 6 | 7 | // =============================================================================== 8 | // LOGGING SYSTEM 9 | // =============================================================================== 10 | 11 | typedef enum 12 | { 13 | LOG_LEVEL_DEBUG = 0, 14 | LOG_LEVEL_INFO = 1, 15 | LOG_LEVEL_WARN = 2, 16 | LOG_LEVEL_ERROR = 3, 17 | LOG_LEVEL_FATAL = 4 18 | } log_level_t; 19 | 20 | // =============================================================================== 21 | // LOGGING FUNCTIONS 22 | // =============================================================================== 23 | 24 | // Basic logging functions 25 | void log_message(log_level_t level, const char *component, const char *message); 26 | void log_debug(const char *component, const char *message); 27 | void log_info(const char *component, const char *message); 28 | void log_warn(const char *component, const char *message); 29 | void log_error(const char *component, const char *message); 30 | void log_fatal(const char *component, const char *message); 31 | 32 | // Formatted logging functions 33 | void log_debug_fmt(const char *component, const char *format, ...); 34 | void log_info_fmt(const char *component, const char *format, ...); 35 | void log_warn_fmt(const char *component, const char *format, ...); 36 | void log_error_fmt(const char *component, const char *format, ...); 37 | void log_fatal_fmt(const char *component, const char *format, ...); 38 | 39 | // System-specific logging 40 | void log_syscall(const char *syscall, int result, const char *args); 41 | void log_filesystem_op(const char *op, const char *path, int result); 42 | void log_memory_op(const char *op, void *ptr, size_t size, int result); 43 | void log_interrupt(uint8_t irq, const char *handler, int result); 44 | void log_subsystem_ok(const char *subsystem_name); 45 | 46 | // Logging initialization 47 | void logging_init(void); 48 | void logging_set_level(log_level_t level); 49 | log_level_t logging_get_level(void); 50 | 51 | // =============================================================================== 52 | // LOGGING MACROS 53 | // =============================================================================== 54 | 55 | #define LOG_DEBUG(component, message) log_debug(component, message) 56 | #define LOG_INFO(component, message) log_info(component, message) 57 | #define LOG_WARNING(component, message) log_warn(component, message) 58 | #define LOG_ERROR(component, message) log_error(component, message) 59 | #define LOG_FATAL(component, message) log_fatal(component, message) 60 | 61 | #define LOG_DEBUG_FMT(component, format, ...) log_debug_fmt(component, format, ##__VA_ARGS__) 62 | #define LOG_INFO_FMT(component, format, ...) log_info_fmt(component, format, ##__VA_ARGS__) 63 | #define LOG_WARNING_FMT(component, format, ...) log_warn_fmt(component, format, ##__VA_ARGS__) 64 | #define LOG_ERROR_FMT(component, format, ...) log_error_fmt(component, format, ##__VA_ARGS__) 65 | #define LOG_FATAL_FMT(component, format, ...) log_fatal_fmt(component, format, ##__VA_ARGS__) 66 | 67 | #define LOG_SYSCALL(syscall, result, args) log_syscall(syscall, result, args) 68 | #define LOG_FS_OP(op, path, result) log_filesystem_op(op, path, result) 69 | #define LOG_MEM_OP(op, ptr, size, result) log_memory_op(op, ptr, size, result) 70 | #define LOG_IRQ(irq, handler, result) log_interrupt(irq, handler, result) 71 | 72 | #endif // IR0_LOGGING_H 73 | -------------------------------------------------------------------------------- /interrupt/arch/idt.h: -------------------------------------------------------------------------------- 1 | #ifndef IDT_H 2 | #define IDT_H 3 | 4 | #include 5 | 6 | #ifdef __x86_64__ 7 | // Estructura de entrada IDT para 64-bit 8 | struct idt_entry64 9 | { 10 | uint16_t offset_low; 11 | uint16_t selector; 12 | uint8_t ist; 13 | uint8_t flags; 14 | uint16_t offset_mid; 15 | uint32_t offset_high; 16 | uint32_t reserved; 17 | } __attribute__((packed)); 18 | 19 | // Puntero IDT para 64-bit 20 | struct idt_ptr64 21 | { 22 | uint16_t limit; 23 | uint64_t base; 24 | } __attribute__((packed)); 25 | #else 26 | // Para 32-bit, incluir las estructuras desde el archivo modular 27 | #include "idt_32.h" 28 | #endif 29 | 30 | // Declaraciones de funciones 31 | void idt_init32(void); 32 | void idt_init64(void); 33 | void idt_load32(void); 34 | void idt_load64(void); 35 | 36 | // Handlers de interrupciones 37 | void isr_handler32(uint32_t interrupt_number); 38 | void isr_handler64(uint64_t interrupt_number); 39 | 40 | // Funciones PIC 41 | void pic_remap32(void); 42 | void pic_remap64(void); 43 | void pic_send_eoi32(uint8_t irq); 44 | void pic_send_eoi64(uint8_t irq); 45 | 46 | // Funciones de teclado 47 | void keyboard_handler32(void); 48 | void keyboard_handler64(void); 49 | void keyboard_init(void); 50 | 51 | // Funciones del buffer de teclado 52 | char keyboard_buffer_get(void); 53 | int keyboard_buffer_has_data(void); 54 | void keyboard_buffer_clear(void); 55 | 56 | 57 | 58 | // Declaraciones de stubs de interrupción 59 | #ifdef __x86_64__ 60 | // Stubs para 64-bit 61 | extern void isr0_64(void); 62 | extern void isr1_64(void); 63 | extern void isr2_64(void); 64 | extern void isr3_64(void); 65 | extern void isr4_64(void); 66 | extern void isr5_64(void); 67 | extern void isr6_64(void); 68 | extern void isr7_64(void); 69 | extern void isr8_64(void); 70 | extern void isr9_64(void); 71 | extern void isr10_64(void); 72 | extern void isr11_64(void); 73 | extern void isr12_64(void); 74 | extern void isr13_64(void); 75 | extern void isr14_64(void); 76 | extern void isr15_64(void); 77 | extern void isr16_64(void); 78 | extern void isr17_64(void); 79 | extern void isr18_64(void); 80 | extern void isr19_64(void); 81 | extern void isr20_64(void); 82 | extern void isr21_64(void); 83 | extern void isr22_64(void); 84 | extern void isr23_64(void); 85 | extern void isr24_64(void); 86 | extern void isr25_64(void); 87 | extern void isr26_64(void); 88 | extern void isr27_64(void); 89 | extern void isr28_64(void); 90 | extern void isr29_64(void); 91 | extern void isr30_64(void); 92 | extern void isr31_64(void); 93 | extern void isr32_64(void); 94 | extern void isr33_64(void); 95 | extern void isr34_64(void); 96 | extern void isr35_64(void); 97 | extern void isr36_64(void); 98 | extern void isr37_64(void); 99 | extern void isr38_64(void); 100 | extern void isr39_64(void); 101 | extern void isr40_64(void); 102 | extern void isr41_64(void); 103 | extern void isr42_64(void); 104 | extern void isr43_64(void); 105 | extern void isr44_64(void); 106 | extern void isr45_64(void); 107 | extern void isr46_64(void); 108 | extern void isr47_64(void); 109 | #else 110 | // Para 32-bit, las declaraciones están en idt_32.h 111 | #endif 112 | 113 | // Variables globales 114 | #ifdef __x86_64__ 115 | extern struct idt_entry64 idt[256]; 116 | extern struct idt_ptr64 idt_ptr; 117 | #else 118 | extern struct idt_entry32 idt[256]; 119 | extern struct idt_ptr32 idt_ptr; 120 | #endif 121 | 122 | #endif // IDT_H 123 | -------------------------------------------------------------------------------- /kernel/elf_loader.h: -------------------------------------------------------------------------------- 1 | // kernel/elf_loader.h - Header para ELF Loader básico 2 | 3 | #pragma once 4 | 5 | #include 6 | #include 7 | 8 | // Forward declaration 9 | struct process; 10 | 11 | // =============================================================================== 12 | // FUNCIONES PRINCIPALES 13 | // =============================================================================== 14 | 15 | /** 16 | * Cargar programa ELF en memoria de proceso 17 | * @param path Ruta del archivo ELF 18 | * @param process Proceso donde cargar el programa 19 | * @return 0 en éxito, -1 en error 20 | */ 21 | int load_elf_program(const char *path, struct process *process); 22 | 23 | /* Backwards-compatible wrapper used by callers in the kernel 24 | * Historically some files call elf_load_and_execute(path) which 25 | * loads and schedules a process. Provide the same symbol here. 26 | */ 27 | int elf_load_and_execute(const char *path); 28 | 29 | // =============================================================================== 30 | // FUNCIONES DE DEBUG 31 | // =============================================================================== 32 | 33 | /** 34 | * Mostrar información del header ELF 35 | * @param header Puntero al header ELF 36 | */ 37 | void debug_elf_header(const void *header); 38 | 39 | /** 40 | * Mostrar información de program header 41 | * @param phdr Puntero al program header 42 | * @param index Índice del program header 43 | */ 44 | void debug_program_header(const void *phdr, int index); 45 | 46 | // =============================================================================== 47 | // CONSTANTES ELF 48 | // =============================================================================== 49 | 50 | #define ELF_MAGIC 0x464C457F // "\x7fELF" 51 | #define PT_LOAD 1 // Segmento cargable 52 | #define PF_R 4 // Readable 53 | #define PF_W 2 // Writable 54 | #define PF_X 1 // Executable 55 | 56 | // =============================================================================== 57 | // ESTRUCTURAS ELF (para uso externo) 58 | // =============================================================================== 59 | 60 | // ELF Header (64-bit) 61 | typedef struct 62 | { 63 | unsigned char e_ident[16]; // Magic number y info 64 | uint16_t e_type; // Tipo de archivo 65 | uint16_t e_machine; // Arquitectura 66 | uint32_t e_version; // Versión ELF 67 | uint64_t e_entry; // Entry point 68 | uint64_t e_phoff; // Offset de program headers 69 | uint64_t e_shoff; // Offset de section headers 70 | uint32_t e_flags; // Flags 71 | uint16_t e_ehsize; // Tamaño del header 72 | uint16_t e_phentsize; // Tamaño de program header 73 | uint16_t e_phnum; // Número de program headers 74 | uint16_t e_shentsize; // Tamaño de section header 75 | uint16_t e_shnum; // Número de section headers 76 | uint16_t e_shstrndx; // Índice de string table 77 | } elf64_header_t; 78 | 79 | // Program Header (64-bit) 80 | typedef struct 81 | { 82 | uint32_t p_type; // Tipo de segmento 83 | uint32_t p_flags; // Flags 84 | uint64_t p_offset; // Offset en archivo 85 | uint64_t p_vaddr; // Dirección virtual 86 | uint64_t p_paddr; // Dirección física 87 | uint64_t p_filesz; // Tamaño en archivo 88 | uint64_t p_memsz; // Tamaño en memoria 89 | uint64_t p_align; // Alineación 90 | } elf64_phdr_t; 91 | -------------------------------------------------------------------------------- /drivers/serial/serial.c: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-only 2 | /** 3 | * IR0 Kernel — Core system software 4 | * Copyright (C) 2025 Iván Rodriguez 5 | * 6 | * This file is part of the IR0 Operating System. 7 | * Distributed under the terms of the GNU General Public License v3.0. 8 | * See the LICENSE file in the project root for full license information. 9 | * 10 | * File: serial.c 11 | * Description: Serial port driver for debugging output 12 | */ 13 | 14 | #include 15 | #include 16 | #include 17 | 18 | /* Compiler optimization hints */ 19 | #define likely(x) __builtin_expect(!!(x), 1) 20 | #define unlikely(x) __builtin_expect(!!(x), 0) 21 | 22 | /* Serial port definitions */ 23 | #define SERIAL_PORT_COM1 0x3F8 24 | #define SERIAL_DATA_REG 0 25 | #define SERIAL_INT_EN_REG 1 26 | #define SERIAL_FIFO_CTRL_REG 2 27 | #define SERIAL_LINE_CTRL_REG 3 28 | #define SERIAL_MODEM_CTRL_REG 4 29 | #define SERIAL_LINE_STATUS_REG 5 30 | 31 | /* Line status register bits */ 32 | #define SERIAL_LSR_THRE 0x20 /* Transmitter holding register empty */ 33 | 34 | static bool serial_initialized = false; 35 | 36 | /** 37 | * serial_init - initialize serial port for debugging 38 | * 39 | * Configure COM1 port for 38400 baud, 8N1. 40 | */ 41 | void serial_init(void) 42 | { 43 | if (serial_initialized) 44 | return; 45 | 46 | /* Disable interrupts */ 47 | outb(SERIAL_PORT_COM1 + SERIAL_INT_EN_REG, 0x00); 48 | 49 | /* Set baud rate divisor (38400 baud) */ 50 | outb(SERIAL_PORT_COM1 + SERIAL_LINE_CTRL_REG, 0x80); /* Enable DLAB */ 51 | outb(SERIAL_PORT_COM1 + SERIAL_DATA_REG, 0x03); /* Divisor low byte */ 52 | outb(SERIAL_PORT_COM1 + SERIAL_INT_EN_REG, 0x00); /* Divisor high byte */ 53 | 54 | /* Configure: 8 bits, no parity, one stop bit */ 55 | outb(SERIAL_PORT_COM1 + SERIAL_LINE_CTRL_REG, 0x03); 56 | 57 | /* Enable FIFO, clear them, with 14-byte threshold */ 58 | outb(SERIAL_PORT_COM1 + SERIAL_FIFO_CTRL_REG, 0xC7); 59 | 60 | /* Enable IRQs, set RTS/DSR */ 61 | outb(SERIAL_PORT_COM1 + SERIAL_MODEM_CTRL_REG, 0x0B); 62 | 63 | serial_initialized = true; 64 | } 65 | 66 | /** 67 | * serial_is_transmit_empty - check if transmitter is ready 68 | * 69 | * Returns true if transmitter holding register is empty. 70 | */ 71 | static bool serial_is_transmit_empty(void) 72 | { 73 | return inb(SERIAL_PORT_COM1 + SERIAL_LINE_STATUS_REG) & SERIAL_LSR_THRE; 74 | } 75 | 76 | /** 77 | * serial_putchar - send a character to serial port 78 | * @c: character to send 79 | */ 80 | void serial_putchar(char c) 81 | { 82 | if (unlikely(!serial_initialized)) 83 | serial_init(); 84 | 85 | while (!serial_is_transmit_empty()) 86 | ; 87 | 88 | outb(SERIAL_PORT_COM1, c); 89 | } 90 | 91 | void serial_print(const char *str) 92 | { 93 | if (!str) return; 94 | 95 | while (*str) { 96 | serial_putchar(*str); 97 | str++; 98 | } 99 | } 100 | 101 | void serial_print_hex32(uint32_t num) 102 | { 103 | serial_print("0x"); 104 | for (int i = 7; i >= 0; i--) { 105 | int digit = (num >> (i * 4)) & 0xF; 106 | char c = (digit < 10) ? '0' + digit : 'a' + digit - 10; 107 | serial_putchar(c); 108 | } 109 | } 110 | void serial_print_hex64(uint64_t num) 111 | { 112 | serial_print("0x"); 113 | for (int i = 15; i >= 0; i--) { 114 | int digit = (num >> (i * 4)) & 0xF; 115 | char c = (digit < 10) ? '0' + digit : 'a' + digit - 10; 116 | serial_putchar(c); 117 | } 118 | } 119 | -------------------------------------------------------------------------------- /includes/ir0/validation.h: -------------------------------------------------------------------------------- 1 | #ifndef IR0_VALIDATION_H 2 | #define IR0_VALIDATION_H 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | // =============================================================================== 9 | // VALIDATION SYSTEM 10 | // =============================================================================== 11 | 12 | // Error codes for validation 13 | typedef enum 14 | { 15 | VALIDATION_SUCCESS = 0, 16 | VALIDATION_ERROR_NULL_POINTER = -1, 17 | VALIDATION_ERROR_INVALID_RANGE = -2, 18 | VALIDATION_ERROR_INVALID_SIZE = -3, 19 | VALIDATION_ERROR_INVALID_FLAGS = -4, 20 | VALIDATION_ERROR_PERMISSION_DENIED = -5, 21 | VALIDATION_ERROR_INVALID_PATH = -6, 22 | VALIDATION_ERROR_BUFFER_OVERFLOW = -7, 23 | VALIDATION_ERROR_INVALID_FD = -8 24 | } validation_error_t; 25 | 26 | // =============================================================================== 27 | // VALIDATION FUNCTIONS 28 | // =============================================================================== 29 | 30 | // Pointer validation 31 | int validate_pointer(const void *ptr, const char *context); 32 | int validate_string(const char *str, const char *context); 33 | int validate_buffer(const void *buf, size_t size, const char *context); 34 | 35 | // Range validation 36 | int validate_range(int value, int min, int max, const char *context); 37 | int validate_range_unsigned(size_t value, size_t min, size_t max, const char *context); 38 | int validate_fd(int fd, const char *context); 39 | 40 | // Path validation 41 | int validate_path(const char *path, const char *context); 42 | int validate_path_length(const char *path, size_t max_length, const char *context); 43 | 44 | // Memory validation 45 | int validate_memory_access(const void *ptr, size_t size, const char *context); 46 | int validate_user_buffer(const void *buf, size_t size, const char *context); 47 | 48 | // Permission validation 49 | int validate_permissions(int flags, int allowed_flags, const char *context); 50 | 51 | // =============================================================================== 52 | // VALIDATION MACROS 53 | // =============================================================================== 54 | 55 | #define VALIDATE_POINTER(ptr, context) \ 56 | do { \ 57 | int result = validate_pointer(ptr, context); \ 58 | if (result != VALIDATION_SUCCESS) return result; \ 59 | } while(0) 60 | 61 | #define VALIDATE_STRING(str, context) \ 62 | do { \ 63 | int result = validate_string(str, context); \ 64 | if (result != VALIDATION_SUCCESS) return result; \ 65 | } while(0) 66 | 67 | #define VALIDATE_RANGE(value, min, max, context) \ 68 | do { \ 69 | int result = validate_range(value, min, max, context); \ 70 | if (result != VALIDATION_SUCCESS) return result; \ 71 | } while(0) 72 | 73 | #define VALIDATE_FD(fd, context) \ 74 | do { \ 75 | int result = validate_fd(fd, context); \ 76 | if (result != VALIDATION_SUCCESS) return result; \ 77 | } while(0) 78 | 79 | #define VALIDATE_PATH(path, context) \ 80 | do { \ 81 | int result = validate_path(path, context); \ 82 | if (result != VALIDATION_SUCCESS) return result; \ 83 | } while(0) 84 | 85 | // =============================================================================== 86 | // ERROR HANDLING 87 | // =============================================================================== 88 | 89 | const char* validation_error_string(validation_error_t error); 90 | void validation_log_error(validation_error_t error, const char *context, const char *operation); 91 | 92 | #endif // IR0_VALIDATION_H 93 | -------------------------------------------------------------------------------- /drivers/SUBSYSTEM.md: -------------------------------------------------------------------------------- 1 | # Drivers Subsystem 2 | 3 | Hardware device drivers for IR0 kernel. 4 | 5 | ## Architecture 6 | 7 | ``` 8 | drivers/ 9 | ├── IO/ - Input/Output devices 10 | │ ├── ps2.c/h - PS/2 controller 11 | │ └── ps2_mouse.c - PS/2 mouse driver 12 | ├── audio/ - Audio devices 13 | │ └── sound_blaster.c - Sound Blaster 16 14 | ├── dma/ - DMA controller 15 | │ └── dma.c/h 16 | ├── serial/ - Serial port 17 | │ └── serial.c/h 18 | ├── storage/ - Storage devices 19 | │ └── ata.c/h - ATA/IDE disk driver 20 | ├── timer/ - Timer devices 21 | │ ├── pit/ - Programmable Interval Timer 22 | │ ├── rtc/ - Real-Time Clock 23 | │ ├── hpet/ - High Precision Event Timer 24 | │ ├── lapic/ - Local APIC timer 25 | │ └── clock_system.c - Unified clock interface 26 | └── video/ - Video devices 27 | └── vbe.c/h - VESA BIOS Extensions 28 | ``` 29 | 30 | ## Driver Categories 31 | 32 | ### Input Devices 33 | - **PS/2 Controller**: Keyboard and mouse interface 34 | - **PS/2 Mouse**: Mouse input handling 35 | 36 | ### Output Devices 37 | - **VGA Text Mode**: 80x25 text display (built-in) 38 | - **VBE**: VESA graphics mode support 39 | 40 | ### Storage Devices 41 | - **ATA/IDE**: Hard disk and CD-ROM support 42 | - Supports PIO mode 0-4 43 | - Master/Slave configuration 44 | 45 | ### Timer Devices 46 | - **PIT**: Legacy 8253/8254 timer (1.193182 MHz) 47 | - **RTC**: CMOS real-time clock 48 | - **HPET**: Modern high-precision timer 49 | - **LAPIC**: Per-CPU timer for SMP 50 | 51 | ### Audio Devices 52 | - **Sound Blaster 16**: Legacy audio card 53 | - DMA-based audio playback 54 | 55 | ## Public Interfaces 56 | 57 | ### Serial Port (`serial.h`) 58 | ```c 59 | void serial_init(void); 60 | void serial_print(const char *str); 61 | void serial_print_hex32(uint32_t value); 62 | void serial_print_hex64(uint64_t value); 63 | char serial_read_char(void); 64 | ``` 65 | 66 | ### Timer (`clock_system.h`) 67 | ```c 68 | void clock_system_init(void); 69 | uint64_t get_system_ticks(void); 70 | uint64_t get_uptime_ms(void); 71 | void sleep_ms(uint64_t ms); 72 | ``` 73 | 74 | ### Storage (`ata.h`) 75 | ```c 76 | void ata_init(void); 77 | int ata_read_sector(uint8_t drive, uint32_t lba, void *buffer); 78 | int ata_write_sector(uint8_t drive, uint32_t lba, const void *buffer); 79 | ``` 80 | 81 | ### PS/2 (`ps2.h`) 82 | ```c 83 | void ps2_init(void); 84 | void keyboard_init(void); 85 | void ps2_mouse_init(void); 86 | char keyboard_getchar(void); 87 | ``` 88 | 89 | ## Driver Initialization Order 90 | 91 | 1. **Serial** - For early debug output 92 | 2. **PIT** - For basic timing 93 | 3. **PS/2** - For keyboard input 94 | 4. **ATA** - For disk access 95 | 5. **VBE** - For graphics (optional) 96 | 6. **Audio** - For sound (optional) 97 | 98 | ## Interrupt Handling 99 | 100 | Drivers register interrupt handlers via the IDT: 101 | - IRQ 0: PIT timer 102 | - IRQ 1: Keyboard 103 | - IRQ 12: PS/2 mouse 104 | - IRQ 14: Primary ATA 105 | - IRQ 15: Secondary ATA 106 | 107 | ## DMA Usage 108 | 109 | Devices using DMA: 110 | - Sound Blaster 16 (channel 1) 111 | - Floppy disk (channel 2) 112 | 113 | ## Port I/O 114 | 115 | All drivers use `inb()`, `outb()`, `inw()`, `outw()` for port access. 116 | Port ranges are documented in each driver's header file. 117 | 118 | ## Future Work 119 | 120 | - [ ] USB support (UHCI, OHCI, EHCI, xHCI) 121 | - [ ] Network cards (RTL8139, E1000) 122 | - [ ] SATA/AHCI support 123 | - [ ] NVMe support 124 | - [ ] GPU drivers (basic framebuffer) 125 | - [ ] Audio: AC'97, HDA 126 | -------------------------------------------------------------------------------- /cpp/runtime/compat.cpp: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-only 2 | /** 3 | * IR0 Kernel — C++ Runtime Support 4 | * Copyright (C) 2025 Iván Rodriguez 5 | * 6 | * This file is part of the IR0 Operating System. 7 | * Distributed under the terms of the GNU General Public License v3.0. 8 | * See the LICENSE file in the project root for full license information. 9 | * 10 | * File: compat.cpp 11 | * Description: C++ runtime implementation for freestanding kernel environment 12 | */ 13 | 14 | /** 15 | * IR0 Kernel - C++ Support Implementation 16 | * 17 | * Provides necessary C++ runtime support for kernel components. 18 | * This file implements operators and functions required for freestanding C++. 19 | */ 20 | 21 | #include 22 | #include 23 | #include 24 | 25 | #ifdef __cplusplus 26 | 27 | namespace ir0 { 28 | 29 | // MEMORY OPERATORS 30 | 31 | /** 32 | * Global new operator using kernel allocator 33 | */ 34 | void* operator_new(size_t size) { 35 | if (size == 0) return nullptr; 36 | void* ptr = kmalloc(size); 37 | if (!ptr) 38 | { 39 | panicex("operator new failed: out of memory", 40 | PANIC_OUT_OF_MEMORY, __FILE__, __LINE__, "operator new"); 41 | } 42 | return ptr; 43 | } 44 | 45 | /** 46 | * Global delete operator using kernel allocator 47 | */ 48 | void operator_delete(void* ptr) noexcept { 49 | if (ptr) 50 | { 51 | kfree(ptr); 52 | } 53 | } 54 | 55 | /** 56 | * Sized delete operator (C++14) 57 | */ 58 | void operator_delete(void* ptr, size_t size) noexcept { 59 | (void)size; // Size not used in our allocator 60 | if (ptr) 61 | { 62 | kfree(ptr); 63 | } 64 | } 65 | 66 | // ARRAY NEW/DELETE 67 | 68 | /** 69 | * Array new operator 70 | */ 71 | void* operator_new_array(size_t size) 72 | { 73 | return operator_new(size); 74 | } 75 | 76 | /** 77 | * Array delete operator 78 | */ 79 | void operator_delete_array(void* ptr) noexcept 80 | { 81 | operator_delete(ptr); 82 | } 83 | 84 | /** 85 | * Sized array delete operator (C++14) 86 | */ 87 | void operator_delete_array(void* ptr, size_t size) noexcept { 88 | operator_delete(ptr, size); 89 | } 90 | 91 | // C++ RUNTIME SUPPORT 92 | 93 | /** 94 | * Pure virtual function call handler 95 | * Called when pure virtual function is invoked 96 | */ 97 | extern "C" void __cxa_pure_virtual() { 98 | panicex("Pure virtual function called", 99 | PANIC_KERNEL_BUG, "unknown", 0, "__cxa_pure_virtual"); 100 | } 101 | 102 | /** 103 | * Guard for static initialization 104 | * Ensures static variables are initialized only once 105 | */ 106 | extern "C" int __cxa_guard_acquire(uint64_t* guard_object) { 107 | // Simple implementation: return 1 if not initialized 108 | return (*guard_object == 0) ? 1 : 0; 109 | } 110 | 111 | extern "C" void __cxa_guard_release(uint64_t* guard_object) { 112 | *guard_object = 1; 113 | } 114 | 115 | extern "C" void __cxa_guard_abort(uint64_t* guard_object) { 116 | (void)guard_object; 117 | // Nothing to do for abort in kernel 118 | } 119 | 120 | // FREESTANDING C++ HELPERS 121 | 122 | /** 123 | * Minimal type_info for RTTI (even though we disable RTTI) 124 | * Some compilers still need this symbol 125 | */ 126 | namespace __cxxabiv1 { 127 | class __class_type_info { 128 | public: 129 | virtual ~__class_type_info() {} 130 | }; 131 | } // namespace __cxxabiv1 132 | 133 | } // namespace ir0 134 | 135 | // GLOBAL OPERATORS (Must be in global namespace) 136 | 137 | /** 138 | * Note: The actual operators are declared inline in compat.h 139 | * to avoid multiple definition errors 140 | */ 141 | 142 | #endif // __cplusplus 143 | -------------------------------------------------------------------------------- /interrupt/arch/pic.c: -------------------------------------------------------------------------------- 1 | #include "pic.h" 2 | #include "io.h" 3 | #include 4 | 5 | // Remapear PIC para 32-bit - usar archivo modular 6 | #ifdef __x86_64__ 7 | // Para 64-bit, usar implementación local 8 | void pic_remap32(void) 9 | { 10 | uint8_t a1, a2; 11 | (void)a1; 12 | (void)a2; // Variables not used in this implementation 13 | 14 | // Guardar máscaras originales 15 | a1 = inb(PIC1_DATA); 16 | a2 = inb(PIC2_DATA); 17 | 18 | // Inicializar PIC1 19 | outb(PIC1_COMMAND, ICW1_INIT | ICW1_ICW4); 20 | io_wait(); 21 | outb(PIC1_DATA, 0x20); // Vector offset 0x20 (32) 22 | io_wait(); 23 | outb(PIC1_DATA, 0x04); // PIC2 en IRQ2 24 | io_wait(); 25 | outb(PIC1_DATA, ICW4_8086); 26 | io_wait(); 27 | 28 | // Inicializar PIC2 29 | outb(PIC2_COMMAND, ICW1_INIT | ICW1_ICW4); 30 | io_wait(); 31 | outb(PIC2_DATA, 0x28); // Vector offset 0x28 (40) 32 | io_wait(); 33 | outb(PIC2_DATA, 0x02); // Cascada 34 | io_wait(); 35 | outb(PIC2_DATA, ICW4_8086); 36 | io_wait(); 37 | 38 | // Configurar máscaras: habilitar solo timer (IRQ0) y teclado (IRQ1) 39 | // Máscara PIC1: 0xFC = 11111100 (habilitar IRQ0 y IRQ1, deshabilitar resto) 40 | // Máscara PIC2: 0xFF = 11111111 (deshabilitar todos) 41 | outb(PIC1_DATA, 0xFC); 42 | outb(PIC2_DATA, 0xFF); 43 | } 44 | 45 | // Enviar EOI para 32-bit 46 | void pic_send_eoi32(uint8_t irq) 47 | { 48 | if (irq >= 8) 49 | { 50 | outb(PIC2_COMMAND, PIC_EOI); 51 | } 52 | outb(PIC1_COMMAND, PIC_EOI); 53 | } 54 | #endif 55 | 56 | // Remapear PIC para 64-bit 57 | void pic_remap64(void) 58 | { 59 | uint8_t a1, a2; 60 | (void)a1; 61 | (void)a2; // Variables not used in this implementation 62 | 63 | // Guardar máscaras originales 64 | a1 = inb(PIC1_DATA); 65 | a2 = inb(PIC2_DATA); 66 | 67 | // Inicializar PIC1 68 | outb(PIC1_COMMAND, ICW1_INIT | ICW1_ICW4); 69 | io_wait(); 70 | outb(PIC1_DATA, 0x20); // Vector offset 0x20 (32) 71 | io_wait(); 72 | outb(PIC1_DATA, 0x04); // PIC2 en IRQ2 73 | io_wait(); 74 | outb(PIC1_DATA, ICW4_8086); 75 | io_wait(); 76 | 77 | // Inicializar PIC2 78 | outb(PIC2_COMMAND, ICW1_INIT | ICW1_ICW4); 79 | io_wait(); 80 | outb(PIC2_DATA, 0x28); // Vector offset 0x28 (40) 81 | io_wait(); 82 | outb(PIC2_DATA, 0x02); // Cascada 83 | io_wait(); 84 | outb(PIC2_DATA, ICW4_8086); 85 | io_wait(); 86 | 87 | // Configurar máscaras: habilitar solo timer (IRQ0) y teclado (IRQ1) 88 | // Máscara PIC1: 0xFC = 11111100 (habilitar IRQ0 y IRQ1, deshabilitar resto) 89 | // Máscara PIC2: 0xFF = 11111111 (deshabilitar todos) 90 | outb(PIC1_DATA, 0xFC); 91 | outb(PIC2_DATA, 0xFF); 92 | } 93 | 94 | // Enviar EOI para 64-bit 95 | void pic_send_eoi64(uint8_t irq) 96 | { 97 | if (irq >= 8) 98 | { 99 | outb(PIC2_COMMAND, PIC_EOI); 100 | } 101 | outb(PIC1_COMMAND, PIC_EOI); 102 | } 103 | 104 | // Enmascarar IRQ 105 | void pic_mask_irq(uint8_t irq) 106 | { 107 | uint16_t port; 108 | uint8_t value; 109 | 110 | if (irq < 8) 111 | { 112 | port = PIC1_DATA; 113 | } 114 | else 115 | { 116 | port = PIC2_DATA; 117 | irq -= 8; 118 | } 119 | 120 | value = inb(port) | (1 << irq); 121 | outb(port, value); 122 | } 123 | 124 | // Desenmascarar IRQ 125 | void pic_unmask_irq(uint8_t irq) 126 | { 127 | uint16_t port; 128 | uint8_t value; 129 | 130 | if (irq < 8) 131 | { 132 | port = PIC1_DATA; 133 | } 134 | else 135 | { 136 | port = PIC2_DATA; 137 | irq -= 8; 138 | } 139 | 140 | value = inb(port) & ~(1 << irq); 141 | outb(port, value); 142 | } 143 | -------------------------------------------------------------------------------- /kernel/SUBSYSTEM.md: -------------------------------------------------------------------------------- 1 | # Kernel Subsystem 2 | 3 | Core kernel functionality including process management, scheduling, and system calls. 4 | 5 | ## Architecture 6 | 7 | ``` 8 | kernel/ 9 | ├── process.c/h - Process lifecycle (fork, exit, wait) 10 | ├── rr_sched.c/h - Round-robin scheduler 11 | ├── syscalls.c/h - System call dispatcher 12 | ├── syscalls_internal.h - Internal syscall implementations 13 | ├── errno_defs.h - POSIX error codes 14 | ├── init.c/h - PID 1 init process 15 | ├── shell.c/h - Built-in shell 16 | ├── elf_loader.c/h - ELF binary loader 17 | └── main.c - Kernel entry point 18 | ``` 19 | 20 | ## Public Interfaces 21 | 22 | ### Process Management (`process.h`) 23 | 24 | **Lifecycle:** 25 | - `void process_init(void)` - Initialize process subsystem 26 | - `pid_t process_fork(void)` - Create child process 27 | - `void process_exit(int code)` - Terminate current process 28 | - `int process_wait(pid_t pid, int *status)` - Wait for child 29 | 30 | **Queries:** 31 | - `pid_t process_get_pid(void)` - Get current PID 32 | - `pid_t process_get_ppid(void)` - Get parent PID 33 | - `process_t *process_get_current(void)` - Get current process 34 | - `process_t *get_process_list(void)` - Get all processes 35 | 36 | **Memory:** 37 | - `uint64_t create_process_page_directory(void)` - Create process page tables 38 | - `void process_init_fd_table(process_t *)` - Initialize file descriptors 39 | 40 | ### Scheduler (`rr_sched.h`) 41 | 42 | - `void rr_add_process(process_t *proc)` - Add process to scheduler 43 | - `void rr_schedule_next(void)` - Switch to next process 44 | - `void rr_remove_process(process_t *proc)` - Remove from scheduler 45 | 46 | ### System Calls (`syscalls.h`) 47 | 48 | - `void syscalls_init(void)` - Initialize syscall subsystem 49 | - `int64_t syscall_handler(...)` - Main syscall dispatcher 50 | 51 | See `syscalls_internal.h` for individual syscall implementations. 52 | 53 | ## Error Codes 54 | 55 | All error codes are defined in `` following POSIX standards. 56 | Use negative error codes for syscall returns: `return -EINVAL;` 57 | 58 | Error strings available via `strerror(int errnum)` in `errno.c`. 59 | 60 | ## Process States 61 | 62 | ```c 63 | typedef enum { 64 | PROCESS_READY = 0, /* Ready to run */ 65 | PROCESS_RUNNING, /* Currently executing */ 66 | PROCESS_BLOCKED, /* Waiting for I/O */ 67 | PROCESS_ZOMBIE /* Terminated, waiting for parent */ 68 | } process_state_t; 69 | ``` 70 | 71 | ## Memory Layout 72 | 73 | Each process has: 74 | - **Code segment**: Loaded from ELF binary 75 | - **Stack**: 8KB default, grows downward 76 | - **Heap**: Managed by `brk()` syscall 77 | - **Page directory**: Isolated virtual address space 78 | 79 | ## Scheduling 80 | 81 | Current implementation: **Round-robin** with 10ms time slices. 82 | 83 | Future: CFS (Completely Fair Scheduler) in `kernel/scheduler/` 84 | 85 | ## System Call Convention 86 | 87 | **x86-64:** 88 | - Syscall number in `RAX` 89 | - Arguments in `RDI, RSI, RDX, R10, R8, R9` 90 | - Return value in `RAX` 91 | - Invoked via `int 0x80` or `syscall` instruction 92 | 93 | ## Dependencies 94 | 95 | - `ir0/memory/kmem.h` - Kernel memory allocator 96 | - `ir0/memory/paging.h` - Page table management 97 | - `drivers/serial/serial.h` - Debug output 98 | - `arch/*/user_mode.h` - Ring 3 transition 99 | 100 | ## Thread Safety 101 | 102 | **NOT thread-safe**. Assumes single-core, cooperative multitasking. 103 | Interrupts are disabled during critical sections. 104 | 105 | ## Future Work 106 | 107 | - [ ] Preemptive multitasking 108 | - [ ] SMP support 109 | - [ ] Process priorities 110 | - [ ] Real-time scheduling 111 | - [ ] Thread support (POSIX threads) 112 | -------------------------------------------------------------------------------- /interrupt/arch/idt_32.c: -------------------------------------------------------------------------------- 1 | #include "idt32.h" 2 | #include 3 | 4 | // Variables globales 5 | struct idt_entry32 idt[256]; 6 | struct idt_ptr32 idt_ptr; 7 | 8 | // Función para configurar una entrada de la IDT 9 | void idt_set_gate32(uint8_t num, uint32_t base, uint16_t sel, uint8_t flags) 10 | { 11 | idt[num].offset_low = base & 0xFFFF; 12 | idt[num].selector = sel; 13 | idt[num].zero = 0; 14 | idt[num].flags = flags; 15 | idt[num].offset_high = (base >> 16) & 0xFFFF; 16 | } 17 | 18 | // Inicialización de la IDT 19 | void idt_init32(void) 20 | { 21 | idt_ptr.limit = sizeof(struct idt_entry32) * 256 - 1; 22 | idt_ptr.base = (uint32_t)&idt; 23 | 24 | // Inicializar todas las entradas a 0 25 | for (int i = 0; i < 256; i++) 26 | { 27 | idt_set_gate32(i, 0, 0, 0); 28 | } 29 | 30 | // Excepciones CPU (ISRs 0–31) 31 | idt_set_gate32(0, (uint32_t)isr0_32, 0x08, 0x8E); 32 | idt_set_gate32(1, (uint32_t)isr1_32, 0x08, 0x8E); 33 | idt_set_gate32(2, (uint32_t)isr2_32, 0x08, 0x8E); 34 | idt_set_gate32(3, (uint32_t)isr3_32, 0x08, 0x8E); 35 | idt_set_gate32(4, (uint32_t)isr4_32, 0x08, 0x8E); 36 | idt_set_gate32(5, (uint32_t)isr5_32, 0x08, 0x8E); 37 | idt_set_gate32(6, (uint32_t)isr6_32, 0x08, 0x8E); 38 | idt_set_gate32(7, (uint32_t)isr7_32, 0x08, 0x8E); 39 | idt_set_gate32(8, (uint32_t)isr8_32, 0x08, 0x8E); 40 | idt_set_gate32(9, (uint32_t)isr9_32, 0x08, 0x8E); 41 | idt_set_gate32(10, (uint32_t)isr10_32, 0x08, 0x8E); 42 | idt_set_gate32(11, (uint32_t)isr11_32, 0x08, 0x8E); 43 | idt_set_gate32(12, (uint32_t)isr12_32, 0x08, 0x8E); 44 | idt_set_gate32(13, (uint32_t)isr13_32, 0x08, 0x8E); 45 | idt_set_gate32(14, (uint32_t)isr14_32, 0x08, 0x8E); 46 | idt_set_gate32(15, (uint32_t)isr15_32, 0x08, 0x8E); 47 | idt_set_gate32(16, (uint32_t)isr16_32, 0x08, 0x8E); 48 | idt_set_gate32(17, (uint32_t)isr17_32, 0x08, 0x8E); 49 | idt_set_gate32(18, (uint32_t)isr18_32, 0x08, 0x8E); 50 | idt_set_gate32(19, (uint32_t)isr19_32, 0x08, 0x8E); 51 | idt_set_gate32(20, (uint32_t)isr20_32, 0x08, 0x8E); 52 | idt_set_gate32(21, (uint32_t)isr21_32, 0x08, 0x8E); 53 | idt_set_gate32(22, (uint32_t)isr22_32, 0x08, 0x8E); 54 | idt_set_gate32(23, (uint32_t)isr23_32, 0x08, 0x8E); 55 | idt_set_gate32(24, (uint32_t)isr24_32, 0x08, 0x8E); 56 | idt_set_gate32(25, (uint32_t)isr25_32, 0x08, 0x8E); 57 | idt_set_gate32(26, (uint32_t)isr26_32, 0x08, 0x8E); 58 | idt_set_gate32(27, (uint32_t)isr27_32, 0x08, 0x8E); 59 | idt_set_gate32(28, (uint32_t)isr28_32, 0x08, 0x8E); 60 | idt_set_gate32(29, (uint32_t)isr29_32, 0x08, 0x8E); 61 | idt_set_gate32(30, (uint32_t)isr30_32, 0x08, 0x8E); 62 | idt_set_gate32(31, (uint32_t)isr31_32, 0x08, 0x8E); 63 | 64 | // IRQs PIC remapeadas 32–47 65 | idt_set_gate32(32, (uint32_t)isr32_32, 0x08, 0x8E); 66 | idt_set_gate32(33, (uint32_t)isr33_32, 0x08, 0x8E); 67 | idt_set_gate32(34, (uint32_t)isr34_32, 0x08, 0x8E); 68 | idt_set_gate32(35, (uint32_t)isr35_32, 0x08, 0x8E); 69 | idt_set_gate32(36, (uint32_t)isr36_32, 0x08, 0x8E); 70 | idt_set_gate32(37, (uint32_t)isr37_32, 0x08, 0x8E); 71 | idt_set_gate32(38, (uint32_t)isr38_32, 0x08, 0x8E); 72 | idt_set_gate32(39, (uint32_t)isr39_32, 0x08, 0x8E); 73 | idt_set_gate32(40, (uint32_t)isr40_32, 0x08, 0x8E); 74 | idt_set_gate32(41, (uint32_t)isr41_32, 0x08, 0x8E); 75 | idt_set_gate32(42, (uint32_t)isr42_32, 0x08, 0x8E); 76 | idt_set_gate32(43, (uint32_t)isr43_32, 0x08, 0x8E); 77 | idt_set_gate32(44, (uint32_t)isr44_32, 0x08, 0x8E); 78 | idt_set_gate32(45, (uint32_t)isr45_32, 0x08, 0x8E); 79 | idt_set_gate32(46, (uint32_t)isr46_32, 0x08, 0x8E); 80 | idt_set_gate32(47, (uint32_t)isr47_32, 0x08, 0x8E); 81 | 82 | // Se pueden agregar más ISRs personalizadas si se necesitan 83 | } 84 | -------------------------------------------------------------------------------- /fs/chmod.c: -------------------------------------------------------------------------------- 1 | #include "chmod.h" 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | /** 8 | * parse_mode - Convert a chmod symbolic/octal mode string to mode bits 9 | * @mode_str: Mode string (e.g. "644" or "u+x") 10 | * 11 | * Return: Mode bits on success, negative error code on failure 12 | */ 13 | int parse_mode(const char *mode_str) 14 | { 15 | // Handle octal mode (e.g. "644") 16 | if (mode_str[0] >= '0' && mode_str[0] <= '7') 17 | { 18 | int mode = 0; 19 | for (int i = 0; mode_str[i]; i++) 20 | { 21 | if (mode_str[i] < '0' || mode_str[i] > '7') 22 | return -1; 23 | mode = mode * 8 + (mode_str[i] - '0'); 24 | } 25 | return mode; 26 | } 27 | 28 | // Handle symbolic mode (e.g. "u+x") 29 | char who = mode_str[0]; 30 | char op = mode_str[1]; 31 | char perm = mode_str[2]; 32 | 33 | // Check who (u/g/o/a) 34 | if (who != 'u' && who != 'g' && who != 'o' && who != 'a') 35 | return -1; 36 | 37 | // Check operator (+/-/=) 38 | if (op != '+' && op != '-' && op != '=') 39 | return -1; 40 | 41 | // Parse permission (r/w/x) 42 | int bits = 0; 43 | switch (perm) 44 | { 45 | case 'r': 46 | bits = (who == 'u' || who == 'a') ? S_IRUSR : 0; 47 | bits |= (who == 'g' || who == 'a') ? S_IRGRP : 0; 48 | bits |= (who == 'o' || who == 'a') ? S_IROTH : 0; 49 | break; 50 | case 'w': 51 | bits = (who == 'u' || who == 'a') ? S_IWUSR : 0; 52 | bits |= (who == 'g' || who == 'a') ? S_IWGRP : 0; 53 | bits |= (who == 'o' || who == 'a') ? S_IWOTH : 0; 54 | break; 55 | case 'x': 56 | bits = (who == 'u' || who == 'a') ? S_IXUSR : 0; 57 | bits |= (who == 'g' || who == 'a') ? S_IXGRP : 0; 58 | bits |= (who == 'o' || who == 'a') ? S_IXOTH : 0; 59 | break; 60 | default: 61 | return -1; 62 | } 63 | 64 | return bits; 65 | } 66 | 67 | /** 68 | * chmod - Change file access permissions 69 | * @path: Path to file 70 | * @mode: New permission bits 71 | * 72 | * Return: 0 on success, negative error code on failure 73 | */ 74 | int chmod(const char *path, mode_t mode) 75 | { 76 | if (!path) 77 | { 78 | return -1; 79 | } 80 | 81 | // Check if MINIX filesystem is available 82 | extern bool minix_fs_is_working(void); 83 | if (!minix_fs_is_working()) 84 | { 85 | return -1; 86 | } 87 | 88 | // Get current file stats 89 | stat_t st; 90 | if (vfs_stat(path, &st) != 0) 91 | { 92 | return -1; 93 | } 94 | 95 | // Get the inode for this path 96 | minix_inode_t *inode_ptr = minix_fs_find_inode(path); 97 | if (!inode_ptr) 98 | { 99 | return -1; 100 | } 101 | 102 | // Get the inode number for this path 103 | uint16_t inode_num = minix_fs_get_inode_number(path); 104 | if (inode_num == 0) 105 | { 106 | return -1; 107 | } 108 | 109 | // Copy the inode to avoid modifying the cached version 110 | minix_inode_t inode; 111 | kmemcpy(&inode, inode_ptr, sizeof(minix_inode_t)); 112 | 113 | // Update mode: preserve file type bits, update permission bits 114 | // File type bits are in the upper bits (IFDIR, IFREG, etc.) 115 | // Permission bits are in the lower 12 bits (07777) 116 | uint16_t file_type = inode.i_mode & ~07777; // Preserve file type 117 | uint16_t new_perms = (mode & 07777); // New permissions 118 | inode.i_mode = file_type | new_perms; 119 | 120 | // Write the updated inode back to disk 121 | if (minix_fs_write_inode(inode_num, &inode) != 0) 122 | { 123 | return -1; 124 | } 125 | 126 | return 0; 127 | } --------------------------------------------------------------------------------