├── .defconfig ├── .gdbinit ├── .github └── workflows │ └── codeql-analysis.yml ├── .gitignore ├── Doxyfile ├── Kconfig ├── LICENSE ├── Makefile ├── README.md ├── kernel ├── Kconfig ├── arch │ ├── Kconfig │ ├── arm32 │ │ ├── Kconfig │ │ ├── hw │ │ │ ├── arm_versatilepb │ │ │ │ └── hw.ld │ │ │ ├── arm_vexpress_a9 │ │ │ │ ├── hw.ld │ │ │ │ ├── module.mk │ │ │ │ └── src │ │ │ │ │ ├── boot │ │ │ │ │ ├── boot.s │ │ │ │ │ ├── entry.c │ │ │ │ │ └── module.mk │ │ │ │ │ ├── init │ │ │ │ │ ├── hw_init.c │ │ │ │ │ └── module.mk │ │ │ │ │ └── module.mk │ │ │ └── broadcom_bcm2837 │ │ │ │ ├── hw.ld │ │ │ │ ├── inc │ │ │ │ └── arch │ │ │ │ │ ├── intr │ │ │ │ │ ├── bcm2835_intctlr.h │ │ │ │ │ └── timer │ │ │ │ │ │ └── bcm2835_systimer.h │ │ │ │ │ └── io │ │ │ │ │ ├── bcm2835_gpio.h │ │ │ │ │ └── bcm2835_mailbox.h │ │ │ │ ├── module.mk │ │ │ │ └── src │ │ │ │ ├── boot │ │ │ │ ├── boot.s │ │ │ │ ├── entry.c │ │ │ │ └── module.mk │ │ │ │ ├── init │ │ │ │ ├── hw_init.c │ │ │ │ └── module.mk │ │ │ │ ├── intr │ │ │ │ ├── bcm2835_intctlr.c │ │ │ │ ├── module.mk │ │ │ │ └── timer │ │ │ │ │ ├── bcm2835_systimer.c │ │ │ │ │ └── module.mk │ │ │ │ └── module.mk │ │ ├── inc │ │ │ └── arch │ │ │ │ ├── init │ │ │ │ ├── hw_init.h │ │ │ │ └── init.h │ │ │ │ ├── intr │ │ │ │ ├── gic.h │ │ │ │ ├── gtimer.h │ │ │ │ ├── int.h │ │ │ │ ├── syscall.h │ │ │ │ ├── timer │ │ │ │ │ └── timer_sp804.h │ │ │ │ └── types │ │ │ │ │ └── intr.h │ │ │ │ ├── io │ │ │ │ └── uart │ │ │ │ │ ├── uart_allwinner.h │ │ │ │ │ └── uart_pl011.h │ │ │ │ ├── mm │ │ │ │ └── mmu.h │ │ │ │ ├── plat │ │ │ │ ├── cpu │ │ │ │ │ ├── cortex_a53.h │ │ │ │ │ ├── cortex_a7.h │ │ │ │ │ └── cortex_a9.h │ │ │ │ ├── hw │ │ │ │ │ ├── allwinner_v3s.h │ │ │ │ │ ├── broadcom_bcm2837.h │ │ │ │ │ └── vexpress_a9.h │ │ │ │ └── platform.h │ │ │ │ ├── proc │ │ │ │ ├── stack.h │ │ │ │ ├── stacktrace.h │ │ │ │ └── tasking.h │ │ │ │ ├── registers.h │ │ │ │ ├── stdint.h │ │ │ │ └── types │ │ │ │ └── mmu.h │ │ ├── module.mk │ │ ├── sdimg.sh │ │ └── src │ │ │ ├── init │ │ │ ├── init.c │ │ │ └── module.mk │ │ │ ├── intr │ │ │ ├── gic.c │ │ │ ├── gtimer.c │ │ │ ├── int.c │ │ │ ├── intr.s │ │ │ ├── module.mk │ │ │ └── timer │ │ │ │ ├── module.mk │ │ │ │ └── timer_sp804.c │ │ │ ├── io │ │ │ ├── module.mk │ │ │ └── uart │ │ │ │ ├── module.mk │ │ │ │ ├── uart_allwinner.c │ │ │ │ └── uart_pl011.c │ │ │ ├── mm │ │ │ ├── mmu.c │ │ │ └── module.mk │ │ │ ├── module.mk │ │ │ └── proc │ │ │ ├── module.mk │ │ │ ├── stack.c │ │ │ ├── stacktrace.c │ │ │ ├── syscall.c │ │ │ └── tasking.c │ ├── module.mk │ ├── riscv │ │ ├── Kconfig │ │ ├── inc │ │ │ └── arch │ │ │ │ ├── plat │ │ │ │ ├── cpu │ │ │ │ │ └── rv64i.h │ │ │ │ ├── hw │ │ │ │ │ └── kendryte_k210.h │ │ │ │ └── platform.h │ │ │ │ └── stdint.h │ │ ├── kendryte-k210.ld │ │ └── module.mk │ └── x86 │ │ ├── Kconfig │ │ ├── hw │ │ └── pc │ │ │ ├── hw.ld │ │ │ ├── module.mk │ │ │ └── src │ │ │ ├── init │ │ │ ├── hw_init.c │ │ │ └── module.mk │ │ │ └── module.mk │ │ ├── inc │ │ └── arch │ │ │ ├── acpi │ │ │ ├── acpi.h │ │ │ └── acpi_data.h │ │ │ ├── boot │ │ │ └── multiboot.h │ │ │ ├── dev │ │ │ ├── keyb │ │ │ │ └── input.h │ │ │ └── vga │ │ │ │ └── print.h │ │ │ ├── init │ │ │ ├── hw_init.h │ │ │ └── init.h │ │ │ ├── intr │ │ │ ├── apic │ │ │ │ ├── apic.h │ │ │ │ └── apictimer.h │ │ │ ├── idt.h │ │ │ ├── int.h │ │ │ ├── pic.h │ │ │ ├── pit.h │ │ │ ├── syscall.h │ │ │ └── types │ │ │ │ ├── idt.h │ │ │ │ ├── intr.h │ │ │ │ └── pic.h │ │ │ ├── io │ │ │ ├── cpuid.h │ │ │ ├── ioport.h │ │ │ ├── msr.h │ │ │ └── serial.h │ │ │ ├── mm │ │ │ ├── gdt.h │ │ │ ├── mem.h │ │ │ └── paging.h │ │ │ ├── proc │ │ │ ├── stack.h │ │ │ ├── stack_trace.h │ │ │ ├── tasking.h │ │ │ └── user.h │ │ │ ├── registers.h │ │ │ ├── stdint.h │ │ │ └── types │ │ │ └── mmu.h │ │ ├── module.mk │ │ └── src │ │ ├── acpi │ │ ├── acpi.c │ │ └── module.mk │ │ ├── boot │ │ ├── boot.s │ │ ├── entry.c │ │ ├── module.mk │ │ └── multiboot.c │ │ ├── dev │ │ ├── keyb │ │ │ ├── input.c │ │ │ └── module.mk │ │ ├── module.mk │ │ └── vga │ │ │ ├── module.mk │ │ │ └── print.c │ │ ├── init │ │ ├── init.c │ │ └── module.mk │ │ ├── intr │ │ ├── apic │ │ │ ├── apic.c │ │ │ ├── apictimer.c │ │ │ └── module.mk │ │ ├── cexceptions.c │ │ ├── exceptions.s │ │ ├── idt.c │ │ ├── intr.s │ │ ├── module.mk │ │ ├── pic.c │ │ └── pit.c │ │ ├── io │ │ ├── module.mk │ │ └── serial.c │ │ ├── mm │ │ ├── gdt.c │ │ ├── mm.s │ │ ├── mmu.c │ │ ├── module.mk │ │ └── paging.c │ │ ├── module.mk │ │ └── proc │ │ ├── module.mk │ │ ├── stack.c │ │ ├── stack_trace.c │ │ ├── syscall.c │ │ ├── tasking.c │ │ └── user.s ├── inc │ ├── crypto │ │ └── comp │ │ │ ├── comp.h │ │ │ ├── lzop.h │ │ │ └── types │ │ │ └── comp.h │ ├── ctype.h │ ├── data │ │ ├── cbuff.h │ │ ├── llist.h │ │ └── types │ │ │ ├── cbuff.h │ │ │ └── llist.h │ ├── err │ │ ├── error.h │ │ └── panic.h │ ├── errno.h │ ├── fs │ │ ├── dirent.h │ │ ├── dirinfo.h │ │ ├── dirstream.h │ │ ├── fs.h │ │ ├── initrd.h │ │ ├── kfile.h │ │ ├── procfs.h │ │ └── stream.h │ ├── hal │ │ ├── clock │ │ │ └── clock.h │ │ ├── intr │ │ │ └── int_ctlr.h │ │ ├── io │ │ │ └── char │ │ │ │ └── char.h │ │ └── timer │ │ │ └── timer.h │ ├── intr │ │ ├── intr.h │ │ └── types │ │ │ └── intr.h │ ├── io │ │ ├── input.h │ │ └── output.h │ ├── kern │ │ └── cmdline.h │ ├── lambda │ │ ├── config_defs.h │ │ ├── export.h │ │ ├── mod │ │ │ └── module.h │ │ ├── platforms.h │ │ └── version.h │ ├── libgen.h │ ├── main │ │ └── main.h │ ├── mm │ │ ├── alloc.h │ │ ├── mm.h │ │ ├── mmap.h │ │ ├── mmu.h │ │ └── symbols.h │ ├── mod │ │ ├── module.h │ │ └── symbols.h │ ├── proc │ │ ├── atomic │ │ │ ├── lock.h │ │ │ ├── tlock.h │ │ │ └── types │ │ │ │ ├── lock.h │ │ │ │ └── tlock.h │ │ ├── cond.h │ │ ├── elf.h │ │ ├── exec.h │ │ ├── ktask │ │ │ ├── kbug.h │ │ │ ├── kinput.h │ │ │ └── kterm.h │ │ ├── ktasks.h │ │ ├── mtask.h │ │ ├── proc.h │ │ ├── syscalls.h │ │ ├── thread.h │ │ └── types │ │ │ ├── cond.h │ │ │ ├── elf.h │ │ │ ├── exec.h │ │ │ ├── kproc.h │ │ │ └── kthread.h │ ├── stdlib.h │ ├── string.h │ ├── sys │ │ ├── stat.h │ │ └── types.h │ ├── time │ │ └── time.h │ └── types.h ├── module.mk └── src │ ├── Kconfig │ ├── crypto │ ├── Kconfig │ ├── comp │ │ ├── comp.c │ │ ├── lzop.c │ │ └── module.mk │ └── module.mk │ ├── data │ ├── cbuff.c │ ├── llist.c │ └── module.mk │ ├── err │ ├── error.c │ ├── module.mk │ └── panic.c │ ├── fs │ ├── fs.c │ ├── initrd.c │ ├── module.mk │ ├── procfs.c │ ├── stat.c │ └── stream.c │ ├── intr │ ├── interrupts.c │ └── module.mk │ ├── io │ ├── input.c │ ├── module.mk │ └── output.c │ ├── kern │ ├── cmdline.c │ └── module.mk │ ├── main │ ├── main.c │ └── module.mk │ ├── mm │ ├── alloc.c │ ├── mm.c │ ├── mmap.c │ ├── mmu.c │ ├── module.mk │ └── symbols.c │ ├── mod │ ├── module.c │ ├── module.mk │ ├── preload.c │ └── symbols.c │ ├── module.mk │ ├── proc │ ├── Kconfig │ ├── atomic │ │ ├── lock.c │ │ ├── module.mk │ │ └── tlock.c │ ├── cond.c │ ├── elf │ │ ├── elf.c │ │ ├── elf_exec.c │ │ └── module.mk │ ├── exec.c │ ├── fork.c │ ├── ktask │ │ ├── kbug.c │ │ ├── kinput.c │ │ ├── ktasks.c │ │ ├── kterm.c │ │ └── module.mk │ ├── module.mk │ ├── mtask.c │ ├── proc.c │ ├── sched.c │ ├── syscalls.c │ ├── thread.c │ └── wait.c │ ├── std │ ├── libgen.c │ ├── module.mk │ ├── stdlib.c │ └── string.c │ └── time │ ├── delay.c │ ├── module.mk │ └── time.c └── scripts ├── build-cross-compiler.sh ├── gdb ├── kalloc.py ├── llist.py └── threads.py └── symbols /.defconfig: -------------------------------------------------------------------------------- 1 | CONFIG_ARCH_X86=y 2 | # CONFIG_ARCH_ARM32 is not set 3 | # CONFIG_ARCH_RISCV is not set 4 | 5 | # 6 | # x86 architecture 7 | # 8 | # CONFIG_ARCH_CPU_386 is not set 9 | CONFIG_ARCH_CPU_486=y 10 | # CONFIG_ARCH_CPU_P5 is not set 11 | # CONFIG_ARCH_CPU_P6 is not set 12 | CONFIG_ARCH_HW_PC=y 13 | 14 | # 15 | # CPU Features 16 | # 17 | 18 | # 19 | # Paging 20 | # 21 | CONFIG_X86_PAGING_KERNEL_WP=y 22 | # end of Paging 23 | 24 | # CONFIG_X86_APIC is not set 25 | # end of CPU Features 26 | 27 | CONFIG_MULTIBOOT=y 28 | CONFIG_MULTIBOOT_VERSION=2 29 | # end of x86 architecture 30 | 31 | CONFIG_LOG_COLORCODE=y 32 | # CONFIG_EMBEDDED_INITRD is not set 33 | CONFIG_SAFETY_CHECKS=y 34 | CONFIG_STRICTNESS=255 35 | 36 | # 37 | # Processes and threads 38 | # 39 | CONFIG_PROC_KERN_STACK_SIZE=4096 40 | CONFIG_PROC_USER_STACK_SIZE=32768 41 | CONFIG_PROC_USER_STACK_SIZE_MAX=65536 42 | # CONFIG_PROC_STACK_GUARD is not set 43 | # CONFIG_KTASK_DEBUGGER is not set 44 | # end of Processes and threads 45 | 46 | # 47 | # General build options 48 | # 49 | CONFIG_BUILD_USE_WERROR=y 50 | # CONFIG_BUILD_USE_CLANG is not set 51 | # end of General build options 52 | -------------------------------------------------------------------------------- /.gdbinit: -------------------------------------------------------------------------------- 1 | source scripts/gdb/llist.py 2 | source scripts/gdb/threads.py 3 | source scripts/gdb/kalloc.py 4 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Object files 2 | *.o 3 | *.ko 4 | *.bc 5 | *.ll 6 | *.d 7 | 8 | # Build config 9 | .config 10 | .config.old 11 | 12 | # Libraries 13 | *.lib 14 | *.a 15 | *.shared 16 | 17 | # Shared objects (inc. Windows DLLs) 18 | *.dll 19 | *.so 20 | *.so.* 21 | *.dylib 22 | 23 | # Executables 24 | *.exe 25 | *.out 26 | *.app 27 | 28 | # Folders 29 | .kdev4 30 | 31 | # Config Files 32 | *.kdev4 33 | 34 | # Output files 35 | *.kern 36 | *.iso 37 | *.cpio 38 | *.bin 39 | *.ukern 40 | *.img 41 | *.log 42 | 43 | # GRUB files 44 | stage2_eltorito 45 | 46 | # vim 47 | *.swp 48 | *.swo 49 | 50 | # Visual Studio Code 51 | .vscode 52 | 53 | # Doxygen output 54 | doc 55 | 56 | # Debug files 57 | .gdb_history 58 | __pycache__ 59 | 60 | # ctags 61 | tags 62 | .cache/ 63 | compile_commands.json 64 | 65 | -------------------------------------------------------------------------------- /Kconfig: -------------------------------------------------------------------------------- 1 | mainmenu "Lambda Kernel Configuration" 2 | 3 | source "kernel/Kconfig" 4 | 5 | menu "General build options" 6 | 7 | config BUILD_USE_WERROR 8 | bool "Enable -Werror" 9 | default y 10 | help 11 | Passes the -Werror flag to the compiler, treating any warning as an error. 12 | This should typically be enabled, except during active development, as 13 | builds should be warning-free. 14 | 15 | config BUILD_USE_CLANG 16 | bool "Use Clang as the compiler" 17 | default n 18 | help 19 | Configures the build system to use Clang rather than GCC (or compatible) 20 | as the compiler. Note that this may not be well-supported for all targets. 21 | 22 | config BUILD_USE_WEVERYTHING 23 | bool "Enable -Weverything" 24 | depends on BUILD_USE_CLANG 25 | default n 26 | help 27 | Passes the -Weverything flag to Clang, enabling many more warnings. Note 28 | that some warnings are explicitly disabled while this is enabled. Do not 29 | expect -Weverything + -Werror to succeed after a Clang update. 30 | 31 | endmenu # General build options 32 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2013-2022 Peter Farley 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Lambda Kernel 2 | ============= 3 | 4 | Lambda OS is a hobby operating system developed by Peter Farley. Lambda OS 5 | is designed to be portable to multiple systems, and currently supports 6 | x86-based PCs, ARMv7 (Cortex-A9) support is in progress, and x86_64 and RISCV 7 | (RV64I) support is planned. 8 | 9 | **NOTE**: This repository only contains the kernel portion of Lambda OS. For a 10 | usable implementation of the kernel, see the lambda-os repository. 11 | 12 | Platform support: 13 | - x86 14 | - x86 PC (platform with the most support) 15 | - ARMv7 16 | - Cortex-A9 17 | - Versatile Express A9 (early stages; partially dropped) 18 | - Cortex-A53 19 | - Broadcom BCM2836/7 (Raspberry Pi) (early stages) 20 | 21 | Building 22 | -------- 23 | 24 | To be able to build the Lambda kernel, you need the following tools: 25 | - `gcc` 26 | - If using `gcc`, you must use a cross-compiler. There is a convenience script for building one: `scripts/build-cross-compiler.sh` 27 | - TODO: reintroduce clang support 28 | - `make` 29 | - `eu-readelf` (elfutils) 30 | - `menuconfig` or similar, for easy configuration 31 | - Not required, `.config` file can be modified by hand 32 | - If no `.config` file is present, `.defconfig` is used instead 33 | - For a standalone Kconfig-compatible `menuconfig`, see [Kconfiglib](https://github.com/ulfalizer/Kconfiglib) 34 | 35 | 36 | To build kernel: 37 | - (If fisrt time) Clone the `lambda-kern` code repository 38 | - (If not first time) Run `git pull` 39 | - If you wish to make changes to the configuration: `menuconfig` (or similar) 40 | - Default config targets x86 41 | - Make: `make CROSS_COMPILE=` 42 | - `CROSS_COMPILE` is not necessary when using Clang 43 | - Clang can be enabled via CONFIG_BUILD_USE_CLANG in the config 44 | - Using clang with ARM is currently not fully supported 45 | - To speed up compilation, add `-j` argument to the `make` command 46 | -------------------------------------------------------------------------------- /kernel/Kconfig: -------------------------------------------------------------------------------- 1 | source "kernel/arch/Kconfig" 2 | source "kernel/src/Kconfig" 3 | 4 | -------------------------------------------------------------------------------- /kernel/arch/Kconfig: -------------------------------------------------------------------------------- 1 | # Architecture config 2 | 3 | choice 4 | prompt "Target arhitecture" 5 | default ARCH_X86 6 | 7 | config ARCH_X86 8 | bool "X86 (32-bit)" 9 | 10 | config ARCH_ARM32 11 | bool "ARM (32-bit)" 12 | 13 | config ARCH_RISCV 14 | bool "RISCV (32-bit)" 15 | 16 | endchoice # Target architecture 17 | 18 | source "kernel/arch/x86/Kconfig" 19 | source "kernel/arch/arm32/Kconfig" 20 | source "kernel/arch/riscv/Kconfig" 21 | 22 | -------------------------------------------------------------------------------- /kernel/arch/arm32/Kconfig: -------------------------------------------------------------------------------- 1 | menu "ARM32 architecture" 2 | depends on ARCH_ARM32 3 | 4 | choice 5 | prompt "CPU family" 6 | 7 | config ARCH_CPU_CORTEX_A7 8 | bool "Cortex A7" 9 | 10 | config ARCH_CPU_CORTEX_A9 11 | bool "Cortex A9" 12 | 13 | config ARCH_CPU_CORTEX_A53 14 | bool "Cortex A53" 15 | 16 | endchoice # CPU family 17 | 18 | choice 19 | prompt "Hardware platform" 20 | 21 | config ARCH_HW_ARM_VEXPRESS_A9 22 | bool "ARM Versatile Express A9" 23 | select ARCH_CPU_CORTEX_A9 24 | 25 | config ARCH_HW_ALLWINNER_V3S 26 | bool "Allwinner V3s (unsupported)" 27 | select ARCH_CPU_CORTEX_A7 28 | 29 | config ARCH_HW_BROADCOM_BCM2837 30 | bool "Broadcom BCM2837" 31 | select ARCH_CPU_CORTEX_A53 32 | 33 | endchoice # Hardware platform 34 | 35 | endmenu # ARM32 architecture 36 | 37 | -------------------------------------------------------------------------------- /kernel/arch/arm32/hw/arm_versatilepb/hw.ld: -------------------------------------------------------------------------------- 1 | ENTRY (reset) 2 | 3 | SECTIONS 4 | { 5 | . = 0x00008000; 6 | 7 | kern_start = .; 8 | 9 | .text : { 10 | *(.entryp) 11 | *(.text) 12 | } 13 | 14 | .rodata : { 15 | *(.rodata) 16 | } 17 | 18 | .data : { 19 | *(.data) 20 | } 21 | 22 | .bss : { 23 | *(COMMON) 24 | *(.bss) 25 | } 26 | 27 | kern_end = .; 28 | 29 | new_stack_begin = .; 30 | . += 0x10000; 31 | new_stack_end = .; 32 | 33 | intr_stack_begin = .; 34 | . += 0x2000; 35 | intr_stack_end = .; 36 | 37 | } -------------------------------------------------------------------------------- /kernel/arch/arm32/hw/arm_vexpress_a9/hw.ld: -------------------------------------------------------------------------------- 1 | ENTRY (reset) 2 | 3 | SECTIONS 4 | { 5 | . = 0x60000000; 6 | 7 | kern_start = .; 8 | 9 | .text : { 10 | __kernel_text_begin = .; 11 | *(.entryp) 12 | *(.text) 13 | __kernel_text_end = .; 14 | } 15 | 16 | .rodata : { 17 | __kernel_rodata_begin = .; 18 | *(.rodata) 19 | 20 | . = ALIGN(8); 21 | __lambda_symbols_begin = .; 22 | *(.__lambda_symbols) 23 | __lambda_symbols_end = .; 24 | 25 | . = ALIGN(8); 26 | __lambda_strings_begin = .; 27 | *(.__lambda_strings) 28 | __lambda_strings_end = .; 29 | 30 | __kernel_rodata_end = .; 31 | } 32 | 33 | .data : { 34 | __kernel_data_begin = .; 35 | *(.data) 36 | __kernel_data_end = .; 37 | } 38 | 39 | .bss : { 40 | __kernel_bss_begin = .; 41 | *(COMMON) 42 | *(.bss) 43 | __kernel_bss_end = .; 44 | } 45 | 46 | kern_end = .; 47 | 48 | new_stack_begin = .; 49 | . += 0x10000; 50 | new_stack_end = .; 51 | 52 | fiq_stack_begin = .; 53 | . += 0x2000; 54 | fiq_stack_end = .; 55 | 56 | irq_stack_begin = .; 57 | . += 0x2000; 58 | irq_stack_end = .; 59 | 60 | } -------------------------------------------------------------------------------- /kernel/arch/arm32/hw/arm_vexpress_a9/module.mk: -------------------------------------------------------------------------------- 1 | # HW-specific Makefile options for ARM VExpress A9 2 | 3 | MDIR = $(dir $(lastword $(MAKEFILE_LIST))) 4 | 5 | CPU = cortex_a9 6 | 7 | KERNEL_OFFSET = 0x00000000 8 | 9 | cflags-y += -march=armv7-a \ 10 | -DKERNEL_OFFSET=${KERNEL_OFFSET} 11 | ldflags-y += -T $(HWDIR)/hw.ld 12 | 13 | # TODO: Make this command-line selectable: 14 | cflags-y += -DCONFIG_ARCH_CPU_ARM_CORTEX_A9 \ 15 | -DCONFIG_ARCH_HW_ARM_VEXPRESS_A9 16 | 17 | asflags-y += -march=armv7-a 18 | 19 | ifeq ($(CONFIG_BUILD_USE_CLANG),y) 20 | cflags-y += -target armv7--eabi -mcpu=cortex-a9 21 | asflags-y += -target armv7--eabi -mcpu=cortex-a9 22 | endif 23 | 24 | include $(MDIR)src/module.mk 25 | 26 | 27 | $(BUILDDIR)/lambda.ukern: $(BUILDDIR)/lambda.kern 28 | @echo -e "\033[33m \033[1mGenerating U-Boot compatible kernel image\033[0m" 29 | $(Q) mkimage -A arm -C none -T kernel -a 0x60000000 -r 0x60000000 -d $< $@ 30 | 31 | $(BUILDDIR)/sd.img: $(BUILDDIR)/lambda.ukern 32 | @echo -e "\033[33m \033[1mGenerating SD card image\033[0m" 33 | # TODO: Find a way to do this without resorting to SUDO 34 | kernel/arch/armv7/sdimg.sh 35 | 36 | 37 | emu: $(BUILDDIR)/lambda.kern 38 | @qemu-system-arm -cpu cortex-a9 -machine vexpress-a9 -kernel $< -serial stdio -no-reboot 39 | 40 | emu-debug: $(BUILDDIR)/lambda.kern 41 | @qemu-system-arm -cpu cortex-a9 -machine vexpress-a9 -kernel $< -serial stdio -no-reboot -s -S 42 | -------------------------------------------------------------------------------- /kernel/arch/arm32/hw/arm_vexpress_a9/src/boot/boot.s: -------------------------------------------------------------------------------- 1 | .section .entryp 2 | 3 | .extern __int_wrap_undefined 4 | .extern __int_wrap_syscall 5 | .extern __int_wrap_prefetchabort 6 | .extern __int_wrap_dataabort 7 | .extern __int_wrap_hyptrap 8 | .extern __int_wrap_irq 9 | .extern __int_wrap_fiq 10 | 11 | .global __int_table 12 | __int_table: 13 | b reset 14 | b __int_wrap_undefined 15 | b __int_wrap_syscall 16 | b __int_wrap_prefetchabort 17 | b __int_wrap_dataabort 18 | b __int_wrap_hyptrap 19 | b __int_wrap_irq 20 | b __int_wrap_fiq 21 | 22 | .extern kentry 23 | .extern new_stack_end 24 | .extern irq_stack_end 25 | .extern fiq_stack_end 26 | .global reset 27 | .type reset, %function 28 | reset: 29 | /* Stack initialization for various modes */ 30 | /* FIQ: */ 31 | msr cpsr_c, 0x11 /* FIQ mode */ 32 | ldr sp, =fiq_stack_end 33 | 34 | msr cpsr_c, 0x12 /* IRQ mode */ 35 | ldr sp, =irq_stack_end 36 | 37 | msr cpsr_c, 0x13 /* SVC mode */ 38 | ldr sp, =new_stack_end 39 | 40 | /*ldr r0, =new_stack_end 41 | mov sp, r0*/ 42 | bl kentry 43 | 44 | endloop: 45 | wfi 46 | b endloop 47 | 48 | .size reset, . - reset 49 | -------------------------------------------------------------------------------- /kernel/arch/arm32/hw/arm_vexpress_a9/src/boot/entry.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include
4 | #include 5 | #include 6 | 7 | #include 8 | 9 | __noreturn void kentry(void); 10 | 11 | /** 12 | * Kernel entry-point: performs target-specific system initialization. 13 | */ 14 | __noreturn void kentry(void) { 15 | arch_init(); 16 | 17 | fs_init(); 18 | 19 | kmain(); 20 | } 21 | -------------------------------------------------------------------------------- /kernel/arch/arm32/hw/arm_vexpress_a9/src/boot/module.mk: -------------------------------------------------------------------------------- 1 | MDIR = $(dir $(lastword $(MAKEFILE_LIST))) 2 | 3 | obj-y += $(MDIR)boot.o \ 4 | $(MDIR)entry.o 5 | 6 | -------------------------------------------------------------------------------- /kernel/arch/arm32/hw/arm_vexpress_a9/src/init/module.mk: -------------------------------------------------------------------------------- 1 | MDIR = $(dir $(lastword $(MAKEFILE_LIST))) 2 | 3 | obj-y += $(MDIR)hw_init.o 4 | 5 | -------------------------------------------------------------------------------- /kernel/arch/arm32/hw/arm_vexpress_a9/src/module.mk: -------------------------------------------------------------------------------- 1 | MDIR = $(dir $(lastword $(MAKEFILE_LIST))) 2 | 3 | dirs-y := boot \ 4 | init 5 | 6 | include $(patsubst %,$(MDIR)%/module.mk,$(dirs-y)) 7 | 8 | -------------------------------------------------------------------------------- /kernel/arch/arm32/hw/broadcom_bcm2837/hw.ld: -------------------------------------------------------------------------------- 1 | PHYS_ENTRYPOINT = 0x00008000; 2 | VIRT_OFFSET = 0xC0000000; 3 | 4 | ENTRY(reset) 5 | 6 | SECTIONS 7 | { 8 | . = PHYS_ENTRYPOINT + VIRT_OFFSET; 9 | 10 | kern_start = .; 11 | 12 | .text : AT(ADDR(.text) - VIRT_OFFSET) { 13 | __kernel_text_begin = .; 14 | *(.entryp) 15 | *(.text.*) 16 | __kernel_text_end = .; 17 | } 18 | 19 | .rodata : AT(ADDR(.rodata) - VIRT_OFFSET) { 20 | __kernel_rodata_begin = .; 21 | *(.rodata.*) 22 | 23 | . = ALIGN(8); 24 | __lambda_symbols_begin = .; 25 | *(.__lambda_symbols) 26 | __lambda_symbols_end = .; 27 | 28 | . = ALIGN(8); 29 | __lambda_strings_begin = .; 30 | *(.__lambda_strings) 31 | __lambda_strings_end = .; 32 | 33 | __kernel_rodata_end = .; 34 | } 35 | 36 | .data : AT(ADDR(.data) - VIRT_OFFSET) { 37 | __kernel_data_begin = .; 38 | *(.data*) 39 | __kernel_data_end = .; 40 | 41 | } 42 | 43 | .bss (NOLOAD) : AT(ADDR(.bss) - VIRT_OFFSET) { 44 | __kernel_bss_begin = .; 45 | *(COMMON) 46 | *(.bss .bss.*) 47 | __kernel_bss_end = .; 48 | } 49 | 50 | kern_end = .; 51 | 52 | new_stack_begin = .; 53 | . += 0x10000; 54 | new_stack_end = .; 55 | 56 | fiq_stack_begin = .; 57 | . += 0x2000; 58 | fiq_stack_end = .; 59 | 60 | irq_stack_begin = .; 61 | . += 0x2000; 62 | irq_stack_end = .; 63 | 64 | } -------------------------------------------------------------------------------- /kernel/arch/arm32/hw/broadcom_bcm2837/inc/arch/intr/bcm2835_intctlr.h: -------------------------------------------------------------------------------- 1 | #ifndef ARCH_ARM32_INTR_BCM2835_INTCTLR_H 2 | #define ARCH_ARM32_INTR_BCM2835_INTCTLR_H 3 | 4 | #include 5 | 6 | #include 7 | 8 | typedef struct { 9 | uint32_t irq_basic_pending; 10 | uint32_t irq_pending[2]; 11 | uint32_t fiq_ctrl; 12 | uint32_t irq_enable[2]; 13 | uint32_t irq_basic_enable; 14 | uint32_t irq_disable[2]; 15 | uint32_t irq_basic_disable; 16 | } bcm2835_intctlr_regmap_t; 17 | 18 | typedef enum { 19 | BCM2835_IRQ_SYSTIMER_MATCH1 = 1, 20 | BCM2835_IRQ_SYSTIMER_MATCH3 = 3, 21 | BCM2835_IRQ_USB_CONTROLLER = 9, 22 | BCM2835_IRQ_AUXILIARY = 29, 23 | BCM2835_IRQ_I2C_SPI_SLAVE = 43, 24 | BCM2835_IRQ_PWA0 = 45, 25 | BCM2835_IRQ_PWA1 = 45, 26 | BCM2835_IRQ_SMI = 48, 27 | BCM2835_IRQ_GPIO_0 = 49, 28 | BCM2835_IRQ_GPIO_1 = 50, 29 | BCM2835_IRQ_GPIO_2 = 51, 30 | BCM2835_IRQ_GPIO_3 = 52, 31 | BCM2835_IRQ_I2C = 53, 32 | BCM2835_IRQ_SPI = 54, 33 | BCM2835_IRQ_PCM = 55, 34 | BCM2835_IRQ_UART = 57, 35 | } bcm2835_irq_e; 36 | 37 | typedef enum { 38 | BCM2835_INT_TIMER = 0, 39 | BCM2835_INT_MAILBOX = 1, 40 | BCM2835_INT_DOORBELL0 = 2, 41 | BCM2835_INT_DOORBELL1 = 3, 42 | BCM2835_INT_GPU0_HALT = 4, 43 | BCM2835_INT_GPU1_HALT = 5, 44 | BCM2835_INT_ILL_ACCESS_T1 = 6, 45 | BCM2835_INT_ILL_ACCESS_T2 = 7, 46 | BCM2835_INT_GPUIRQ_0 = 8, 47 | BCM2835_INT_GPUIRQ_1 = 9, 48 | 49 | BCM2835_INT_OFFSET = 128 /*!< Add this offset when registering one of these interrupts */ 50 | } bcm2835_int_e; 51 | 52 | typedef struct { 53 | uint32_t int_n; 54 | void *data; 55 | 56 | void (*callback)(uint32_t, void *); 57 | } bcm2835_intctlr_callback_t; 58 | 59 | typedef struct { 60 | bcm2835_intctlr_regmap_t *regmap; 61 | 62 | #define BCM2835_INTCTLR_MAX_CALLBACKS (16) 63 | bcm2835_intctlr_callback_t callbacks[BCM2835_INTCTLR_MAX_CALLBACKS]; 64 | } bcm2835_intctlr_handle_t; 65 | 66 | int bcm2835_intctlr_create_intctlrdev(bcm2835_intctlr_handle_t *hand, hal_intctlr_dev_t *intctlrdev); 67 | 68 | int bcm2835_intctlr_init(bcm2835_intctlr_handle_t *hand, volatile void *base); 69 | 70 | int bcm2835_intctlr_irqhandle(bcm2835_intctlr_handle_t *hand); 71 | 72 | #endif 73 | -------------------------------------------------------------------------------- /kernel/arch/arm32/hw/broadcom_bcm2837/inc/arch/intr/timer/bcm2835_systimer.h: -------------------------------------------------------------------------------- 1 | #ifndef ARCH_ARM32_INTR_TIMER_BCM2835_SYSTIMER_H 2 | #define ARCH_ARM32_INTR_TIMER_BCM2835_SYSTIMER_H 3 | 4 | #include 5 | 6 | #include 7 | #include 8 | #include 9 | 10 | typedef struct { 11 | volatile uint32_t status; /*!< Control & status */ 12 | #define BCM2835_SYSTIMER_STATUS_M0__POS (0UL) /*!< Timer 0 match */ 13 | #define BCM2835_SYSTIMER_STATUS_M1__POS (1UL) /*!< Timer 1 match */ 14 | #define BCM2835_SYSTIMER_STATUS_M2__POS (2UL) /*!< Timer 2 match */ 15 | #define BCM2835_SYSTIMER_STATUS_M3__POS (3UL) /*!< Timer 3 match */ 16 | volatile uint32_t count_l; /*!< Lower 32-bits of counter */ 17 | volatile uint32_t count_h; /*!< Upper 32-bits of counter */ 18 | volatile uint32_t compare[4]; /*!< Four timer comparison values */ 19 | } bcm2835_systimer_regmap_t; 20 | 21 | typedef struct { 22 | bcm2835_systimer_regmap_t *base; /*!< Register map base address */ 23 | hal_clock_dev_t *src_clock; /*!< Clock source for systimer */ 24 | 25 | uint32_t reload[2]; /*!< Reload values when timers expire */ 26 | 27 | void (*callbacks[2])(void); /*!< Registered callbacks */ 28 | } bcm2835_systimer_handle_t; 29 | 30 | int bcm2835_systimer_create_timerdev(bcm2835_systimer_handle_t *hand, hal_timer_dev_t *dev); 31 | 32 | int bcm2835_systimer_init(bcm2835_systimer_handle_t *hand, void *base); 33 | 34 | int bcm2835_systimer_int_attach(bcm2835_systimer_handle_t *hand, hal_intctlr_dev_t *intctlr); 35 | 36 | #endif 37 | -------------------------------------------------------------------------------- /kernel/arch/arm32/hw/broadcom_bcm2837/inc/arch/io/bcm2835_mailbox.h: -------------------------------------------------------------------------------- 1 | #ifndef ARCH_ARM32_INTR_BCM2835_MAILBOX_H 2 | #define ARCH_ARM32_INTR_BCM2835_MAILBOX_H 3 | 4 | #include 5 | 6 | #include 7 | 8 | typedef volatile struct { 9 | struct { 10 | uint32_t rw; 11 | uint32_t _reserved[3]; 12 | uint32_t peek; 13 | uint32_t sender; 14 | uint32_t status; 15 | #define BCM2835_MAILMOX_STATUS_EMPTY (1UL << 30) 16 | #define BCM2835_MAILMOX_STATUS_FULL (1UL << 31) 17 | uint32_t config; 18 | } box[2]; 19 | } bcm2835_mailbox_regmap_t; 20 | 21 | typedef enum { 22 | BCM2835_MAILBOX_CHAN_POWER = 0, 23 | BCM2835_MAILBOX_CHAN_FRAMEBUFFER = 1, 24 | BCM2835_MAILBOX_CHAN_VIRTUALUART = 2, 25 | BCM2835_MAILBOX_CHAN_VCHIQ = 3, 26 | BCM2835_MAILBOX_CHAN_LEDS = 4, 27 | BCM2835_MAILBOX_CHAN_BUTTONS = 5, 28 | BCM2835_MAILBOX_CHAN_TOUCHSCREEN = 6, 29 | 30 | BCM2835_MAILBOX_CHAN_PROPTAGS_TOVC = 8, 31 | BCM2835_MAILBOX_CHAN_PROPTAGS_FROMVC = 9, 32 | } bcm2835_mailbox_channel_e; 33 | 34 | static inline void bcm2835_mailbox_write(bcm2835_mailbox_regmap_t *regmap, uint8_t channel, uint32_t data) { 35 | while(regmap->box[1].status & BCM2835_MAILMOX_STATUS_FULL) {} 36 | regmap->box[1].rw = (data & 0xFFFFFFF0) | (channel & 0x0F); 37 | } 38 | 39 | static inline uint32_t bcm2835_mailbox_read(bcm2835_mailbox_regmap_t *regmap, uint8_t channel) { 40 | uint32_t read; 41 | do { 42 | while(regmap->box[0].status & BCM2835_MAILMOX_STATUS_EMPTY) {} 43 | read = regmap->box[0].rw; 44 | } while((read & 0x0F) != channel); 45 | 46 | return (read & 0xFFFFFFF0); 47 | } 48 | 49 | #endif 50 | -------------------------------------------------------------------------------- /kernel/arch/arm32/hw/broadcom_bcm2837/module.mk: -------------------------------------------------------------------------------- 1 | # HW-specific Makefile options for the Broadcom BCM2837 2 | 3 | MDIR = $(dir $(lastword $(MAKEFILE_LIST))) 4 | 5 | CPU = cortex_a53 6 | 7 | KERNEL_OFFSET = 0x00000000 8 | 9 | cflags-y += -march=armv7-a -marm \ 10 | -DKERNEL_OFFSET=${KERNEL_OFFSET} 11 | 12 | cflags-y += -DCONFIG_ARCH_CPU_CORTEX_A53 \ 13 | -DCONFIG_ARCH_HW_BROADCOM_BCM2837 14 | 15 | asflags-y += -march=armv7-a 16 | 17 | ifeq ($(CONFIG_BUILD_USE_CLANG),y) 18 | cflags-y += -target armv8--eabi -mcpu=cortex-a53 19 | asflags-y += -target armv8--eabi -mcpu=cortex-a53 20 | endif 21 | 22 | include $(MDIR)src/module.mk 23 | 24 | .DEFAULT_GOAL=$(BUILDDIR)/kernel7.img 25 | 26 | $(BUILDDIR)/kernel7.img: $(BUILDDIR)/lambda.kern 27 | @echo -e "\033[33m \033[1mProducing RPi binary\033[0m" 28 | $(Q) $(OBJCOPY) $< -O binary $@ 29 | 30 | 31 | $(BUILDDIR)/lambda.ukern: $(BUILDDIR)/lambda.kern 32 | @echo -e "\033[33m \033[1mGenerating U-Boot compatible kernel image\033[0m" 33 | $(Q) mkimage -A arm -C none -T kernel -a 0x00008000 -r 0x00008000 -d $< $@ 34 | 35 | 36 | #@qemu-system-aarch64 -M raspi3 -kernel $< -serial stdio -no-reboot 37 | emu: $(BUILDDIR)/lambda.kern 38 | @qemu-system-arm -M raspi2b -kernel $< -serial stdio -no-reboot 39 | 40 | #@qemu-system-aarch64 -M raspi3 -kernel $< -serial stdio -no-reboot -s -S 41 | emu-debug: $(BUILDDIR)/lambda.kern 42 | @qemu-system-arm -M raspi2b -kernel $< -serial stdio -no-reboot -s -S 43 | 44 | -------------------------------------------------------------------------------- /kernel/arch/arm32/hw/broadcom_bcm2837/src/boot/boot.s: -------------------------------------------------------------------------------- 1 | .section .entryp 2 | 3 | .global __int_table 4 | __int_table: 5 | b reset /* + 0x00 */ 6 | b __int_wrap_undefined /* + 0x04 */ 7 | b __int_wrap_syscall /* + 0x08 */ 8 | b __int_wrap_prefetchabort /* + 0x0C */ 9 | b __int_wrap_dataabort /* + 0x10 */ 10 | b __int_wrap_hyptrap /* + 0x14 */ 11 | b __int_wrap_irq /* + 0x18 */ 12 | b __int_wrap_fiq /* + 0x20 */ 13 | .size __int_table, . - __int_table 14 | 15 | .extern new_stack_end 16 | .extern irq_stack_end 17 | .extern fiq_stack_end 18 | 19 | .extern kern_premap 20 | .global reset 21 | .type reset, %function 22 | reset: 23 | /* Shutdown all cores but one: */ 24 | mrc p15, 0, r5, c0, c0, 5 25 | and r5, r5, #3 26 | cmp r5, #0 27 | bne endloop 28 | 29 | /* Check if we are in HYP mode */ 30 | mrs r0, cpsr 31 | and r2, r0, #0x1F 32 | mov r1, #0x1A 33 | cmp r2, r1 34 | bne _set_stacks 35 | 36 | _exit_hyp: 37 | bic r0, r0, #0x1F 38 | orr r0, r0, #0xD3 /* SVC, disabled interrupts */ 39 | orr r0, r0, #0x100 /* Disabled data abort */ 40 | msr spsr_cxsf, r0 41 | ldr lr, =_set_stacks 42 | .long 0xE12EF30E /* "msr ELR_hyp, lr" */ 43 | .long 0xE160006E /* "eret" */ 44 | 45 | _set_stacks: 46 | msr cpsr_c, 0x11 /* FIQ mode */ 47 | ldr sp, =fiq_stack_end 48 | msr cpsr_c, 0x12 /* IRQ mode */ 49 | ldr sp, =irq_stack_end 50 | msr cpsr_c, 0x17 /* ABT mode */ 51 | ldr sp, =irq_stack_end 52 | msr cpsr_c, 0x1B /* UND mode */ 53 | ldr sp, =irq_stack_end 54 | msr cpsr_c, 0x1F /* SVC mode */ 55 | ldr sp, =new_stack_end 56 | sub sp, sp, #0xC0000000 57 | 58 | bl kern_premap 59 | 60 | endloop: 61 | wfi 62 | b endloop 63 | 64 | .size reset, . - reset 65 | -------------------------------------------------------------------------------- /kernel/arch/arm32/hw/broadcom_bcm2837/src/boot/module.mk: -------------------------------------------------------------------------------- 1 | MDIR = $(dir $(lastword $(MAKEFILE_LIST))) 2 | 3 | obj-y += $(MDIR)boot.o \ 4 | $(MDIR)entry.o 5 | 6 | -------------------------------------------------------------------------------- /kernel/arch/arm32/hw/broadcom_bcm2837/src/init/module.mk: -------------------------------------------------------------------------------- 1 | MDIR = $(dir $(lastword $(MAKEFILE_LIST))) 2 | 3 | obj-y += $(MDIR)hw_init.o 4 | -------------------------------------------------------------------------------- /kernel/arch/arm32/hw/broadcom_bcm2837/src/intr/module.mk: -------------------------------------------------------------------------------- 1 | MDIR = $(dir $(lastword $(MAKEFILE_LIST))) 2 | 3 | obj-y += $(MDIR)bcm2835_intctlr.o 4 | 5 | dirs-y := timer 6 | 7 | include $(patsubst %,$(MDIR)%/module.mk,$(dirs-y)) 8 | 9 | -------------------------------------------------------------------------------- /kernel/arch/arm32/hw/broadcom_bcm2837/src/intr/timer/module.mk: -------------------------------------------------------------------------------- 1 | MDIR = $(dir $(lastword $(MAKEFILE_LIST))) 2 | 3 | obj-y += $(MDIR)bcm2835_systimer.o 4 | 5 | -------------------------------------------------------------------------------- /kernel/arch/arm32/hw/broadcom_bcm2837/src/module.mk: -------------------------------------------------------------------------------- 1 | MDIR = $(dir $(lastword $(MAKEFILE_LIST))) 2 | 3 | dirs-y := boot \ 4 | init \ 5 | intr 6 | 7 | include $(patsubst %,$(MDIR)%/module.mk,$(dirs-y)) 8 | 9 | -------------------------------------------------------------------------------- /kernel/arch/arm32/inc/arch/init/hw_init.h: -------------------------------------------------------------------------------- 1 | #ifndef ARCH_ARM32_HW_INIT_H 2 | #define ARCH_ARM32_HW_INIT_H 3 | 4 | /* These are common fuctions that are provided by the HW platforms. See 5 | * hw//init/hwinit.c */ 6 | 7 | #include 8 | 9 | /** 10 | * @brief Initialize console (typically serial) used by kernel for early boot messages 11 | */ 12 | int hw_init_console(void); 13 | 14 | /** 15 | * @brief Initialize interrupt controller 16 | */ 17 | int hw_init_interrupts(void); 18 | 19 | /** 20 | * @brief Initialize memory management 21 | */ 22 | int hw_init_mm(void); 23 | 24 | /** 25 | * @brief Initialize timers for timekeeping and task switching 26 | * 27 | * @param rate Rate of clock keeping kernel time 28 | */ 29 | int hw_init_timer(uint32_t rate); 30 | 31 | #endif 32 | -------------------------------------------------------------------------------- /kernel/arch/arm32/inc/arch/init/init.h: -------------------------------------------------------------------------------- 1 | /** \file init.h 2 | * \brief Defines initialization function(s) for the target architecture. 3 | * 4 | */ 5 | 6 | #ifndef ARCH_ARM32_INIT_H 7 | #define ARCH_ARM32_INIT_H 8 | 9 | #include 10 | 11 | extern hal_intctlr_dev_t intctlr; 12 | 13 | void arch_init(void); 14 | 15 | #endif -------------------------------------------------------------------------------- /kernel/arch/arm32/inc/arch/intr/gtimer.h: -------------------------------------------------------------------------------- 1 | /** \file gtimer.h 2 | * \brief Contains support for the ARMv7 (optional) generic timer. 3 | * 4 | */ 5 | #ifndef ARCH_ARM32_INTR_GTIMER_H 6 | #define ARCH_ARM32_INTR_GTIMER_H 7 | 8 | #include 9 | 10 | #include 11 | 12 | void armv7_gtimer_create_timerdev(hal_timer_dev_t *dev); 13 | 14 | int armv7_gtimer_init(uint32_t freq); 15 | 16 | /** Clock frequency, in Hz */ 17 | #define __READ_CNTFRQ(VAR) __mrc(VAR, p15, 0, c14, c0, 0) 18 | #define __WRITE_CNTFRQ(VAR) __mcr(VAR, p15, 0, c14, c0, 0) 19 | 20 | #define __READ_CNTHCTL(VAR) __mrc(VAR, p15, 4, c14, c1, 0) 21 | #define __WRITE_CNTHCTL(VAR) __mcr(VAR, p15, 4, c14, c1, 0) 22 | 23 | #define __READ_CNTHP_CTL(VAR) __mrc(VAR, p15, 4, c14, c2, 1) 24 | #define __WRITE_CNTHP_CTL(VAR) __mcr(VAR, p15, 4, c14, c2, 1) 25 | 26 | #define __READ_CNTHP_CVAL(VARL, VARH) __mrrc(VARL, VARH, p15, 6, c14) 27 | #define __WRITE_CNTHP_CVAL(VARL, VARH) __mcrr(VARL, VARH, p15, 6, c14) 28 | 29 | #define __READ_CNTHP_TVAL(VAR) __mrc(VAR, p15, 4, c14, c2, 0) 30 | #define __WRITE_CNTHP_TVAL(VAR) __mcr(VAR, p15, 4, c14, c2, 0) 31 | 32 | #define __READ_CNTKCTL(VAR) __mrc(VAR, p15, 0, c14, c1, 0) 33 | #define __WRITE_CNTKCTL(VAR) __mcr(VAR, p15, 0, c14, c1, 0) 34 | 35 | #define __READ_CNTPCTL(VAR) __mrc(VAR, p15, 0, c14, c2, 1) 36 | #define __WRITE_CNTPCTL(VAR) __mcr(VAR, p15, 0, c14, c2, 1) 37 | 38 | #define __READ_CNTP_CVAL(VARL, VARH) __mrrc(VARL, VARH, p15, 2, c14) 39 | #define __WRITE_CNTP_CVAL(VARL, VARH) __mcrr(VARL, VARH, p15, 2, c14) 40 | 41 | #define __READ_CNTP_TVAL(VAR) __mrc(VAR, p15, 0, c14, c2, 0) 42 | #define __WRITE_CNTP_TVAL(VAR) __mcr(VAR, p15, 0, c14, c2, 0) 43 | 44 | #define __READ_CNTPCT(VARL, VARH) __mrrc(VARL, VARH, p15, 0, c14) 45 | 46 | #define __READ_CNTV_CTL(VAR) __mrc(VAR, p15, 0, c14, c3, 1) 47 | #define __WRITE_CNTV_CTL(VAR) __mcr(VAR, p15, 0, c14, c3, 1) 48 | 49 | #define __READ_CNTV_CVAL(VARL, VARH) __mrrc(VARL, VARH, p15, 3, c14) 50 | #define __WRITE_CNTV_CVAL(VARL, VARH) __mcrr(VARL, VARH, p15, 3, c14) 51 | 52 | #define __READ_CNTV_TVAL(VAR) __mrc(VAR, p15, 0, c14, c3, 0) 53 | #define __WRITE_CNTV_TVAL(VAR) __mcr(VAR, p15, 0, c14, c3, 0) 54 | 55 | #define __READ_CNTVCT(VARL, VARH) __mrrc(VARL, VARH, p15, 1, c14) 56 | 57 | #define __READ_CNTVOFF(VARL, VARH) __mrrc(VARL, VARH, p15, 4, c14) 58 | #define __WRITE_CNTVOFF(VARL, VARH) __mcrr(VARL, VARH, p15, 4, c14) 59 | 60 | #endif -------------------------------------------------------------------------------- /kernel/arch/arm32/inc/arch/intr/int.h: -------------------------------------------------------------------------------- 1 | #ifndef INT_FUNCS_H 2 | #define INT_FUNCS_H 3 | 4 | #include 5 | 6 | #include 7 | #include 8 | 9 | #define enable_interrupts() asm volatile("cpsie i") 10 | #define disable_interrupts() asm volatile("cpsid i") 11 | #define interrupt_halt() asm volatile("wfi") 12 | #define busy_wait() asm volatile("wfi") 13 | //#define interrupt_halt() asm volatile("nop") 14 | //#define busy_wait() asm volatile("nop") 15 | 16 | #define enable_fiqs() asm volatile("cpsie f") 17 | #define disable_fiqs() asm volatile("cpsid f") 18 | 19 | 20 | 21 | 22 | #include 23 | 24 | static inline int interrupts_enabled() { 25 | uint32_t tmp; 26 | asm volatile("mrs %0, cpsr" : "=r" (tmp)); 27 | return !(tmp & 0x80); 28 | } 29 | 30 | void intr_set_handler(interrupt_idx_e idx, intr_handler_hand_t *hdlr); 31 | 32 | void intr_init(void); 33 | 34 | void intr_attach_irqhandler(void (*handler)(void *), void *data); 35 | 36 | /** 37 | * @brief Attach handler for interrupt 38 | * 39 | * @param idx Interrupt ID 40 | * @param hdlr Interrupt handler handle 41 | */ 42 | static inline void arch_interrupt_attach(interrupt_idx_e n, intr_handler_hand_t *hdlr) { 43 | // idt_add_callback((uint8_t)n, hdlr); 44 | intr_set_handler(n, hdlr); 45 | } 46 | 47 | /** 48 | * @brief Call syscall 49 | * 50 | * @param scn Syscall number 51 | * @param args Pointer to arguments list 52 | */ 53 | static inline void arch_call_syscall(uint32_t scn, syscallarg_t *args) { 54 | (void)scn; 55 | (void)args; 56 | /* @todo */ 57 | asm volatile("swi #1"); 58 | } 59 | 60 | /** 61 | * @brief Force division by zero, for debugging purposes 62 | */ 63 | static inline void arch_div0(void) { 64 | /* @todo */ 65 | #if 0 66 | asm volatile("mov r0, #0 \n" 67 | "sdiv r0, r0, r0\n" 68 | ::: "%r0"); 69 | #endif 70 | } 71 | 72 | #endif 73 | -------------------------------------------------------------------------------- /kernel/arch/arm32/inc/arch/intr/syscall.h: -------------------------------------------------------------------------------- 1 | #ifndef ARCH_INTR_SYSCALL_H 2 | #define ARCH_INTR_SYSCALL_H 3 | 4 | #include 5 | 6 | /** 7 | * @brief Architecture-specific handler for the syscall interrupt, calls syscall_service 8 | */ 9 | void arch_syscall_interrupt(intr_handler_hand_t *hdlr); 10 | 11 | #endif 12 | 13 | -------------------------------------------------------------------------------- /kernel/arch/arm32/inc/arch/intr/types/intr.h: -------------------------------------------------------------------------------- 1 | #ifndef ARCH_INTR_TYPES_INTR_H 2 | #define ARCH_INTR_TYPES_INTR_H 3 | 4 | typedef enum arm32_interrupt_idx_enum { 5 | INTR_RESET = 0, 6 | INTR_UNDEFINED = 1, 7 | INTR_SYSCALL = 2, 8 | INTR_PREFETCHABORT = 3, 9 | INTR_DATAABORT = 4, 10 | INTR_HYPTRAP = 5, 11 | INTR_IRQ = 6, 12 | INTR_FIQ = 7, 13 | INTR_MAX = 8 14 | } interrupt_idx_e; 15 | 16 | /** Data stored on stack by interrupt handlers */ 17 | typedef struct arm32_intr_frame_struct { 18 | uint32_t _padding; /**< Padding for 8-byte stack alignment */ 19 | uint32_t cpsr; /**< USR Current Program Status Register */ 20 | uint32_t r[13]; /**< USR R0-R12 */ 21 | uint32_t lr; /**< Link Register */ 22 | } arm32_intr_frame_t; 23 | 24 | typedef struct arm32_intr_handler_hand_data_struct { 25 | uint32_t int_n; /**< Interrupt number */ 26 | arm32_intr_frame_t *frame; /**< Saved interrupts on interrupt */ 27 | } arch_intr_handler_hand_data_t; 28 | 29 | #endif 30 | 31 | -------------------------------------------------------------------------------- /kernel/arch/arm32/inc/arch/plat/cpu/cortex_a53.h: -------------------------------------------------------------------------------- 1 | #ifndef ARCH_PLAT_CPU_CORTEX_A9_H 2 | #define ARCH_PLAT_CPU_CORTEX_A9_H 3 | 4 | #define MPCORE_PERIPHBASE_OFF_SCU (0x0000UL) 5 | #define MPCORE_PERIPHBASE_OFF_ICC (0x0100UL) 6 | #define MPCORE_PERIPHBASE_OFF_GTIMER (0x0200UL) 7 | #define MPCORE_PERIPHBASE_OFF_PTIMER (0x0600UL) 8 | #define MPCORE_PERIPHBASE_OFF_DCU (0x1000UL) 9 | 10 | #endif -------------------------------------------------------------------------------- /kernel/arch/arm32/inc/arch/plat/cpu/cortex_a7.h: -------------------------------------------------------------------------------- 1 | #ifndef ARCH_PLAT_CPU_CORTEX_A7_H 2 | #define ARCH_PLAT_CPU_CORTEX_A7_H 3 | 4 | /* TODO */ 5 | 6 | #endif -------------------------------------------------------------------------------- /kernel/arch/arm32/inc/arch/plat/cpu/cortex_a9.h: -------------------------------------------------------------------------------- 1 | #ifndef ARCH_PLAT_CPU_CORTEX_A9_H 2 | #define ARCH_PLAT_CPU_CORTEX_A9_H 3 | 4 | #define MPCORE_PERIPHBASE_OFF_SCU (0x0000UL) 5 | #define MPCORE_PERIPHBASE_OFF_ICC (0x0100UL) 6 | #define MPCORE_PERIPHBASE_OFF_GTIMER (0x0200UL) 7 | #define MPCORE_PERIPHBASE_OFF_PTIMER (0x0600UL) 8 | #define MPCORE_PERIPHBASE_OFF_DCU (0x1000UL) 9 | 10 | #endif -------------------------------------------------------------------------------- /kernel/arch/arm32/inc/arch/plat/hw/allwinner_v3s.h: -------------------------------------------------------------------------------- 1 | #ifndef ARCH_PLAT_HW_ALLWINNER_V3S_H 2 | #define ARCH_PLAT_HW_ALLWINNER_V3S_H 3 | 4 | #include 5 | 6 | /* TODO */ 7 | 8 | #endif -------------------------------------------------------------------------------- /kernel/arch/arm32/inc/arch/plat/hw/broadcom_bcm2837.h: -------------------------------------------------------------------------------- 1 | #ifndef ARCH_PLAT_HW_BROADCOM_BCM2837_H 2 | #define ARCH_PLAT_HW_BROADCOM_BCM2837_H 3 | 4 | typedef struct { 5 | uint32_t ctrl; 6 | uint32_t _reserved_0; 7 | uint32_t core_timer_prescaler; 8 | uint32_t gpu_introuting; 9 | uint32_t perfmon_introute_set; 10 | uint32_t perfmon_introute_clr; 11 | uint32_t _reserved_1; 12 | uint32_t core_timer_access[2]; 13 | uint32_t local_introute[2]; 14 | uint32_t axi_outstanding_counters; 15 | uint32_t axi_outstanding_irq; 16 | uint32_t local_timer_ctrl; 17 | uint32_t local_timer_flags; 18 | uint32_t _reserved_2; 19 | uint32_t core_timer_intrctrl[4]; 20 | uint32_t core_mailbox_intrctrl[4]; 21 | uint32_t core_irqsource[4]; 22 | uint32_t core_fiqsource[4]; 23 | uint32_t core_mailbox_writeset[4][4]; 24 | uint32_t core_mailbox_readclr[4][4]; 25 | } bcm2837_regs_t; 26 | 27 | #define BROADCOM_BCM2837_REGS_BASE (void *)(0x40000000) 28 | 29 | #define BROADCOM_BCM2837_PERIPHBASE_PI1 (void *)(0x20000000) 30 | #define BROADCOM_BCM2837_PERIPHBASE_PI2 (void *)(0x3F000000) 31 | #define BROADCOM_BCM2837_PERIPHBASE_PI4 (void *)(0xFE000000) 32 | 33 | #define BROADCOM_BCM2837_PERIPHBASE_OFF_SYSTIMER (0x00003000UL) 34 | #define BROADCOM_BCM2837_PERIPHBASE_OFF_SP804 (0x0000B000UL) 35 | #define BROADCOM_BCM2837_PERIPHBASE_OFF_INTCTLR (0x0000B200UL) 36 | #define BROADCOM_BCM2837_PERIPHBASE_OFF_TIMER (0x0000B400UL) 37 | #define BROADCOM_BCM2837_PERIPHBASE_OFF_MAILBOX (0x0000B880UL) 38 | #define BROADCOM_BCM2837_PERIPHBASE_OFF_GPIO (0x00200000UL) 39 | #define BROADCOM_BCM2837_PERIPHBASE_OFF_PL011 (0x00201000UL) 40 | 41 | 42 | #endif /* ARCH_PLAT_HW_BROADCOM_BCM2837_H */ 43 | -------------------------------------------------------------------------------- /kernel/arch/arm32/inc/arch/plat/hw/vexpress_a9.h: -------------------------------------------------------------------------------- 1 | #ifndef ARCH_PLAT_HW_VEXPRESS_A9_H 2 | #define ARCH_PLAT_HW_VEXPRESS_A9_H 3 | 4 | #include 5 | 6 | /* TODO: Either determine at runtime, or have this user-configurable. */ 7 | #define VEXPRESSA9_ALLOC_BASE (0x60200000) 8 | #define VEXPRESSA9_ALLOC_SIZE (0x00E00000) 9 | 10 | #define VEXPRESSA9_INT_WDOG0 (32) 11 | #define VEXPRESSA9_INT_SWI (33) 12 | #define VEXPRESSA9_INT_TIM01 (34) 13 | #define VEXPRESSA9_INT_TIM23 (35) 14 | #define VEXPRESSA9_INT_RTC (36) 15 | #define VEXPRESSA9_INT_UART0 (37) 16 | #define VEXPRESSA9_INT_UART1 (38) 17 | #define VEXPRESSA9_INT_UART2 (39) 18 | #define VEXPRESSA9_INT_UART3 (40) 19 | #define VEXPRESSA9_INT_MCI0 (41) 20 | #define VEXPRESSA9_INT_MCI1 (42) 21 | #define VEXPRESSA9_INT_AACI (43) 22 | #define VEXPRESSA9_INT_KMI0 (44) 23 | #define VEXPRESSA9_INT_KMI1 (45) 24 | #define VEXPRESSA9_INT_CLCD (46) 25 | #define VEXPRESSA9_INT_ETH (47) 26 | #define VEXPRESSA9_INT_USB (48) 27 | #define VEXPRESSA9_INT_PCIE (49) 28 | 29 | #define VEXPRESS_A9_PERIPH_UART0_BASE (void *)(0x10009000) 30 | #define VEXPRESS_A9_PERIPH_UART1_BASE (void *)(0x1000a000) 31 | #define VEXPRESS_A9_PERIPH_UART2_BASE (void *)(0x1000b000) 32 | #define VEXPRESS_A9_PERIPH_UART3_BASE (void *)(0x1000c000) 33 | 34 | #define VEXPRESS_A9_PERIPH_TIMER01_BASE (void *)(0x10011000) 35 | #define VEXPRESS_A9_PERIPH_TIMER23_BASE (void *)(0x10012000) 36 | 37 | #endif -------------------------------------------------------------------------------- /kernel/arch/arm32/inc/arch/plat/platform.h: -------------------------------------------------------------------------------- 1 | #ifndef ARCH_PLAT_PLATFORM_H 2 | #define ARCH_PLAT_PLATFORM_H 3 | 4 | #include 5 | 6 | #define PLATFORM_CPU_ARM_CORTEX_A9 (1) 7 | #define PLATFORM_CPU_ARM_CORTEX_A7 (2) 8 | #define PLATFORM_CPU_ARM_CORTEX_A53 (3) 9 | 10 | #define PLATFORM_HW_ARM_VEXPRESS_A9 (1) 11 | #define PLATFORM_HW_ALLWINNER_V3S (2) 12 | #define PLATFORM_HW_BROADCOM_BCM2837 (3) 13 | 14 | #if defined(CONFIG_ARCH_CPU_ARM_CORTEX_A9) 15 | # include 16 | #elif defined(CONFIG_ARCH_CPU_ARM_CORTEX_A7) 17 | # include 18 | #elif defined(CONFIG_ARCH_CPU_ARM_CORTEX_A53) 19 | # include 20 | #endif 21 | 22 | #if defined(CONFIG_ARCH_HW_ARM_VEXPRESS_A9) 23 | # include 24 | #elif defined(CONFIG_ARCH_HW_ALLWINNER_V3S) 25 | # include 26 | #elif defined(CONFIG_ARCH_HW_BROADCOM_BCM2837) 27 | # include 28 | #endif 29 | 30 | #endif 31 | -------------------------------------------------------------------------------- /kernel/arch/arm32/inc/arch/proc/stack.h: -------------------------------------------------------------------------------- 1 | #ifndef ARCH_ARM32_PROC_STACK_H 2 | #define ARCH_ARM32_PROC_STACK_H 3 | 4 | #include 5 | 6 | /** 7 | * @brief Copies stack of calling process to that of the child process. 8 | * 9 | * Note: The source process is assumed to be the current process 10 | * 11 | * @param dest Destination process 12 | * @param src Source process 13 | * @return int 0 on success 14 | */ 15 | int proc_copy_stack(kthread_t *dest, const kthread_t *src); 16 | 17 | /** 18 | * @brief Copies the kernel stack to that of the child process. 19 | * 20 | * Note: The source process is assumed to be the current process 21 | * 22 | * @param dest Destination process 23 | * @param src Source process 24 | * @return int 0 on success 25 | */ 26 | int proc_copy_kernel_stack(kthread_t *dest, const kthread_t *src); 27 | 28 | #endif // ARCH_ARM32_PROC_STACK_H -------------------------------------------------------------------------------- /kernel/arch/arm32/inc/arch/proc/stacktrace.h: -------------------------------------------------------------------------------- 1 | #ifndef PROC_STACKTRACE_H 2 | #define PROC_STACKTRACE_H 3 | 4 | #include 5 | #include 6 | 7 | typedef struct { 8 | uintptr_t fp; /*!< Frame Pointer */ 9 | uintptr_t sp; /*!< Stack Pointer */ 10 | uintptr_t pc; /*!< Program Counter / Return Address */ 11 | } arch_stackframe_t; 12 | 13 | /** 14 | * @brief Print a stacktrace 15 | * 16 | * @param fp Frame pointer 17 | * @param pc Last program counter, if available 18 | * @param max_frames Maximum number of frames to print 19 | * @param symbols Pointer to extra symbols, if applicable 20 | */ 21 | void arch_stacktrace(void *fp, uintptr_t pc, uint32_t max_frames, const symbol_t *symbols); 22 | 23 | /** 24 | * @brief 25 | * 26 | * @param max_frames 27 | */ 28 | void stacktrace_here(int max_frames); 29 | 30 | #endif 31 | -------------------------------------------------------------------------------- /kernel/arch/arm32/inc/arch/registers.h: -------------------------------------------------------------------------------- 1 | #ifndef ARCH_ARM32_REGISTERS_H 2 | #define ARCH_ARM32_REGISTERS_H 3 | 4 | #include 5 | 6 | #define __mrc(VAR, NAME, OPCODE, SRC, CREG, OPCODE2) asm volatile("mrc " #NAME ", " #OPCODE ", %0, " #SRC ", " #CREG ", " #OPCODE2 "\n" : "=r"(VAR)) 7 | #define __mcr(VAR, NAME, OPCODE, SRC, CREG, OPCODE2) asm volatile("mcr " #NAME ", " #OPCODE ", %0, " #SRC ", " #CREG ", " #OPCODE2 "\n" :: "r"(VAR)) 8 | 9 | #define __mrrc(VARL, VARH, NAME, OPCODE, CREG) asm volatile("mrrc " #NAME ", " #OPCODE ", %0, %1, " #CREG "\n" : "=r"(VARL), "=r"(VARH)) 10 | #define __mcrr(VARL, VARH, NAME, OPCODE, CREG) asm volatile("mcrr " #NAME ", " #OPCODE ", %0, %1, " #CREG "\n" :: "r"(VARL), "r"(VARH)) 11 | 12 | /* SCTLR - System Control Register */ 13 | #define __READ_SCTLR(VAR) __mrc(VAR, p15, 0, c1, c0, 0) 14 | #define __WRITE_SCTLR(VAR) __mcr(VAR, p15, 0, c1, c0, 0) 15 | 16 | /* SCTLR - Secure Configuration Register */ 17 | #define __READ_SCR(VAR) __mrc(VAR, p15, 0, c1, c1, 0) 18 | #define __WRITE_SCR(VAR) __mcr(VAR, p15, 0, c1, c1, 0) 19 | 20 | /* PERIPHBASE - Peripheral base address */ 21 | #define __READ_PERIPHBASE(VAR) __mrc(VAR, p15, 4, c15, c0, 0) 22 | 23 | /* VBAR - Vector Base Address Register */ 24 | #define __READ_VBAR(VAR) __mrc(VAR, p15, 0, c12, c0, 0) 25 | #define __WRITE_VBAR(VAR) __mcr(VAR, p15, 0, c12, c0, 0) 26 | 27 | #endif 28 | -------------------------------------------------------------------------------- /kernel/arch/arm32/inc/arch/stdint.h: -------------------------------------------------------------------------------- 1 | #ifndef ARCH_STDINT_H 2 | #define ARCH_STDINT_H 3 | 4 | typedef signed char int8_t; //!< Signed 8 bit value 5 | typedef short int16_t; //!< Signed 16 bit value 6 | typedef int int32_t; //!< Signed 32 bit value 7 | typedef long long int64_t; //!< Signed 64 bit value 8 | 9 | typedef unsigned char uint8_t; //!< Unsigned 8 bit value 10 | typedef unsigned short uint16_t; //!< Unsigned 16 bit value 11 | typedef unsigned int uint32_t; //!< Unsigned 32 bit value 12 | typedef unsigned long long uint64_t; //!< Unsigned 64 bit value 13 | 14 | typedef uint32_t ptr_t; //!< Pointer 15 | 16 | typedef uint32_t uintptr_t; //!< Unsigned pointer 17 | typedef int32_t intptr_t; //!< Signed pointer 18 | 19 | typedef uint32_t size_t; //!< Size/length 20 | typedef int32_t ssize_t; //!< Size/length/error 21 | 22 | /* @todo Move this elsewhere */ 23 | typedef uint32_t syscallarg_t; /** Syscall argument type */ 24 | 25 | #define CHAR_MAX 127 26 | #define UCHAR_MAX 255 27 | 28 | #define SHORT_MAX 32767 29 | #define USHORT_MAX 65535 30 | 31 | #define INT_MAX 2147483647 32 | #define UINT_MAX 4294967295 33 | 34 | #define LONG_MAX 9223372036854775807 35 | #define ULONG_MAX 18446744073709551615 36 | 37 | #define INTPTR_MAX INT_MAX 38 | #define UINTPTR_MAX UINT_MAX 39 | 40 | #define SSIZE_MAX INT_MAX 41 | #define SIZE_MAX UINT_MAX 42 | 43 | #endif -------------------------------------------------------------------------------- /kernel/arch/arm32/inc/arch/types/mmu.h: -------------------------------------------------------------------------------- 1 | #ifndef ARCH_TYPES_MMU_H 2 | #define ARCH_TYPES_MMU_H 3 | 4 | #include 5 | 6 | typedef struct { 7 | uint32_t mmu_table[4096]; 8 | } mmu_table_t; 9 | 10 | #endif 11 | -------------------------------------------------------------------------------- /kernel/arch/arm32/module.mk: -------------------------------------------------------------------------------- 1 | # Architecture-specific Makefile options for armv7 2 | 3 | MDIR = $(dir $(lastword $(MAKEFILE_LIST))) 4 | 5 | ARCH := arm32 6 | 7 | ifeq ($(CONFIG_ARCH_CPU_CORTEX_A7),y) 8 | CPU := cortex_a7 9 | else ifeq ($(CONFIG_ARCH_CPU_CORTEX_A9),y) 10 | CPU := cortex_a9 11 | else ifeq ($(CONFIG_ARCH_CPU_CORTEX_A53),y) 12 | CPU := cortex_a53 13 | endif 14 | 15 | ifeq ($(CONFIG_ARCH_HW_ARM_VEXPRESS_A9),y) 16 | HW := arm_vexpress_a9 17 | else ifeq ($(CONFIG_ARCH_HW_ALLWINNER_V3S),y) 18 | HW := arm_allwinner_v3s 19 | else ifeq ($(CONFIG_ARCH_HW_BROADCOM_BCM2837),y) 20 | HW := broadcom_bcm2837 21 | endif 22 | 23 | HWDIR := $(MDIR)hw/$(HW) 24 | HWINC := $(HWDIR)/inc 25 | 26 | cflags-y += -marm 27 | LDARCH = -marmelf 28 | ldflags-y += -marm -nostartfiles 29 | 30 | asflags-y += -marm 31 | 32 | cflags-y += -DCONFIG_ARCH_ARM32 \ 33 | -I$(HWINC) 34 | 35 | ifneq ($(CONFIG_BUILD_USE_CLANG),y) 36 | cflags-y += -Wno-unknown-pragmas \ 37 | -mapcs-frame -mpoke-function-name 38 | endif 39 | 40 | include $(MDIR)src/module.mk 41 | include $(HWDIR)/module.mk 42 | 43 | -------------------------------------------------------------------------------- /kernel/arch/arm32/sdimg.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | dd if=/dev/zero of=sd.img bs=1M count=32 4 | mkfs.ext4 sd.img 5 | mkdir -p sd_tmp 6 | sudo mount -o loop sd.img ./sd_tmp/ 7 | sudo cp lambda.ukern sd_tmp/ 8 | sudo umount sd_tmp 9 | sleep 1 10 | sudo rm -rf sd_tmp -------------------------------------------------------------------------------- /kernel/arch/arm32/src/init/init.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include 6 | 7 | #include 8 | #include 9 | #include 10 | 11 | 12 | void arch_init(void) { 13 | disable_interrupts(); 14 | disable_fiqs(); 15 | 16 | /* Alloy for early exception debugging */ 17 | __WRITE_VBAR(0xC0008000); 18 | 19 | armv7_mmu_init(); 20 | hw_init_mm(); 21 | 22 | if(hw_init_console()) { 23 | /* Of course, if we fail to initialize the console, this message may 24 | * not be visible/transmitted. */ 25 | kpanic("Could not initialize kernel console!"); 26 | } 27 | kerror(ERR_INFO, "Console Initialized"); 28 | 29 | intr_init(); 30 | hw_init_interrupts(); 31 | kerror(ERR_INFO, "Interrupts Initialized"); 32 | } -------------------------------------------------------------------------------- /kernel/arch/arm32/src/init/module.mk: -------------------------------------------------------------------------------- 1 | MDIR = $(dir $(lastword $(MAKEFILE_LIST))) 2 | 3 | obj-y += $(MDIR)init.o 4 | 5 | -------------------------------------------------------------------------------- /kernel/arch/arm32/src/intr/gtimer.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include 5 | 6 | static void (*gtimer_callback)(void) = NULL; 7 | 8 | static int timerdev_setfreq(void *data, uint8_t idx, uint32_t freq); 9 | static int timerdev_attach(void *data, uint8_t idx, void (*callback)(void)); 10 | 11 | void armv7_gtimer_create_timerdev(hal_timer_dev_t *dev) { 12 | memset(dev, 0, sizeof(hal_timer_dev_t)); 13 | 14 | dev->setfreq = timerdev_setfreq; 15 | dev->setperiod = NULL; 16 | dev->attach = timerdev_attach; 17 | 18 | dev->cap = HAL_TIMERDEV_CAP_VARFREQ | HAL_TIMERDEV_CAP_CALLBACK; 19 | } 20 | 21 | int armv7_gtimer_init(uint32_t freq) { 22 | uint32_t tmp; 23 | 24 | __WRITE_CNTFRQ(freq); 25 | 26 | //__READ_CNTKCTL(tmp); 27 | tmp = (1UL << 1) | /* Enable PL0 access to Vitual timer */ 28 | (1UL << 2) | /* Enable event */ 29 | (8UL << 4) | /* Trigger event on 8th bit of CNTVCT */ 30 | (1UL << 8); /* Enable PL0 access to Vitual timer */ 31 | __WRITE_CNTKCTL(tmp); 32 | 33 | //__READ_CNTV_CTL(tmp); 34 | tmp = (1UL << 0); /* Enable virtual timer */ 35 | __WRITE_CNTV_CTL(tmp); 36 | 37 | /* Clear CompareValue register */ 38 | tmp = 0; 39 | __WRITE_CNTV_CVAL(tmp, tmp); 40 | 41 | return 0; 42 | } 43 | 44 | static int timerdev_setfreq(void __unused *data, uint8_t idx, uint32_t freq) { 45 | if(idx != 0) { 46 | return -EINVAL; 47 | } 48 | 49 | __WRITE_CNTFRQ(freq); 50 | 51 | return 0; 52 | } 53 | 54 | static int timerdev_attach(void __unused *data, uint8_t idx, void (*callback)(void)) { 55 | if(idx != 0) { 56 | return -EINVAL; 57 | } 58 | 59 | if(gtimer_callback) { 60 | /* Presently only support a single callback */ 61 | return -EUNSPEC; 62 | } 63 | 64 | gtimer_callback = callback; 65 | 66 | return 0; 67 | } 68 | -------------------------------------------------------------------------------- /kernel/arch/arm32/src/intr/intr.s: -------------------------------------------------------------------------------- 1 | 2 | .macro __INTR_BEGIN intn 3 | sub lr, lr, #4 4 | push {lr} 5 | push {r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11, r12} 6 | mrs r0, spsr 7 | push {r0} 8 | sub sp, sp, #4 /* Padding to 8-byte align stack */ 9 | 10 | mov r0, \intn /* ARG0: Interrupt number */ 11 | mov r1, sp /* ARG1: Pointer to data just pushed to the stack */ 12 | .endm 13 | 14 | .macro __INTR_END 15 | add sp, sp, #4 /* Pop padding byte */ 16 | pop {r0} 17 | msr spsr, r0 18 | pop {r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11, r12} 19 | ldm sp!, {pc}^ 20 | .endm 21 | 22 | .global __int_wrap_undefined 23 | .global __int_wrap_syscall 24 | .global __int_wrap_prefetchabort 25 | .global __int_wrap_dataabort 26 | .global __int_wrap_hyptrap 27 | .global __int_wrap_irq 28 | .global __int_wrap_fiq 29 | 30 | .extern intr_handler 31 | .extern irq_stack_end 32 | .extern fiq_stack_end 33 | 34 | __int_wrap_undefined: 35 | __INTR_BEGIN #1 36 | bl intr_handler 37 | __INTR_END 38 | 39 | __int_wrap_syscall: 40 | push {lr} 41 | push {r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11, r12} 42 | mrs r0, cpsr 43 | push {r0} 44 | sub sp, sp, #4 /* Padding to 8-byte align stack */ 45 | 46 | mov r0, #2 /* ARG0: Interrupt Number */ 47 | mov r1, sp /* ARG1: Pointer to data just pushed to the stack */ 48 | 49 | bl intr_handler 50 | 51 | add sp, sp, #4 /* Pop padding byte */ 52 | pop {r0} 53 | msr cpsr, r0 54 | pop {r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11, r12} 55 | ldm sp!, {pc}^ 56 | 57 | __int_wrap_prefetchabort: 58 | __INTR_BEGIN #3 59 | bl intr_handler 60 | __INTR_END 61 | 62 | __int_wrap_dataabort: 63 | __INTR_BEGIN #4 64 | bl intr_handler 65 | __INTR_END 66 | 67 | __int_wrap_hyptrap: 68 | __INTR_BEGIN #5 69 | bl intr_handler 70 | __INTR_END 71 | 72 | __int_wrap_irq: 73 | __INTR_BEGIN #6 74 | bl intr_handler 75 | __INTR_END 76 | 77 | __int_wrap_fiq: 78 | ldr sp, =fiq_stack_end 79 | __INTR_BEGIN #7 80 | bl intr_handler 81 | __INTR_END 82 | 83 | 84 | .global get_pc 85 | # uint32_t get_pc(void) 86 | get_pc: 87 | mov r0, lr 88 | bx lr 89 | -------------------------------------------------------------------------------- /kernel/arch/arm32/src/intr/module.mk: -------------------------------------------------------------------------------- 1 | MDIR = $(dir $(lastword $(MAKEFILE_LIST))) 2 | 3 | obj-y += $(MDIR)gic.o \ 4 | $(MDIR)gtimer.o \ 5 | $(MDIR)int.o \ 6 | $(MDIR)intr.o 7 | 8 | dirs-y := timer 9 | 10 | include $(patsubst %,$(MDIR)%/module.mk,$(dirs-y)) 11 | 12 | -------------------------------------------------------------------------------- /kernel/arch/arm32/src/intr/timer/module.mk: -------------------------------------------------------------------------------- 1 | MDIR = $(dir $(lastword $(MAKEFILE_LIST))) 2 | 3 | obj-y += $(MDIR)timer_sp804.o 4 | 5 | -------------------------------------------------------------------------------- /kernel/arch/arm32/src/io/module.mk: -------------------------------------------------------------------------------- 1 | MDIR = $(dir $(lastword $(MAKEFILE_LIST))) 2 | 3 | dirs-y := uart 4 | 5 | include $(patsubst %,$(MDIR)%/module.mk,$(dirs-y)) 6 | 7 | -------------------------------------------------------------------------------- /kernel/arch/arm32/src/io/uart/module.mk: -------------------------------------------------------------------------------- 1 | MDIR = $(dir $(lastword $(MAKEFILE_LIST))) 2 | 3 | obj-y += $(MDIR)uart_allwinner.o \ 4 | $(MDIR)uart_pl011.o 5 | -------------------------------------------------------------------------------- /kernel/arch/arm32/src/io/uart/uart_allwinner.c: -------------------------------------------------------------------------------- 1 | /* NOTE: Currently supports Allwinner V3s compatible UART structures only */ 2 | 3 | #include 4 | #include 5 | 6 | #include 7 | 8 | static void chardev_putc(void *data, int c); 9 | static int chardev_getc(void *data); 10 | static int chardev_chavail(void *data); 11 | 12 | int uart_allwinner_create_chardev(uart_allwinner_handle_t *hand, hal_io_char_dev_t *chardev) { 13 | memset(chardev, 0, sizeof(hal_io_char_dev_t)); 14 | 15 | chardev->data = (void *)hand; 16 | 17 | chardev->putc = chardev_putc; 18 | chardev->getc = chardev_getc; 19 | chardev->chavail = chardev_chavail; 20 | 21 | chardev->cap = HAL_IO_CHARDEV_CAP_OUTPUT | HAL_IO_CHARDEV_CAP_INPUT; 22 | 23 | return 0; 24 | } 25 | 26 | int uart_allwinner_init(uart_allwinner_handle_t *hand, void *base, uint32_t baud) { 27 | if(!base) { 28 | return -EINVAL; 29 | } 30 | 31 | hand->base = (uart_allwinner_regmap_t *)base; 32 | 33 | hand->base->LCR |= (1UL << UART_ALLWINNER_LCR_DLAB__POS); 34 | 35 | /* Baud rate = sclk / (div * 16) */ 36 | /* Need to ungate UART1 in BUS_CLK_GATING_REG3 */ 37 | (void)baud; 38 | 39 | return 0; 40 | } 41 | 42 | static void chardev_putc(void *data, int c) { 43 | __unused 44 | uart_allwinner_handle_t *hand = (uart_allwinner_handle_t *)data; 45 | (void)c; 46 | } 47 | 48 | static int chardev_getc(void *data) { 49 | __unused 50 | uart_allwinner_handle_t *hand = (uart_allwinner_handle_t *)data; 51 | 52 | return 0; 53 | } 54 | 55 | static int chardev_chavail(void *data) { 56 | __unused 57 | uart_allwinner_handle_t *hand = (uart_allwinner_handle_t *)data; 58 | 59 | return 0; 60 | } 61 | -------------------------------------------------------------------------------- /kernel/arch/arm32/src/mm/module.mk: -------------------------------------------------------------------------------- 1 | MDIR = $(dir $(lastword $(MAKEFILE_LIST))) 2 | 3 | obj-y += $(MDIR)mmu.o 4 | 5 | -------------------------------------------------------------------------------- /kernel/arch/arm32/src/module.mk: -------------------------------------------------------------------------------- 1 | MDIR = $(dir $(lastword $(MAKEFILE_LIST))) 2 | 3 | dirs-y := init \ 4 | intr \ 5 | io \ 6 | mm \ 7 | proc 8 | 9 | include $(patsubst %,$(MDIR)%/module.mk,$(dirs-y)) 10 | 11 | -------------------------------------------------------------------------------- /kernel/arch/arm32/src/proc/module.mk: -------------------------------------------------------------------------------- 1 | 2 | MDIR = $(dir $(lastword $(MAKEFILE_LIST))) 3 | 4 | obj-y += $(MDIR)stack.o \ 5 | $(MDIR)stacktrace.o \ 6 | $(MDIR)syscall.o \ 7 | $(MDIR)tasking.o 8 | -------------------------------------------------------------------------------- /kernel/arch/arm32/src/proc/stack.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | int proc_copy_stack(kthread_t *dest, const kthread_t *src) { 8 | kpanic("proc_copy_stack() not yet implemented on this architecture!"); 9 | 10 | (void)dest; 11 | (void)src; 12 | 13 | return 0; 14 | } 15 | 16 | int proc_copy_kernel_stack(kthread_t *dest, const kthread_t *src) { 17 | kpanic("proc_copy_kernel_stack() not yet implemented on this architecture!"); 18 | 19 | (void)dest; 20 | (void)src; 21 | 22 | return 0; 23 | } -------------------------------------------------------------------------------- /kernel/arch/arm32/src/proc/syscall.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | void arch_syscall_interrupt(intr_handler_hand_t *hdlr) { 8 | (void)hdlr; 9 | 10 | /* @todo */ 11 | uint32_t scn = 0; 12 | syscallarg_t *args = NULL; 13 | 14 | if(syscall_service(scn, args)) { 15 | /* @todo Stack trace */ 16 | exit(1); 17 | } 18 | } 19 | 20 | -------------------------------------------------------------------------------- /kernel/arch/module.mk: -------------------------------------------------------------------------------- 1 | MDIR = $(dir $(lastword $(MAKEFILE_LIST))) 2 | 3 | ifeq ($(CONFIG_ARCH_X86),y) 4 | include $(MDIR)x86/module.mk 5 | else ifeq ($(CONFIG_ARCH_ARM32),y) 6 | include $(MDIR)arm32/module.mk 7 | else ifeq ($(CONFIG_ARCH_RISCV),y) 8 | include $(MDIR)riscv/module.mk 9 | endif 10 | 11 | #cflags-$(CONFIG_VERBOSE_PANIC) += -DCONFIG_VERBOSE_PANIC 12 | 13 | -------------------------------------------------------------------------------- /kernel/arch/riscv/Kconfig: -------------------------------------------------------------------------------- 1 | menu "RISC-V architecture" 2 | depends on ARCH_RISCV 3 | 4 | choice 5 | prompt "CPU family" 6 | 7 | config ARCH_CPU_RV64I 8 | prompt "RISC-V RV64I" 9 | 10 | endchoice # CPU family 11 | 12 | choice 13 | prompt "Hardware platform" 14 | 15 | config ARCH_HW_KENDRYTE_K210 16 | bool "Kendryte k210" 17 | select ARCH_CPU_RV64I 18 | 19 | endchoice # Hardware platform 20 | 21 | endmenu # RISC-V architecture 22 | -------------------------------------------------------------------------------- /kernel/arch/riscv/inc/arch/plat/cpu/rv64i.h: -------------------------------------------------------------------------------- 1 | #ifndef ARCH_PLAT_CPU_RV64I_H 2 | #define ARCH_PLAT_CPU_RV64I_H 3 | 4 | /* TODO */ 5 | 6 | #endif -------------------------------------------------------------------------------- /kernel/arch/riscv/inc/arch/plat/hw/kendryte_k210.h: -------------------------------------------------------------------------------- 1 | #ifndef ARCH_PLAT_HW_KENDRYTE_K210_H 2 | #define ARCH_PLAT_HW_KENDRYTE_K210_H 3 | 4 | #include 5 | 6 | /* TODO */ 7 | 8 | #endif -------------------------------------------------------------------------------- /kernel/arch/riscv/inc/arch/plat/platform.h: -------------------------------------------------------------------------------- 1 | #ifndef ARCH_PLAT_PLATFORM_H 2 | #define ARCH_PLAT_PLATFORM_H 3 | 4 | #if defined(CONFIG_ARCH_CPU_RISCV_RV64I) 5 | # include 6 | #endif 7 | 8 | #if defined(CONFIG_ARCH_HW_KENDRYTE_K210) 9 | # include 10 | #endif 11 | 12 | #endif 13 | -------------------------------------------------------------------------------- /kernel/arch/riscv/inc/arch/stdint.h: -------------------------------------------------------------------------------- 1 | #ifndef ARCH_STDINT_H 2 | #define ARCH_STDINT_H 3 | 4 | typedef signed char int8_t; //!< Signed 8 bit value 5 | typedef short int16_t; //!< Signed 16 bit value 6 | typedef int int32_t; //!< Signed 32 bit value 7 | 8 | typedef unsigned char uint8_t; //!< Unsigned 8 bit value 9 | typedef unsigned short uint16_t; //!< Unsigned 16 bit value 10 | typedef unsigned int uint32_t; //!< Unsigned 32 bit value 11 | 12 | #if defined(CONFIG_ARCH_CPU_RISCV_RV64I) 13 | typedef long int64_t; //!< Signed 64 bit value 14 | 15 | typedef unsigned long uint64_t; //!< Unsigned 64 bit value 16 | 17 | typedef uint64_t ptr_t; //!< Pointer 18 | 19 | typedef uint64_t uintptr_t; //!< Unsigned pointer 20 | typedef int64_t intptr_t; //!< Signed pointer 21 | 22 | typedef uint64_t size_t; //!< Size/length 23 | 24 | /* @todo Move this elsewhere */ 25 | typedef uint64_t syscallarg_t; /** Syscall argument type */ 26 | 27 | #elif defined(CONFIG_ARCH_CPU_RISCV_RV32I) || \ 28 | defined(CONFIG_ARCH_CPU_RISCV_RV32E) 29 | typedef long long int64_t; //!< Signed 64 bit value 30 | 31 | typedef unsigned long long uint64_t; //!< Unsigned 64 bit value 32 | 33 | typedef uint32_t ptr_t; //!< Pointer 34 | 35 | typedef uint32_t uintptr_t; //!< Unsigned pointer 36 | typedef int32_t intptr_t; //!< Signed pointer 37 | 38 | typedef uint32_t size_t; //!< Size/length 39 | 40 | /* @todo Move this elsewhere */ 41 | typedef uint32_t syscallarg_t; /** Syscall argument type */ 42 | 43 | #endif /* CONFIG_ARCH_CPU_* */ 44 | 45 | #endif 46 | -------------------------------------------------------------------------------- /kernel/arch/riscv/kendryte-k210.ld: -------------------------------------------------------------------------------- 1 | ENTRY (reset) 2 | 3 | SECTIONS 4 | { 5 | /* TODO */ 6 | . = 0x00008000; 7 | 8 | kern_start = .; 9 | 10 | .text : { 11 | *(.entryp) 12 | *(.text) 13 | } 14 | 15 | .rodata : { 16 | *(.rodata) 17 | } 18 | 19 | .data : { 20 | *(.data) 21 | } 22 | 23 | .bss : { 24 | *(COMMON) 25 | *(.bss) 26 | } 27 | 28 | kern_end = .; 29 | } -------------------------------------------------------------------------------- /kernel/arch/riscv/module.mk: -------------------------------------------------------------------------------- 1 | # Architecture-specific Makefile options for riscv 2 | 3 | cflags-y += 4 | ldflags-y += -T kernel/arch/$(ARCH)/kendryte-k210.ld 5 | 6 | cflags-y += -DCONFIG_ARCH_RISCV \ 7 | -DCONFIG_ARCH_CPU_RISCV_RV64I \ 8 | -DCONFIG_ARCH_HW_KENDRYTE_K210 9 | 10 | -------------------------------------------------------------------------------- /kernel/arch/x86/Kconfig: -------------------------------------------------------------------------------- 1 | menu "x86 architecture" 2 | depends on ARCH_X86 3 | 4 | choice 5 | prompt "CPU family" 6 | default ARCH_CPU_486 7 | help 8 | CPU family/architecture to support. This will automatically select 9 | features supported by the target. Note that currently, the kernel does not 10 | use CPUID to determine support at runtime, so a CPU at or below the desired 11 | target must be chosen to reliably operate on a given machine. 12 | 13 | config ARCH_CPU_386 14 | bool "i386" 15 | 16 | config ARCH_CPU_486 17 | bool "i486" 18 | 19 | config ARCH_CPU_P5 20 | bool "Pentium/P5" 21 | 22 | config ARCH_CPU_P6 23 | bool "Pentium Pro/P6" 24 | 25 | endchoice # CPU family 26 | 27 | choice 28 | prompt "Hardware target" 29 | 30 | config ARCH_HW_PC 31 | bool "PC" 32 | 33 | endchoice # Hardware target 34 | 35 | 36 | menu "CPU Features" 37 | 38 | menu "Paging" 39 | 40 | config X86_PAGING_GLOBAL_PAGES 41 | bool "Global page support" 42 | depends on !ARCH_CPU_386 && !ARCH_CPU_486 43 | default y 44 | 45 | config X86_PAGING_KERNEL_WP 46 | bool "Enable write-protect support while in kernel mode" 47 | default y 48 | 49 | endmenu # Paging 50 | 51 | menuconfig X86_APIC 52 | bool "APIC (Advanced Programmable Interrupt Controller) Support" 53 | depends on !ARCH_CPU_386 54 | default y if !ARCH_CPU_486 55 | 56 | if X86_APIC 57 | 58 | config X86_APIC_TIMER 59 | bool "APIC timer support (experimental)" 60 | default n 61 | 62 | endif # X86_APIC 63 | 64 | endmenu # CPU Features 65 | 66 | 67 | config MULTIBOOT 68 | bool "Enable Multiboot support (do not disable)" 69 | default y 70 | help 71 | Enables Multiboot support for the kernel. Currently, this is the only 72 | supported boot method, so it must remain enabled. 73 | 74 | config MULTIBOOT_VERSION 75 | int "Select Multiboot version" 76 | range 1 2 77 | default 2 78 | help 79 | Select Multiboot speicification version to use. Note that LBoot only 80 | supports version 2. 81 | 82 | endmenu # x86 Architecture Config 83 | 84 | -------------------------------------------------------------------------------- /kernel/arch/x86/hw/pc/hw.ld: -------------------------------------------------------------------------------- 1 | ENTRY (start) 2 | 3 | PHYS_ENTRYPOINT = 0x00100000; 4 | VIRT_OFFSET = 0xC0000000; 5 | 6 | SECTIONS 7 | { 8 | . = PHYS_ENTRYPOINT; 9 | 10 | 11 | .boot BLOCK(4K) : ALIGN(4K) { 12 | __kernel_boot_begin = .; 13 | *(.mboot) 14 | *(.boot.*) 15 | __kernel_boot_end = .; 16 | } 17 | 18 | . += VIRT_OFFSET; 19 | 20 | kern_start = .; 21 | 22 | .text ALIGN(4K) : AT(ADDR(.text) - VIRT_OFFSET) { 23 | __kernel_text_begin = .; 24 | *(.text.*) 25 | __kernel_text_end = .; 26 | } 27 | 28 | .rodata ALIGN(4K) : AT(ADDR(.rodata) - VIRT_OFFSET) { 29 | __kernel_rodata_begin = .; 30 | *(.rodata.*) 31 | 32 | . = ALIGN(8); 33 | __lambda_symbols_begin = .; 34 | *(.__lambda_symbols) 35 | __lambda_symbols_end = .; 36 | 37 | . = ALIGN(8); 38 | __lambda_strings_begin = .; 39 | *(.__lambda_strings) 40 | __lambda_strings_end = .; 41 | 42 | __kernel_rodata_end = .; 43 | } 44 | 45 | .data ALIGN(4K) : AT(ADDR(.data) - VIRT_OFFSET) { 46 | __kernel_data_begin = .; 47 | *(.data.*) 48 | __kernel_data_end = .; 49 | } 50 | 51 | .bss ALIGN(4K) : AT(ADDR(.bss) - VIRT_OFFSET) { 52 | __kernel_bss_begin = .; 53 | *(COMMON) 54 | *(.bss.*) 55 | __kernel_bss_end = .; 56 | } 57 | 58 | kern_end = .; 59 | } -------------------------------------------------------------------------------- /kernel/arch/x86/hw/pc/module.mk: -------------------------------------------------------------------------------- 1 | # HW-specific Makefile options for X86-based PCs 2 | 3 | MDIR = $(dir $(lastword $(MAKEFILE_LIST))) 4 | 5 | HW := pc 6 | 7 | KERNEL_OFFSET = 0xC0000000 8 | 9 | cflags-y += -DKERNEL_OFFSET=${KERNEL_OFFSET} 10 | ldflags-y += -T $(HWDIR)/hw.ld 11 | 12 | cflags-y += -DCONFIG_ARCH_HW_PC 13 | 14 | asflags-y += 15 | 16 | .DEFAULT_GOAL=$(BUILDDIR)/lambda.kern 17 | 18 | include $(MDIR)src/module.mk 19 | 20 | -------------------------------------------------------------------------------- /kernel/arch/x86/hw/pc/src/init/hw_init.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | __hot 8 | static void _task_switch_handler() { 9 | /* TODO: Determine from timer struct */ 10 | time_update(10000000); 11 | /* TODO: Make this more effecient */ 12 | sched_processes(); 13 | do_task_switch(); 14 | } 15 | 16 | static hal_timer_dev_t _timer; 17 | #ifdef CONFIG_X86_APIC_TIMER 18 | static apictimer_handle_t _apictimer_hand; 19 | static hal_timer_dev_t _apictimer; 20 | #endif 21 | 22 | int hw_init_timer(uint32_t rate) { 23 | pit_init(rate); 24 | pit_create_timerdev(&_timer); 25 | hal_timer_dev_setfreq(&_timer, 0, rate); 26 | #ifdef CONFIG_X86_APIC_TIMER 27 | apictimer_init(&_apictimer_hand); 28 | apictimer_create_timerdev(&_apictimer_hand, &_apictimer); 29 | hal_timer_dev_setfreq(&_apictimer, 0, rate); 30 | hal_timer_dev_attach(&_apictimer, 0, _task_switch_handler); 31 | #else 32 | hal_timer_dev_attach(&_timer, 0, _task_switch_handler); 33 | #endif 34 | 35 | return 0; 36 | } 37 | -------------------------------------------------------------------------------- /kernel/arch/x86/hw/pc/src/init/module.mk: -------------------------------------------------------------------------------- 1 | MDIR = $(dir $(lastword $(MAKEFILE_LIST))) 2 | 3 | obj-y += $(MDIR)hw_init.o 4 | 5 | -------------------------------------------------------------------------------- /kernel/arch/x86/hw/pc/src/module.mk: -------------------------------------------------------------------------------- 1 | MDIR = $(dir $(lastword $(MAKEFILE_LIST))) 2 | 3 | dirs-y := init 4 | 5 | include $(patsubst %,$(MDIR)%/module.mk,$(dirs-y)) 6 | 7 | -------------------------------------------------------------------------------- /kernel/arch/x86/inc/arch/acpi/acpi.h: -------------------------------------------------------------------------------- 1 | #ifndef ARCH_ACPI_ACPI_H 2 | #define ARCH_ACPI_ACPI_H 3 | 4 | #include 5 | #include 6 | 7 | void acpi_init(const mboot_t *head); 8 | 9 | const acpi_sdt_head_t *acpi_find_sdt(const char *signature); 10 | 11 | #endif 12 | -------------------------------------------------------------------------------- /kernel/arch/x86/inc/arch/dev/keyb/input.h: -------------------------------------------------------------------------------- 1 | #ifndef KEYB_H 2 | #define KEYB_H 3 | 4 | #include 5 | 6 | /** 7 | * Initializes the keyboard. 8 | * * Checks that the keyboard is in working condition 9 | * * Sets the keyboard interrupt handler 10 | * * Enables the keyboard IRQ 11 | * * Creates and adds an input device driver entry corresponding to this keyboard 12 | */ 13 | void keyb_init(void); 14 | 15 | #endif -------------------------------------------------------------------------------- /kernel/arch/x86/inc/arch/dev/vga/print.h: -------------------------------------------------------------------------------- 1 | /** \file print.h 2 | * \brief Contains functions dealing with printing to the VGA screen. 3 | * 4 | * Contains functions that help print to and manage the VGA screen. 5 | */ 6 | 7 | #ifndef VGA_PRINT_H 8 | #define VGA_PRINT_H 9 | 10 | #include 11 | 12 | /** 13 | * Clears the first plane of VGA memory, effectively clearing all text from 14 | * the screen. 15 | */ 16 | void vga_clear(void); 17 | 18 | /** 19 | * Checks if character is printable, if so it places it in VGA memory, 20 | * along with a color byte. If the character is not printable, it deals 21 | * with it accordingly 22 | * 23 | * @param c the input character 24 | */ 25 | void vga_put(char c); 26 | 27 | 28 | /** 29 | * Prints every character in a character array , until it reaches 30 | * a NULL terminator. 31 | * 32 | * @param str the string to print 33 | * @see vga_put 34 | */ 35 | void vga_print(char *str); 36 | 37 | /** 38 | * Prints a number using any base between 2 and 16, inclusive. 39 | * 40 | * @param n number to be printed 41 | * @param base base to use when printing the number 42 | * @see vga_print 43 | */ 44 | void vga_printnum(uint32_t n, uint32_t base); 45 | 46 | 47 | #define is_ansi(x) ((x == 'A') || (x == 'B') || (x == 'C') || (x == 'D') || (x == 's') || (x == 'u') || (x == 'H') || (x == 'J') || (x == 'K') || (x == 'm')) 48 | 49 | #endif -------------------------------------------------------------------------------- /kernel/arch/x86/inc/arch/init/hw_init.h: -------------------------------------------------------------------------------- 1 | #ifndef ARCH_ARM32_HW_INIT_H 2 | #define ARCH_ARM32_HW_INIT_H 3 | 4 | #include 5 | 6 | /* These are common fuctions that are provided by the HW platforms. See 7 | * hw//init/hwinit.c */ 8 | 9 | /** 10 | * @brief Initialize timers for timekeeping and task switching 11 | * 12 | * @param rate Rate of clock keeping kernel time 13 | */ 14 | int hw_init_timer(uint32_t rate); 15 | 16 | #endif 17 | -------------------------------------------------------------------------------- /kernel/arch/x86/inc/arch/init/init.h: -------------------------------------------------------------------------------- 1 | /** \file init.h 2 | * \brief Defines initialization function(s) for the target architecture. 3 | * 4 | */ 5 | 6 | #ifndef ARCH_X86_INIT_H 7 | #define ARCH_X86_INIT_H 8 | 9 | #include 10 | 11 | void arch_init(mboot_t *mboot_head); 12 | 13 | #endif -------------------------------------------------------------------------------- /kernel/arch/x86/inc/arch/intr/apic/apictimer.h: -------------------------------------------------------------------------------- 1 | #ifndef ARCH_INTR_APIC_APICTIMER_H 2 | #define ARCH_INTR_APIC_APICTIMER_H 3 | 4 | #include 5 | 6 | #include 7 | 8 | typedef struct { 9 | apic_lapic_regs_t *lapic; /*!< Pointer to local APIC registers */ 10 | 11 | uint32_t busfreq; /*!< Calculated CPU BUS frequency */ 12 | } apictimer_handle_t; 13 | 14 | /** 15 | * @brief Initialize local APIC timer 16 | * 17 | * @param hand Timer handle 18 | */ 19 | void apictimer_init(apictimer_handle_t *hand); 20 | 21 | /** 22 | * @brief Create timer device from local APIC timer handle 23 | * 24 | * @param hand Timer handle 25 | * @param dev Timer device 26 | */ 27 | void apictimer_create_timerdev(apictimer_handle_t *hand, hal_timer_dev_t *dev); 28 | 29 | #endif 30 | -------------------------------------------------------------------------------- /kernel/arch/x86/inc/arch/intr/idt.h: -------------------------------------------------------------------------------- 1 | /** \file idt.h 2 | * \brief Contains definitions for the IDT. 3 | * 4 | * Contains functions and defenitions that allow for the setup and usage 5 | * of the IDT and interrupts in general. 6 | */ 7 | 8 | #ifndef ARCH_INTR_IDT_H 9 | #define ARCH_INTR_IDT_H 10 | 11 | #include 12 | 13 | #include 14 | 15 | /** 16 | * \brief Initializes the IDT 17 | * Initializes the IDT by first setting every IDT entry to use the dummy 18 | * interrupt then loads the IDT pointer and remaps the PIC. 19 | * @see reload_idt 20 | */ 21 | void idt_init(void); 22 | 23 | /** 24 | * @brief Set an entry in the IDT. 25 | * 26 | * @param intr the interrupt number 27 | * @param sel the GDT selector 28 | * @param flags the entrys flags 29 | * @param func the interrupt handler function 30 | * @see IDT_ATTR 31 | */ 32 | void idt_set_entry(uint8_t intr, uint16_t sel, uint8_t flags, void *func); 33 | 34 | /** 35 | * @brief Add callback for interrupt 36 | * 37 | * @param int_n Interrupt number 38 | * @param hdlr Interrupt handler handle 39 | * 40 | * @return 0 on success, else < 0 41 | */ 42 | int idt_add_callback(uint8_t int_n, intr_handler_hand_t *hdlr); 43 | 44 | #endif 45 | 46 | -------------------------------------------------------------------------------- /kernel/arch/x86/inc/arch/intr/int.h: -------------------------------------------------------------------------------- 1 | #ifndef INT_FUNCS_H 2 | #define INT_FUNCS_H 3 | 4 | #include 5 | 6 | #include 7 | #include 8 | 9 | #include 10 | 11 | #define enable_interrupts() asm volatile("sti") 12 | #define disable_interrupts() asm volatile("cli") 13 | #define interrupt_halt() asm volatile("hlt") 14 | #define busy_wait() asm volatile("hlt") 15 | 16 | #define INTERRUPT(int_n) __INTERRUPT(int_n) //!< Call interrupt 17 | #define __INTERRUPT(int_n) asm volatile("int $" #int_n) 18 | 19 | 20 | /** 21 | * @brief Checks if interrupts are currently enabled 22 | * 23 | * @return int 1 if enabled, else 0. 24 | */ 25 | int interrupts_enabled(void); 26 | 27 | /** 28 | * @brief Attach handler for interrupt 29 | * 30 | * @param idx Interrupt ID 31 | * @param hdlr Interrupt handler handle 32 | */ 33 | static inline void arch_interrupt_attach(interrupt_idx_e n, intr_handler_hand_t *hdlr) { 34 | idt_add_callback((uint8_t)n, hdlr); 35 | } 36 | 37 | /** 38 | * @brief Setup handler for interrupt, callable from userspace 39 | * 40 | * @param idx Interrupt ID 41 | * @param handler Handler 42 | */ 43 | void arch_set_interrupt_handler_user(interrupt_idx_e idx, void *handler); 44 | 45 | extern void call_syscall_int(uint32_t, syscallarg_t *); 46 | /** 47 | * @brief Call syscall 48 | * 49 | * @param scn Syscall number 50 | * @param args Pointer to arguments list 51 | */ 52 | static inline void arch_call_syscall(uint32_t scn, syscallarg_t *args) { 53 | call_syscall_int(scn, args); 54 | } 55 | 56 | /** 57 | * @brief Force division by zero, for debugging purposes 58 | */ 59 | static inline void arch_div0(void) { 60 | asm volatile("mov $0, %%ecx\n" 61 | "divl %%ecx\n" 62 | ::: "%eax", "%ecx"); 63 | } 64 | 65 | #endif 66 | 67 | -------------------------------------------------------------------------------- /kernel/arch/x86/inc/arch/intr/pic.h: -------------------------------------------------------------------------------- 1 | #ifndef ARCH_INTR_PIC_H 2 | #define ARCH_INTR_PIC_H 3 | 4 | #include 5 | 6 | #include 7 | 8 | /** 9 | * @brief Disable an IRQ line 10 | * 11 | * @param irq the IRQ to be disabled 12 | * @return returns 0 if success 13 | */ 14 | int pic_irq_disable(uint8_t irq); 15 | 16 | /** 17 | * @brief Enable an IRQ line 18 | * 19 | * @param irq the IRQ to be enabled 20 | * @return returns 0 if success 21 | */ 22 | int pic_irq_enable(uint8_t irq); 23 | 24 | /** 25 | * @brief Remaps the PIC so when an IRQ fires, it adds `offx` to the IRQ number. 26 | * 27 | * @param master the offset for the master PIC 28 | * @param slave the offset for the slave PIC 29 | */ 30 | void pic_remap(uint8_t master, uint8_t slave); 31 | 32 | #endif 33 | 34 | -------------------------------------------------------------------------------- /kernel/arch/x86/inc/arch/intr/pit.h: -------------------------------------------------------------------------------- 1 | #ifndef PIT_H 2 | #define PIT_H 3 | 4 | #include 5 | 6 | #include 7 | 8 | 9 | /** 10 | * \brief Initialize the PIT. 11 | * Initialized the PIT using the supplied frequency if possible. 12 | * @param freq frequency in Hz 13 | */ 14 | void pit_init(uint32_t freq); 15 | 16 | void pit_create_timerdev(hal_timer_dev_t *dev); 17 | 18 | #endif 19 | -------------------------------------------------------------------------------- /kernel/arch/x86/inc/arch/intr/syscall.h: -------------------------------------------------------------------------------- 1 | #ifndef ARCH_INTR_SYSCALL_H 2 | #define ARCH_INTR_SYSCALL_H 3 | 4 | #include 5 | 6 | /** 7 | * @brief Architecture-specific handler for the syscall interrupt, calls syscall_service 8 | */ 9 | void arch_syscall_interrupt(intr_handler_hand_t *hdlr); 10 | 11 | #endif 12 | 13 | -------------------------------------------------------------------------------- /kernel/arch/x86/inc/arch/intr/types/intr.h: -------------------------------------------------------------------------------- 1 | #ifndef ARCH_INTR_TYPES_INTR_H 2 | #define ARCH_INTR_TYPES_INTR_H 3 | 4 | #include 5 | 6 | typedef enum x86_interrupt_idx_enum { 7 | INTR_TIMER = 32, 8 | INTR_KEYBOARD = 33, 9 | INTR_SERIALA = 35, 10 | INTR_SERIALB = 36, 11 | INTR_PARALLELB = 37, 12 | INTR_FLOPPY = 38, 13 | INTR_PARALLELA = 39, 14 | INTR_RTC = 40, 15 | INTR_IRQ9 = 41, 16 | INTR_IRQ10 = 42, 17 | INTR_IRQ11 = 43, 18 | INTR_PS2 = 44, 19 | INTR_COPROCESSOR = 45, 20 | INTR_ATAPRIMARY = 46, 21 | INTR_ATASECONDARY = 47, 22 | INTR_SCHED = 64, 23 | INTR_SYSCALL = 255 24 | } interrupt_idx_e; 25 | 26 | 27 | /** 28 | * Registers pushed on the stack via `pusha` 29 | */ 30 | typedef struct x86_pusha_regs_struct { 31 | uint32_t edi, esi; 32 | uint32_t ebp, esp; 33 | uint32_t ebx, edx, ecx, eax; 34 | } x86_pusha_regs_t; 35 | 36 | /** 37 | * Registers pushed on the stack on an interrupt 38 | */ 39 | typedef struct x86_iret_regs_struct { 40 | uint32_t eip, cs; 41 | uint32_t eflags; 42 | uint32_t esp, ds; 43 | } x86_iret_regs_t; 44 | 45 | typedef struct x86_intr_handler_hand_data_struct { 46 | x86_iret_regs_t *iregs; /**< Pointer to iret regs at interrupt entrypoint */ 47 | x86_pusha_regs_t *pregs; /**< Pointer to pusha regs at interrupt entrypoint */ 48 | } arch_intr_handler_hand_data_t; 49 | 50 | 51 | #endif 52 | 53 | -------------------------------------------------------------------------------- /kernel/arch/x86/inc/arch/intr/types/pic.h: -------------------------------------------------------------------------------- 1 | #ifndef ARCH_INTR_TYPES_PIC_H 2 | #define ARCH_INTR_TYPES_PIC_H 3 | 4 | #define PIC_IRQ_TIMER ( 0) 5 | #define PIC_IRQ_KEYBOARD ( 1) 6 | #define PIC_IRQ_SERIALA ( 3) 7 | #define PIC_IRQ_SERIALB ( 4) 8 | #define PIC_IRQ_PARALLELB ( 5) 9 | #define PIC_IRQ_FLOPPY ( 6) 10 | #define PIC_IRQ_PARALLELA ( 7) 11 | #define PIC_IRQ_RTC ( 8) 12 | #define PIC_IRQ_IRQ9 ( 9) 13 | #define PIC_IRQ_IRQ10 (10) 14 | #define PIC_IRQ_IRQ11 (11) 15 | #define PIC_IRQ_PS2 (12) 16 | #define PIC_IRQ_COPROCESSOR (13) 17 | #define PIC_IRQ_ATAPRIMARY (14) 18 | #define PIC_IRQ_ATASECONDARY (15) 19 | #define PIC_IRQ_MAX (16) 20 | 21 | #define PIC_OFFSET_MASTER (32) 22 | #define PIC_OFFSET_SLAVE (PIC_OFFSET_MASTER + 8) 23 | 24 | #define PIC_BIOS_OFFSET_MASTER (0x08) 25 | #define PIC_BIOS_OFFSET_SLAVE (0x70) 26 | 27 | #define PIC1_BASE (0x20) 28 | #define PIC2_BASE (0xa0) 29 | 30 | #define PIC1_COMMAND (PIC1_BASE + 0) 31 | #define PIC1_DATA (PIC1_BASE + 1) 32 | #define PIC2_COMMAND (PIC2_BASE + 0) 33 | #define PIC2_DATA (PIC2_BASE + 1) 34 | 35 | #define PIC_ICW1_IC4 (1U << 0) /**< ICW4 needed */ 36 | #define PIC_ICW1_SNGL (1U << 1) /**< 1: Single mode, 0: Cascade mode */ 37 | #define PIC_ICW1_ADI (1U << 2) /**< Call address interval (1: 4, 0: 8) */ 38 | #define PIC_ICW1_LTIM (1U << 3) /**< 1: Level triggered mode, 0: Edge triggered mode */ 39 | #define PIC_ICW1_1 (1U << 4) /**< Set to 1 */ 40 | 41 | #define PIC_ICW4_uPM (1U << 0) /**< 0: MCS-80/85 Mode, 1: 8086/8088 Mode */ 42 | #define PIC_ICW4_AEOI (1U << 1) /**< Enable automatic EOI */ 43 | #define PIC_ICW4_MS (1U << 2) /**< 0: Slave, 1: Master */ 44 | #define PIC_ICW4_BUF (1U << 3) /**< Buffered mode enable */ 45 | #define PIC_ICW4_SFNM (1U << 4) /**< Enable Special Fully Nested Mode */ 46 | 47 | #define PIC_OCW2_EOI (1U << 5) /**< End of interrupt */ 48 | #define PIC_OCW2_SL (1U << 5) /**< */ 49 | #define PIC_OCW2_R (1U << 5) /**< Rotate */ 50 | 51 | #endif 52 | 53 | -------------------------------------------------------------------------------- /kernel/arch/x86/inc/arch/io/ioport.h: -------------------------------------------------------------------------------- 1 | /** \file ioport.h 2 | * \brief Contains functions to read from and write to ports. 3 | * 4 | * Contains functions that allow you to read and write dato to and from 5 | * ports in C. 6 | */ 7 | 8 | #ifndef IOPORT_H 9 | #define IOPORT_H 10 | 11 | #include 12 | 13 | /** 14 | * \brief Output a byte to a port. 15 | * Outputs a byte on a port. 16 | * @param port the port the byte will be sent to 17 | * @param value the value of the byte to send 18 | * @see inb 19 | */ 20 | static inline void outb(uint16_t port, uint8_t value) { 21 | asm volatile ("outb %1, %0" : : "dN" (port), "a" (value)); 22 | } 23 | 24 | /** 25 | * \brief Output a word to a port. 26 | * Outputs a word on a port. 27 | * @param port the port the word //!< in intr.asm word to send 28 | * @see inw 29 | */ 30 | static inline void outw(uint16_t port, uint16_t value) { 31 | asm volatile("outw %0,%1" : : "a" (value), "dN" (port)); 32 | } 33 | 34 | /** 35 | * \brief Output a long word to a port. 36 | * Outputs a long word on a port. 37 | * @param port the port the long word will be sent to 38 | * @param value the value of the long word to send 39 | * @see inl 40 | */ 41 | static inline void outl(uint16_t port, uint32_t value) { 42 | asm volatile("outl %0,%1" : : "a" (value), "dN" (port)); 43 | } 44 | 45 | 46 | /** 47 | * \brief read a byte from a port. 48 | * Grab a byte from a port. 49 | * @param port the port the byte will taken from 50 | * @see outb 51 | */ 52 | static inline uint8_t inb(uint16_t port) { 53 | uint8_t ret; 54 | asm volatile("inb %1, %0" : "=a" (ret) : "dN" (port)); 55 | return ret; 56 | } 57 | 58 | /** 59 | * \brief read a word from a port. 60 | * Grab a word from a port. 61 | * @param port the port the word will taken from 62 | * @see outw 63 | */ 64 | static inline uint16_t inw(uint16_t port) { 65 | uint16_t ret; 66 | asm volatile ("inw %1, %0" : "=a" (ret) : "dN" (port)); 67 | return ret; 68 | } 69 | 70 | /** 71 | * \brief read a long word from a port. 72 | * Grab a long word from a port. 73 | * @param port the port the long word will taken from 74 | * @see outl 75 | */ 76 | static inline uint32_t inl(uint16_t port) { 77 | uint32_t ret; 78 | asm volatile ("inl %1, %0" : "=a" (ret) : "dN" (port)); 79 | return ret; 80 | } 81 | 82 | 83 | #endif -------------------------------------------------------------------------------- /kernel/arch/x86/inc/arch/io/msr.h: -------------------------------------------------------------------------------- 1 | #ifndef ARCH_IO_MSR 2 | #define ARCH_IO_MSR 3 | 4 | #include 5 | 6 | /** 7 | * @brief Check if the CPU suports the MSR instructions 8 | * 9 | * @return 1 if supported, else 0 10 | */ 11 | static inline int msr_avail(void) { 12 | return cpuid_featurecheck_edx(CPUIDFEATURE_EDX_MSR); 13 | } 14 | 15 | typedef enum { 16 | MSRREG_APICBASE = 0x0000001B 17 | } msr_register_e; 18 | 19 | /** 20 | * @brief Read current value of MSR 21 | * 22 | * @param reg MSR to read 23 | * @return value of MSR 24 | */ 25 | static inline uint64_t msr_read(msr_register_e reg) { 26 | uint32_t eax, edx; 27 | asm volatile("rdmsr" : 28 | "=a"(eax), "=d"(edx) : 29 | "c"(reg)); 30 | return ((uint64_t)edx << 32) | eax; 31 | } 32 | 33 | /** 34 | * @brief Write value to MSR 35 | * 36 | * @param reg MSR to write to 37 | * @param value Value to write to MSR 38 | */ 39 | static inline void msr_write(msr_register_e reg, uint64_t value) { 40 | uint32_t eax = (uint32_t)value; 41 | uint32_t edx = (uint32_t)(value >> 32); 42 | asm volatile("wrmsr" : : 43 | "a"(eax), "d"(edx), "c"(reg)); 44 | } 45 | 46 | 47 | #endif 48 | -------------------------------------------------------------------------------- /kernel/arch/x86/inc/arch/io/serial.h: -------------------------------------------------------------------------------- 1 | #ifndef SERIAL_H 2 | #define SERIAL_H 3 | 4 | #include 5 | 6 | #include 7 | 8 | #define SERIAL_COM1 0x3F8 9 | #define SERIAL_COM2 0x2F8 10 | #define SERIAL_COM3 0x3E8 11 | #define SERIAL_COM4 0x2E8 12 | 13 | int serial_create_chardev(uint16_t port, hal_io_char_dev_t *chardev); 14 | 15 | /** 16 | * \brief Initialize the serial port. 17 | * Initialize the serial port. 18 | * @param port which port to initialize 19 | */ 20 | void serial_init(uint16_t port); 21 | 22 | /** 23 | * \brief Check if a byte is waiting to be read. 24 | * Check if a byte is waiting to be read. 25 | * @param port serial port to check 26 | */ 27 | int serial_received(uint16_t port); 28 | 29 | /** 30 | * \brief Reads a byte from the serial port. 31 | * Reads a byte from the specified serial port. 32 | * @param port serial port to read from 33 | * @see serial_received 34 | */ 35 | char serial_read(uint16_t port); 36 | 37 | /** 38 | * \brief Checks if it is okay to send a byte to the serial port. 39 | * Checks if it is okay to send a byte to the specified serial port. 40 | * @param port serial port to check 41 | */ 42 | int is_transmit_empty(uint16_t port); 43 | 44 | /** 45 | * \brief Writes a byte to a serial port. 46 | * Writes a byte to the specified serial port. 47 | * @param port the serial port to write to 48 | * @param a the byte to write to the port 49 | * @see is_transmit_empty 50 | */ 51 | void serial_write(uint16_t port, char a); 52 | 53 | 54 | 55 | 56 | /** 57 | * @brief Write string to specified serial port 58 | * 59 | * @param port Serial port to write to 60 | * @param str NULL-terminated string to write to port 61 | */ 62 | void serial_print(uint16_t port, char *str); 63 | 64 | /** 65 | * @brief Conver number to string and write to specified serial port 66 | * 67 | * @param port Port to write to 68 | * @param n Number to convert to string 69 | * @param base Base in which to interpret number 70 | */ 71 | void serial_printnum(uint16_t port, uint32_t n, int base); 72 | 73 | #endif -------------------------------------------------------------------------------- /kernel/arch/x86/inc/arch/mm/mem.h: -------------------------------------------------------------------------------- 1 | #ifndef MEM_H 2 | #define MEM_H 3 | 4 | #include 5 | 6 | #define FRAMES_START (((uint32_t)&kern_end & 0xFFFFF000) + 0x1000) //!< Start of page frames 7 | 8 | #endif -------------------------------------------------------------------------------- /kernel/arch/x86/inc/arch/proc/stack.h: -------------------------------------------------------------------------------- 1 | #ifndef ARCH_X86_PROC_STACK_H 2 | #define ARCH_X86_PROC_STACK_H 3 | 4 | #include 5 | 6 | /** 7 | * @brief Copies stack of calling process to that of the child process. 8 | * 9 | * Note: The source process is assumed to be the current process 10 | * 11 | * @param dest Destination process 12 | * @param src Source process 13 | * @return int 0 on success 14 | */ 15 | int proc_copy_stack(kthread_t *dest, const kthread_t *src); 16 | 17 | /** 18 | * @brief Copies the kernel stack to that of the child process. 19 | * 20 | * Note: The source process is assumed to be the current process 21 | * 22 | * @param dest Destination process 23 | * @param src Source process 24 | * @return int 0 on success 25 | */ 26 | int proc_copy_kernel_stack(kthread_t *dest, const kthread_t *src); 27 | 28 | #endif // ARCH_X86_PROC_STACK_H -------------------------------------------------------------------------------- /kernel/arch/x86/inc/arch/proc/stack_trace.h: -------------------------------------------------------------------------------- 1 | #ifndef MEM_STACK_TRACE_H 2 | #define MEM_STACK_TRACE_H 3 | 4 | #include 5 | #include 6 | 7 | /** 8 | * @brief Print stack trace 9 | * 10 | * TODO: Add functionality to specify where to output stack trace 11 | * 12 | * @param max_frames Maximum number of function calls to traverse 13 | * @param ebp Last saved stack pointer from which to start 14 | * @param saved_eip Address of function from which stack trace was triggered (optional) 15 | * @param symbols Symbol table 16 | */ 17 | void stack_trace(uint32_t max_frames, uint32_t *ebp, uint32_t saved_eip, symbol_t *symbols); 18 | 19 | /** 20 | * @brief Generate stack trace from current address and stack 21 | * 22 | * @param max_frames Maximum number of function calls to traverse 23 | * 24 | * @see stack_trace 25 | */ 26 | void stack_trace_here(int max_frames); 27 | 28 | #endif 29 | -------------------------------------------------------------------------------- /kernel/arch/x86/inc/arch/proc/user.h: -------------------------------------------------------------------------------- 1 | #ifndef X86_PROC_H 2 | #define X86_PROC_H 3 | 4 | #include 5 | 6 | extern void enter_ring(uint8_t ring, void *address); 7 | extern void enter_ring_newstack(uint8_t ring, void *address, void *esp); 8 | 9 | extern void return_from_fork(void); 10 | 11 | #endif 12 | -------------------------------------------------------------------------------- /kernel/arch/x86/inc/arch/stdint.h: -------------------------------------------------------------------------------- 1 | #ifndef ARCH_STDINT_H 2 | #define ARCH_STDINT_H 3 | 4 | typedef char int8_t; //!< Signed 8 bit value 5 | typedef short int16_t; //!< Signed 16 bit value 6 | typedef int int32_t; //!< Signed 32 bit value 7 | typedef long long int64_t; //!< Signed 64 bit value 8 | 9 | typedef unsigned char uint8_t; //!< Unsigned 8 bit value 10 | typedef unsigned short uint16_t; //!< Unsigned 16 bit value 11 | typedef unsigned int uint32_t; //!< Unsigned 32 bit value 12 | typedef unsigned long long uint64_t; //!< Unsigned 64 bit value 13 | 14 | typedef uint32_t ptr_t; //!< Pointer 15 | 16 | typedef uint32_t uintptr_t; //!< Unsigned pointer 17 | typedef int32_t intptr_t; //!< Signed pointer 18 | 19 | typedef uint32_t size_t; //!< Size/length 20 | typedef int32_t ssize_t; //!< Size/length/error 21 | 22 | /* @todo Move this elsewhere */ 23 | typedef uint32_t syscallarg_t; /** Syscall argument type */ 24 | 25 | 26 | 27 | #define CHAR_MAX 127 28 | #define UCHAR_MAX 255 29 | 30 | #define SHORT_MAX 32767 31 | #define USHORT_MAX 65535 32 | 33 | #define INT_MAX 2147483647 34 | #define UINT_MAX 4294967295 35 | 36 | #define LONG_MAX 9223372036854775807 37 | #define ULONG_MAX 18446744073709551615 38 | 39 | #define INTPTR_MAX INT_MAX 40 | #define UINTPTR_MAX UINT_MAX 41 | 42 | #define SSIZE_MAX INT_MAX 43 | #define SIZE_MAX UINT_MAX 44 | 45 | #endif -------------------------------------------------------------------------------- /kernel/arch/x86/inc/arch/types/mmu.h: -------------------------------------------------------------------------------- 1 | #ifndef ARCH_TYPES_MMU_H 2 | #define ARCH_TYPES_MMU_H 3 | 4 | #include 5 | 6 | #define PAGE_SZ 4096 7 | #define PGDIR_ENTRIES 1024 8 | #define PGTBL_ENTRIES 1024 9 | 10 | typedef struct { 11 | uint32_t pagedir_ents[PGDIR_ENTRIES]; 12 | } mmu_table_t; 13 | 14 | #endif 15 | -------------------------------------------------------------------------------- /kernel/arch/x86/module.mk: -------------------------------------------------------------------------------- 1 | # Architecture-specific Makefile options for X86 2 | 3 | MDIR = $(dir $(lastword $(MAKEFILE_LIST))) 4 | 5 | ARCH := x86 6 | 7 | ifeq ($(CONFIG_ARCH_CPU_386),y) 8 | CPU := i386 9 | cflags-y += -DCONFIG_ARCH_CPU_386 10 | else ifeq ($(CONFIG_ARCH_CPU_486),y) 11 | CPU := i486 12 | cflags-y += -DCONFIG_ARCH_CPU_386 13 | else ifeq ($(CONFIG_ARCH_CPU_P5),y) 14 | CPU := p5 15 | cflags-y += -DCONFIG_ARCH_CPU_P5 16 | else ifeq ($(CONFIG_ARCH_CPU_P6),y) 17 | CPU := p6 18 | cflags-y += -DCONFIG_ARCH_CPU_P6 19 | endif 20 | 21 | ifeq ($(CONFIG_ARCH_HW_PC),y) 22 | HW := pc 23 | endif 24 | 25 | HWDIR := $(MDIR)hw/$(HW) 26 | HWINC := $(HWDIR)/inc 27 | 28 | LDARCH = 29 | ldflags-y += $(LDARCH) 30 | 31 | cflags-y += -DCONFIG_ARCH_X86 \ 32 | -I$(HWINC) 33 | 34 | ifeq ($(CONFIG_BUILD_USE_CLANG),y) 35 | # TODO: Select based on CPU selection, to (presumably) enable more 36 | # optimizations 37 | cflags-y += -target i486 38 | asflags-y += -target i486 39 | ldoflags-y += -melf_i386 40 | ldkflags-y += -target i486 -static 41 | endif 42 | 43 | include $(MDIR)src/module.mk 44 | include $(HWDIR)/module.mk 45 | 46 | 47 | -------------------------------------------------------------------------------- /kernel/arch/x86/src/acpi/module.mk: -------------------------------------------------------------------------------- 1 | MDIR = $(dir $(lastword $(MAKEFILE_LIST))) 2 | 3 | obj-y += $(MDIR)acpi.o 4 | 5 | -------------------------------------------------------------------------------- /kernel/arch/x86/src/boot/boot.s: -------------------------------------------------------------------------------- 1 | .set STACK_SZ, 0x2000 2 | 3 | .global start 4 | .extern kern_premap 5 | .section .boot.text 6 | .type start, @function 7 | start: 8 | //mov $(new_stack_t + STACK_SZ), %esp 9 | mov %esp, %ebp 10 | 11 | push %eax # Bootloader magic number 12 | push %ebx # Bootloader data header 13 | 14 | cli 15 | call kern_premap 16 | cli 17 | 18 | endloop: 19 | hlt 20 | jmp endloop 21 | 22 | .size start, . - start 23 | 24 | 25 | .section .text 26 | .global get_eip 27 | get_eip: 28 | mov (%esp), %eax 29 | ret 30 | 31 | 32 | .section .boot.data 33 | .lcomm new_stack_t, STACK_SZ 34 | -------------------------------------------------------------------------------- /kernel/arch/x86/src/boot/module.mk: -------------------------------------------------------------------------------- 1 | MDIR = $(dir $(lastword $(MAKEFILE_LIST))) 2 | 3 | obj-y += $(MDIR)boot.o \ 4 | $(MDIR)entry.o \ 5 | $(MDIR)multiboot.o 6 | 7 | cflags-$(CONFIG_MULTIBOOT) += -DCONFIG_MULTIBOOT \ 8 | -DCONFIG_MULTIBOOT_VERSION=$(CONFIG_MULTIBOOT_VERSION) 9 | -------------------------------------------------------------------------------- /kernel/arch/x86/src/dev/keyb/module.mk: -------------------------------------------------------------------------------- 1 | MDIR = $(dir $(lastword $(MAKEFILE_LIST))) 2 | 3 | obj-y += $(MDIR)input.o 4 | 5 | -------------------------------------------------------------------------------- /kernel/arch/x86/src/dev/module.mk: -------------------------------------------------------------------------------- 1 | MDIR = $(dir $(lastword $(MAKEFILE_LIST))) 2 | 3 | dirs-y := keyb \ 4 | vga 5 | 6 | include $(patsubst %,$(MDIR)%/module.mk,$(dirs-y)) 7 | 8 | -------------------------------------------------------------------------------- /kernel/arch/x86/src/dev/vga/module.mk: -------------------------------------------------------------------------------- 1 | MDIR = $(dir $(lastword $(MAKEFILE_LIST))) 2 | 3 | obj-y += $(MDIR)print.o 4 | 5 | -------------------------------------------------------------------------------- /kernel/arch/x86/src/init/module.mk: -------------------------------------------------------------------------------- 1 | MDIR = $(dir $(lastword $(MAKEFILE_LIST))) 2 | 3 | obj-y += $(MDIR)init.o 4 | 5 | -------------------------------------------------------------------------------- /kernel/arch/x86/src/intr/apic/apictimer.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include 5 | 6 | /* NOTE: Divisor = 2 ^ D, except for where D == 7, where Divisor = 1 */ 7 | #define DIVISOR_CONV(D) (((D) & 0x03) | (((D) & 0x04) << 1)) 8 | 9 | static int _timerdev_setfreq(void *, uint8_t, uint32_t); 10 | 11 | void apictimer_init(apictimer_handle_t *hand) { 12 | memset(hand, 0, sizeof(apictimer_handle_t)); 13 | 14 | hand->lapic = (apic_lapic_regs_t *)apic_getaddr(); 15 | 16 | /* TODO: Calibration via PIT */ 17 | } 18 | 19 | void apictimer_create_timerdev(apictimer_handle_t *hand, hal_timer_dev_t *dev) { 20 | memset(dev, 0, sizeof(hal_timer_dev_t)); 21 | 22 | dev->data = hand; 23 | 24 | dev->setfreq = _timerdev_setfreq; 25 | dev->setperiod = NULL; 26 | dev->attach = NULL; 27 | 28 | dev->cap = HAL_TIMERDEV_CAP_VARFREQ; 29 | } 30 | 31 | static int _timerdev_setfreq(void *data, uint8_t idx, uint32_t freq) { 32 | if(idx >= 1) { 33 | return -EINVAL; 34 | } 35 | apictimer_handle_t *hand = (apictimer_handle_t *)data; 36 | if(freq > (hand->busfreq / 2)) { 37 | return -EINVAL; 38 | } 39 | 40 | /* Just a static divisor of 2 for now */ 41 | hand->lapic->timer_div_config.value = DIVISOR_CONV(0); 42 | 43 | /* Only periodic for now */ 44 | hand->lapic->lvt_timer.value = ((hand->lapic->lvt_timer.value & 45 | ~(APIC_LVTENTRY_TIMERMODE__MASK << APIC_LVTENTRY_TIMERMODE__POS)) | 46 | (APIC_LVTENTRY_TIMERMODE_PERIODIC << APIC_LVTENTRY_TIMERMODE__POS)); 47 | 48 | /** Set the reload value and start the timer */ 49 | hand->lapic->timer_initial_cnt.value = hand->busfreq / freq; 50 | 51 | return 0; 52 | } 53 | -------------------------------------------------------------------------------- /kernel/arch/x86/src/intr/apic/module.mk: -------------------------------------------------------------------------------- 1 | MDIR = $(dir $(lastword $(MAKEFILE_LIST))) 2 | 3 | obj-$(CONFIG_X86_APIC) += $(MDIR)apic.o 4 | obj-$(CONFIG_X86_APIC_TIMER) += $(MDIR)apictimer.o 5 | 6 | cflags-$(CONFIG_X86_APIC) += -DCONFIG_X86_APIC 7 | cflags-$(CONFIG_X86_APIC_TIMER) += -DCONFIG_X86_APIC_TIMER 8 | 9 | -------------------------------------------------------------------------------- /kernel/arch/x86/src/intr/exceptions.s: -------------------------------------------------------------------------------- 1 | # Contains all exception ISR entrypoints 2 | 3 | .altmacro 4 | 5 | .macro setidt intr, sel, flags, func 6 | pusha 7 | pushl \func 8 | pushl \flags 9 | pushl \sel 10 | pushl \intr 11 | call idt_set_entry 12 | addl $16, %esp 13 | popa 14 | .endm 15 | 16 | .extern handle_exception 17 | 18 | .macro except_isr num err 19 | exception_isr_\num: 20 | .if !\err 21 | push $0 # Errcode 22 | .endif 23 | pusha 24 | push $\num 25 | call handle_exception 26 | popa 27 | .if !\err 28 | addl $4, %esp # Errcode 29 | .endif 30 | iret 31 | .endm 32 | 33 | .macro setidt_exception num 34 | setidt $\num, $0x08, $0x8E, $exception_isr_\num 35 | .endm 36 | 37 | .global idt_setup_exceptions 38 | idt_setup_exceptions: 39 | .set n, 0 40 | .rept 32 41 | setidt_exception %n 42 | .set n, n+1 43 | .endr 44 | ret 45 | 46 | 47 | except_isr 0, 0 48 | except_isr 1, 0 49 | except_isr 2, 0 50 | except_isr 3, 0 51 | except_isr 4, 0 52 | except_isr 5, 0 53 | except_isr 6, 0 54 | except_isr 7, 0 55 | except_isr 8, 1 56 | except_isr 9, 0 57 | except_isr 10, 1 58 | except_isr 11, 1 59 | except_isr 12, 1 60 | except_isr 13, 1 61 | except_isr 14, 1 62 | except_isr 15, 0 63 | except_isr 16, 0 64 | except_isr 17, 1 65 | except_isr 18, 0 66 | except_isr 19, 0 67 | except_isr 20, 0 68 | except_isr 21, 0 69 | except_isr 22, 0 70 | except_isr 23, 0 71 | except_isr 24, 0 72 | except_isr 25, 0 73 | except_isr 26, 0 74 | except_isr 27, 0 75 | except_isr 28, 0 76 | except_isr 29, 0 77 | except_isr 30, 1 78 | except_isr 31, 0 79 | 80 | -------------------------------------------------------------------------------- /kernel/arch/x86/src/intr/intr.s: -------------------------------------------------------------------------------- 1 | .altmacro 2 | 3 | .extern idt_set_entry 4 | 5 | 6 | 7 | .macro gen_int_handler num 8 | int_handler_\num: 9 | pusha 10 | push $\num 11 | call idt_handle_interrupt 12 | 13 | .if \num < 40 14 | movb $0x20, %al 15 | outb %al, $0x20 16 | .elseif \num < 48 17 | movb $0x20, %al 18 | outb %al, $0xA0 19 | .endif 20 | 21 | addl $4, %esp # Int number 22 | popa 23 | iret 24 | .endm 25 | 26 | .set n, 32 27 | .rept (256 - 32) 28 | gen_int_handler %n 29 | .set n, n+1 30 | .endr 31 | 32 | 33 | .macro setidt intr, sel, flags, func 34 | pusha 35 | pushl \func 36 | pushl \flags 37 | pushl \sel 38 | pushl \intr 39 | call idt_set_entry 40 | addl $16, %esp 41 | popa 42 | .endm 43 | 44 | .macro setidt_intr num 45 | setidt $\num $0x08 $0x8E $int_handler_\num 46 | .endm 47 | 48 | .global idt_setup_handlers 49 | idt_setup_handlers: 50 | .set n, 32 51 | .rept (256 - 32) 52 | setidt_intr %n 53 | .set n, n+1 54 | .endr 55 | ret 56 | 57 | 58 | 59 | 60 | .global interrupts_enabled 61 | # Checks to see if interrupts are currently enabled 62 | interrupts_enabled: 63 | pushf 64 | popl %eax 65 | andl $(1 << 9), %eax # Get IF flag 66 | shrl $9, %eax 67 | ret 68 | 69 | 70 | 71 | .extern restore_syscall_regs 72 | .global return_from_syscall 73 | return_from_syscall: 74 | popa 75 | iret 76 | 77 | .global call_syscall_int 78 | # Call interrupt for a syscall 79 | call_syscall_int: 80 | movl %esp, %ebp 81 | pusha 82 | 83 | movl 4(%ebp), %eax 84 | movl 8(%ebp), %ebx 85 | 86 | int $0xFF 87 | 88 | popa 89 | ret 90 | 91 | -------------------------------------------------------------------------------- /kernel/arch/x86/src/intr/module.mk: -------------------------------------------------------------------------------- 1 | MDIR = $(dir $(lastword $(MAKEFILE_LIST))) 2 | 3 | obj-y += $(MDIR)cexceptions.o \ 4 | $(MDIR)exceptions.o \ 5 | $(MDIR)idt.o \ 6 | $(MDIR)intr.o \ 7 | $(MDIR)pic.o \ 8 | $(MDIR)pit.o 9 | 10 | dirs-y := apic 11 | 12 | include $(patsubst %,$(MDIR)%/module.mk,$(dirs-y)) 13 | 14 | -------------------------------------------------------------------------------- /kernel/arch/x86/src/intr/pic.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | 6 | #include 7 | 8 | int pic_irq_disable(uint8_t irq_id) { 9 | if(irq_id >= 16) { 10 | return -EINVAL; 11 | } 12 | 13 | uint16_t port = PIC1_DATA; 14 | if(irq_id >= 8) { 15 | port = PIC2_DATA; 16 | irq_id -= 8; 17 | } 18 | 19 | uint8_t mask = inb(port) | (1U << irq_id); 20 | outb(port, mask); 21 | 22 | return 0; 23 | } 24 | EXPORT_FUNC(pic_irq_disable); 25 | 26 | int pic_irq_enable(uint8_t irq_id) { 27 | if(irq_id >= 16) { 28 | return -EINVAL; 29 | } 30 | 31 | uint16_t port = PIC1_DATA; 32 | if(irq_id >= 8) { 33 | port = PIC2_DATA; 34 | irq_id -= 8; 35 | } 36 | 37 | uint8_t mask = inb(port) & ~(1U << irq_id); 38 | outb(port, mask); 39 | 40 | return 0; 41 | } 42 | EXPORT_FUNC(pic_irq_enable); 43 | 44 | void pic_remap(uint8_t master, uint8_t slave) { 45 | /* Save interrupt masks */ 46 | uint8_t m_mask = inb(PIC1_DATA); 47 | uint8_t s_mask = inb(PIC2_DATA); 48 | 49 | /* ICW 1 */ 50 | outb(PIC1_COMMAND, PIC_ICW1_IC4 | PIC_ICW1_1); 51 | outb(PIC2_COMMAND, PIC_ICW1_IC4 | PIC_ICW1_1); 52 | /* ICW 2 - vector offset*/ 53 | outb(PIC1_DATA, master); 54 | outb(PIC2_DATA, slave); 55 | /* ICW 3 */ 56 | outb(PIC1_DATA, (1U << 2)); /* IRQ2 as slave input */ 57 | outb(PIC2_DATA, 2); /* Slave identity is 2 */ 58 | /* ICW 4 */ 59 | outb(PIC1_DATA, PIC_ICW4_uPM); 60 | outb(PIC2_DATA, PIC_ICW4_uPM); 61 | 62 | /* Restore interrupt masks */ 63 | outb(PIC1_DATA, m_mask); 64 | outb(PIC2_DATA, s_mask); 65 | } 66 | 67 | -------------------------------------------------------------------------------- /kernel/arch/x86/src/io/module.mk: -------------------------------------------------------------------------------- 1 | MDIR = $(dir $(lastword $(MAKEFILE_LIST))) 2 | 3 | obj-y += $(MDIR)serial.o 4 | 5 | -------------------------------------------------------------------------------- /kernel/arch/x86/src/mm/gdt.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | 5 | static uint8_t system_stack[0x2000]; 6 | 7 | static tss_t TSS = { 0, }; 8 | 9 | static uint64_t GDT[10] = //!< The Global Descriptor Table 10 | { 11 | GDT_NULL, // 00 12 | 13 | GDT_CODE_RING0, // 08 14 | GDT_DATA_RING0, // 10 15 | 16 | GDT_CODE_RING1, // 18 17 | GDT_DATA_RING1, // 20 18 | 19 | GDT_CODE_RING2, // 28 20 | GDT_DATA_RING2, // 30 21 | 22 | GDT_CODE_RING3, // 38 23 | GDT_DATA_RING3, // 40 24 | 25 | GDT_NULL // 48 <- Placeholder for TSS 26 | }; 27 | 28 | extern void load_gdt(uint64_t *, uint32_t); //!< Sets the GDT pointer with `lidt` 29 | extern void seg_reload(void); //!< Reloads the segment registers 30 | extern void load_tss(void); //!< Sets the TSS descriptor 31 | 32 | /** 33 | * \brief Initialize the GDT 34 | * Initializes the GDT then the TSS. 35 | */ 36 | void gdt_init(void) { 37 | TSS.ss0 = 0x10; 38 | TSS.ss1 = 0x21; 39 | TSS.ss2 = 0x32; 40 | 41 | TSS.esp0 = (uint32_t)system_stack; 42 | 43 | TSS.es = 0x13; 44 | TSS.cs = 0x0B; 45 | TSS.ss = 0x13; 46 | TSS.ds = 0x13; 47 | TSS.fs = 0x13; 48 | TSS.gs = 0x13; 49 | 50 | TSS.iopb_offset = sizeof(tss_t); 51 | 52 | GDT[9] = GDT_ENTRY((uint32_t)&TSS, sizeof(TSS)-1, 0x40E9); 53 | 54 | load_gdt(GDT, sizeof(GDT)); 55 | seg_reload(); 56 | load_tss(); 57 | } 58 | 59 | void tss_set_kern_stack(uint32_t stack) { 60 | TSS.esp0 = stack; 61 | } -------------------------------------------------------------------------------- /kernel/arch/x86/src/mm/mm.s: -------------------------------------------------------------------------------- 1 | # Memory Management related functions 2 | 3 | .global load_gdt 4 | .global seg_reload 5 | .global load_tss 6 | 7 | # Load the new GDT 8 | load_gdt: 9 | movl 4(%esp), %eax 10 | movl %eax, (gdtr+2) 11 | movw 8(%esp), %ax 12 | movw %ax, (gdtr) 13 | lgdt (gdtr) 14 | ret 15 | 16 | # Reload various segments to allow the GDT to take effect 17 | seg_reload: 18 | jmp $0x08,$.reload_cs 19 | .reload_cs: 20 | movw $0x10, %ax 21 | movw %ax, %ds 22 | movw %ax, %es 23 | movw %ax, %fs 24 | movw %ax, %gs 25 | movw %ax, %ss 26 | ret 27 | 28 | # Let the computer know which GDT descriptor contains TSS info 29 | load_tss: 30 | movw $0x4B, %ax 31 | ltr %ax 32 | ret 33 | 34 | .section .data 35 | gdtr: .word 0 # For limit storage 36 | .long 0 # For base storage 37 | -------------------------------------------------------------------------------- /kernel/arch/x86/src/mm/module.mk: -------------------------------------------------------------------------------- 1 | MDIR = $(dir $(lastword $(MAKEFILE_LIST))) 2 | 3 | obj-y += $(MDIR)gdt.o \ 4 | $(MDIR)mm.o \ 5 | $(MDIR)mmu.o \ 6 | $(MDIR)paging.o 7 | 8 | -------------------------------------------------------------------------------- /kernel/arch/x86/src/module.mk: -------------------------------------------------------------------------------- 1 | MDIR = $(dir $(lastword $(MAKEFILE_LIST))) 2 | 3 | dirs-y := acpi \ 4 | boot \ 5 | dev \ 6 | init \ 7 | intr \ 8 | io \ 9 | mm \ 10 | proc 11 | 12 | include $(patsubst %,$(MDIR)%/module.mk,$(dirs-y)) 13 | 14 | -------------------------------------------------------------------------------- /kernel/arch/x86/src/proc/module.mk: -------------------------------------------------------------------------------- 1 | MDIR = $(dir $(lastword $(MAKEFILE_LIST))) 2 | 3 | obj-y += $(MDIR)stack.o \ 4 | $(MDIR)stack_trace.o \ 5 | $(MDIR)syscall.o \ 6 | $(MDIR)tasking.o \ 7 | $(MDIR)user.o 8 | 9 | -------------------------------------------------------------------------------- /kernel/arch/x86/src/proc/stack.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include 6 | #include 7 | 8 | int proc_copy_stack(kthread_t *dest, const kthread_t *src) { 9 | kdebug(DEBUGSRC_PROC, ERR_TRACE, "proc_copy_stack %08X (%08X) -> %08X (%08X)", 10 | src->arch.stack_user.begin, (pgdir_get_page_entry((uint32_t *)src->process->mmu_table, (void *)(src->arch.stack_user.begin - 4096)) & (~0xFFF)) + 4096, 11 | dest->arch.stack_user.begin, (pgdir_get_page_entry((uint32_t *)dest->process->mmu_table, (void *)(dest->arch.stack_user.begin - 4096)) & (~0xFFF)) + 4096 12 | ); 13 | 14 | uintptr_t end_src = src->arch.stack_user.begin - src->arch.stack_user.size; 15 | uintptr_t end_dest = dest->arch.stack_user.begin - dest->arch.stack_user.size; 16 | 17 | mmu_copy_data(dest->process->mmu_table, end_dest, 18 | src->process->mmu_table, end_src, 19 | src->arch.stack_user.size); 20 | 21 | return 0; 22 | } 23 | 24 | int proc_copy_kernel_stack(kthread_t *dest, const kthread_t *src) { 25 | kdebug(DEBUGSRC_PROC, ERR_TRACE, "proc_copy_kernel_stack %08X (%08X) -> %08X (%08X)", 26 | src->arch.stack_kern.begin, (pgdir_get_page_entry((uint32_t *)src->process->mmu_table, (void *)(src->arch.stack_kern.begin - 4096)) & (~0xFFF)) + 4096, 27 | dest->arch.stack_kern.begin, (pgdir_get_page_entry((uint32_t *)dest->process->mmu_table, (void *)(dest->arch.stack_kern.begin - 4096)) & (~0xFFF)) + 4096 28 | ); 29 | 30 | mmu_copy_data(dest->process->mmu_table, (dest->arch.stack_kern.begin - CONFIG_PROC_KERN_STACK_SIZE), 31 | src->process->mmu_table, (src->arch.stack_kern.begin - CONFIG_PROC_KERN_STACK_SIZE), 32 | CONFIG_PROC_KERN_STACK_SIZE); 33 | 34 | return 0; 35 | } 36 | -------------------------------------------------------------------------------- /kernel/arch/x86/src/proc/syscall.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | void arch_syscall_interrupt(intr_handler_hand_t *hdlr) { 9 | kthread_t *curr_thread = mtask_get_curr_thread(); 10 | 11 | curr_thread->arch.esp = (uint32_t)&hdlr->arch.pregs; 12 | 13 | curr_thread->arch.syscall_regs.pusha = hdlr->arch.pregs; 14 | curr_thread->arch.syscall_regs.iret = hdlr->arch.iregs; 15 | 16 | uint32_t scn = hdlr->arch.pregs->eax; 17 | uint32_t *args = (uint32_t *)hdlr->arch.pregs->ebx; 18 | 19 | if(syscall_service(scn, args)) { 20 | stack_trace(15, (uint32_t *)hdlr->arch.pregs->ebp, hdlr->arch.iregs->eip, curr_thread->process->symbols); 21 | exit(1); 22 | } 23 | } 24 | 25 | -------------------------------------------------------------------------------- /kernel/inc/crypto/comp/comp.h: -------------------------------------------------------------------------------- 1 | #ifndef CRYPTO_COMP_H 2 | #define CRYPTO_COMP_H 3 | 4 | #include 5 | 6 | #include 7 | 8 | /** 9 | * @brief Decompress compressed data 10 | * 11 | * @param handle Crypto compression handle, includes the type of compression 12 | * @param input Input buffer 13 | * @param input_len Size of input buffer 14 | * @param output Where to store pointer to allocated output buffer 15 | * @param output_len Where to store decompressed data length 16 | * 17 | * @return 0 on success, else negative error code 18 | */ 19 | int crypto_comp_decompress(const crypto_comp_handle_t *handle, const void *const input, size_t input_len, void **const output, size_t *const output_len); 20 | 21 | #endif 22 | 23 | -------------------------------------------------------------------------------- /kernel/inc/crypto/comp/lzop.h: -------------------------------------------------------------------------------- 1 | #ifndef CRYPTO_COMP_LZOP_H 2 | #define CRYPTO_COMP_LZOP_H 3 | 4 | #include 5 | 6 | /** 7 | * @brief Decompress lzop-compressed data using LZO1X 8 | * 9 | * @note This should not be used outside of crypto_comp - external users should 10 | * utilise crypto_comp_decompress instead. 11 | * 12 | * @param handle Crypto compression handle 13 | * @param input Input buffer 14 | * @param input_len Size of input buffer 15 | * @param output Where to store pointer to allocated output buffer 16 | * @param output_len Where to store decompressed data length 17 | * 18 | * @return 0 on success, else negative error code 19 | */ 20 | int lzop_decompress(const crypto_comp_handle_t *handle, const void *const input, size_t input_len, void **const output, size_t *const output_len); 21 | 22 | #endif 23 | 24 | -------------------------------------------------------------------------------- /kernel/inc/crypto/comp/types/comp.h: -------------------------------------------------------------------------------- 1 | #ifndef CRYPTO_COMP_TYPES_COMP_H 2 | #define CRYPTO_COMP_TYPES_COMP_H 3 | 4 | #include 5 | 6 | typedef enum crypto_comp_format_enum { 7 | CRYPTO_COMP_FMT_NONE = 0, 8 | #ifdef CONFIG_CRYPTO_COMP_LZOP 9 | CRYPTO_COMP_FMT_LZOP, 10 | #endif 11 | } crypto_comp_format_e; 12 | 13 | typedef struct crypto_comp_handle_struct { 14 | /** Compression format */ 15 | uint8_t format; 16 | /* Per-format options to go into a union here */ 17 | } crypto_comp_handle_t; 18 | 19 | #endif 20 | 21 | -------------------------------------------------------------------------------- /kernel/inc/ctype.h: -------------------------------------------------------------------------------- 1 | #ifndef CTYPE_H 2 | #define CTYPE_H 3 | 4 | static inline int isspace(int c) { 5 | return ((c == ' ') || 6 | (c == '\t') || 7 | (c == '\v') || 8 | (c == '\r') || 9 | (c == '\n')); 10 | } 11 | 12 | static inline int isnum(int c) { 13 | return ((c >= '0') && 14 | (c <= '9')); 15 | } 16 | 17 | static inline int isupper(int c) { 18 | return ((c >= 'A') && 19 | (c <= 'Z')); 20 | } 21 | 22 | static inline int islower(int c) { 23 | return ((c >= 'a') && 24 | (c <= 'z')); 25 | } 26 | 27 | static inline int isalpha(int c) { 28 | return (islower(c) || isupper(c)); 29 | } 30 | 31 | static inline int isalnum(int c) { 32 | return (isnum(c) || isalpha(c)); 33 | } 34 | 35 | static inline int tolower(int c) { 36 | if(islower(c)) { return c; } 37 | if(isupper(c)) { return c + ('a' - 'A'); } 38 | return 0; 39 | } 40 | 41 | #endif 42 | -------------------------------------------------------------------------------- /kernel/inc/data/cbuff.h: -------------------------------------------------------------------------------- 1 | #ifndef DATA_CBUFF_H 2 | #define DATA_CBUFF_H 3 | 4 | #include 5 | 6 | #include 7 | 8 | int cbuff_allocate(cbuff_t *buff, size_t size); 9 | 10 | void cbuff_free(cbuff_t *buff); 11 | 12 | /** 13 | * @brief Place byte into circular buffer 14 | * 15 | * @param data Byte to place in buffer 16 | * @param buff Circular buffer in which to place byte 17 | * @return int 0 on success, 18 | * -E* on failure 19 | */ 20 | int cbuff_put(uint8_t data, cbuff_t *buff); 21 | 22 | /** 23 | * @brief Read byte from circular buffer 24 | * 25 | * @param buff Circular buffer from which to read 26 | * @return int Read byte on success, 27 | * -E* on failure 28 | */ 29 | int cbuff_get(cbuff_t *buff); 30 | 31 | /** 32 | * @brief Write data into circular buffer 33 | * 34 | * Will return CBUFF_FULL if the entire set of data cannot be placed in the buffer 35 | * 36 | * @param data Pointer to data to write into buffer 37 | * @param size Size of data in bytes 38 | * @param buff Buffer to write data into 39 | * 40 | * @return int 0 on success, 41 | * -E* on failure 42 | */ 43 | int cbuff_write(const uint8_t *data, size_t size, cbuff_t *buff); 44 | 45 | /** 46 | * @brief Read data from circular buffer 47 | * 48 | * @param data Pointer to where to store data 49 | * @param size Number of bytes to read 50 | * @param buff Buffer to read from 51 | * 52 | * @return int 0 on success, 53 | * -E* on failure 54 | */ 55 | int cbuff_read(uint8_t *data, size_t size, cbuff_t *buff); 56 | 57 | 58 | #endif // CBUFF_H 59 | -------------------------------------------------------------------------------- /kernel/inc/data/types/cbuff.h: -------------------------------------------------------------------------------- 1 | #ifndef DATA_TYPES_CBUFF_H 2 | #define DATA_TYPES_CBUFF_H 3 | 4 | #include 5 | 6 | /** FIFO cicular buffer */ 7 | typedef struct { 8 | uint32_t begin; /** Index of first written byte */ 9 | uint32_t count; /** Number of readable bytes in the buffer */ 10 | uint32_t size; /** Size of the buffer */ 11 | uint8_t *buff; /** The buffer */ 12 | } cbuff_t; 13 | 14 | /** Helper to create a static cbuff */ 15 | #define STATIC_CBUFF(SZ) { .size = (SZ), .buff = (uint8_t[(SZ)]){ 0, }} 16 | 17 | #endif // CBUFF_H 18 | -------------------------------------------------------------------------------- /kernel/inc/data/types/llist.h: -------------------------------------------------------------------------------- 1 | #ifndef DATA_TYPES_LLIST_H 2 | #define DATA_TYPES_LLIST_H 3 | 4 | 5 | typedef struct llist_item llist_item_t; 6 | typedef struct llist llist_t; 7 | typedef struct llist_iterator llist_iterator_t; 8 | 9 | #include 10 | 11 | /** 12 | * Represents an item in a linked list 13 | */ 14 | struct llist_item { 15 | void *data; /** Data represented by list item */ 16 | llist_item_t *prev; /** Previous item in list */ 17 | llist_item_t *next; /** Next item in list */ 18 | }; 19 | 20 | /** 21 | * Represents a linked list 22 | */ 23 | struct llist { 24 | llist_item_t *list; /** Pointer to first item in list */ 25 | lock_t lock; /** Lock to ensure only a single thread touches the list at a time */ 26 | }; 27 | 28 | /** 29 | * llist iterator state 30 | */ 31 | struct llist_iterator { 32 | llist_item_t *first; /** First item encountered in list */ 33 | llist_item_t *curr; /** Current list item */ 34 | }; 35 | 36 | #endif 37 | 38 | -------------------------------------------------------------------------------- /kernel/inc/err/panic.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | /** 4 | * \brief Halts OS after printing error information. 5 | * 6 | * Disabled interrupts, prints the provided error message, then halts the computer. 7 | * 8 | * @param msg format string 9 | * @param ... arguments to go along with format string 10 | */ 11 | __noreturn 12 | void _kpanic(char *msg, ...); 13 | 14 | #define __kpanic_stringify1(X) #X 15 | #define __kpanic_stringify2(X) __kpanic_stringify1(X) 16 | 17 | #define kpanic(...) _kpanic(__FILE__ ":" __kpanic_stringify2(__LINE__) ": " __VA_ARGS__) 18 | 19 | #define kassert(EXPR, ...) if(!(EXPR)) { kpanic(__VA_ARGS__); } 20 | 21 | /* TODO: Move this declaration elsewhere */ 22 | void arch_kpanic_hook(void); 23 | -------------------------------------------------------------------------------- /kernel/inc/fs/dirent.h: -------------------------------------------------------------------------------- 1 | #ifndef FS_DIRENT_H 2 | #define FS_DIRENT_H 3 | 4 | #include 5 | 6 | #define FILE_NAME_MAX 256 7 | 8 | struct dirent { 9 | uint32_t ino; //!< i-node of the file 10 | char name[FILE_NAME_MAX]; //!< name of the file 11 | }; 12 | 13 | #endif -------------------------------------------------------------------------------- /kernel/inc/fs/dirinfo.h: -------------------------------------------------------------------------------- 1 | #ifndef FS_DIRINFO_H 2 | #define FS_DIRINFO_H 3 | 4 | #include 5 | 6 | struct dirinfo { 7 | uint32_t ino; //!< Inode 8 | 9 | uint32_t n_children; //!< Number of children 10 | uint32_t parent_ino; //!< Inode of parent directory 11 | 12 | char name[FILE_NAME_MAX]; //!< Name of directory 13 | }; 14 | 15 | #endif -------------------------------------------------------------------------------- /kernel/inc/fs/dirstream.h: -------------------------------------------------------------------------------- 1 | #ifndef FS_DIRSTREAM_H 2 | #define FS_DIRSTREAM_H 3 | 4 | //struct kfile; 5 | 6 | struct dirstream { 7 | struct kfile *dir; //!< kfile representing directory 8 | 9 | struct kfile *current; //!< Current file (next file to be returned by a call to `readdir`) 10 | struct kfile *prev; //!< Previous file returned by `readdir` 11 | }; 12 | 13 | #define DIR struct dirstream 14 | 15 | #endif -------------------------------------------------------------------------------- /kernel/inc/fs/fs.h: -------------------------------------------------------------------------------- 1 | #ifndef FS_H 2 | #define FS_H 3 | 4 | #include 5 | #include 6 | 7 | #include 8 | 9 | #define PERMISSIONS(u, g, w) ((u << 6) | (g << 3) | (w << 0)) 10 | 11 | int fs_add_file(kfile_t *file, kfile_t *parent); 12 | 13 | ssize_t fs_read (kfile_hand_t *f, uint32_t off, uint32_t sz, void *buff); 14 | ssize_t fs_write (kfile_hand_t *f, uint32_t off, uint32_t sz, const void *buff); 15 | int fs_open (kfile_t *f, kfile_hand_t *hand); 16 | int fs_close (kfile_hand_t *f); 17 | struct dirent *fs_readdir(DIR *d); 18 | kfile_t *fs_finddir(kfile_t *f, const char *name); 19 | DIR *fs_opendir(kfile_t *f); 20 | int fs_mkdir (kfile_t *f, const char *name, uint32_t perms); 21 | int fs_create (kfile_t *f, const char *name, uint32_t perms); 22 | int fs_ioctl (kfile_hand_t *f, int req, void *args); 23 | 24 | kfile_t *fs_dirfile(DIR *d); 25 | 26 | kfile_hand_t *fs_handle_create(void); 27 | kfile_hand_t *fs_handle_create_open(kfile_t *f, uint32_t flags); 28 | int fs_handle_destroy(kfile_hand_t *hand); 29 | int fs_read_file_by_path(const char *path, kfile_t *cwd, void **buff, size_t *sz, size_t max_sz); 30 | 31 | /** 32 | * \brief Find a file relative to the given directory 33 | * 34 | * @param f Directory for path to be relative to 35 | * @param path Path 36 | * 37 | * @return kfile representing requested file/directory, NULL if not found 38 | */ 39 | kfile_t *fs_find_file(kfile_t *f, const char *path); 40 | 41 | /** 42 | * @brief Returns root node of virtual filesystem 43 | * 44 | * @return kfile_t* Pointer to root node 45 | */ 46 | kfile_t *fs_get_root(void); 47 | 48 | void fs_init(void); 49 | 50 | #endif // FS_H 51 | -------------------------------------------------------------------------------- /kernel/inc/fs/initrd.h: -------------------------------------------------------------------------------- 1 | #ifndef INITRD_H 2 | #define INITRD_H 3 | 4 | #include 5 | #include 6 | 7 | #ifdef CONFIG_EMBEDDED_INITRD 8 | /* Linked in through initrd.o */ 9 | # ifdef CONFIG_EMBEDDED_INITRD_LZOP 10 | extern int _binary_initrd_cpio_start; 11 | extern int _binary_initrd_cpio_end; 12 | # define INITRD_START _binary_initrd_cpio_start 13 | # define INITRD_END _binary_initrd_cpio_start 14 | # else 15 | extern int _binary_initrd_cpio_lzo_start; 16 | extern int _binary_initrd_cpio_lzo_end; 17 | # define INITRD_START _binary_initrd_cpio_lzo_start 18 | # define INITRD_END _binary_initrd_cpio_lzo_start 19 | # endif 20 | #endif 21 | 22 | /** 23 | * @brief Load INITRD 24 | * 25 | * @param mntpoint where to mount initrd 26 | * @param initrd pointer to CPIO structure in memory 27 | * @param len length of initrd data 28 | */ 29 | void initrd_mount(struct kfile *mntpoint, uintptr_t initrd, size_t len); 30 | 31 | /** 32 | * @brief CPIO header 33 | */ 34 | struct header_old_cpio { 35 | uint16_t c_magic; //!< Magic number (070707) 36 | uint16_t c_dev; //!< Device number 37 | uint16_t c_ino; //!< Inode number 38 | uint16_t c_mode; //!< Mode 39 | uint16_t c_uid; //!< UID of owner 40 | uint16_t c_gid; //!< GID of owner 41 | uint16_t c_nlink; //!< Number of links to this file 42 | uint16_t c_rdev; //!< Device number (for block/char devices) 43 | uint32_t c_mtime; //!< Modification time (seconds since epoch) 44 | uint16_t c_namesize; //!< Bytes in name, including NULL byte 45 | uint32_t c_filesize; //!< Size of file (MAX 4 GiB) 46 | } __packed; 47 | 48 | /** 49 | * @brief CPIO c_mode values 50 | */ 51 | enum old_cpio_mode { 52 | CPIO_MODE_SOCKET = 0140000, //!< Socket 53 | CPIO_MODE_SYMLINK = 0120000, //!< Symbolic link 54 | CPIO_MODE_REGULAR = 0100000, //!< Regular file 55 | CPIO_MODE_BLOCK = 0060000, //!< Block device 56 | CPIO_MODE_DIRECTORY = 0040000, //!< Directory 57 | CPIO_MODE_CHAR = 0020000, //!< Character device 58 | CPIO_MODE_PIPE = 0010000, //!< Named pipe or FIFO 59 | CPIO_MODE_SUID = 0004000, //!< SUID 60 | CPIO_MODE_SGID = 0002000, //!< SGID 61 | CPIO_MODE_STICKY = 0001000, //!< Sticky bit 62 | 63 | CPIO_MODE_PERM_MASK = 0000777 //!< POSIX permissions 64 | }; 65 | 66 | #endif // INITRD_H 67 | -------------------------------------------------------------------------------- /kernel/inc/fs/procfs.h: -------------------------------------------------------------------------------- 1 | #ifndef PROCFS_H 2 | #define PROCFS_H 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | struct user_dirent { 9 | uint32_t d_ino; 10 | char d_name[]; 11 | }; 12 | 13 | uint32_t proc_fs_read (int desc, uint32_t off, uint32_t sz, uint8_t *buff); 14 | uint32_t proc_fs_write (int desc, uint32_t off, uint32_t sz, uint8_t *buff); 15 | int proc_fs_open (const char *name, uint32_t flags); 16 | int proc_fs_close (int desc); 17 | int proc_fs_mkdir (int desc, char *name, uint32_t perms); 18 | int proc_fs_create (int desc, char *name, uint32_t perms); 19 | int proc_fs_ioctl (int desc, int req, void *args); 20 | uint32_t proc_fs_read_blk(int desc, uint32_t off, uint32_t sz, uint8_t *buff); 21 | 22 | int proc_fs_getdirinfo(int desc, struct dirinfo *dinfo); 23 | 24 | int proc_fs_readdir(int desc, uint32_t idx, struct user_dirent *buff, uint32_t buff_size); 25 | 26 | int proc_fs_stat(const char *path, kstat_t *buf, uint32_t flags); 27 | 28 | #define SYSCALL_ACCESS_FLAG_CWDOVER (1UL << 0) /** Override CWD with given fd */ 29 | int proc_fs_access(int dirfd, const char *pathname, uint32_t mode, uint32_t flags); 30 | 31 | #endif -------------------------------------------------------------------------------- /kernel/inc/fs/stream.h: -------------------------------------------------------------------------------- 1 | #ifndef FS_STREAM_H 2 | #define FS_STREAM_H 3 | 4 | #include 5 | 6 | /** 7 | * \brief Creates a new stream, and returns the file representation 8 | * 9 | * @param length Length of stream buffer 10 | * 11 | * @return Pointer to kfile representing the stream 12 | */ 13 | struct kfile *stream_create(int length); 14 | 15 | #endif -------------------------------------------------------------------------------- /kernel/inc/hal/clock/clock.h: -------------------------------------------------------------------------------- 1 | #ifndef HAL_CLOCK_CLOCK_H 2 | #define HAL_CLOCK_CLOCK_H 3 | 4 | #include 5 | 6 | /* Max representable frequency is 4.29 GHz, might need to increase to 64-bit */ 7 | typedef uint32_t hal_clkfreq_t; 8 | 9 | typedef struct { 10 | /* TODO: Add functionality to modify clock and get clock information. */ 11 | 12 | hal_clkfreq_t freq; /* Clock frequency */ 13 | } hal_clock_dev_t; 14 | 15 | #endif 16 | -------------------------------------------------------------------------------- /kernel/inc/hal/intr/int_ctlr.h: -------------------------------------------------------------------------------- 1 | #ifndef HAL_INTR_INTCTLR_H 2 | #define HAL_INTR_INTCTLR_H 3 | 4 | #include 5 | 6 | typedef struct { 7 | int (*intr_enable)(void *data, uint32_t int_n); //!< Enable interrupt 8 | int (*intr_disable)(void *data, uint32_t int_n); //!< Disable interrupt 9 | int (*intr_attach)(void *data, uint32_t int_n, void (*callback)(uint32_t, void *), void *int_data); //!< Attach interrupt handler 10 | 11 | void *data; 12 | 13 | #define HAL_INTCTLRDEV_CAP_INTENDISABLE (1UL << 0) //!< Interrupt en/disable 14 | #define HAL_INTCTLRDEV_CAP_INTATTACH (1UL << 1) //!< Interrupt handler attach 15 | uint32_t cap; 16 | } hal_intctlr_dev_t; 17 | 18 | static inline int hal_intctlr_dev_intr_enable(hal_intctlr_dev_t *dev, uint32_t int_n) { 19 | if(!dev) return -1; 20 | if(!(dev->cap & HAL_INTCTLRDEV_CAP_INTENDISABLE) || !dev->intr_enable) return -1; 21 | 22 | return dev->intr_enable(dev->data, int_n); 23 | } 24 | 25 | static inline int hal_intctlr_dev_intr_disable(hal_intctlr_dev_t *dev, uint32_t int_n) { 26 | if(!dev) return -1; 27 | if(!(dev->cap & HAL_INTCTLRDEV_CAP_INTENDISABLE) || !dev->intr_disable) return -1; 28 | 29 | return dev->intr_disable(dev->data, int_n); 30 | } 31 | 32 | static inline int hal_intctlr_dev_intr_attach(hal_intctlr_dev_t *dev, uint32_t int_n, void (*callback)(uint32_t, void *), void *data) { 33 | if(!dev) return -1; 34 | if(!(dev->cap & HAL_INTCTLRDEV_CAP_INTATTACH) || !dev->intr_attach) return -1; 35 | 36 | return dev->intr_attach(dev->data, int_n, callback, data); 37 | } 38 | 39 | #endif 40 | -------------------------------------------------------------------------------- /kernel/inc/hal/io/char/char.h: -------------------------------------------------------------------------------- 1 | #ifndef HAL_IO_CHAR_CHAR_H 2 | #define HAL_IO_CHAR_CHAR_H 3 | 4 | #include 5 | 6 | typedef struct { 7 | void (*putc)(void *data, int c); //!< Send a character 8 | int (*getc)(void *data); //!< Receive a character 9 | int (*chavail)(void *data); //!< Check if character is available 10 | 11 | void *data; 12 | 13 | #define HAL_IO_CHARDEV_CAP_INPUT (1UL << 0) 14 | #define HAL_IO_CHARDEV_CAP_OUTPUT (1UL << 1) 15 | uint32_t cap; //!< Capabilities 16 | } hal_io_char_dev_t; 17 | 18 | /** 19 | * Write character to character device. 20 | */ 21 | static inline void hal_io_char_dev_putc(hal_io_char_dev_t *dev, int c) { 22 | if(!dev) return; 23 | if(!(dev->cap & HAL_IO_CHARDEV_CAP_OUTPUT) || !dev->putc) return; 24 | 25 | return dev->putc(dev->data, c); 26 | } 27 | 28 | /** 29 | * Read character from character device. 30 | */ 31 | static inline int hal_io_char_dev_getc(hal_io_char_dev_t *dev) { 32 | if(!dev) return -1; 33 | if(!(dev->cap & HAL_IO_CHARDEV_CAP_INPUT) || !dev->getc) return -1; 34 | 35 | return dev->getc(dev->data); 36 | } 37 | 38 | /** 39 | * Check if character is available from character device. 40 | */ 41 | static inline int hal_io_char_dev_chavail(hal_io_char_dev_t *dev) { 42 | if(!dev) return -1; 43 | if(!(dev->cap & HAL_IO_CHARDEV_CAP_INPUT) || !dev->getc) return -1; 44 | 45 | return dev->chavail(dev->data); 46 | } 47 | 48 | #endif 49 | -------------------------------------------------------------------------------- /kernel/inc/hal/timer/timer.h: -------------------------------------------------------------------------------- 1 | #ifndef HAL_TIMER_TIMER_H 2 | #define HAL_TIMER_TIMER_H 3 | 4 | #include 5 | 6 | typedef struct { 7 | int (*setfreq)(void *data, uint8_t idx, uint32_t freq); //!< Set timer rate, >= 1Hz 8 | int (*setperiod)(void *data, uint8_t idx, uint32_t period); //!< Set timer rate, <= 1Hz 9 | int (*attach)(void *data, uint8_t idx, void (*callback)(void)); //!< Attach callback (return -1 if full) 10 | 11 | void *data; 12 | 13 | #define HAL_TIMERDEV_CAP_VARFREQ (1UL << 0) //!< Configurable frequency 14 | #define HAL_TIMERDEV_CAP_CALLBACK (1UL << 1) //!< Attachable callback support 15 | uint32_t cap; 16 | } hal_timer_dev_t; 17 | 18 | static inline int hal_timer_dev_setfreq(hal_timer_dev_t *dev, uint8_t idx, uint32_t freq) { 19 | if(!dev) return -1; 20 | if(!(dev->cap & HAL_TIMERDEV_CAP_VARFREQ) || !dev->setfreq) return -1; 21 | 22 | return dev->setfreq(dev->data, idx, freq); 23 | } 24 | 25 | static inline int hal_timer_dev_setpperiod(hal_timer_dev_t *dev, uint8_t idx, uint32_t period) { 26 | if(!dev) return -1; 27 | if(!(dev->cap & HAL_TIMERDEV_CAP_VARFREQ) || !dev->setperiod) return -1; 28 | 29 | return dev->setperiod(dev->data, idx, period); 30 | } 31 | 32 | static inline int hal_timer_dev_attach(hal_timer_dev_t *dev, uint8_t idx, void (*callback)(void)) { 33 | if(!dev) return -1; 34 | if(!(dev->cap & HAL_TIMERDEV_CAP_CALLBACK) || !dev->attach) return -1; 35 | 36 | return dev->attach(dev->data, idx, callback); 37 | } 38 | 39 | #endif 40 | -------------------------------------------------------------------------------- /kernel/inc/intr/intr.h: -------------------------------------------------------------------------------- 1 | #ifndef INTR_INTR_H 2 | #define INTR_INTR_H 3 | 4 | #include 5 | 6 | #include 7 | 8 | /* TODO: Add platform-agnosting interrupt_enable/_disable functions */ 9 | 10 | /** 11 | * @brief Attaches an interrupt handler to an interrupt. 12 | * 13 | * @param n Interrupt ID 14 | * @param hdlr Interrupt handler handle 15 | */ 16 | void interrupt_attach(interrupt_idx_e n, intr_handler_hand_t *hdlr); 17 | 18 | /** 19 | * @brief Initializes the system timer. 20 | * 21 | * @param quantum the speed in Hz 22 | */ 23 | void timer_init(uint32_t quantum); 24 | 25 | #endif 26 | -------------------------------------------------------------------------------- /kernel/inc/intr/types/intr.h: -------------------------------------------------------------------------------- 1 | #ifndef INTR_TYPES_INTR_H 2 | #define INTR_TYPES_INTR_H 3 | 4 | typedef struct intr_handler_hand_struct intr_handler_hand_t; 5 | 6 | #include 7 | 8 | /** 9 | * Interrupt handler handle 10 | */ 11 | struct intr_handler_hand_struct { 12 | /** 13 | * @brief Pointer to interrupt callback function 14 | * 15 | * @param hdlr Pointer to this structure 16 | */ 17 | void (*callback)(intr_handler_hand_t *hdlr); 18 | /** Data to be used by interrupt handler, if needed */ 19 | void *data; 20 | /** Architecture-specific interrupt handler data */ 21 | arch_intr_handler_hand_data_t arch; 22 | }; 23 | 24 | #endif 25 | 26 | -------------------------------------------------------------------------------- /kernel/inc/io/output.h: -------------------------------------------------------------------------------- 1 | #ifndef IO_OUTPUT_H 2 | #define IO_OUTPUT_H 3 | 4 | #include 5 | #include 6 | 7 | /** 8 | * @brief Set I/O device to write kernel output to 9 | * 10 | * @param dev Character device 11 | */ 12 | void output_set_dev(hal_io_char_dev_t *dev); 13 | 14 | 15 | /** 16 | * \brief Prints a single character. 17 | * Uses the current architecture's put function 18 | * @param c the input character 19 | */ 20 | void kput(char c); 21 | 22 | /** 23 | * \brief Prints a string of characters. 24 | * Uses the current architecture's print function 25 | * @param str the input string 26 | */ 27 | void kprint(char *str); 28 | 29 | 30 | /** 31 | * \brief Creates a string based on input format string and arguments. 32 | * Uses `print` to convert the format string and any number of arguments to 33 | * an output string. 34 | * @param out output string 35 | * @param format format string 36 | * @param ... argument list 37 | * @return the number of characters placed in `out` 38 | * @see print 39 | */ 40 | int sprintf(char *out, const char *format, ...); 41 | 42 | /** 43 | * \brief Creates and prints a string based on input format string and arguments. 44 | * Uses `print` to convert the format string and any number of arguments to 45 | * a string then prints that string to the screen. 46 | * @param format format string 47 | * @param ... argument list 48 | * @return the number of characters printed 49 | * @see print 50 | */ 51 | int kprintf(const char *format, ...); 52 | 53 | /** 54 | * \brief Creates and prints a string based on input format string and arguments. 55 | * Uses `print` to convert the format string and any number of arguments in varg to 56 | * a string then prints that string to the screen. 57 | * @param format format string 58 | * @param varg argument list 59 | * @return the number of characters printed 60 | * @see print 61 | */ 62 | int kprintv(const char *format, __builtin_va_list varg); 63 | 64 | #endif 65 | 66 | -------------------------------------------------------------------------------- /kernel/inc/kern/cmdline.h: -------------------------------------------------------------------------------- 1 | #ifndef KERN_CMDLINE_H 2 | #define KERN_CMDLINE_H 3 | 4 | /** 5 | * @brief Sets the pointer to the kernel commandline 6 | * 7 | * @param cmdline Pointer to commandline string 8 | */ 9 | void cmdline_set(const char *cmdline); 10 | 11 | /** 12 | * @brief Initialize and parse kernel commandine. Requires that memory-management 13 | * be setup first. 14 | */ 15 | void cmdline_init(void); 16 | 17 | /** 18 | * @brief Handle architecture-independant kernel options 19 | */ 20 | void cmdline_handle_common(void); 21 | 22 | /** 23 | * @brief Get a string value from commandline, in format of = 24 | * 25 | * @note At present, this function returns a pointer into the commandline array, 26 | * so illegal modifications will affect future calls. 27 | * 28 | * @param var Variable to search for 29 | * 30 | * @return Value of variable if found, else NULL 31 | */ 32 | const char *cmdline_getstr(const char *var); 33 | 34 | /** 35 | * @brief Gets boolean value from commandline variable 36 | * 37 | * TRUE: 38 | * 39 | * =true 40 | * =TRUE 41 | * FALSE: 42 | * otherwise 43 | * 44 | * @param var Name of variable to find 45 | * @return 1 if true, 0 if false 46 | */ 47 | int cmdline_getbool(const char *var); 48 | 49 | #endif 50 | -------------------------------------------------------------------------------- /kernel/inc/lambda/config_defs.h: -------------------------------------------------------------------------------- 1 | #ifndef LAMBDA_CONFIG_DEFS_H 2 | #define LAMBDA_CONFIG_DEFS_H 3 | 4 | /* Strictness levels */ 5 | #define LAMBDA_STRICTNESS_NONE ( 0) /* Do not enable any strict checks */ 6 | #define LAMBDA_STRICTNESS_USER ( 1) /* Strict checks where userland input is processed */ 7 | #define LAMBDA_STRICTNESS_NOIMPACT ( 2) /* Strict checks where performance impact is negligible */ 8 | #define LAMBDA_STRICTNESS_LOWIMPACT ( 3) /* Strict checks where performance impact is low */ 9 | #define LAMBDA_STRICTNESS_MEDIMPACT ( 4) /* Strict checks where performance impact is moderate */ 10 | #define LAMBDA_STRICTNESS_HIGHIMPACT ( 5) /* Strict checks where performance impact is high */ 11 | #define LAMBDA_STRICTNESS_ALL (255) /* Enable all strictness checks */ 12 | 13 | #define CHECK_STRICTNESS(X) ((X) <= CONFIG_STRICTNESS) 14 | 15 | #endif 16 | -------------------------------------------------------------------------------- /kernel/inc/lambda/export.h: -------------------------------------------------------------------------------- 1 | #ifndef LAMBDA_EXPORT_H 2 | #define LAMBDA_EXPORT_H 3 | 4 | #include 5 | 6 | #define LAMBDA_SYMBOLS_SECTION_NAME ".__lambda_symbols" 7 | #define LAMBDA_STRINGS_SECTION_NAME ".__lambda_strings" 8 | 9 | typedef struct { 10 | uintptr_t addr; 11 | const char *name; 12 | } lambda_symbol_t; 13 | 14 | extern lambda_symbol_t __lambda_symbols_begin; 15 | extern lambda_symbol_t __lambda_symbols_end; 16 | 17 | extern char __lambda_strings_begin; 18 | extern char __lambda_strings_end; 19 | 20 | #define EXPORT_FUNC(func) \ 21 | static const char \ 22 | __attribute__((__used__, __section__(LAMBDA_STRINGS_SECTION_NAME))) \ 23 | __lstr_func_##func[] = #func; \ 24 | static const lambda_symbol_t \ 25 | __attribute__((__used__, __section__(LAMBDA_SYMBOLS_SECTION_NAME))) \ 26 | __lsym_func_##func = { \ 27 | .addr = (uintptr_t)&func, \ 28 | .name = __lstr_func_##func \ 29 | } 30 | 31 | #endif 32 | -------------------------------------------------------------------------------- /kernel/inc/lambda/mod/module.h: -------------------------------------------------------------------------------- 1 | #ifndef LAMBDA_MOD_MODULE_H 2 | #define LAMBDA_MOD_MODULE_H 3 | 4 | #include 5 | 6 | #include 7 | 8 | #define LAMBDA_MODULE_SECTION_NAME ".lambda_module_data" 9 | 10 | /* @todo It might be useful to add a driver-specific logging function */ 11 | 12 | /** 13 | * Kernel module metadata. 14 | */ 15 | typedef struct { 16 | char *ident; /** Module identifier/name. Must not contain spaces. */ 17 | char *name; /** Module human-readable name. */ 18 | char *description; /** Module description. Optional */ 19 | char *license; /** Module license. NONE if no license. */ 20 | char **authors; /** Module authors. Optional */ 21 | char **requirements; /** List of drivers that must be loaded prior to this one. Optional. */ 22 | } __packed lambda_mod_metadata_t; 23 | 24 | typedef enum { 25 | LAMBDA_MODFUNC_START = 0, 26 | LAMBDA_MODFUNC_STOP = 1, 27 | } lambda_mod_func_e; 28 | 29 | typedef int (*lambda_mod_func_t)(uint32_t, void *); /** Module management function. */ 30 | 31 | /** 32 | * Kernel module header structure. 33 | */ 34 | typedef struct { 35 | #define LAMBDA_MODULE_HEAD_MAGIC (0xBAC0BEEFUL) 36 | uint32_t head_magic; /** Header magic number, see LAMBDA_DRV_HEAD_MAGIC. */ 37 | #define LAMBDA_MODULE_HEAD_VERSION (0) /** Current header version. */ 38 | uint16_t head_version; /** Header version. */ 39 | uint16_t _reserved; /** Reserved */ 40 | lambda_version_t kernel; /** Kernel version the driver was compiled for. */ 41 | lambda_mod_func_t function; /** Module management function. */ 42 | 43 | lambda_mod_metadata_t metadata; /** Module metadata. */ 44 | } __packed lambda_mod_head_t; 45 | 46 | #define MODULE_HEADER \ 47 | static lambda_mod_head_t \ 48 | __attribute__((__used__, \ 49 | __section__((LAMBDA_MODULE_SECTION_NAME)))) \ 50 | __mod_head 51 | 52 | #endif -------------------------------------------------------------------------------- /kernel/inc/lambda/platforms.h: -------------------------------------------------------------------------------- 1 | #ifndef LAMBDA_PLATFORMS_H 2 | #define LAMBDA_PLATFORMS_H 3 | 4 | /* TODO: Move this if/when non-32-bit systems are supported */ 5 | #define PLATFORM_BITS_8 (8) 6 | #define PLATFORM_BITS_16 (16) 7 | #define PLATFORM_BITS_32 (32) 8 | #define PLATFORM_BITS_64 (64) 9 | #define PLATFORM_BITS (PLATFORM_BITS_32) 10 | 11 | #endif 12 | -------------------------------------------------------------------------------- /kernel/inc/lambda/version.h: -------------------------------------------------------------------------------- 1 | #ifndef LAMBDA_VERSION_H 2 | #define LAMBDA_VERSION_H 3 | 4 | #include 5 | 6 | /* 7 | * Kernel versioning: 8 | * 9 | * Kernel versions are incremented according to the degree to which changes 10 | * effect the whole, and not arbitrary milestones: 11 | * 12 | * Patch: Minor changes have been made. Most if not all software (e.g. 13 | * drivers) relying on the kernel's internal functionality should 14 | * function as before. All user software only relying on syscalls 15 | * should function as before, unless relying on undefined or buggy 16 | * behaviour. 17 | * 18 | * Minor: Moderate-to-significant changes have been made. Software relying 19 | * on the kernel's internal functionality is not guaranteed to operate 20 | * as before. Changes to syscall interface are possible, and some 21 | * software/libraries may need to be recompiled against the new kernel. 22 | * 23 | * Major: Significant changes have been made to the kernel. No software is 24 | * guaranteed to remain functional. 25 | * 26 | * When a higher version position is increased, all lower version positions are 27 | * reset to zero. 28 | * 29 | * When a lower version position reaches 255, the next version will result in the 30 | * higher version incrementing regardless of the degree of the changes. 31 | */ 32 | 33 | #define LAMBDA_VERSION_MAJOR 0 34 | #define LAMBDA_VERSION_MINOR 1 35 | #define LAMBDA_VERSION_PATCH 0 36 | 37 | #define LAMBDA_VERSION_STR STR(LAMBDA_VERSION_MAJOR) "." STR(LAMBDA_VERSION_MINOR) "." STR(LAMBDA_VERSION_PATCH) 38 | #define LAMBDA_VERSION_STR_FULL LAMBDA_VERSION_STR "-" KERNEL_GIT 39 | 40 | typedef struct { 41 | uint8_t major; /** Kernel major version. */ 42 | uint8_t minor; /** Kernel minor version. */ 43 | uint8_t patch; /** Kernel patch revision. */ 44 | uint8_t __reserved; 45 | } lambda_version_t; 46 | 47 | #define LAMBDA_VERSION { \ 48 | .major = LAMBDA_VERSION_MAJOR, \ 49 | .minor = LAMBDA_VERSION_MINOR, \ 50 | .patch = LAMBDA_VERSION_PATCH \ 51 | } 52 | 53 | #endif 54 | -------------------------------------------------------------------------------- /kernel/inc/libgen.h: -------------------------------------------------------------------------------- 1 | #ifndef LIBGEN_H 2 | #define LIBGEN_H 3 | 4 | char *dirname(char *path); 5 | 6 | char *basename(char *path); 7 | 8 | #endif -------------------------------------------------------------------------------- /kernel/inc/main/main.h: -------------------------------------------------------------------------------- 1 | #ifndef MAIN_H 2 | #define MAIN_H 3 | 4 | #include 5 | 6 | /* TODO: Move this to a more appropriate location, and probably restructure */ 7 | /** 8 | * Kernel options that can be specified on the kernel command line. 9 | */ 10 | typedef struct { 11 | #define INITRD_MODULE_MAX_LEN 64 12 | char init_ramdisk_name[INITRD_MODULE_MAX_LEN]; /** Name of initial ramdisk module */ 13 | #define INITEXEC_PATH_MAX_LEN 128 14 | char init_executable[INITEXEC_PATH_MAX_LEN]; /** Path to init executable. If NULL, kterm is launched */ 15 | 16 | #ifdef CONFIG_ARCH_X86 17 | int output_serial; /** Serial device to output to */ 18 | #endif 19 | } boot_options_t; 20 | 21 | extern boot_options_t boot_options; 22 | 23 | __noreturn void kmain(void); 24 | 25 | #endif 26 | -------------------------------------------------------------------------------- /kernel/inc/mm/alloc.h: -------------------------------------------------------------------------------- 1 | #ifndef MM_ALLOC_H 2 | #define MM_ALLOC_H 3 | 4 | #include 5 | #include 6 | 7 | #include 8 | 9 | #define ALLOC_BLOCK 1024 10 | #define ALLOC_BLOCKS 512 11 | 12 | struct alcent //!< Describes a block of memory 13 | { 14 | uint8_t valid; //!< Is this a valid block? (If not, it can be replaced) 15 | uint8_t used; //!< Is this describing used memory? 16 | uint32_t addr; //!< The address of the block of memory 17 | uint32_t size; //!< Size of the block of memory 18 | }; 19 | 20 | /** 21 | * \brief Allocates a block of memory. Adds accounting to kmalloc. 22 | * 23 | * @param sz Size of requested memory block 24 | * @return Pointer to memory block on success, else NULL 25 | */ 26 | void *malloc(size_t sz); 27 | 28 | /** 29 | * \brief Frees a previously allocated block of memory. Adds accounting to kfree, 30 | * 31 | * @param ptr Pointer to previously-allocated memory block. 32 | */ 33 | void free(void *ptr); 34 | 35 | /** 36 | * Allocates a block of memory 37 | * 38 | * @param sz size of the required memory block 39 | * @returns pointer to memory block on success, else NULL 40 | */ 41 | void *kmalloc(size_t sz); 42 | 43 | /** 44 | * Allocates a block of memory with requested alignment 45 | * 46 | * @param sz size of the required memory block 47 | * @param align desired alignment 48 | * @returns pointer to memory block on success, else NULL 49 | */ 50 | void *kamalloc(size_t sz, size_t align); 51 | 52 | /** 53 | * Allocates a block of memory with requested alignment, in multiples of the 54 | * alignment value 55 | * 56 | * @param sz size of the required memory block 57 | * @param align desired alignment 58 | * @returns pointer to memory block on success, else NULL 59 | */ 60 | void *kmamalloc(size_t sz, size_t align); 61 | 62 | /** 63 | * Free an allocated memory block 64 | * 65 | * @param pointer to previously allocated memory block 66 | */ 67 | void kfree(void *ptr); 68 | 69 | size_t alloc_get_used(void); 70 | size_t alloc_get_free(void); 71 | 72 | 73 | /** 74 | * Initialize allocation functions. 75 | * 76 | * @param base location of usable memory 77 | * @param size size of usable memory 78 | */ 79 | void init_alloc(uint32_t base, uint32_t size); 80 | 81 | #endif 82 | -------------------------------------------------------------------------------- /kernel/inc/mm/mm.h: -------------------------------------------------------------------------------- 1 | #ifndef MM_H 2 | #define MM_H 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | /** 9 | * @brief Sets up page mapping on kernel sections 10 | * 11 | * @return int 0 on success, else non-zero 12 | */ 13 | int mm_init_kernel_map(void); 14 | 15 | /** 16 | * \brief Check if memory address is valid. 17 | * 18 | * @param addr Address to check 19 | * 20 | * @return 1 if readable, 2 if writable, else 0 21 | */ 22 | int mm_check_addr(const void *addr); 23 | 24 | /** 25 | * @brief Translate process-given address to physical address 26 | * 27 | * @param proc Process from which address originated 28 | * @param addr Address to translate 29 | * 30 | * @return void* Physical address 31 | */ 32 | void *mm_translate_proc_addr(struct kproc *proc, const void *addr); 33 | 34 | /** 35 | * \brief Add memory map entry to process. 36 | * 37 | * @param proc Process to add entry to 38 | * @param phys Physical address 39 | * @param virt Virtual address 40 | * @param sz Size 41 | * 42 | * @return 0 on success, non-zero otherwise 43 | */ 44 | int mm_proc_mmap_add(struct kproc *proc, uintptr_t phys, uintptr_t virt, size_t sz); 45 | 46 | /** 47 | * \brief Remove memory map entry from process by virtual address. 48 | * 49 | * @param proc Process to remove entry from 50 | * @param virt Virtual address of entry 51 | * 52 | * @return 0 on success, non-zero on entry not found 53 | */ 54 | int mm_proc_mmap_remove_virt(struct kproc *proc, uintptr_t virt); 55 | 56 | /** 57 | * \brief Remove memory map entry from process by physical address. 58 | * 59 | * @param proc Process to remove entry from 60 | * @param phys Physical address of entry 61 | * 62 | * @return 0 on success, non-zero on entry not found 63 | */ 64 | int mm_proc_mmap_remove_phys(struct kproc *proc, uintptr_t phys); 65 | 66 | #endif -------------------------------------------------------------------------------- /kernel/inc/mm/mmap.h: -------------------------------------------------------------------------------- 1 | #ifndef MM_MMAP_H 2 | #define MM_MMAP_H 3 | 4 | #include 5 | #include 6 | 7 | #define SYSCALL_MMAPFLAG_TYPE (0x0F) 8 | #define SYSCALL_MMAPFLAG_PRIVATE (1UL) /** Private mapping for this process only */ 9 | #define SYSCALL_MMAPFLAG_SHARED (2UL) /** Mapping is shared with other processes */ 10 | 11 | #define SYSCALL_MMAPFLAG_FIXED (1UL << 4) /** Use addr as physical address */ 12 | #define SYSCALL_MMAPFLAG_ANONYMOUS (1UL << 5) /** Memory is not bound to a file */ 13 | 14 | #define SYSCALL_MMAPPROT_NONE (0) /** No permissions */ 15 | #define SYSCALL_MMAPPROT_READ (1UL << 0) /** Memory can be read */ 16 | #define SYSCALL_MMAPPROT_WRITE (1UL << 1) /** Memory can be written */ 17 | #define SYSCALL_MMAPPROT_EXEC (1UL << 2) /** Memory can be executed */ 18 | 19 | /** 20 | * \brief mmap 21 | * 22 | * @param addr Desired address, 0 if specific address not required 23 | * @param len Length of memory desired 24 | * @param prot Requested permissions 25 | * @param flags Map type 26 | * @param filedes File descriptor, or -1 27 | * @param off Offset into file 28 | * 29 | * @return Virtual address of region, NULL on error 30 | */ 31 | uintptr_t mmap(uintptr_t addr, size_t len, uint32_t prot, uint32_t flags, int filedes, off_t off); 32 | 33 | /** 34 | * \brief munmap 35 | * 36 | * @param addr Start address of mapped region 37 | * @param len Length of mapped region 38 | */ 39 | int munmap(uintptr_t addr, size_t len); 40 | 41 | #endif -------------------------------------------------------------------------------- /kernel/inc/mm/symbols.h: -------------------------------------------------------------------------------- 1 | #ifndef SYMBOLS_H 2 | #define SYMBOLS_H 3 | 4 | #include 5 | 6 | extern uint32_t kern_start; // Start of the kernel 7 | extern uint32_t kern_end; // Start of the kernel 8 | 9 | typedef struct symbol { 10 | char *name; //!< Symbol name 11 | uint32_t addr; //!< Start address of symbol 12 | uint32_t size; //!< Length of address space bounded by symbol 13 | } symbol_t; 14 | 15 | extern symbol_t sym_objects[]; 16 | extern symbol_t sym_functions[]; 17 | 18 | /** 19 | * @brief Find symbol within table given address 20 | * 21 | * @param addr Address 22 | * @param symbols Symbol table in which to search 23 | * @return symbol_t* Symbol table entry, NULL if not found 24 | */ 25 | symbol_t *sym_find_object(uint32_t addr, symbol_t *symbols); 26 | 27 | #endif 28 | -------------------------------------------------------------------------------- /kernel/inc/mod/module.h: -------------------------------------------------------------------------------- 1 | #ifndef MOD_MODULE_H 2 | #define MOD_MODULE_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | /** 10 | * Loaded module information 11 | */ 12 | typedef struct { 13 | char *ident; /** Module identifier */ 14 | 15 | lambda_mod_func_t func; 16 | 17 | /* TODO: Possibly use linked-list for threads */ 18 | #define MOD_THREAD_MAX 4 19 | int threads[MOD_THREAD_MAX]; 20 | 21 | const symbol_t *symbols; 22 | 23 | llist_item_t list_item; 24 | } module_entry_t; 25 | 26 | int module_read(kfile_hand_t *file, lambda_mod_head_t **head, uintptr_t *base, Elf32_Ehdr **elf); 27 | 28 | int module_install(kfile_hand_t *file); 29 | 30 | int module_uninstall(module_entry_t *mod); 31 | 32 | /** 33 | * @brief Preload modules before entering userspace 34 | * 35 | * @note This may be a temporary feature, and removed once syscalls are added to 36 | * manage modules. 37 | * 38 | * @param path Path to file containing absolute paths to modules to load 39 | * @return int 0 on success, > 0 on non-critical failure, < 0 on critical failure 40 | */ 41 | int modules_preload(const char *path); 42 | 43 | int module_start_thread(module_entry_t *mod, void (*entry)(void *), void *data, const char *name); 44 | 45 | #endif 46 | -------------------------------------------------------------------------------- /kernel/inc/mod/symbols.h: -------------------------------------------------------------------------------- 1 | #ifndef MOD_SYMBOLS_H 2 | #define MOD_SYMBOLS_H 3 | 4 | #include 5 | 6 | #include 7 | 8 | /** 9 | * Find exported kernel symbol address by name 10 | * 11 | * @param symbol Name of symbol to find address of 12 | * @param addr Address of symbol 13 | * 14 | * @return 0 if symbol found and addr valid, else non-zero 15 | */ 16 | int module_symbol_find_kernel(const char *symbol, uintptr_t *addr); 17 | 18 | int module_symbol_find_module(const char *symbol, uintptr_t *addr, const symbol_t *symbols); 19 | 20 | #endif 21 | -------------------------------------------------------------------------------- /kernel/inc/proc/atomic/lock.h: -------------------------------------------------------------------------------- 1 | #ifndef PROC_ATOMIC_LOCK_H 2 | #define PROC_ATOMIC_LOCK_H 3 | 4 | #include 5 | #include 6 | 7 | #include 8 | 9 | /** 10 | * \brief Release an atomic lock 11 | * 12 | * @param lock Lock to release 13 | */ 14 | static inline void unlock(lock_t *lock) { 15 | atomic_store_explicit(lock, 0, memory_order_release); 16 | } 17 | 18 | /** 19 | * \brief Aquire an atomic lock 20 | * 21 | * @param lock Lock to aquire 22 | */ 23 | void lock(lock_t *lock); 24 | 25 | /** 26 | * \brief Aquire atomic lock, with timeout 27 | * 28 | * @param lock Lock to attempt to aquire 29 | * @param ticks How long to attempt to aquire lock, in milliseconds 30 | * @return int 0 if successful, else -ETIMEDOUT 31 | */ 32 | int lock_for(lock_t *lock, uint32_t ms); 33 | 34 | /** 35 | * \brief Attempt to acquire lock without blocking 36 | * 37 | * @param lock Lock to acquire 38 | * @return 0 on success, -EUNSPEC on failure 39 | */ 40 | static inline int lock_try(lock_t *lock) { 41 | int test = 1; 42 | return (atomic_exchange_explicit(lock, test, memory_order_acquire) ? 0 : -EUNSPEC); 43 | } 44 | 45 | #endif 46 | 47 | -------------------------------------------------------------------------------- /kernel/inc/proc/atomic/tlock.h: -------------------------------------------------------------------------------- 1 | #ifndef PROC_ATOMIC_TLOCK_H 2 | #define PROC_ATOMIC_TLOCK_H 3 | 4 | #include 5 | 6 | /** 7 | * @brief Initialize and acquire memory for a thread-aware lock 8 | * 9 | * @param tlock Lock to initialize 10 | * 11 | * @return 0 on success, else < 0 12 | */ 13 | int tlock_init(tlock_t *tlock); 14 | 15 | /** 16 | * @brief Destroy and free a thread-aware lock 17 | * 18 | * @param tlock Lock to destroy 19 | */ 20 | void tlock_destroy(tlock_t *tlock); 21 | 22 | /** 23 | * @brief Acquire a thread-aware lock 24 | * 25 | * @param tlock Lock to acquire 26 | */ 27 | void tlock_acquire(tlock_t *tlock); 28 | 29 | /** 30 | * @brief Release a thread-aware lock, signaling the next awating threade (if 31 | * applicable) to acquire it. 32 | * 33 | * @param tlock Lock to release 34 | */ 35 | void tlock_release(tlock_t *tlock); 36 | 37 | #endif 38 | 39 | -------------------------------------------------------------------------------- /kernel/inc/proc/atomic/types/lock.h: -------------------------------------------------------------------------------- 1 | #ifndef PROC_ATOMIC_TYPES_LOCK_H 2 | #define PROC_ATOMIC_TYPES_LOCK_H 3 | 4 | #include 5 | 6 | typedef atomic_int lock_t; 7 | 8 | #endif 9 | 10 | -------------------------------------------------------------------------------- /kernel/inc/proc/atomic/types/tlock.h: -------------------------------------------------------------------------------- 1 | #ifndef PROC_ATOMIC_TYPES_TLOCK_H 2 | #define PROC_ATOMIC_TYPES_TLOCK_H 3 | 4 | #include 5 | 6 | typedef struct tlock_struct tlock_t; 7 | 8 | #include 9 | #include 10 | #include 11 | 12 | /* TODO: Add to Kconfig */ 13 | #define CONFIG_PROC_TLOCK_THREADS 4 14 | 15 | 16 | typedef struct tlock_thread_struct { 17 | /** Condition variable to notify thread */ 18 | cond_t *cond; 19 | } tlock_thread_t; 20 | 21 | /** 22 | * @brief Thread-aware lock 23 | */ 24 | struct tlock_struct { 25 | /** Main lock */ 26 | lock_t lock; 27 | /** Lock for accessing threads field */ 28 | lock_t thread_lock; 29 | /* TODO: Should this use a cbuff or a llist? */ 30 | /** List of threads that are attempting to acquire this lock */ 31 | cbuff_t threads; 32 | }; 33 | 34 | #define STATIC_TLOCK() { .lock = 0, .thread_lock = 0, .threads = STATIC_CBUFF(CONFIG_PROC_TLOCK_THREADS * sizeof(tlock_thread_t))} 35 | 36 | #endif 37 | 38 | -------------------------------------------------------------------------------- /kernel/inc/proc/cond.h: -------------------------------------------------------------------------------- 1 | #ifndef PROC_COND_H 2 | #define PROC_COND_H 3 | 4 | #include 5 | #include 6 | 7 | /** 8 | * @brief Initialize condition variable 9 | * 10 | * @param cond Condition veriable 11 | * @return int 0 on success, else non-zero 12 | */ 13 | int cond_init(cond_t *cond); 14 | 15 | /** 16 | * @brief Allocate and initialize a condition variable 17 | * 18 | * @return Pointer to condition variable on success, else NULL 19 | */ 20 | static inline cond_t *cond_create(void) { 21 | cond_t *cond = kmalloc(sizeof(cond_t)); 22 | if(!cond) { 23 | return NULL; 24 | } 25 | /* Currently, cond_init never returns error */ 26 | cond_init(cond); 27 | return cond; 28 | } 29 | 30 | /** 31 | * @brief Wait for condition variable to be signaled 32 | * 33 | * @param cond Condition variable 34 | * @return int 0 on success, else non-zero 35 | */ 36 | int cond_wait(cond_t *cond); 37 | 38 | /** 39 | * @brief Wakeup threads waiting on condition varialbe 40 | * 41 | * @param cond Condition variable 42 | * @return int 0 on success, else non-zero 43 | */ 44 | int cond_signal(cond_t *cond); 45 | 46 | #endif 47 | -------------------------------------------------------------------------------- /kernel/inc/proc/elf.h: -------------------------------------------------------------------------------- 1 | #ifndef PROC_ELF_H 2 | #define PROC_ELF_H 3 | 4 | #include 5 | 6 | #include 7 | #include 8 | #include 9 | 10 | int elf_find_section(const Elf32_Ehdr *elf, Elf32_Shdr **section, const char *section_name); 11 | 12 | uintptr_t elf_find_data(const Elf32_Ehdr *elf, uintptr_t addr); 13 | 14 | int elf_check_header(void *data); 15 | 16 | int elf_load_symbols(const Elf32_Ehdr *elf, symbol_t **symbols); 17 | 18 | int exec_elf(exec_data_t *exec_data); 19 | 20 | #endif 21 | -------------------------------------------------------------------------------- /kernel/inc/proc/exec.h: -------------------------------------------------------------------------------- 1 | #ifndef PROC_EXEC_H 2 | #define PROC_EXEC_H 3 | 4 | /** 5 | * Replace current process with a new process crated using the provided 6 | * executable, arguments, and environment 7 | * 8 | * @param filename Filename of executable 9 | * @param argv NULL-terminated list of string arguments (argv[0] same as filename) 10 | * @param envp NULL-terminated list of environment variables 11 | * 12 | * @return No return on success, -1 on error 13 | */ 14 | int execve(const char *filename, const char **argv, const char **envp); 15 | 16 | /** 17 | * Wait for child process to exit. 18 | * 19 | * @param stat_loc Pointer to variable in which to store child exit information, or NULL. 20 | * @returns PID of child process 21 | */ 22 | int wait(int *stat_loc); 23 | 24 | #endif 25 | 26 | -------------------------------------------------------------------------------- /kernel/inc/proc/ktask/kbug.h: -------------------------------------------------------------------------------- 1 | #ifndef KTASK_KBUG_H 2 | #define KTASK_KBUG_H 3 | 4 | #include 5 | 6 | #define KBUG_IDEBUG_SUCCESS 0x00000DEB //!< IDEBUG successfully started 7 | 8 | #ifdef DEBUGGER 9 | 10 | enum kbug_types 11 | { 12 | KBUG_PROCINFO = 0, //!< Request info about a process 13 | KBUG_CPUINFO = 1, //!< Request info about the CPU 14 | KBUG_MEMINFO = 2, //!< Request info about memory 15 | KBUG_IDEBUG = 3 //!< Start the interactive debugger 16 | }; 17 | 18 | enum kbug_proc_type 19 | { 20 | KBUG_PROC_NPROCS = 0, //!< Number of currently running processes 21 | KBUG_PROC_PROCPID = 1, //!< The PID of the selected process 22 | KBUG_PROC_UPROC = 2 //!< Request a user version of the task structure 23 | }; 24 | 25 | struct kbug_type_msg //!< Message containing type of next message 26 | { 27 | uint8_t type; //!< Type of request 28 | }; 29 | 30 | struct kbug_proc_msg //!< Message containing type of process info it requests 31 | { 32 | int pid; //!< PID of the process whose information is wanted (not always used) 33 | uint8_t type; //!< Type of information it requests 34 | uint32_t info; //!< Extra required information (not always used) 35 | }; 36 | 37 | struct kbug_mem_msg //!< Message containing memory request 38 | { 39 | uintptr_t mem_addr; //!< Address of memory to request 40 | uint32_t mem_len; //!< Length of memory request 41 | }; 42 | 43 | 44 | 45 | // All-in-one structures, use these: 46 | struct kbug_type_proc_msg 47 | { 48 | struct kbug_type_msg ktm; 49 | struct kbug_proc_msg kpm; 50 | }; 51 | 52 | struct kbug_type_mem_msg 53 | { 54 | struct kbug_type_msg ktm; 55 | struct kbug_mem_msg kmm; 56 | }; 57 | 58 | __noreturn void kbug_task(void); 59 | 60 | #endif // DEBUGGER 61 | 62 | #endif // KTASK_KBUG_H 63 | -------------------------------------------------------------------------------- /kernel/inc/proc/ktask/kinput.h: -------------------------------------------------------------------------------- 1 | #ifndef KTASK_KINPUT_H 2 | #define KTASK_KINPUT_H 3 | 4 | #include 5 | 6 | extern kfile_hand_t *kinput_dest; 7 | 8 | __noreturn void kinput_task(void); 9 | 10 | #endif // KTASK_KINPUT_H 11 | -------------------------------------------------------------------------------- /kernel/inc/proc/ktask/kterm.h: -------------------------------------------------------------------------------- 1 | #ifndef KTASK_KTERM_H 2 | #define KTASK_KTERM_H 3 | 4 | #include 5 | 6 | __noreturn void kterm_task(void); 7 | 8 | #endif // KTASK_KTERM_H 9 | -------------------------------------------------------------------------------- /kernel/inc/proc/ktasks.h: -------------------------------------------------------------------------------- 1 | #ifndef KTASKS_H 2 | #define KTASKS_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #define KINPUT_TASK_SLOT 0 11 | #define KTERM_TASK_SLOT 1 12 | #define KBUG_TASK_SLOT 2 13 | 14 | #define KTASK_SLOTS 3 15 | 16 | extern int ktask_pids[KTASK_SLOTS]; 17 | 18 | void init_ktasks(void); 19 | 20 | 21 | #endif 22 | -------------------------------------------------------------------------------- /kernel/inc/proc/syscalls.h: -------------------------------------------------------------------------------- 1 | #ifndef SYSCALLS_H 2 | #define SYSCALLS_H 3 | 4 | #include 5 | 6 | #include 7 | 8 | enum syscalls { 9 | SYSCALL_EXIT = 3, 10 | 11 | SYSCALL_MMAP = 4, 12 | SYSCALL_MUNMAP = 5, 13 | 14 | SYSCALL_FS_ACCESS = 9, 15 | SYSCALL_FS_READDIR = 10, 16 | SYSCALL_FS_STAT = 11, 17 | SYSCALL_FS_READ = 12, 18 | SYSCALL_FS_WRITE = 13, 19 | SYSCALL_FS_OPEN = 14, 20 | SYSCALL_FS_CLOSE = 15, 21 | SYSCALL_FS_MKDIR = 16, 22 | SYSCALL_FS_CREATE = 17, 23 | SYSCALL_FS_IOCTL = 18, 24 | 25 | SYSCALL_FS_READ_BLK = 19, 26 | SYSCALL_FS_GETDIRINFO = 20, 27 | 28 | SYSCALL_FORK = 21, 29 | SYSCALL_EXECVE = 22, 30 | SYSCALL_WAIT = 23, 31 | 32 | SYSCALL_TASK_SWITCH = 24, 33 | 34 | SYSCALL_MAX 35 | }; 36 | 37 | 38 | void syscalls_init(void); 39 | 40 | void syscall_call(uint32_t scn, syscallarg_t *arg); 41 | int syscall_service(uint32_t scn, syscallarg_t *args); 42 | 43 | extern void return_from_syscall(void); 44 | 45 | #endif 46 | -------------------------------------------------------------------------------- /kernel/inc/proc/thread.h: -------------------------------------------------------------------------------- 1 | #ifndef PROC_THREAD_H 2 | #define PROC_THREAD_H 3 | 4 | #include 5 | 6 | #include 7 | 8 | /** 9 | * \brief Create a new thread 10 | * 11 | * New thread will not be attached to a process, and will require more setup 12 | * before it is ready to be scheduled. 13 | * 14 | * @param entrypoint Execution entry point of thread 15 | * @param data Pointer to pass to thread function 16 | * @param name Name of thread 17 | * @param stack_size Size of user stack 18 | * @param prio Thread priority 19 | * 20 | * @return NULL on error, else pointer to thread 21 | */ 22 | kthread_t *thread_create(uintptr_t entrypoint, void *data, const char *name, size_t stack_size, int prio); 23 | 24 | /** 25 | * \brief Add a thread to the current process 26 | * 27 | * @param entrypoint Entrypoint function of the thread 28 | * @param data Data to pass to thread function 29 | * @param name Optional name to give the thread 30 | * @param stack_size Desired thread stack size 31 | * @param prio Thread priority 32 | * 33 | * @return < 0 on error, else TID of newly spawned thread 34 | */ 35 | int thread_spawn(uintptr_t entrypoint, void *data, const char *name, size_t stack_size, int prio); 36 | 37 | /** 38 | * @brief Destroy thread and free memory 39 | * 40 | * @param thread Thread to destroy 41 | * 42 | * @return int 0 on success, else non-zero 43 | */ 44 | int thread_destroy(kthread_t *thread); 45 | 46 | /** 47 | * @brief Get the TID of the running thread on the current CPU 48 | * 49 | * @return TID on success, else < 0 50 | */ 51 | int thread_get_tid(void); 52 | 53 | #endif 54 | -------------------------------------------------------------------------------- /kernel/inc/proc/types/cond.h: -------------------------------------------------------------------------------- 1 | #ifndef PROC_TYPES_COND_H 2 | #define PROC_TYPES_COND_H 3 | 4 | typedef struct cond_listitem cond_listitem_t; 5 | typedef struct cond cond_t; 6 | 7 | #include 8 | #include 9 | 10 | struct cond { 11 | lock_t lock; /** Lock */ 12 | llist_t list; /** Threads waiting on condition. */ 13 | }; 14 | 15 | struct cond_listitem { 16 | llist_item_t list_item; 17 | /** Pointer to thread that is waiting on the cond */ 18 | void *thread; 19 | }; 20 | 21 | 22 | #endif 23 | -------------------------------------------------------------------------------- /kernel/inc/proc/types/exec.h: -------------------------------------------------------------------------------- 1 | #ifndef PROC_TYPES_EXEC_H 2 | #define PROC_TYPES_EXEC_H 3 | 4 | #include 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | /** 12 | * @brief Structure to simplify passing of applicable data in exec methods 13 | */ 14 | typedef struct { 15 | /** Pointer to buffer containing loaded file */ 16 | void *file_data; 17 | /** Size of file buffer */ 18 | size_t file_size; 19 | 20 | /** Program argument list */ 21 | const char **argv; 22 | /** Program executable list */ 23 | const char **envp; 24 | 25 | /** Process/thread name */ 26 | char name[KPROC_NAME_MAX]; 27 | /** Thread entrypoint */ 28 | uintptr_t entrypoint; 29 | 30 | /** MMU table for the replacement process */ 31 | mmu_table_t *mmu_table; 32 | 33 | /** Symbols found during program loading */ 34 | symbol_t *symbols; 35 | /** Mapped memory allocated during program loading */ 36 | struct kproc_mem_map_ent *mmap_entries; 37 | /** ELF-specific data, if applicable */ 38 | proc_elf_data_t *elf_data; 39 | } exec_data_t; 40 | 41 | #endif 42 | 43 | -------------------------------------------------------------------------------- /kernel/inc/proc/types/kthread.h: -------------------------------------------------------------------------------- 1 | #ifndef PROC_TYPES_KTHREAD_H 2 | #define PROC_TYPES_KTHREAD_H 3 | 4 | typedef struct kthread kthread_t; 5 | typedef struct kthread_stats kthread_stats_t; 6 | 7 | #define PRIO_IDLE 0 //!< Only idle processes use this priority 8 | #define PRIO_USERPROG 1 //!< Priority for user programs 9 | #define PRIO_KERNELPROG 2 //!< Priority for kernel programs 10 | #define PRIO_DRIVER 3 //!< Priority for kernel drivers 11 | #define PRIO_KERNEL 4 //!< Priority for main kernel tasks 12 | 13 | #define KTHREAD_FLAG_RUNNABLE (1UL << 31) /** Thread contents is valid */ 14 | #define KTHREAD_FLAG_RUNNING (1UL << 0) /** Thread is currently running */ 15 | #define KTHREAD_FLAG_RANONCE (1UL << 1) /** Thread has ran at least once */ 16 | #define KTHREAD_FLAG_STACKSETUP (1UL << 2) /** User stack has been initialized already */ 17 | 18 | #include 19 | #include 20 | #include 21 | #include 22 | 23 | struct kthread_stats { 24 | uint64_t sched_time_last; /** Time at which thread was last scheduled */ 25 | uint64_t sched_time_accum; /** Accumulated time for which this thread has been scheduled, in nanoseconds */ 26 | uint32_t sched_count; /** Number of times this thread has been scheduled */ 27 | }; 28 | 29 | struct kthread { 30 | char name[KPROC_NAME_MAX+1]; /** Name of thread */ 31 | uint32_t tid; /** Thread ID */ 32 | uint32_t flags; /** Thread flags */ 33 | int prio; /** Thread priority */ 34 | 35 | cond_t *cond; /** Conditional thread is waiting on, if applicable */ 36 | 37 | struct kproc *process; /** Pointer to owning process */ 38 | 39 | kthread_arch_t arch; /** Architecture-specific thread data */ 40 | uintptr_t entrypoint; /** Program start */ 41 | size_t stack_size; /** Size of stack */ 42 | void *thread_data; /** Data to be provided to thread as an argument */ 43 | 44 | kthread_stats_t stats; /** Thread statistics */ 45 | 46 | llist_item_t list_item; /** List item for owning process */ 47 | llist_item_t sched_item; /** List item for scheduling */ 48 | }; 49 | 50 | #endif 51 | -------------------------------------------------------------------------------- /kernel/inc/stdlib.h: -------------------------------------------------------------------------------- 1 | #ifndef STDLIB_H 2 | #define STDLIB_H 3 | 4 | unsigned long strtoul(const char *__restrict ptr, char **__restrict endptr, int base); 5 | 6 | #endif 7 | -------------------------------------------------------------------------------- /kernel/inc/string.h: -------------------------------------------------------------------------------- 1 | #ifndef STRING_H 2 | #define STRING_H 3 | 4 | #include 5 | #include 6 | 7 | /** 8 | * Calculates the length of a string. 9 | * 10 | * @param str the string to calculate the length of 11 | * @return the length of the string 12 | */ 13 | size_t strlen(const char *str); 14 | 15 | /** 16 | * Calculates the length of a wide string. 17 | * 18 | * @param str the wide string to calculate the length of 19 | * @return the length of the wide string 20 | */ 21 | size_t wcslen(const short *str); 22 | 23 | /** 24 | * Checks to see if two strings are identical 25 | * 26 | * @param str1 first string 27 | * @param str2 second string 28 | */ 29 | int strcmp(const char *str1, const char *str2); 30 | 31 | int strncmp(const char *str1, const char *str2, size_t num); 32 | 33 | char *strchr(const char *s, int c); 34 | 35 | char *strcpy(char *dest, const char *src); 36 | 37 | char *strncpy(char *dest, const char *src, size_t n); 38 | 39 | void *memcpy(void *dest, const void *src, size_t n); 40 | 41 | void *memset(void *s, int c, size_t n); 42 | 43 | void *memmove(void *dst, const void *src, size_t n); 44 | 45 | /** 46 | * @brief Compare two sets of data for equality 47 | * 48 | * @param s1 Pointer to first set of data 49 | * @param s2 Pointer to second set of data 50 | * @param n Size of data to compare, in bytes 51 | * 52 | * @return 0 if both sets of data are equal, else non-zero 53 | */ 54 | int memcmp(const void *s1, const void *s2, size_t n); 55 | 56 | #endif 57 | 58 | -------------------------------------------------------------------------------- /kernel/inc/sys/stat.h: -------------------------------------------------------------------------------- 1 | #ifndef SYS_STAT_H 2 | #define SYS_STAT_H 3 | 4 | #include 5 | 6 | #include 7 | 8 | /** 9 | * @brief Kernel representatino of file information 10 | */ 11 | typedef struct kstat { 12 | /** Device ID */ 13 | uint32_t dev_id; 14 | /** Special file device ID */ 15 | uint32_t rdev_id; 16 | /** inode number */ 17 | uint64_t inode; 18 | /** Unix permissions */ 19 | uint32_t mode; 20 | /** Number of hard links to this file */ 21 | uint32_t n_link; 22 | /** Owning user ID */ 23 | uint32_t uid; 24 | /** Owner group ID */ 25 | uint32_t gid; 26 | /** File size in bytes */ 27 | uint64_t size; 28 | /** Actual size of allocated space for file on storage medium */ 29 | uint64_t alloc_size; 30 | /** Access time, in nanoseconds since 1970-01-01 UTC */ 31 | int64_t atime; 32 | /** Creation time, in nanoseconds since 1970-01-01 UTC */ 33 | int64_t btime; 34 | /** Status change time, in nanoseconds since 1970-01-01 UTC */ 35 | int64_t ctime; 36 | /** Modification time, in nanoseconds since 1970-01-01 UTC */ 37 | int64_t mtime; 38 | /** Preferred block size, in bytes */ 39 | uint32_t blksize; 40 | } kstat_t; 41 | 42 | int kfstat(kfile_t *f, kstat_t *buf); 43 | 44 | int fstat(int fd, kstat_t *buf); 45 | 46 | #endif -------------------------------------------------------------------------------- /kernel/inc/sys/types.h: -------------------------------------------------------------------------------- 1 | #ifndef SYS_TYPES_H 2 | #define SYS_TYPES_H 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | typedef uint32_t dev_t; 9 | typedef uint32_t ino_t; 10 | typedef uint32_t mode_t; 11 | typedef uint16_t nlink_t; 12 | typedef uint32_t uid_t; 13 | typedef uint32_t gid_t; 14 | typedef size_t off_t; 15 | typedef uint32_t blksize_t; 16 | typedef uint32_t blkcnt_t; 17 | 18 | #if (SIZE_MAX == 0xFFFFFFFFFFFFFFFF) 19 | typedef int64_t ssize_t; 20 | #else 21 | typedef int32_t ssize_t; 22 | #endif 23 | 24 | #endif 25 | -------------------------------------------------------------------------------- /kernel/inc/time/time.h: -------------------------------------------------------------------------------- 1 | #ifndef TIME_H 2 | #define TIME_H 3 | 4 | #include 5 | 6 | /** 7 | * @brief Nanoseconds since system timer initialization 8 | * 9 | * @note 2^64 nanoseconds = ~585 years 10 | */ 11 | 12 | extern uint64_t kerneltime; 13 | 14 | /** 15 | * Used when specifying UNIX time (not timer ticks). 16 | * - It is signed so it can represent time before January 1, 1970 17 | */ 18 | typedef int64_t time_t; //!< Typedef used when specifying UNIX time (not timer ticks) 19 | 20 | struct timespec { 21 | /** Time in seconds */ 22 | time_t tv_sec; 23 | /** Offset in nanoseconds */ 24 | int32_t tv_nsec; 25 | }; 26 | 27 | /** 28 | * \brief A structure to help with timing. 29 | * A structure that helps processes keep time. Every timer tick, count will 30 | * be decremented by 1. When count reaches 0, event() is called. 31 | * @see do_time_block_timeup 32 | */ 33 | typedef struct time_block { 34 | void (*event)(void *data); /** Called when `count` = 0 */ 35 | void *data; /** Data passed into event() */ 36 | uint64_t end; /** Value of kerneltime at which timer expires */ 37 | int tid; /** TID of the thread using this block */ 38 | } time_block_t; 39 | 40 | #define MAX_TIME_BLOCKS 64 //!< Maximum number of timer blocks able to be used. We cannot let this get too high, or we will experience slowdown. 41 | 42 | /** 43 | * \brief Adds a time block to time_blocks[]. 44 | * Finds the first free time_block and sets its values to the ones supplied. 45 | * @param func the function to call when count reaches 0 46 | * @param data value to pass into func() 47 | * @param off the number of nanoseconds to wait before calling func() 48 | * @param tid the tid of the thread that is using this time_block 49 | */ 50 | void add_time_block(void (*func)(void *), void *data, uint64_t off, int tid); 51 | 52 | /** 53 | * \brief Waits for a specified amount of time. 54 | * Creates a time block to wait for `delay` clock ticks, then waits until the 55 | * time has run out. 56 | * @param delay number of milliseconds to wait for 57 | */ 58 | void delay(uint32_t delay); 59 | 60 | /** 61 | * \brief Updates kernel time and time blocks. 62 | * 63 | * @param off Number of nanoseconds since last call 64 | */ 65 | void time_update(uint64_t off); 66 | 67 | #endif 68 | -------------------------------------------------------------------------------- /kernel/module.mk: -------------------------------------------------------------------------------- 1 | # Kernel source root 2 | 3 | MDIR = $(dir $(lastword $(MAKEFILE_LIST))) 4 | 5 | dirs-y := arch \ 6 | src 7 | 8 | include $(patsubst %,$(MDIR)%/module.mk,$(dirs-y)) 9 | 10 | #cflags-$(CONFIG_VERBOSE_PANIC) += -DCONFIG_VERBOSE_PANIC 11 | 12 | -------------------------------------------------------------------------------- /kernel/src/Kconfig: -------------------------------------------------------------------------------- 1 | # Common kernel configuration 2 | 3 | config LOG_COLORCODE 4 | bool "Color-code kernel log output" 5 | 6 | config EMBEDDED_INITRD 7 | bool "Embeded initrd into kernel image" 8 | 9 | config EMBEDDED_INITRD_LZOP 10 | bool "Use LZO1X compression for embedded initrd" 11 | depends on EMBEDDED_INITRD 12 | 13 | config SAFETY_CHECKS 14 | bool "Enable runtime data checks" 15 | default y 16 | help 17 | Enables checks for input/data validity within the kernel, including data 18 | that comes from userspace. This causes some overhead for kernel calls and 19 | other operations. Disabling this is a huge security risk, and should only 20 | be done if you know what you are doing. 21 | 22 | This is an older config and may one day be merged with STRICTNESS, or a 23 | similar config. 24 | 25 | config STRICTNESS 26 | int "Kernel strictness level" 27 | range 0 255 28 | default 255 29 | help 30 | How strictly the kernel should monitor data and parameters. Setting this 31 | to 0 creates a security risk, as validation of userland input is not 32 | checked. See SAFETY_CHECKS for details. It is useful to set this to a 33 | higher level during development to catch bugs. 34 | 35 | Levels: 36 | 0: Disable all checks 37 | 1: Enable checking of data passed in from userland 38 | 2: Enable additional checks where performance impact is negligible 39 | 3: Enable additional checks where performance impact is low 40 | 4: Enable additional checks where performance impact is moderate 41 | 5: Enable additional checks where performance impact is high 42 | 255: Enable all checks 43 | 44 | source "kernel/src/crypto/Kconfig" 45 | source "kernel/src/proc/Kconfig" 46 | 47 | -------------------------------------------------------------------------------- /kernel/src/crypto/Kconfig: -------------------------------------------------------------------------------- 1 | menuconfig CRYPTO 2 | bool "Crypto support" 3 | default y 4 | help 5 | Cryptogrophy support, includes compression/decompression support 6 | 7 | if CRYPTO 8 | 9 | menuconfig CRYPTO_COMP 10 | bool "Compression/decompression support" 11 | default y 12 | help 13 | Enable support for compression and decompression in the kernel 14 | 15 | 16 | if CRYPTO_COMP 17 | 18 | config CRYPTO_COMP_LZOP 19 | bool "LZOP support" 20 | default y 21 | help 22 | Enable support for LZOP compressed file format, decompression only 23 | 24 | endif # CRYPTO_COMP 25 | 26 | endif # CRYPTO 27 | 28 | -------------------------------------------------------------------------------- /kernel/src/crypto/comp/comp.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | 9 | typedef int (*crypto_comp_decomp_func)(const crypto_comp_handle_t *handle, 10 | const void *const input, size_t input_len, 11 | void **const output, size_t *const output_len); 12 | 13 | typedef struct crypto_comp_format_struct { 14 | uint8_t format; 15 | crypto_comp_decomp_func decomp; 16 | } crypto_comp_format_t; 17 | 18 | static const crypto_comp_format_t _comp_formats[] = { 19 | #ifdef CONFIG_CRYPTO_COMP_LZOP 20 | { .format = CRYPTO_COMP_FMT_LZOP, 21 | .decomp = lzop_decompress, }, 22 | #endif 23 | }; 24 | 25 | int crypto_comp_decompress(const crypto_comp_handle_t *handle, const void *const input, size_t input_len, void **const output, size_t *const output_len) { 26 | for (unsigned i = 0; i < ARRAY_SZ(_comp_formats); i++) { 27 | if (_comp_formats[i].format == handle->format) { 28 | if (!_comp_formats[i].decomp) { 29 | return -EINVAL; 30 | } 31 | 32 | return _comp_formats[i].decomp(handle, input, input_len, output, output_len); 33 | } 34 | } 35 | 36 | return -EINVAL; 37 | } 38 | 39 | -------------------------------------------------------------------------------- /kernel/src/crypto/comp/module.mk: -------------------------------------------------------------------------------- 1 | MDIR = $(dir $(lastword $(MAKEFILE_LIST))) 2 | 3 | obj-y += $(MDIR)comp.o 4 | obj-$(CONFIG_CRYPTO_COMP_LZOP) += $(MDIR)lzop.o 5 | 6 | cflags-$(CONFIG_CRYPTO_COMP_LZOP) += -DCONFIG_CRYPTO_COMP_LZOP 7 | 8 | -------------------------------------------------------------------------------- /kernel/src/crypto/module.mk: -------------------------------------------------------------------------------- 1 | MDIR = $(dir $(lastword $(MAKEFILE_LIST))) 2 | 3 | dirs-$(CONFIG_CRYPTO_COMP) := comp 4 | 5 | include $(patsubst %,$(MDIR)%/module.mk,$(dirs-y)) 6 | 7 | -------------------------------------------------------------------------------- /kernel/src/data/cbuff.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #define WRAP(N, M) (((N) >= (M)) ? ((N) - (M)) : (N)) 9 | 10 | int cbuff_allocate(cbuff_t *buff, size_t size) { 11 | if(size == 0) { 12 | return -1; 13 | } 14 | 15 | memset(buff, 0, sizeof(&buff)); 16 | 17 | buff->size = size; 18 | buff->buff = kmalloc(buff->size); 19 | if(!buff->buff) { 20 | return -1; 21 | } 22 | 23 | return 0; 24 | } 25 | 26 | void cbuff_free(cbuff_t *buff) { 27 | kfree(buff->buff); 28 | memset(buff, 0, sizeof(*buff)); 29 | } 30 | 31 | int cbuff_put(uint8_t data, cbuff_t *buff) { 32 | if(!buff || !buff->buff) return -EINVAL; // Invalid buffer 33 | if(buff->count >= buff->size) return -ENOMEM; // Not enough room in cbuff 34 | 35 | buff->buff[WRAP(buff->begin + buff->count, buff->size)] = data; 36 | 37 | buff->count++; 38 | 39 | return 0; 40 | } 41 | EXPORT_FUNC(cbuff_put); 42 | 43 | int cbuff_get(cbuff_t *buff) { 44 | if(!buff || !buff->buff) return -EINVAL; // Invalid buffer 45 | if(buff->count == 0) return -ENOMEM; // No data to be read 46 | 47 | uint8_t d = buff->buff[buff->begin]; 48 | 49 | buff->begin = WRAP(buff->begin + 1, buff->size); 50 | buff->count--; 51 | 52 | return d; 53 | } 54 | EXPORT_FUNC(cbuff_get); 55 | 56 | 57 | int cbuff_write(const uint8_t *data, size_t size, cbuff_t *buff) { 58 | if(!data || !buff || !buff->buff) return -EINVAL; // Invalid data or buffer 59 | if(size > (buff->size - buff->count)) return -ENOMEM; // Also not enough room in the buffer 60 | 61 | int i = 0; 62 | while(size--) { 63 | int err = cbuff_put(data[i++], buff); 64 | if(err) return err; 65 | } 66 | 67 | return 0; 68 | } 69 | EXPORT_FUNC(cbuff_write); 70 | 71 | int cbuff_read(uint8_t *data, size_t size, cbuff_t *buff) { 72 | if(!data || !buff || !buff->buff) return -EINVAL; // Invalid data or buffer 73 | if(size > buff->count) return -ENODATA; // Not enough readable data 74 | 75 | int i = 0; 76 | while(size--) { 77 | int err = cbuff_get(buff); 78 | if((uint32_t)err & 0xFFFFFF00) return err; 79 | data[i++] = (uint8_t)err; 80 | } 81 | 82 | return 0; 83 | } 84 | EXPORT_FUNC(cbuff_read); 85 | -------------------------------------------------------------------------------- /kernel/src/data/module.mk: -------------------------------------------------------------------------------- 1 | MDIR = $(dir $(lastword $(MAKEFILE_LIST))) 2 | 3 | obj-y += $(MDIR)cbuff.o \ 4 | $(MDIR)llist.o 5 | 6 | -------------------------------------------------------------------------------- /kernel/src/err/error.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include