├── .github └── workflows │ └── build.yml ├── .gitignore ├── LICENSE ├── Makefile ├── README.md ├── count ├── createfs ├── debug ├── kernel ├── Makefile ├── aboutboot.txt ├── async.c ├── async.h ├── boot.S ├── console │ ├── kconsole │ │ ├── console.cpp │ │ ├── kconsole.cpp │ │ ├── kconsole.h │ │ └── kconsole.hpp │ ├── kio.c │ ├── kio.h │ └── serial │ │ ├── uart.c │ │ └── uart.h ├── dtb.c ├── dtb.h ├── exceptions │ ├── exception_handler.c │ ├── exception_handler.h │ ├── exception_vectors_as.S │ ├── irq.c │ ├── irq.h │ ├── timer.c │ └── timer.h ├── filesystem │ ├── disk.cpp │ ├── disk.h │ ├── exfat.cpp │ ├── exfat.hpp │ ├── fat32.cpp │ ├── fat32.hpp │ ├── sdhci.cpp │ ├── sdhci.hpp │ ├── virtio_blk_pci.c │ └── virtio_blk_pci.h ├── fw │ ├── fw_cfg.c │ └── fw_cfg.h ├── gpio.c ├── gpio.h ├── graph │ ├── drivers │ │ ├── gpu_driver.hpp │ │ ├── ramfb_driver │ │ │ ├── ramfb.cpp │ │ │ └── ramfb.hpp │ │ ├── videocore │ │ │ ├── videocore.cpp │ │ │ └── videocore.hpp │ │ └── virtio_gpu_pci │ │ │ ├── virtio_gpu_pci.cpp │ │ │ └── virtio_gpu_pci.hpp │ ├── font8x8_basic.h │ ├── font8x8_bridge.c │ ├── font8x8_bridge.h │ ├── graphics.cpp │ └── graphics.h ├── hw │ ├── hw.c │ └── hw.h ├── input │ ├── USBDevice.cpp │ ├── USBDevice.hpp │ ├── USBKeyboard.cpp │ ├── USBKeyboard.hpp │ ├── USBManager.cpp │ ├── USBManager.hpp │ ├── dwc2.cpp │ ├── dwc2.hpp │ ├── input_dispatch.cpp │ ├── input_dispatch.h │ ├── usb.cpp │ ├── usb.hpp │ ├── xhci.cpp │ ├── xhci.hpp │ └── xhci_types.h ├── kernel.c ├── kernel_processes │ ├── boot │ │ ├── bootprocess.cpp │ │ ├── bootprocess.h │ │ ├── bootprocess_sm.cpp │ │ ├── bootprocess_sm.hpp │ │ ├── bootscreen.c │ │ ├── bootscreen.h │ │ ├── login_screen.c │ │ └── login_screen.h │ ├── kprocess_loader.c │ ├── kprocess_loader.h │ ├── monitor │ │ ├── monitor_processes.c │ │ └── monitor_processes.h │ └── windows │ │ ├── desktop.cpp │ │ ├── desktop.hpp │ │ ├── window_manager.cpp │ │ ├── window_manager.hpp │ │ ├── windows.cpp │ │ └── windows.h ├── kstring.c ├── kstring.h ├── linker.ld ├── mailbox │ ├── mailbox.c │ └── mailbox.h ├── memory │ ├── dma.c │ ├── dma.h │ ├── kalloc.c │ ├── kalloc.h │ ├── memory_access.c │ ├── memory_access.h │ ├── memory_types.h │ ├── mmu.c │ ├── mmu.h │ ├── page_allocator.c │ └── page_allocator.h ├── mtree.txt ├── networking │ ├── drivers │ │ ├── net_driver.hpp │ │ └── virtio_net_pci │ │ │ ├── virtio_net_pci.cpp │ │ │ └── virtio_net_pci.hpp │ ├── network.cpp │ ├── network.h │ ├── network_dispatch.cpp │ ├── network_dispatch.hpp │ └── processes │ │ ├── net_proc.c │ │ └── net_proc.h ├── pci.c ├── pci.h ├── process │ ├── context_switch.S │ ├── loading │ │ ├── elf_file.c │ │ ├── elf_file.h │ │ ├── process_loader.c │ │ └── process_loader.h │ ├── process.h │ ├── scheduler.c │ ├── scheduler.h │ ├── syscall.c │ ├── syscall.h │ └── syscall_as.S ├── theme │ ├── RedactedOS.h │ └── theme.h └── virtio │ ├── virtio_pci.c │ └── virtio_pci.h ├── run_raspi ├── run_virt ├── rundebug ├── shared ├── Makefile ├── input_keycodes.h ├── keypress.h ├── math │ └── math.h ├── net │ ├── arp.c │ ├── arp.h │ ├── checksums.c │ ├── dhcp.c │ ├── dhcp.h │ ├── eth.c │ ├── eth.h │ ├── http.c │ ├── http.h │ ├── icmp.c │ ├── icmp.h │ ├── ipv4.c │ ├── ipv4.h │ ├── network_types.h │ ├── tcp.c │ ├── tcp.h │ ├── udp.c │ └── udp.h ├── std │ ├── allocator.cpp │ ├── allocator.hpp │ ├── args.h │ ├── array.hpp │ ├── indexmap.hpp │ ├── memfunctions.c │ ├── memfunctions.h │ ├── std.hpp │ ├── string.c │ └── string.h ├── syscalls │ ├── syscalls.c │ ├── syscalls.h │ └── syscalls_as.S ├── types.h └── ui │ ├── UIElement.hpp │ ├── draw │ ├── draw.c │ └── draw.h │ ├── graphic_types.h │ ├── label.cpp │ ├── label.hpp │ └── ui.hpp ├── user ├── Makefile ├── default_process.c ├── default_process.h └── linker.ld ├── virt.dtb └── virt.dts /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | name: Build CI 2 | 3 | on: 4 | push: 5 | branches: ['main'] 6 | pull_request: 7 | workflow_dispatch: 8 | 9 | env: 10 | arm_toolchain_version: 14.2.rel1 11 | 12 | jobs: 13 | build: 14 | name: ${{ matrix.config.name }} 15 | runs-on: ${{ matrix.config.os }}-${{ matrix.config.os-version }} 16 | 17 | strategy: 18 | fail-fast: false 19 | matrix: 20 | config: 21 | - name: Linux (x64) 22 | os: ubuntu 23 | os-version: 22.04 24 | toolchain_arch: x86_64 25 | 26 | steps: 27 | - uses: actions/checkout@v4 28 | with: 29 | fetch-depth: '0' 30 | 31 | - name: Install Linux Dependencies 32 | if: matrix.config.os == 'ubuntu' 33 | run: | 34 | sudo apt-get update 35 | sudo apt-get install -y qemu-system-aarch64 qemu-utils make mtools dosfstools wget xz-utils 36 | 37 | - name: Install Toolchain 38 | run: | 39 | wget -q "https://developer.arm.com/-/media/Files/downloads/gnu/${{env.arm_toolchain_version}}/binrel/arm-gnu-toolchain-${{env.arm_toolchain_version}}-${{matrix.config.toolchain_arch}}-aarch64-none-elf.tar.xz" -O "toolchain.tar.xz" 40 | tar -xf toolchain.tar.xz 41 | mv "arm-gnu-toolchain-${{env.arm_toolchain_version}}-${{matrix.config.toolchain_arch}}-aarch64-none-elf/" "$RUNNER_TEMP/arm-toolchain" 42 | echo "$RUNNER_TEMP/arm-toolchain/bin" >> $GITHUB_PATH 43 | 44 | - name: Build 45 | run: | 46 | mkdir -pv fs/redos/user 47 | make all 48 | 49 | - name: Upload artifacts 50 | uses: actions/upload-artifact@v4 51 | with: 52 | name: "${{ matrix.config.name }} - kernel + disk.img + user programs" 53 | path: | 54 | kernel.elf 55 | kernel.img 56 | disk.img 57 | run_virt 58 | debug 59 | createfs 60 | fs/redos/user/*.elf -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.o 2 | *.img 3 | *.elf 4 | *.bin 5 | *.log 6 | .vscode 7 | libshared.a 8 | *.a 9 | dump.dtb 10 | fs 11 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | MODE ?= virt 2 | LOAD_ADDR ?= 0x41000000 3 | 4 | .PHONY: all kernel user shared clean raspi virt run debug 5 | 6 | all: shared user kernel 7 | @echo "Build complete." 8 | ./createfs 9 | 10 | shared: 11 | $(MAKE) -C shared 12 | 13 | user: 14 | $(MAKE) -C user 15 | 16 | kernel: 17 | $(MAKE) -C kernel LOAD_ADDR=$(LOAD_ADDR) 18 | 19 | clean: 20 | $(MAKE) -C shared clean 21 | $(MAKE) -C kernel clean 22 | $(MAKE) -C user clean 23 | 24 | raspi: 25 | $(MAKE) LOAD_ADDR=0x80000 all 26 | 27 | virt: 28 | $(MAKE) LOAD_ADDR=0x41000000 all 29 | 30 | debug: 31 | $(MAKE) $(MODE) 32 | ./rundebug MODE=$(MODE) $(ARGS) 33 | 34 | run: 35 | $(MAKE) $(MODE) 36 | ./run_$(MODE) -------------------------------------------------------------------------------- /count: -------------------------------------------------------------------------------- 1 | find . \( -name "*.c" -o -name "*.cpp" -o -name "*.h" -o -name "*.hpp" -o -name "*.S" \) -print0 | xargs -0 cat | wc -l 2 | -------------------------------------------------------------------------------- /createfs: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | FOLDER="fs" 4 | VOLUME_LABEL="REDACTED OS" 5 | IMAGE=disk.img 6 | 7 | if ! command -v "mcopy" >/dev/null 2>&1; then 8 | echo "Error: this script depends on mtools. Please install it" >&2 9 | exit 1 10 | fi 11 | 12 | if ! command -v "mkfs.fat" >/dev/null 2>&1; then 13 | echo "Error: this script depends on dosfstools. Please install it" >&2 14 | exit 1 15 | fi 16 | 17 | 18 | if [[ "$OSTYPE" == "darwin"* ]]; then 19 | SIZE_KB=$(du -sk "$FOLDER" | cut -f1) 20 | else 21 | SIZE_KB=$(du -s -B1 "$FOLDER" | awk '{print int($1/1024)}') 22 | fi 23 | 24 | power_of_two() { 25 | local n=$1 26 | local p=1 27 | while (( p < n )); do 28 | (( p *= 2 )) 29 | done 30 | echo $p 31 | } 32 | 33 | SIZE_MB=$(( (SIZE_KB * 12 / 10 + 1023) / 1024 )) 34 | 35 | SIZE_MB=$(power_of_two "$SIZE_MB") 36 | 37 | if ((SIZE_MB < 64)); then 38 | SIZE_MB=64 39 | fi 40 | 41 | dd if=/dev/zero of=$IMAGE bs=1M count=$SIZE_MB 42 | 43 | mkfs.fat -F 32 -n "$VOLUME_LABEL" $IMAGE 44 | 45 | mcopy -i $IMAGE -s "$FOLDER"/* :: -------------------------------------------------------------------------------- /debug: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | echo "Starting debug..." 4 | 5 | ARGS=("-ex" "file kernel.elf" "-ex" "target remote :1234") 6 | 7 | i=1 8 | while [ $i -le $# ]; do 9 | eval arg=\$$i 10 | if [ "$arg" = "b" ]; then 11 | i=$((i + 1)) 12 | eval bp=\$$i 13 | ARGS+=("-ex" "b $bp") 14 | fi 15 | i=$((i + 1)) 16 | done 17 | 18 | echo "aarch64-none-elf-gdb ${ARGS[*]}" 19 | exec aarch64-none-elf-gdb "${ARGS[@]}" -------------------------------------------------------------------------------- /kernel/Makefile: -------------------------------------------------------------------------------- 1 | ARCH= aarch64-none-elf 2 | CC = $(ARCH)-gcc 3 | LD = $(ARCH)-ld 4 | OBJCOPY = $(ARCH)-objcopy 5 | 6 | CFLAGS = -g -O0 -std=c17 -nostdlib -ffreestanding -fno-exceptions -fno-unwind-tables -fno-asynchronous-unwind-tables -Wall -Wextra -mcpu=cortex-a72 -I. -I../shared -I../user 7 | 8 | LDFLAGS = -T $(shell ls *.ld) --defsym=LOAD_ADDR=$(LOAD_ADDR) 9 | 10 | C_SRC = $(shell find . -name '*.c') 11 | ASM_SRC = $(shell find . -name '*.S') 12 | CPP_SRC = $(shell find . -name '*.cpp') 13 | OBJ = $(C_SRC:.c=.o) $(CPP_SRC:.cpp=.o) $(ASM_SRC:.S=.o) 14 | OBJL = $(filter-out ./boot.o, $(OBJ)) 15 | 16 | TARGET = kernel.img 17 | ELF = kernel.elf 18 | 19 | all: $(TARGET) 20 | 21 | $(TARGET): ../shared/libshared.a $(OBJ) 22 | $(LD) $(LDFLAGS) -o ../$(ELF) $(OBJL) ../shared/libshared.a 23 | $(OBJCOPY) -O binary ../$(ELF) ../$(TARGET) 24 | 25 | %.o: %.S 26 | $(CC) $(CFLAGS) -c $< -o $@ 27 | 28 | %.o: %.c 29 | $(CC) $(CFLAGS) -c $< -o $@ 30 | 31 | %.o: %.cpp 32 | $(CC) $(CFLAGS) -fno-rtti -c $< -o $@ 33 | 34 | clean: 35 | rm -f $(shell find . -name '*.o') ../$(ELF) ../$(TARGET) $(TARGET) -------------------------------------------------------------------------------- /kernel/aboutboot.txt: -------------------------------------------------------------------------------- 1 | Currently, there's an issue with boot.s/boot.S 2 | MacOS is case insensitive as is git 3 | Make is not 4 | It seems since boot.s is currently called .s instead of .S, it still detects .S 5 | Maybe this means boot cannot be modified as there's a ghost copy of it? 6 | It does mean the build can break if you change the name. It's possible to checkout an older commit and go back to current and it'll work, but it needs to be fixed eventually -------------------------------------------------------------------------------- /kernel/async.c: -------------------------------------------------------------------------------- 1 | #include "async.h" 2 | #include "console/kio.h" 3 | 4 | void delay(uint32_t ms) { 5 | uint64_t freq; 6 | asm volatile ("mrs %0, cntfrq_el0" : "=r"(freq)); 7 | 8 | uint64_t ticks; 9 | asm volatile ("mrs %0, cntvct_el0" : "=r"(ticks)); 10 | 11 | uint64_t target = ticks + (freq / 1000) * ms; 12 | 13 | while (1) { 14 | uint64_t now; 15 | asm volatile ("mrs %0, cntvct_el0" : "=r"(now)); 16 | if (now >= target) break; 17 | } 18 | } 19 | 20 | bool wait(uint32_t *reg, uint32_t expected_value, bool match, uint32_t timeout){ 21 | bool condition; 22 | do { 23 | delay(1); 24 | timeout--; 25 | if (timeout == 0) 26 | return false; 27 | condition = (*reg & expected_value) == expected_value; 28 | } while ((match > 0) ^ condition); 29 | 30 | return true; 31 | } -------------------------------------------------------------------------------- /kernel/async.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "types.h" 4 | 5 | #ifdef __cplusplus 6 | extern "C" { 7 | #endif 8 | void delay(uint32_t count); 9 | bool wait(uint32_t *reg, uint32_t expected_value, bool match, uint32_t timeout); 10 | #ifdef __cplusplus 11 | } 12 | #endif -------------------------------------------------------------------------------- /kernel/boot.S: -------------------------------------------------------------------------------- 1 | .global _start 2 | .section .text 3 | _start: 4 | mrs x0, mpidr_el1 5 | and x0, x0, #3 6 | cbz x0, setup_vars 7 | half: 8 | wfe 9 | b half 10 | 11 | setup_vars: 12 | ldr x5, =__bss_start 13 | ldr x6, =__bss_end 14 | clear_bss: 15 | cmp x5, x6 16 | b.ge check_hw 17 | str xzr, [x5], #8 18 | b clear_bss 19 | 20 | check_hw: 21 | adr x0, . 22 | 23 | movz x1, #0x4100, lsl #16 24 | and x2, x0, #0xFFF00000 25 | cmp x2, x1 26 | b.eq virt 27 | 28 | movz x1, #0x4000, lsl #16 29 | and x2, x0, #0xFFF00000 30 | cmp x2, x1 31 | b.eq virt 32 | 33 | mov x1, #0x80000 34 | and x2, x0, #0xFFFFF000 35 | cmp x2, x1 36 | b.eq rpi 37 | 38 | mov x1, #0x100000 39 | and x2, x0, #0xFFFFF000 40 | cmp x2, x1 41 | b.eq rpi 42 | 43 | b .//Halt if none 44 | 45 | virt: 46 | mov w0, #1 47 | adrp x1, BOARD_TYPE 48 | strb w0, [x1, #:lo12:BOARD_TYPE] 49 | b stack_setup 50 | rpi: 51 | mov w0, #2 52 | adrp x1, BOARD_TYPE 53 | strb w0, [x1, #:lo12:BOARD_TYPE] 54 | b drop_el3 55 | 56 | drop_el3: 57 | mrs x0, CurrentEL 58 | lsr x0, x0, #2 59 | cmp x0, #3 60 | b.ne el2_entry 61 | 62 | msr sctlr_el2, xzr 63 | mrs x0, hcr_el2 64 | orr x0, x0, #(1<<19) 65 | msr hcr_el2, x0 66 | 67 | mrs x0, scr_el3 68 | orr x0, x0, #(1<<10) 69 | orr x0, x0, #(1<<0) 70 | msr scr_el3, x0 71 | 72 | mov x0, #0b01001//DAIF 0000 73 | msr spsr_el3, x0 74 | 75 | adr x0, el2_entry 76 | msr elr_el3, x0 77 | eret 78 | 79 | el2_entry: 80 | mrs x0, CurrentEL 81 | lsr x0, x0, #2 82 | cmp x0, #2 83 | b.ne el1_non_secure 84 | 85 | mov x0, #3 << 20 86 | msr cpacr_el1, x0 87 | 88 | ldr x0, =0x30C00800 89 | msr sctlr_el1, x0 90 | 91 | mrs x0, hcr_el2 92 | orr x0, x0, #(1<<31) 93 | msr hcr_el2, x0 94 | 95 | mov x0, 0x1C5 96 | msr spsr_el2, x0 97 | 98 | adr x0, el1_non_secure 99 | msr elr_el2, x0 100 | 101 | eret 102 | 103 | el1_non_secure: 104 | stack_setup: 105 | ldr x1, =stack_top 106 | mov sp, x1 107 | 108 | mov x29, xzr 109 | mov x30, xzr 110 | mrs x1, CPACR_EL1 111 | orr x1, x1, #(3 << 20) 112 | msr CPACR_EL1, x1 113 | bl kernel_main 114 | 115 | b . -------------------------------------------------------------------------------- /kernel/console/kconsole/console.cpp: -------------------------------------------------------------------------------- 1 | #include "kconsole.hpp" 2 | #include "kconsole.h" 3 | #include "graph/graphics.h" 4 | 5 | KernelConsole kconsole; 6 | 7 | extern "C" void kconsole_putc(char c) { 8 | kconsole.put_char(c); 9 | gpu_flush(); 10 | } 11 | 12 | extern "C" void kconsole_puts(const char *s) { 13 | kconsole.put_string(s); 14 | } 15 | 16 | extern "C" void kconsole_clear() { 17 | kconsole.clear(); 18 | } 19 | 20 | extern "C" void kconsole_puthex(uint64_t value){ 21 | kconsole.put_hex(value); 22 | } -------------------------------------------------------------------------------- /kernel/console/kconsole/kconsole.cpp: -------------------------------------------------------------------------------- 1 | #include "kconsole.hpp" 2 | #include "memory/kalloc.h" 3 | #include "graph/graphics.h" 4 | #include "console/serial/uart.h" 5 | 6 | KernelConsole::KernelConsole() 7 | : cursor_x(0), cursor_y(0), scroll_row_offset(0) 8 | { 9 | resize(); 10 | clear(); 11 | } 12 | 13 | bool KernelConsole::check_ready(){ 14 | if (!gpu_ready()) return false; 15 | if (!is_initialized){ 16 | is_initialized = true; 17 | resize(); 18 | clear(); 19 | } 20 | return true; 21 | } 22 | 23 | void KernelConsole::resize() { 24 | gpu_size screen = gpu_get_screen_size(); 25 | columns = screen.width / char_width; 26 | rows = screen.height / char_height; 27 | 28 | if (buffer_header_size > 0) 29 | temp_free(buffer,buffer_header_size); 30 | if (buffer_data_size > 0) 31 | temp_free(row_data,buffer_data_size); 32 | 33 | buffer_header_size = rows * sizeof(char*); 34 | buffer = (char**)talloc(rows * sizeof(char*)); 35 | buffer_data_size = rows * columns * sizeof(char); 36 | row_data = (char*)talloc(buffer_data_size); 37 | 38 | for (unsigned int i = 0; i < rows; i++) { 39 | buffer[i] = row_data + (i * columns); 40 | } 41 | } 42 | 43 | void KernelConsole::put_char(char c) { 44 | if (!check_ready()) 45 | return; 46 | 47 | if (c == '\n') { 48 | newline(); 49 | return; 50 | } 51 | 52 | if (cursor_x >= columns) 53 | newline(); 54 | 55 | buffer[(scroll_row_offset + cursor_y) % rows][cursor_x] = c; 56 | gpu_draw_char({cursor_x * char_width, cursor_y * char_height}, c, 1, 0xFFFFFFFF); 57 | cursor_x++; 58 | } 59 | 60 | void KernelConsole::put_string(const char *str) { 61 | if (!check_ready()) 62 | return; 63 | for (uint32_t i = 0; str[i] != 0; i++) { 64 | put_char(str[i]); 65 | } 66 | gpu_flush(); 67 | } 68 | 69 | void KernelConsole::put_hex(uint64_t value) { 70 | if (!check_ready()) 71 | return; 72 | put_char('0'); 73 | put_char('x'); 74 | bool started = false; 75 | for (uint32_t i = 60;; i -= 4) { 76 | uint8_t nibble = (value >> i) & 0xF; 77 | char curr_char = nibble < 10 ? '0' + nibble : 'A' + (nibble - 10); 78 | if (started || curr_char != '0' || i == 0) { 79 | started = true; 80 | put_char(curr_char); 81 | } 82 | if (i == 0) break; 83 | } 84 | 85 | gpu_flush(); 86 | } 87 | 88 | void KernelConsole::newline() { 89 | if (!check_ready()) 90 | return; 91 | for (unsigned x = cursor_x; x < columns; x++){ 92 | buffer[(scroll_row_offset + cursor_y) % rows][x] = 0; 93 | } 94 | cursor_x = 0; 95 | cursor_y++; 96 | if (cursor_y >= rows) { 97 | scroll(); 98 | cursor_y = rows - 1; 99 | } 100 | } 101 | 102 | void KernelConsole::scroll() { 103 | if (!check_ready()) 104 | return; 105 | 106 | scroll_row_offset = (scroll_row_offset + 1) % rows; 107 | 108 | for (unsigned int x = 0; x < columns; x++) { 109 | buffer[(scroll_row_offset + rows - 1) % rows][x] = 0; 110 | } 111 | 112 | redraw(); 113 | } 114 | 115 | void KernelConsole::redraw(){ 116 | screen_clear(); 117 | for (unsigned int y = 0; y < rows; y++) { 118 | for (unsigned int x = 0; x < columns; x++) { 119 | char c = buffer[(scroll_row_offset + y) % rows][x]; 120 | gpu_draw_char({x * char_width, y * char_height}, c, 1, 0xFFFFFFFF); 121 | } 122 | } 123 | } 124 | 125 | void KernelConsole::screen_clear(){ 126 | gpu_clear(0x0); 127 | } 128 | 129 | void KernelConsole::clear() { 130 | screen_clear(); 131 | for (unsigned int y = 0; y < rows; y++) { 132 | for (unsigned int x = 0; x < columns; x++) { 133 | buffer[y][x] = 0; 134 | } 135 | } 136 | cursor_x = 0; 137 | cursor_y = 0; 138 | scroll_row_offset = 0; 139 | gpu_flush(); 140 | } -------------------------------------------------------------------------------- /kernel/console/kconsole/kconsole.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #ifdef __cplusplus 4 | extern "C" { 5 | #endif 6 | 7 | void kconsole_putc(char c); 8 | void kconsole_puts(const char *s); 9 | void kconsole_puthex(uint64_t value); 10 | void kconsole_clear(); 11 | 12 | #ifdef __cplusplus 13 | } 14 | #endif -------------------------------------------------------------------------------- /kernel/console/kconsole/kconsole.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "types.h" 4 | 5 | class KernelConsole { 6 | public: 7 | KernelConsole(); 8 | 9 | void put_char(char c); 10 | void put_string(const char *str); 11 | void put_hex(uint64_t value); 12 | void newline(); 13 | void scroll(); 14 | void clear(); 15 | void resize(); 16 | 17 | private: 18 | bool check_ready(); 19 | void screen_clear(); 20 | void redraw(); 21 | 22 | unsigned int cursor_x; 23 | unsigned int cursor_y; 24 | unsigned int columns; 25 | unsigned int rows; 26 | bool is_initialized = false; 27 | int scroll_row_offset = 0; 28 | static constexpr int char_width = 8; 29 | static constexpr int char_height = 16; 30 | char** buffer; 31 | char* row_data; 32 | 33 | uint64_t buffer_header_size; 34 | uint64_t buffer_data_size; 35 | }; 36 | extern KernelConsole kconsole; -------------------------------------------------------------------------------- /kernel/console/kio.c: -------------------------------------------------------------------------------- 1 | #include "kio.h" 2 | #include "serial/uart.h" 3 | #include "kstring.h" 4 | #include "exceptions/irq.h" 5 | #include "memory/kalloc.h" 6 | #include "kconsole/kconsole.h" 7 | 8 | static bool use_visual = true; 9 | 10 | void puts(const char *s){ 11 | uart_raw_puts(s); 12 | if (use_visual) 13 | kconsole_puts(s); 14 | } 15 | 16 | void putc(const char c){ 17 | uart_raw_putc(c); 18 | if (use_visual) 19 | kconsole_putc(c); 20 | } 21 | 22 | void puthex(uint64_t value){ 23 | uart_puthex(value); 24 | if (use_visual) 25 | kconsole_puthex(value); 26 | } 27 | 28 | void kprintf_args(const char *fmt, const uint64_t *args, uint32_t arg_count){ 29 | kprintf_args_raw(fmt, args, arg_count); 30 | } 31 | 32 | void kprintf_args_raw(const char *fmt, const uint64_t *args, uint32_t arg_count){ 33 | kstring s = kstring_format_args(fmt, args, arg_count); 34 | puts(s.data); 35 | putc('\n'); 36 | temp_free(s.data,256); 37 | } 38 | 39 | void kprintf_l(const char *fmt){ 40 | puts(fmt); 41 | putc('\n'); 42 | } 43 | 44 | void kputf_args_raw(const char *fmt, const uint64_t *args, uint32_t arg_count){ 45 | kstring s = kstring_format_args(fmt, args, arg_count); 46 | puts(s.data); 47 | temp_free(s.data,256); 48 | } 49 | 50 | void disable_visual(){ 51 | use_visual = false; 52 | } 53 | 54 | void enable_visual(){ 55 | use_visual = true; 56 | } -------------------------------------------------------------------------------- /kernel/console/kio.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #ifdef __cplusplus 4 | extern "C" { 5 | #endif 6 | 7 | #include "types.h" 8 | 9 | #define kprintf(fmt, ...) \ 10 | ({ \ 11 | uint64_t _args[] = { __VA_ARGS__ }; \ 12 | kprintf_args((fmt), _args, sizeof(_args) / sizeof(_args[0])); \ 13 | }) 14 | 15 | #define kprintf_raw(fmt, ...) \ 16 | ({ \ 17 | uint64_t _args[] = { __VA_ARGS__ }; \ 18 | kprintf_args_raw((fmt), _args, sizeof(_args) / sizeof(_args[0])); \ 19 | }) 20 | 21 | #define kputf_raw(fmt, ...) \ 22 | ({ \ 23 | uint64_t _args[] = { __VA_ARGS__ }; \ 24 | kputf_args_raw((fmt), _args, sizeof(_args) / sizeof(_args[0])); \ 25 | }) 26 | 27 | void kprintf_args(const char *fmt, const uint64_t *args, uint32_t arg_count); 28 | void kprintf_args_raw(const char *fmt, const uint64_t *args, uint32_t arg_count); 29 | void kputf_args_raw(const char *fmt, const uint64_t *args, uint32_t arg_count); 30 | void kprintf_l(const char *fmt); 31 | void puts(const char *s); 32 | void putc(const char c); 33 | void puthex(uint64_t value); 34 | void disable_visual(); 35 | void enable_visual(); 36 | 37 | #ifdef __cplusplus 38 | } 39 | #endif -------------------------------------------------------------------------------- /kernel/console/serial/uart.c: -------------------------------------------------------------------------------- 1 | #include "console/serial/uart.h" 2 | #include "memory/memory_access.h" 3 | #include "exceptions/irq.h" 4 | #include "gpio.h" 5 | #include "hw/hw.h" 6 | 7 | #define UART0_DR (UART0_BASE + 0x00) 8 | #define UART0_FR (UART0_BASE + 0x18) 9 | #define UART0_IBRD (UART0_BASE + 0x24) 10 | #define UART0_FBRD (UART0_BASE + 0x28) 11 | #define UART0_LCRH (UART0_BASE + 0x2C) 12 | #define UART0_CR (UART0_BASE + 0x30) 13 | 14 | uint64_t get_uart_base(){ 15 | return UART0_BASE; 16 | } 17 | 18 | void enable_uart() { 19 | write32(UART0_CR, 0x0); 20 | 21 | if (BOARD_TYPE == 2){ 22 | enable_gpio_pin(14); 23 | enable_gpio_pin(15); 24 | } 25 | 26 | write32(UART0_IBRD, 1); 27 | write32(UART0_FBRD, 40); 28 | 29 | write32(UART0_LCRH, (1 << 4) | (1 << 5) | (1 << 6)); 30 | 31 | write32(UART0_CR, (1 << 0) | (1 << 8) | (1 << 9)); 32 | } 33 | 34 | void uart_raw_putc(const char c) { 35 | while (read32(UART0_FR) & (1 << 5)); 36 | write32(UART0_DR, c); 37 | } 38 | 39 | void uart_putc(const char c){ 40 | uart_raw_putc(c); 41 | } 42 | 43 | void uart_puts(const char *s) { 44 | uart_raw_puts(s); 45 | } 46 | 47 | void uart_raw_puts(const char *s) { 48 | while (*s != '\0') { 49 | uart_raw_putc(*s); 50 | s++; 51 | } 52 | } 53 | 54 | void uart_puthex(uint64_t value) { 55 | bool started = false; 56 | uart_raw_putc('0'); 57 | uart_raw_putc('x'); 58 | for (int i = 60; i >= 0; i -= 4) { 59 | uint8_t nibble = (value >> i) & 0xF; 60 | char curr_char = nibble < 10 ? '0' + nibble : 'A' + (nibble - 10); 61 | if (started || curr_char != '0' || i == 0) { 62 | started = true; 63 | uart_raw_putc(curr_char); 64 | } 65 | } 66 | } -------------------------------------------------------------------------------- /kernel/console/serial/uart.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #ifdef __cplusplus 4 | extern "C" { 5 | #endif 6 | 7 | #include "types.h" 8 | #include "hw/hw.h" 9 | 10 | uint64_t get_uart_base(); 11 | void enable_uart(); 12 | void uart_puts(const char *s); 13 | void uart_putc(const char c); 14 | void uart_puthex(uint64_t value); 15 | 16 | void uart_raw_putc(const char c); 17 | void uart_raw_puts(const char *s); 18 | 19 | #ifdef __cplusplus 20 | } 21 | #endif -------------------------------------------------------------------------------- /kernel/dtb.c: -------------------------------------------------------------------------------- 1 | #include "dtb.h" 2 | #include "console/kio.h" 3 | #include "std/string.h" 4 | #include "memory/kalloc.h" 5 | 6 | #define DTB_ADDR 0x40000000UL 7 | #define FDT_MAGIC 0xD00DFEED 8 | 9 | #define FDT_BEGIN_NODE 0x00000001 10 | #define FDT_END_NODE 0x00000002 11 | #define FDT_PROP 0x00000003 12 | #define FDT_NOP 0x00000004 13 | #define FDT_END 0x00000009 14 | 15 | struct fdt_header { 16 | uint32_t magic; 17 | uint32_t totalsize; 18 | uint32_t off_dt_struct; 19 | uint32_t off_dt_strings; 20 | uint32_t off_mem_rsvmap; 21 | uint32_t version; 22 | uint32_t last_comp_version; 23 | uint32_t boot_cpuid_phys; 24 | uint32_t size_dt_strings; 25 | uint32_t size_dt_struct; 26 | }; 27 | 28 | static struct fdt_header *hdr; 29 | 30 | bool dtb_get_header(){ 31 | if (!hdr) 32 | hdr = (struct fdt_header *)DTB_ADDR; 33 | if (__builtin_bswap32(hdr->magic) != FDT_MAGIC) return false; 34 | return true; 35 | } 36 | 37 | bool dtb_addresses(uint64_t *start, uint64_t *size){ 38 | if (!dtb_get_header()) return false; 39 | *start = (uint64_t)DTB_ADDR; 40 | *size = __builtin_bswap32(hdr->totalsize); 41 | return true; 42 | } 43 | 44 | void dtb_debug_print_all() { 45 | if (!dtb_get_header()) return; 46 | 47 | uint32_t *p = (uint32_t *)(DTB_ADDR + __builtin_bswap32(hdr->off_dt_struct)); 48 | 49 | while (1) { 50 | uint32_t token = __builtin_bswap32(*p++); 51 | if (token == FDT_END) break; 52 | if (token == FDT_BEGIN_NODE) { 53 | const char *name = (const char *)p; 54 | uint32_t skip = 0; 55 | while (((char *)p)[skip]) skip++; 56 | skip = (skip + 4) & ~3; 57 | p += skip / 4; 58 | kprintf_raw(name); 59 | } 60 | } 61 | } 62 | 63 | bool dtb_scan(const char *search_name, dtb_node_handler handler, dtb_match_t *match) { 64 | if (!dtb_get_header()) return false; 65 | 66 | uint32_t *p = (uint32_t *)(DTB_ADDR + __builtin_bswap32(hdr->off_dt_struct)); 67 | const char *strings = (const char *)(DTB_ADDR + __builtin_bswap32(hdr->off_dt_strings)); 68 | int depth = 0; 69 | bool active = 0; 70 | 71 | while (1) { 72 | uint32_t token = __builtin_bswap32(*p++); 73 | if (token == FDT_END) break; 74 | if (token == FDT_BEGIN_NODE) { 75 | const char *name = (const char *)p; 76 | uint32_t skip = 0; 77 | while (((char *)p)[skip]) skip++; 78 | skip = (skip + 4) & ~3; 79 | p += skip / 4; 80 | depth++; 81 | active = strcont(name, search_name); 82 | } else if (token == FDT_PROP && active) { 83 | uint32_t len = __builtin_bswap32(*p++); 84 | uint32_t nameoff = __builtin_bswap32(*p++); 85 | const char *propname = strings + nameoff; 86 | const void *prop = p; 87 | 88 | handler(propname, prop, len, match); 89 | 90 | p += (len + 3) / 4; 91 | } else if (token == FDT_END_NODE) { 92 | depth--; 93 | if (active && match->found) 94 | return true; 95 | active = 0; 96 | match->compatible = 0; 97 | match->reg_base = 0; 98 | match->reg_size = 0; 99 | match->irq = 0; 100 | match->found = 0; 101 | } 102 | } 103 | return false; 104 | } -------------------------------------------------------------------------------- /kernel/dtb.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "types.h" 4 | 5 | typedef struct { 6 | const char *compatible; 7 | uint64_t reg_base; 8 | uint64_t reg_size; 9 | uint32_t irq; 10 | int found; 11 | } dtb_match_t; 12 | 13 | typedef int (*dtb_node_handler)(const char *propname, const void *prop, uint32_t len, dtb_match_t *out); 14 | 15 | bool dtb_addresses(uint64_t *start, uint64_t *size); 16 | bool dtb_scan(const char *search_name, dtb_node_handler handler, dtb_match_t *match); -------------------------------------------------------------------------------- /kernel/exceptions/exception_handler.c: -------------------------------------------------------------------------------- 1 | #include "exception_handler.h" 2 | #include "console/serial/uart.h" 3 | #include "kstring.h" 4 | #include "console/kio.h" 5 | #include "memory/mmu.h" 6 | #include "graph/graphics.h" 7 | #include "timer.h" 8 | #include "theme/theme.h" 9 | #include "std/string.h" 10 | 11 | static bool panic_triggered = false; 12 | 13 | void set_exception_vectors(){ 14 | extern char exception_vectors[]; 15 | kprintf("Exception vectors setup at %x", (uint64_t)&exception_vectors); 16 | asm volatile ("msr vbar_el1, %0" :: "r"(exception_vectors)); 17 | } 18 | 19 | void handle_exception(const char* type) { 20 | uint64_t esr, elr, far; 21 | asm volatile ("mrs %0, esr_el1" : "=r"(esr)); 22 | asm volatile ("mrs %0, elr_el1" : "=r"(elr)); 23 | asm volatile ("mrs %0, far_el1" : "=r"(far)); 24 | 25 | disable_visual();//Disable visual kprintf, since it has additional memory accesses that could be faulting 26 | 27 | kstring s = kstring_format("%s \nESR_EL1: %x\nELR_EL1: %x\nFAR_EL1: %x",(uint64_t)kstring_l(type).data,esr,elr,far); 28 | panic(s.data); 29 | } 30 | 31 | void handle_exception_with_info(const char* type, uint64_t info) { 32 | uint64_t esr, elr, far; 33 | asm volatile ("mrs %0, esr_el1" : "=r"(esr)); 34 | asm volatile ("mrs %0, elr_el1" : "=r"(elr)); 35 | asm volatile ("mrs %0, far_el1" : "=r"(far)); 36 | 37 | disable_visual();//Disable visual kprintf, since it has additional memory accesses that could be faulting 38 | 39 | kstring s = kstring_format("%s \nESR_EL1: %x\nELR_EL1: %x\nFAR_EL1: %x",(uint64_t)kstring_l(type).data,esr,elr,far); 40 | panic_with_info(s.data, info); 41 | } 42 | 43 | void fiq_el1_handler(){ handle_exception("FIQ EXCEPTION\n"); } 44 | 45 | void error_el1_handler(){ handle_exception("ERROR EXCEPTION\n"); } 46 | 47 | void draw_panic_screen(kstring s){ 48 | gpu_clear(0x0000FF); 49 | uint32_t scale = 3; 50 | gpu_draw_string(*(string *)&s, (gpu_point){20,20}, scale, 0xFFFFFF); 51 | gpu_flush(); 52 | } 53 | 54 | void panic(const char* panic_msg) { 55 | permanent_disable_timer(); 56 | 57 | bool old_panic_triggered = panic_triggered; 58 | panic_triggered = true; 59 | uart_raw_puts("*** "); 60 | uart_raw_puts(PANIC_TEXT); 61 | uart_raw_puts(" ***\n"); 62 | uart_raw_puts(panic_msg); 63 | uart_raw_putc('\n'); 64 | uart_raw_puts("System Halted"); 65 | if (!old_panic_triggered){ 66 | kstring s = kstring_format("%s\n%s\nSystem Halted",(uint64_t)PANIC_TEXT,(uint64_t)panic_msg); 67 | draw_panic_screen(s); 68 | } 69 | while (1);//TODO: OPT 70 | } 71 | 72 | void panic_with_info(const char* msg, uint64_t info) { 73 | permanent_disable_timer(); 74 | 75 | uint64_t esr, elr, far; 76 | asm volatile ("mrs %0, esr_el1" : "=r"(esr)); 77 | asm volatile ("mrs %0, elr_el1" : "=r"(elr)); 78 | asm volatile ("mrs %0, far_el1" : "=r"(far)); 79 | 80 | bool old_panic_triggered = panic_triggered; 81 | panic_triggered = true; 82 | uart_raw_puts("*** "); 83 | uart_raw_puts(PANIC_TEXT); 84 | uart_raw_puts(" ***\n"); 85 | uart_raw_puts(msg); 86 | uart_raw_putc('\n'); 87 | uart_raw_puts("Additional info: "); 88 | uart_puthex(info); 89 | uart_raw_putc('\n'); 90 | uart_raw_puts("System Halted"); 91 | if (!old_panic_triggered){ 92 | kstring s = kstring_format("%s\n%s\nError code: %x\nSystem Halted",(uint64_t)PANIC_TEXT,(uint64_t)msg,info); 93 | draw_panic_screen(s); 94 | } 95 | while (1);//TODO: OPT 96 | } -------------------------------------------------------------------------------- /kernel/exceptions/exception_handler.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "types.h" 4 | 5 | void set_exception_vectors(); 6 | void fiq_el1_handler(); 7 | void error_el1_handler(); 8 | void panic(const char* msg); 9 | void handle_exception(const char* type); 10 | void handle_exception_with_info(const char* type, uint64_t info); 11 | void panic_with_info(const char* msg, uint64_t info); -------------------------------------------------------------------------------- /kernel/exceptions/exception_vectors_as.S: -------------------------------------------------------------------------------- 1 | .section .vectors, "a", %progbits 2 | .align 11 3 | .global exception_vectors 4 | 5 | exception_vectors: 6 | 7 | .macro vector_slot handler 8 | b \handler 9 | .space 0x80 - 4 10 | .endm 11 | 12 | vector_slot sync_el0_handler_as // EL1t sync 13 | vector_slot irq_el1_asm_handler // EL1t irq 14 | vector_slot fiq_el1_handler // EL1t fiq 15 | vector_slot error_el1_handler // EL1t serror 16 | 17 | vector_slot sync_el0_handler_as // EL1h sync 18 | vector_slot irq_el1_asm_handler // EL1h irq 19 | vector_slot fiq_el1_handler // EL1h fiq 20 | vector_slot error_el1_handler // EL1h serror 21 | 22 | vector_slot sync_el0_handler_as // EL0_64 sync 23 | vector_slot irq_el1_asm_handler // EL0_64 irq 24 | vector_slot fiq_el1_handler // EL0_64 fiq 25 | vector_slot error_el1_handler // EL0_64 serror 26 | 27 | vector_slot sync_el0_handler_as // EL0_32 sync 28 | vector_slot irq_el1_asm_handler // EL0_32 irq 29 | vector_slot fiq_el1_handler // EL0_32 fiq 30 | vector_slot error_el1_handler // EL0_32 serror 31 | 32 | .global irq_el1_asm_handler 33 | irq_el1_asm_handler: 34 | mov x15, x0 35 | mov x14, x1 36 | mov x13, x29 37 | mov x12, x30 38 | mov x11, sp 39 | mov x9, x2 40 | mov x16, x3 41 | 42 | mrs x10, spsr_el1 43 | 44 | bl irq_el1_handler 45 | 46 | eret; -------------------------------------------------------------------------------- /kernel/exceptions/irq.c: -------------------------------------------------------------------------------- 1 | #include "irq.h" 2 | #include "console/kio.h" 3 | #include "memory/memory_access.h" 4 | #include "process/scheduler.h" 5 | #include "input/input_dispatch.h" 6 | #include "input/xhci_types.h" 7 | #include "pci.h" 8 | #include "console/serial/uart.h" 9 | #include "networking/network.h" 10 | 11 | #define IRQ_TIMER 30 12 | #define SLEEP_TIMER 27 13 | 14 | extern void irq_el1_asm_handler(); 15 | 16 | static void gic_enable_irq(uint32_t irq, uint8_t priority, uint8_t cpu_target) { 17 | uint32_t reg_offset = (irq / 32) * 4; 18 | uint32_t bit = 1 << (irq % 32); 19 | 20 | uint32_t flag = read32(GICD_BASE + 0x100 + reg_offset); 21 | write32(GICD_BASE + 0x100 + reg_offset, flag | bit); 22 | 23 | write8(GICD_BASE + 0x800 + irq, cpu_target); 24 | write8(GICD_BASE + 0x400 + irq, priority); 25 | 26 | uint32_t config_offset = (irq / 16) * 4; 27 | uint32_t config_shift = (irq % 16) * 2; 28 | uint32_t config = read32(GICD_BASE + 0xC00 + config_offset); 29 | config &= ~(3 << config_shift); 30 | config |= (2 << config_shift); // 0b10 = edge-triggered 31 | write32(GICD_BASE + 0xC00 + config_offset, config); 32 | } 33 | 34 | void irq_init() { 35 | write8(GICD_BASE, 0); // Disable Distributor 36 | write8(GICC_BASE, 0); // Disable CPU Interface 37 | 38 | gic_enable_irq(IRQ_TIMER, 0x80, 0); 39 | gic_enable_irq(MSI_OFFSET + XHCI_IRQ, 0x80, 0); 40 | gic_enable_irq(MSI_OFFSET + NET_IRQ, 0x80, 0); 41 | gic_enable_irq(MSI_OFFSET + NET_IRQ + 1, 0x80, 0); 42 | gic_enable_irq(SLEEP_TIMER, 0x80, 0); 43 | 44 | write32(GICC_BASE + 0x004, 0xF0); //Priority 45 | 46 | write8(GICC_BASE, 1); // Enable CPU Interface 47 | write8(GICD_BASE, 1); // Enable Distributor 48 | 49 | kprintf("[GIC] GIC enabled\n"); 50 | } 51 | 52 | void enable_interrupt() { 53 | asm volatile ("msr daifclr, #2"); 54 | asm volatile ("isb"); 55 | } 56 | 57 | void disable_interrupt(){ 58 | asm volatile ("msr daifset, #2"); 59 | asm volatile ("isb"); 60 | } 61 | 62 | void irq_el1_handler() { 63 | save_context_registers(); 64 | save_return_address_interrupt(); 65 | if (ksp != 0){ 66 | asm volatile ("mov sp, %0" :: "r"(ksp)); 67 | } 68 | uint32_t irq = read32(GICC_BASE + 0xC); 69 | 70 | if (irq == IRQ_TIMER) { 71 | write32(GICC_BASE + 0x10, irq); 72 | switch_proc(INTERRUPT); 73 | } else if (irq == MSI_OFFSET + XHCI_IRQ){ 74 | handle_input_interrupt(); 75 | write32(GICC_BASE + 0x10, irq); 76 | process_restore(); 77 | } else if (irq == SLEEP_TIMER){ 78 | wake_processes(); 79 | write32(GICC_BASE + 0x10, irq); 80 | process_restore(); 81 | } else if (irq == MSI_OFFSET + NET_IRQ){ 82 | network_handle_download_interrupt(); 83 | write32(GICC_BASE + 0x10, irq); 84 | process_restore(); 85 | } else if (irq == MSI_OFFSET + NET_IRQ + 1){ 86 | network_handle_upload_interrupt(); 87 | write32(GICC_BASE + 0x10, irq); 88 | process_restore(); 89 | } else { 90 | kprintf_raw("[GIC error] Received unknown interrupt"); 91 | write32(GICC_BASE + 0x10, irq); 92 | process_restore(); 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /kernel/exceptions/irq.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "types.h" 4 | #include "hw/hw.h" 5 | 6 | void irq_init(); 7 | void irq_el1_handler(); 8 | void disable_interrupt(); 9 | void enable_interrupt(); 10 | -------------------------------------------------------------------------------- /kernel/exceptions/timer.c: -------------------------------------------------------------------------------- 1 | #include "timer.h" 2 | 3 | static uint64_t _msecs; 4 | 5 | void timer_reset() { 6 | uint64_t freq; 7 | asm volatile ("mrs %0, cntfrq_el0" : "=r"(freq)); 8 | uint64_t interval = (freq * _msecs)/1000; 9 | asm volatile ("msr cntp_tval_el0, %0" :: "r"(interval)); 10 | } 11 | 12 | void timer_enable() { 13 | uint64_t val = 1; 14 | asm volatile ("msr cntp_ctl_el0, %0" :: "r"(val)); 15 | asm volatile ("msr cntkctl_el1, %0" :: "r"(val)); 16 | } 17 | 18 | void permanent_disable_timer(){ 19 | uint64_t ctl = 0; 20 | asm volatile ("msr cntp_ctl_el0, %0" :: "r"(ctl)); 21 | } 22 | 23 | void timer_init(uint64_t msecs) { 24 | _msecs = msecs; 25 | timer_reset(); 26 | timer_enable(); 27 | } 28 | 29 | void virtual_timer_reset(uint64_t smsecs) { 30 | uint64_t freq; 31 | asm volatile ("mrs %0, cntfrq_el0" : "=r"(freq)); 32 | uint64_t interval = (freq * smsecs)/1000; 33 | asm volatile ("msr cntv_tval_el0, %0" :: "r"(interval)); 34 | } 35 | 36 | void virtual_timer_enable() { 37 | uint64_t val = 1; 38 | asm volatile ("msr cntv_ctl_el0, %0" :: "r"(val)); 39 | } 40 | 41 | uint64_t virtual_timer_remaining_msec() { 42 | uint64_t ticks; 43 | uint64_t freq; 44 | asm volatile ("mrs %0, cntv_tval_el0" : "=r"(ticks)); 45 | asm volatile ("mrs %0, cntfrq_el0" : "=r"(freq)); 46 | return (ticks * 1000) / freq; 47 | } 48 | 49 | uint64_t timer_now() { 50 | uint64_t val; 51 | asm volatile ("mrs %0, cntvct_el0" : "=r"(val)); 52 | return val; 53 | } 54 | 55 | uint64_t timer_now_msec() { 56 | uint64_t ticks, freq; 57 | asm volatile ("mrs %0, cntvct_el0" : "=r"(ticks)); 58 | asm volatile ("mrs %0, cntfrq_el0" : "=r"(freq)); 59 | return (ticks * 1000) / freq; 60 | } -------------------------------------------------------------------------------- /kernel/exceptions/timer.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "types.h" 4 | 5 | void timer_init(uint64_t msecs); 6 | void timer_reset(); 7 | 8 | void virtual_timer_reset(uint64_t smsecs); 9 | void virtual_timer_enable(); 10 | uint64_t virtual_timer_remaining_msec(); 11 | 12 | uint64_t timer_now(); 13 | uint64_t timer_now_msec(); 14 | 15 | void permanent_disable_timer(); -------------------------------------------------------------------------------- /kernel/filesystem/disk.cpp: -------------------------------------------------------------------------------- 1 | #include "disk.h" 2 | #include "exfat.hpp" 3 | #include "fat32.hpp" 4 | #include "virtio_blk_pci.h" 5 | #include "sdhci.hpp" 6 | #include "hw/hw.h" 7 | 8 | static bool disk_enable_verbose; 9 | SDHCI sdhci_driver; 10 | FAT32FS fs_driver; 11 | 12 | void disk_verbose(){ 13 | disk_enable_verbose = true; 14 | vblk_disk_verbose(); 15 | if (BOARD_TYPE == 2){ 16 | sdhci_driver.enable_verbose(); 17 | } 18 | } 19 | 20 | #define kprintfv(fmt, ...) \ 21 | ({ \ 22 | if (mmu_verbose){\ 23 | uint64_t _args[] = { __VA_ARGS__ }; \ 24 | kprintf_args_raw((fmt), _args, sizeof(_args) / sizeof(_args[0])); \ 25 | }\ 26 | }) 27 | 28 | 29 | bool find_disk(){ 30 | if (BOARD_TYPE == 2) 31 | return sdhci_driver.init(); 32 | else 33 | return vblk_find_disk(); 34 | } 35 | 36 | bool disk_init(){ 37 | return fs_driver.init(); 38 | } 39 | 40 | void disk_write(const void *buffer, uint32_t sector, uint32_t count){ 41 | vblk_write(buffer, sector, count); 42 | } 43 | 44 | void disk_read(void *buffer, uint32_t sector, uint32_t count){ 45 | if (BOARD_TYPE == 2) 46 | sdhci_driver.read(buffer, sector, count); 47 | else 48 | vblk_read(buffer, sector, count); 49 | } 50 | 51 | void* read_file(char *path){ 52 | return fs_driver.read_file(path); 53 | } 54 | 55 | string_list* list_directory_contents(char *path){ 56 | return fs_driver.list_contents(path); 57 | } -------------------------------------------------------------------------------- /kernel/filesystem/disk.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #ifdef __cplusplus 4 | extern "C" { 5 | #endif 6 | 7 | #include "types.h" 8 | #include "std/string.h" 9 | 10 | bool find_disk(); 11 | void disk_verbose(); 12 | bool disk_init(); 13 | 14 | void disk_write(const void *buffer, uint32_t sector, uint32_t count); 15 | void disk_read(void *buffer, uint32_t sector, uint32_t count); 16 | 17 | void* read_file(char *path); 18 | string_list* list_directory_contents(char *path); 19 | 20 | #ifdef __cplusplus 21 | } 22 | #endif -------------------------------------------------------------------------------- /kernel/filesystem/exfat.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "types.h" 4 | #include "std/string.h" 5 | 6 | typedef struct exfat_mbs { 7 | uint8_t jumpboot[3];//3 8 | char fsname[8];//8 9 | uint8_t mustbezero[53]; 10 | uint64_t partition_offset; 11 | uint64_t volume_length; 12 | uint32_t fat_offset; 13 | uint32_t fat_length; 14 | uint32_t cluster_heap_offset; 15 | uint32_t cluster_count; 16 | uint32_t first_cluster_of_root_directory; 17 | uint32_t volume_serial_number; 18 | uint16_t fs_revision; 19 | uint16_t volume_flags; 20 | uint8_t bytes_per_sector_shift; 21 | uint8_t sectors_per_cluster_shift; 22 | uint8_t number_of_fats; 23 | uint8_t drive_select; 24 | uint8_t percent_in_use; 25 | uint8_t rsvd[7]; 26 | char bootcode[390]; 27 | uint16_t bootsignature; 28 | }__attribute__((packed)) exfat_mbs; 29 | 30 | typedef struct file_entry { 31 | uint8_t entry_type; 32 | uint8_t entry_count; 33 | uint16_t checksum; 34 | struct { 35 | uint16_t read_only: 1; 36 | uint16_t hidden: 1; 37 | uint16_t system: 1; 38 | uint16_t rsvd: 1; 39 | uint16_t directory: 1; 40 | uint16_t archive: 1; 41 | uint16_t rsvd2: 10; 42 | } flags; 43 | 44 | uint16_t rsvd; 45 | uint32_t create_timestamp; 46 | uint32_t last_modified; 47 | uint32_t last_accessed; 48 | uint8_t create10msincrement; 49 | uint8_t lastmod10msincrement; 50 | uint8_t createutcoffset; 51 | uint8_t lastmodutcoffset; 52 | uint8_t lastaccutcoffset; 53 | 54 | uint8_t rsvd2[7]; 55 | }__attribute__((packed)) file_entry; 56 | 57 | typedef struct fileinfo_entry { 58 | uint8_t entry_type; 59 | uint8_t flags; 60 | uint8_t rsvd; 61 | uint8_t name_length; 62 | uint16_t name_hash; 63 | uint16_t rsvd2; 64 | uint64_t valid_filesize; 65 | uint32_t rsvd3; 66 | uint32_t first_cluster; 67 | uint64_t filesize; 68 | }__attribute__((packed)) fileinfo_entry; 69 | 70 | typedef struct filename_entry { 71 | uint8_t entry_type; 72 | uint8_t flags; 73 | uint16_t name[15]; 74 | }__attribute__((packed)) filename_entry; 75 | 76 | class ExFATFS; 77 | 78 | typedef void* (*ef_entry_handler)(ExFATFS *instance, file_entry*, fileinfo_entry*, filename_entry*, char *seek); 79 | 80 | class ExFATFS { 81 | public: 82 | bool init(); 83 | void* read_full_file(uint32_t cluster_start, uint32_t cluster_size, uint32_t cluster_count, uint64_t file_size, uint32_t root_index); 84 | void* read_file(char *path); 85 | string_list* list_contents(char *path); 86 | 87 | protected: 88 | void read_FAT(uint32_t location, uint32_t size, uint8_t count); 89 | void* list_directory(uint32_t cluster_count, uint32_t root_index); 90 | void* walk_directory(uint32_t cluster_count, uint32_t root_index, char *seek, ef_entry_handler handler); 91 | void* read_cluster(uint32_t cluster_start, uint32_t cluster_size, uint32_t cluster_count, uint32_t root_index); 92 | char* advance_path(char *path); 93 | 94 | exfat_mbs* mbs; 95 | void *fs_page; 96 | 97 | static void* read_entry_handler(ExFATFS *instance, file_entry *entry, fileinfo_entry *info, filename_entry *name, char *seek); 98 | static void* list_entries_handler(ExFATFS *instance, file_entry *entry, fileinfo_entry *info, filename_entry *name, char *seek); 99 | }; -------------------------------------------------------------------------------- /kernel/filesystem/fat32.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "types.h" 4 | #include "std/string.h" 5 | 6 | typedef struct fat32_mbs { 7 | uint8_t jumpboot[3];//3 8 | char fsname[8];//8 9 | uint16_t bytes_per_sector; 10 | uint8_t sectors_per_cluster; 11 | uint16_t reserved_sectors; 12 | uint8_t number_of_fats; 13 | uint16_t root_directory_entries; 14 | uint16_t num_sectors;//Could be 0, in which case it's stored in large_num_sectors 15 | uint8_t media_descriptor_type; 16 | uint16_t num_sectors_fat;//Used only in 12/16 17 | uint16_t num_sectors_track; 18 | uint16_t num_heads; 19 | uint32_t num_hidden_sectors; 20 | uint32_t large_num_sectors; 21 | 22 | uint32_t sectors_per_fat; 23 | uint16_t flags; 24 | uint16_t fat_version;//high major low minor 25 | uint32_t first_cluster_of_root_directory; 26 | uint16_t fsinfo_sector; 27 | uint16_t backup_boot_sector; 28 | uint8_t reserved[12]; 29 | uint8_t drive_number; 30 | uint8_t reserved_flags; 31 | uint8_t signature;//0x28 or 0x29 32 | uint32_t volume_id; 33 | char volume_label[11]; 34 | char system_identifier[8]; 35 | uint8_t boot_code[420]; 36 | uint16_t boot_signature; 37 | }__attribute__((packed)) fat32_mbs; 38 | 39 | typedef struct f32file_entry { 40 | char filename[11]; 41 | struct { 42 | uint8_t read_only: 1; 43 | uint8_t hidden: 1; 44 | uint8_t system: 1; 45 | uint8_t volume_id: 1; 46 | uint8_t directory: 1; 47 | uint8_t archive: 1; 48 | uint8_t long_filename: 1; 49 | } flags; 50 | 51 | uint8_t rsvd;//Can be used for case sensitivity 52 | 53 | uint8_t create10msincrement; 54 | uint16_t create_timestamp;//Multiply seconds by 2 55 | uint16_t create_date; 56 | uint16_t last_accessed_date; 57 | uint16_t hi_first_cluster; 58 | uint16_t last_modified_time; 59 | uint16_t last_modified_date; 60 | uint16_t lo_first_cluster; 61 | uint32_t filesize; 62 | 63 | }__attribute__((packed)) f32file_entry; 64 | 65 | typedef struct f32longname { 66 | uint8_t order; 67 | uint16_t name1[5]; 68 | uint8_t attribute; 69 | uint8_t long_type; 70 | uint8_t checksum; 71 | uint16_t name2[6]; 72 | uint16_t rsvd2; 73 | uint16_t name3[2]; 74 | }__attribute__((packed)) f32longname; 75 | 76 | class FAT32FS; 77 | 78 | typedef void* (*f32_entry_handler)(FAT32FS *instance, f32file_entry*, char *filename, char *seek); 79 | 80 | class FAT32FS { 81 | public: 82 | bool init(); 83 | void* read_file(char *path); 84 | string_list* list_contents(char *path); 85 | 86 | protected: 87 | void* read_full_file(uint32_t cluster_start, uint32_t cluster_size, uint32_t cluster_count, uint64_t file_size, uint32_t root_index); 88 | void read_FAT(uint32_t location, uint32_t size, uint8_t count); 89 | uint32_t count_FAT(uint32_t first); 90 | void* list_directory(uint32_t cluster_count, uint32_t root_index); 91 | void* walk_directory(uint32_t cluster_count, uint32_t root_index, char *seek, f32_entry_handler handler); 92 | void* read_cluster(uint32_t cluster_start, uint32_t cluster_size, uint32_t cluster_count, uint32_t root_index); 93 | char* advance_path(char *path); 94 | 95 | fat32_mbs* mbs; 96 | void *fs_page; 97 | uint32_t cluster_count; 98 | uint32_t data_start_sector; 99 | uint32_t* fat; 100 | uint32_t total_fat_entries; 101 | uint16_t bytes_per_sector; 102 | 103 | static void* read_entry_handler(FAT32FS *instance, f32file_entry *entry, char *filename, char *seek); 104 | static void* list_entries_handler(FAT32FS *instance, f32file_entry *entry, char *filename, char *seek); 105 | 106 | void parse_longnames(f32longname entries[], uint16_t count, char* out); 107 | void parse_shortnames(f32file_entry* entry, char* out); 108 | 109 | bool verbose = false; 110 | }; -------------------------------------------------------------------------------- /kernel/filesystem/sdhci.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "types.h" 4 | 5 | typedef struct sdhci_regs { 6 | uint32_t arg2; 7 | uint32_t blksize_count; 8 | uint32_t arg1; 9 | uint32_t cmd_transfmode; 10 | uint32_t resp0; 11 | uint32_t resp1; 12 | uint32_t resp2; 13 | uint32_t resp3; 14 | uint32_t data; 15 | uint32_t status; 16 | uint32_t ctrl0; 17 | uint32_t ctrl1; 18 | uint32_t interrupt; 19 | uint32_t irpt_mask; 20 | uint32_t irpt_en; 21 | uint32_t ctrl2; 22 | uint32_t __reserved[0x2F]; 23 | uint32_t slotisr_ver; 24 | } sdhci_regs; 25 | 26 | class SDHCI { 27 | public: 28 | bool init(); 29 | void write(void *buffer, uint32_t sector, uint32_t count); 30 | bool read(void *buffer, uint32_t sector, uint32_t count); 31 | void enable_verbose(); 32 | private: 33 | sdhci_regs* regs; 34 | bool issue_command(uint32_t cmd_index, uint32_t arg, uint32_t flags = 0); 35 | bool issue_app_command(uint32_t cmd, uint32_t arg, uint32_t flags = 0); 36 | bool setup_clock(); 37 | uint32_t clock_divider(uint32_t target_rate); 38 | bool switch_clock_rate(uint32_t target_rate); 39 | uint32_t clock_rate; 40 | uint32_t rca; 41 | bool verbose; 42 | }; -------------------------------------------------------------------------------- /kernel/filesystem/virtio_blk_pci.c: -------------------------------------------------------------------------------- 1 | #include "disk.h" 2 | #include "std/string.h" 3 | #include "memory/memory_access.h" 4 | #include "memory/page_allocator.h" 5 | #include "console/kio.h" 6 | #include "pci.h" 7 | #include "virtio/virtio_pci.h" 8 | #include "std/memfunctions.h" 9 | 10 | #define VIRTIO_BLK_T_IN 0 11 | #define VIRTIO_BLK_T_OUT 1 12 | 13 | struct virtio_blk_req { 14 | uint32_t type; 15 | uint32_t reserved; 16 | uint64_t sector; 17 | } __attribute__((packed)); 18 | 19 | struct virtio_blk_config { 20 | uint64_t capacity;//In number of sectors 21 | uint32_t size_max; 22 | uint32_t seg_max; 23 | struct { 24 | uint16_t cylinders; 25 | uint8_t heads; 26 | uint8_t sectors; 27 | } geometry; 28 | uint32_t blk_size; 29 | } __attribute__((packed)); 30 | 31 | #define VIRTIO_BLK_SUPPORTED_FEATURES \ 32 | ((1 << 0) | (1 << 1) | (1 << 4)) 33 | 34 | static bool blk_disk_enable_verbose; 35 | 36 | void vblk_disk_verbose(){ 37 | blk_disk_enable_verbose = true; 38 | virtio_enable_verbose(); 39 | } 40 | 41 | #define kprintfv(fmt, ...) \ 42 | ({ \ 43 | if (blk_disk_enable_verbose){\ 44 | uint64_t _args[] = { __VA_ARGS__ }; \ 45 | kprintf_args_raw((fmt), _args, sizeof(_args) / sizeof(_args[0])); \ 46 | }\ 47 | }) 48 | 49 | static virtio_device blk_dev; 50 | 51 | bool vblk_find_disk(){ 52 | uint64_t addr = find_pci_device(0x1AF4, 0x1001); 53 | if (!addr){ 54 | kprintf("Disk device not found"); 55 | return false; 56 | } 57 | 58 | pci_enable_device(addr); 59 | 60 | uint64_t disk_device_address, disk_device_size; 61 | 62 | virtio_get_capabilities(&blk_dev, addr, &disk_device_address, &disk_device_size); 63 | pci_register(disk_device_address, disk_device_size); 64 | if (!virtio_init_device(&blk_dev)) { 65 | kprintf("Failed disk initialization"); 66 | return false; 67 | } 68 | 69 | return true; 70 | } 71 | 72 | void vblk_write(const void *buffer, uint32_t sector, uint32_t count) { 73 | void* cmd = allocate_in_page(blk_dev.memory_page, sizeof(struct virtio_blk_req), ALIGN_64B, true, true); 74 | void* data = allocate_in_page(blk_dev.memory_page, count * 512, ALIGN_64B, true, true); 75 | 76 | memcpy(data, buffer, count * 512); 77 | 78 | struct virtio_blk_req *req = (struct virtio_blk_req *)(uintptr_t)cmd; 79 | req->type = VIRTIO_BLK_T_OUT; 80 | req->reserved = 0; 81 | req->sector = sector; 82 | 83 | virtio_send(&blk_dev, blk_dev.common_cfg->queue_desc, blk_dev.common_cfg->queue_driver, blk_dev.common_cfg->queue_device, 84 | (uintptr_t)cmd, sizeof(struct virtio_blk_req), (uintptr_t)data, count * 512, 0); 85 | 86 | free_from_page((void *)cmd,sizeof(struct virtio_blk_req)); 87 | free_from_page((void *)data,count * 512); 88 | } 89 | 90 | void vblk_read(void *buffer, uint32_t sector, uint32_t count) { 91 | void* cmd = allocate_in_page(blk_dev.memory_page, sizeof(struct virtio_blk_req), ALIGN_64B, true, true); 92 | void* data = allocate_in_page(blk_dev.memory_page, count * 512, ALIGN_64B, true, true); 93 | 94 | struct virtio_blk_req *req = (struct virtio_blk_req *)cmd; 95 | req->type = VIRTIO_BLK_T_IN; 96 | req->reserved = 0; 97 | req->sector = sector; 98 | 99 | virtio_send(&blk_dev, blk_dev.common_cfg->queue_desc, blk_dev.common_cfg->queue_driver, blk_dev.common_cfg->queue_device, (uintptr_t)cmd, sizeof(struct virtio_blk_req), (uintptr_t)data, count * 512, VIRTQ_DESC_F_WRITE); 100 | 101 | memcpy(buffer, (void *)(uintptr_t)data, count * 512); 102 | 103 | free_from_page((void *)cmd,sizeof(struct virtio_blk_req)); 104 | free_from_page((void *)data,count * 512); 105 | } -------------------------------------------------------------------------------- /kernel/filesystem/virtio_blk_pci.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "types.h" 4 | 5 | #ifdef __cplusplus 6 | extern "C" { 7 | #endif 8 | //TODO port to c++ 9 | bool vblk_find_disk(); 10 | void vblk_disk_verbose(); 11 | void vblk_write(const void *buffer, uint32_t sector, uint32_t count); 12 | void vblk_read(void *buffer, uint32_t sector, uint32_t count); 13 | #ifdef __cplusplus 14 | } 15 | #endif -------------------------------------------------------------------------------- /kernel/fw/fw_cfg.c: -------------------------------------------------------------------------------- 1 | #include "fw_cfg.h" 2 | #include "console/kio.h" 3 | #include "memory/memory_access.h" 4 | #include "kstring.h" 5 | 6 | #define FW_CFG_DATA 0x09020000 7 | #define FW_CFG_CTL (FW_CFG_DATA + 0x8) 8 | #define FW_CFG_DMA (FW_CFG_DATA + 0x10) 9 | 10 | #define FW_CFG_DMA_READ 0x2 11 | #define FW_CFG_DMA_SELECT 0x8 12 | #define FW_CFG_DMA_WRITE 0x10 13 | #define FW_CFG_DMA_ERROR 0x1 14 | 15 | #define FW_LIST_DIRECTORY 0x19 16 | 17 | 18 | static bool checked = false; 19 | 20 | struct fw_cfg_dma_access { 21 | uint32_t control; 22 | uint32_t length; 23 | uint64_t address; 24 | }__attribute__((packed)); 25 | 26 | bool fw_cfg_check(){ 27 | if (checked) return true; 28 | checked = read64(FW_CFG_DATA) == 0x554D4551; 29 | return checked; 30 | } 31 | 32 | void fw_cfg_dma_operation(void* dest, uint32_t size, uint32_t ctrl) { 33 | struct fw_cfg_dma_access access = { 34 | .address = __builtin_bswap64((uint64_t)dest), 35 | .length = __builtin_bswap32(size), 36 | .control = __builtin_bswap32(ctrl), 37 | }; 38 | 39 | write64(FW_CFG_DMA, __builtin_bswap64((uint64_t)&access)); 40 | 41 | __asm__("ISB"); 42 | 43 | while (__builtin_bswap32(access.control) & ~0x1) {} 44 | 45 | } 46 | 47 | void fw_cfg_dma_read(void* dest, uint32_t size, uint32_t ctrl){ 48 | if (!fw_cfg_check()) 49 | return; 50 | 51 | fw_cfg_dma_operation(dest, size, (ctrl << 16) | FW_CFG_DMA_SELECT | FW_CFG_DMA_READ); 52 | } 53 | 54 | void fw_cfg_dma_write(void* dest, uint32_t size, uint32_t ctrl){ 55 | if (!fw_cfg_check()) 56 | return; 57 | 58 | fw_cfg_dma_operation(dest, size, (ctrl << 16) | FW_CFG_DMA_SELECT | FW_CFG_DMA_WRITE); 59 | } 60 | 61 | bool fw_find_file(kstring search, struct fw_cfg_file *file) { 62 | 63 | if (!fw_cfg_check()) 64 | return false; 65 | 66 | uint32_t count; 67 | fw_cfg_dma_read(&count, sizeof(count), FW_LIST_DIRECTORY); 68 | 69 | count = __builtin_bswap32(count); 70 | 71 | for (uint32_t i = 0; i < count; i++) { 72 | 73 | fw_cfg_dma_operation(file, sizeof(struct fw_cfg_file), FW_CFG_DMA_READ); 74 | 75 | file->size = __builtin_bswap32(file->size); 76 | file->selector = __builtin_bswap16(file->selector); 77 | 78 | kstring filename = kstring_ca_max(file->name, 56); 79 | if (kstring_equals(filename, search)){ 80 | kprintf("Found device at selector %x", file->selector); 81 | return true; 82 | } 83 | } 84 | 85 | return false; 86 | } -------------------------------------------------------------------------------- /kernel/fw/fw_cfg.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #ifdef __cplusplus 4 | extern "C" { 5 | #endif 6 | 7 | #include "types.h" 8 | #include "kstring.h" 9 | 10 | struct fw_cfg_file { 11 | uint32_t size; 12 | uint16_t selector; 13 | uint16_t reserved; 14 | char name[56]; 15 | }__attribute__((packed)); 16 | 17 | bool fw_find_file(kstring search, struct fw_cfg_file *file); 18 | void fw_cfg_dma_write(void* dest, uint32_t size, uint32_t ctrl); 19 | void fw_cfg_dma_read(void* dest, uint32_t size, uint32_t ctrl); 20 | 21 | #ifdef __cplusplus 22 | } 23 | #endif -------------------------------------------------------------------------------- /kernel/gpio.c: -------------------------------------------------------------------------------- 1 | #include "gpio.h" 2 | #include "hw/hw.h" 3 | #include "async.h" 4 | #include "memory/memory_access.h" 5 | 6 | void reset_gpio(){ 7 | write32(GPIO_BASE + GPIO_PIN_BASE + 0x94, 0x0); 8 | delay(150); 9 | } 10 | 11 | void enable_gpio_pin(uint8_t pin){ 12 | uint32_t v = read32(GPIO_BASE + GPIO_PIN_BASE + 0x98); 13 | write32(GPIO_BASE + GPIO_PIN_BASE + 0x98, v | (1 << pin)); 14 | } -------------------------------------------------------------------------------- /kernel/gpio.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "types.h" 4 | 5 | void reset_gpio(); 6 | void enable_gpio_pin(uint8_t pin); -------------------------------------------------------------------------------- /kernel/graph/drivers/gpu_driver.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "types.h" 4 | #include "std/string.h" 5 | #include "ui/graphic_types.h" 6 | 7 | class GPUDriver { 8 | public: 9 | GPUDriver(){} 10 | virtual bool init(gpu_size preferred_screen_size) = 0; 11 | 12 | virtual void flush() = 0; 13 | 14 | virtual void clear(color color) = 0; 15 | virtual void draw_pixel(uint32_t x, uint32_t y, color color) = 0; 16 | virtual void fill_rect(uint32_t x, uint32_t y, uint32_t width, uint32_t height, color color) = 0; 17 | virtual void draw_line(uint32_t x0, uint32_t y0, uint32_t x1,uint32_t y1, color color) = 0; 18 | virtual void draw_char(uint32_t x, uint32_t y, char c, uint32_t scale, uint32_t color) = 0; 19 | virtual gpu_size get_screen_size() = 0; 20 | virtual void draw_string(string s, uint32_t x, uint32_t y, uint32_t scale, uint32_t color) = 0; 21 | virtual uint32_t get_char_size(uint32_t scale) = 0; 22 | 23 | virtual ~GPUDriver() = default; 24 | }; -------------------------------------------------------------------------------- /kernel/graph/drivers/ramfb_driver/ramfb.cpp: -------------------------------------------------------------------------------- 1 | #include "ramfb.hpp" 2 | #include "fw/fw_cfg.h" 3 | #include "memory/kalloc.h" 4 | #include "console/kio.h" 5 | #include "graph/font8x8_bridge.h" 6 | #include "ui/draw/draw.h" 7 | #include "memory/memory_access.h" 8 | #include "std/std.hpp" 9 | #include "std/memfunctions.h" 10 | 11 | typedef struct { 12 | uint64_t addr; 13 | uint32_t fourcc; 14 | uint32_t flags; 15 | uint32_t width; 16 | uint32_t height; 17 | uint32_t stride; 18 | }__attribute__((packed)) ramfb_structure; 19 | 20 | #define RGB_FORMAT_XRGB8888 ((uint32_t)('X') | ((uint32_t)('R') << 8) | ((uint32_t)('2') << 16) | ((uint32_t)('4') << 24)) 21 | 22 | #define bpp 4 23 | 24 | RamFBGPUDriver* RamFBGPUDriver::try_init(gpu_size preferred_screen_size){ 25 | RamFBGPUDriver* driver = new RamFBGPUDriver(); 26 | if (driver->init(preferred_screen_size)) 27 | return driver; 28 | delete driver; 29 | return nullptr; 30 | } 31 | 32 | bool RamFBGPUDriver::init(gpu_size preferred_screen_size){ 33 | screen_size = preferred_screen_size; 34 | 35 | stride = bpp * screen_size.width; 36 | 37 | fb_set_stride(stride); 38 | fb_set_bounds(screen_size.width,screen_size.height); 39 | 40 | struct fw_cfg_file file; 41 | fw_find_file(kstring_l("etc/ramfb"), &file); 42 | 43 | if (file.selector == 0x0){ 44 | kprintf("Ramfb not found"); 45 | return false; 46 | } 47 | 48 | framebuffer = talloc(screen_size.width * screen_size.height * bpp); 49 | back_framebuffer = talloc(screen_size.width * screen_size.height * bpp); 50 | 51 | ramfb_structure fb = { 52 | .addr = __builtin_bswap64(framebuffer), 53 | .fourcc = __builtin_bswap32(RGB_FORMAT_XRGB8888), 54 | .flags = __builtin_bswap32(0), 55 | .width = __builtin_bswap32(screen_size.width), 56 | .height = __builtin_bswap32(screen_size.height), 57 | .stride = __builtin_bswap32(stride), 58 | }; 59 | 60 | fw_cfg_dma_write(&fb, sizeof(fb), file.selector); 61 | 62 | kprintf("ramfb configured"); 63 | 64 | return true; 65 | } 66 | 67 | void RamFBGPUDriver::flush(){ 68 | if (full_redraw) { 69 | memcpy((void*)framebuffer, (void*)back_framebuffer, screen_size.width * screen_size.height * bpp); 70 | dirty_count = 0; 71 | full_redraw = false; 72 | return; 73 | } 74 | 75 | volatile uint32_t* fb = (volatile uint32_t*)framebuffer; 76 | volatile uint32_t* bfb = (volatile uint32_t*)back_framebuffer; 77 | 78 | for (uint32_t i = 0; i < dirty_count; i++) { 79 | gpu_rect r = dirty_rects[i]; 80 | 81 | for (uint32_t y = 0; y < r.size.height; y++) { 82 | uint32_t dest_y = r.point.y + y; 83 | if (dest_y >= screen_size.height) break; 84 | 85 | uint32_t* dst = (uint32_t*)&fb[dest_y * (stride / 4) + r.point.x]; 86 | uint32_t* src = (uint32_t*)&bfb[dest_y * (stride / 4) + r.point.x]; 87 | 88 | uint32_t copy_width = r.size.width; 89 | if (r.point.x + copy_width > screen_size.width) 90 | copy_width = screen_size.width - r.point.x; 91 | 92 | memcpy(dst, src, copy_width * sizeof(uint32_t)); 93 | } 94 | } 95 | 96 | full_redraw = false; 97 | dirty_count = 0; 98 | } 99 | 100 | void RamFBGPUDriver::clear(color color){ 101 | fb_clear((uint32_t*)back_framebuffer, color); 102 | } 103 | 104 | void RamFBGPUDriver::draw_pixel(uint32_t x, uint32_t y, color color){ 105 | fb_draw_pixel((uint32_t*)back_framebuffer, x, y, color); 106 | mark_dirty(x,y,1,1); 107 | } 108 | 109 | void RamFBGPUDriver::fill_rect(uint32_t x, uint32_t y, uint32_t width, uint32_t height, color color){ 110 | fb_fill_rect((uint32_t*)back_framebuffer, x, y, width, height, color); 111 | } 112 | 113 | void RamFBGPUDriver::draw_line(uint32_t x0, uint32_t y0, uint32_t x1,uint32_t y1, color color){ 114 | gpu_rect rect = fb_draw_line((uint32_t*)framebuffer, x0, y0, x1, y1, color); 115 | } 116 | 117 | void RamFBGPUDriver::draw_char(uint32_t x, uint32_t y, char c, uint32_t scale, uint32_t color){ 118 | fb_draw_char((uint32_t*)back_framebuffer, x, y, c, scale, color); 119 | } 120 | 121 | gpu_size RamFBGPUDriver::get_screen_size(){ 122 | return screen_size; 123 | } 124 | 125 | void RamFBGPUDriver::draw_string(string s, uint32_t x, uint32_t y, uint32_t scale, uint32_t color){ 126 | gpu_size drawn_string = fb_draw_string((uint32_t*)back_framebuffer, s, x, y, scale, color); 127 | } 128 | 129 | uint32_t RamFBGPUDriver::get_char_size(uint32_t scale){ 130 | return fb_get_char_size(scale); 131 | } -------------------------------------------------------------------------------- /kernel/graph/drivers/ramfb_driver/ramfb.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "../gpu_driver.hpp" 4 | 5 | class RamFBGPUDriver : public GPUDriver { 6 | public: 7 | static RamFBGPUDriver* try_init(gpu_size preferred_screen_size); 8 | RamFBGPUDriver(){} 9 | bool init(gpu_size preferred_screen_size) override; 10 | 11 | void flush() override; 12 | 13 | void clear(color color) override; 14 | void draw_pixel(uint32_t x, uint32_t y, color color) override; 15 | void fill_rect(uint32_t x, uint32_t y, uint32_t width, uint32_t height, color color) override; 16 | void draw_line(uint32_t x0, uint32_t y0, uint32_t x1,uint32_t y1, color color) override; 17 | void draw_char(uint32_t x, uint32_t y, char c, uint32_t scale, uint32_t color) override; 18 | gpu_size get_screen_size() override; 19 | void draw_string(string s, uint32_t x, uint32_t y, uint32_t scale, uint32_t color) override; 20 | uint32_t get_char_size(uint32_t scale) override; 21 | 22 | ~RamFBGPUDriver() = default; 23 | 24 | private: 25 | uintptr_t framebuffer; 26 | uintptr_t back_framebuffer; 27 | uint64_t framebuffer_size; 28 | gpu_size screen_size; 29 | uint32_t stride; 30 | }; -------------------------------------------------------------------------------- /kernel/graph/drivers/videocore/videocore.cpp: -------------------------------------------------------------------------------- 1 | #include "videocore.hpp" 2 | #include "fw/fw_cfg.h" 3 | #include "memory/kalloc.h" 4 | #include "console/kio.h" 5 | #include "graph/font8x8_bridge.h" 6 | #include "ui/draw/draw.h" 7 | #include "memory/memory_access.h" 8 | #include "std/std.hpp" 9 | #include "std/memfunctions.h" 10 | #include "mailbox/mailbox.h" 11 | #include "math/math.h" 12 | #include "memory/mmu.h" 13 | 14 | #define RGB_FORMAT_XRGB8888 ((uint32_t)('X') | ((uint32_t)('R') << 8) | ((uint32_t)('2') << 16) | ((uint32_t)('4') << 24)) 15 | 16 | VideoCoreGPUDriver* VideoCoreGPUDriver::try_init(gpu_size preferred_screen_size){ 17 | VideoCoreGPUDriver* driver = new VideoCoreGPUDriver(); 18 | if (driver->init(preferred_screen_size)) 19 | return driver; 20 | delete driver; 21 | return nullptr; 22 | } 23 | 24 | volatile uint32_t rmbox[36] __attribute__((aligned(16))) = { 25 | 25 * 4,// Buf size 26 | 0,// Request. Code 0 27 | 0x00048003, 8, 0, 640, 480,// Physical size 28 | 0x00048004, 8, 0, 0, 0,// Virtual size 29 | 0x00048005, 4, 0, 32,// Depth 30 | 0x00040008, 4, 0, 0,//Pitch 31 | 0x00048006, 4, 0, 0, //BGR 32 | 0,// End 33 | };//TODO: Screen resolution seems fixed at 640x480 (on QEMU at least). Setting it to anything else hangs the system 34 | 35 | volatile uint32_t fb_mbox[36] __attribute__((aligned(16))) = { 36 | 32, 0, 37 | 0x00040001, 8, 0, 16, 0, 38 | 0 39 | }; 40 | 41 | bool VideoCoreGPUDriver::init(gpu_size preferred_screen_size){ 42 | kprintf("Initializing VideoCore GPU"); 43 | if (mailbox_call(rmbox, 8)) { 44 | uint32_t phys_w = rmbox[5]; 45 | uint32_t phys_h = rmbox[6]; 46 | uint32_t virt_w = rmbox[10]; 47 | uint32_t virt_h = rmbox[11]; 48 | uint32_t depth = rmbox[15]; 49 | stride = rmbox[19]; 50 | 51 | bpp = depth/8; 52 | 53 | screen_size = (gpu_size){phys_w,phys_h}; 54 | kprintf("Size %ix%i (%ix%i) (%ix%i) | %i (%i)",phys_w,phys_h,virt_w,virt_h,screen_size.width,screen_size.height,depth, stride); 55 | 56 | fb_set_stride(bpp * screen_size.width); 57 | fb_set_bounds(screen_size.width,screen_size.height); 58 | if (!mailbox_call(fb_mbox, 8)){ 59 | kprintf("Error"); 60 | return false; 61 | } 62 | framebuffer = fb_mbox[5]; 63 | size_t fb_size = fb_mbox[6]; 64 | page = alloc_page(0x1000, true, true, false); 65 | back_framebuffer = (uintptr_t)allocate_in_page(page, fb_size, ALIGN_16B, true, true); 66 | kprintf("Framebuffer allocated to %x. BPP %i. Stride %i",framebuffer, bpp, stride/bpp); 67 | //TODO: Mark the fb memory as used in the page allocator manually 68 | for (size_t i = framebuffer; i < framebuffer + fb_size; i += GRANULE_4KB) 69 | register_device_memory(i,i); 70 | return true; 71 | } 72 | return false; 73 | } 74 | 75 | void VideoCoreGPUDriver::flush(){ 76 | if (full_redraw) { 77 | memcpy((void*)framebuffer, (void*)back_framebuffer, screen_size.width * screen_size.height * bpp); 78 | dirty_count = 0; 79 | full_redraw = false; 80 | return; 81 | } 82 | 83 | volatile uint32_t* fb = (volatile uint32_t*)framebuffer; 84 | volatile uint32_t* bfb = (volatile uint32_t*)back_framebuffer; 85 | 86 | for (uint32_t i = 0; i < dirty_count; i++) { 87 | gpu_rect r = dirty_rects[i]; 88 | 89 | for (uint32_t y = 0; y < r.size.height; y++) { 90 | uint32_t dest_y = r.point.y + y; 91 | if (dest_y >= screen_size.height) break; 92 | 93 | uint32_t* dst = (uint32_t*)&fb[dest_y * (stride / 4) + r.point.x]; 94 | uint32_t* src = (uint32_t*)&bfb[dest_y * (stride / 4) + r.point.x]; 95 | 96 | uint32_t copy_width = r.size.width; 97 | if (r.point.x + copy_width > screen_size.width) 98 | copy_width = screen_size.width - r.point.x; 99 | 100 | memcpy(dst, src, copy_width * sizeof(uint32_t)); 101 | } 102 | } 103 | 104 | full_redraw = false; 105 | dirty_count = 0; 106 | } 107 | 108 | void VideoCoreGPUDriver::clear(color color){ 109 | fb_clear((uint32_t*)back_framebuffer, color); 110 | } 111 | 112 | void VideoCoreGPUDriver::draw_pixel(uint32_t x, uint32_t y, color color){ 113 | fb_draw_pixel((uint32_t*)back_framebuffer, x, y, color); 114 | mark_dirty(x,y,1,1); 115 | } 116 | 117 | void VideoCoreGPUDriver::fill_rect(uint32_t x, uint32_t y, uint32_t width, uint32_t height, color color){ 118 | fb_fill_rect((uint32_t*)back_framebuffer, x, y, width, height, color); 119 | } 120 | 121 | void VideoCoreGPUDriver::draw_line(uint32_t x0, uint32_t y0, uint32_t x1,uint32_t y1, color color){ 122 | fb_draw_line((uint32_t*)back_framebuffer, x0, y0, x1, y1, color); 123 | } 124 | 125 | void VideoCoreGPUDriver::draw_char(uint32_t x, uint32_t y, char c, uint32_t scale, uint32_t color){ 126 | fb_draw_char((uint32_t*)back_framebuffer, x, y, c, scale, color); 127 | } 128 | 129 | gpu_size VideoCoreGPUDriver::get_screen_size(){ 130 | return screen_size; 131 | } 132 | 133 | void VideoCoreGPUDriver::draw_string(string s, uint32_t x, uint32_t y, uint32_t scale, uint32_t color){ 134 | fb_draw_string((uint32_t*)back_framebuffer, s, x, y, scale, color); 135 | } 136 | 137 | uint32_t VideoCoreGPUDriver::get_char_size(uint32_t scale){ 138 | return fb_get_char_size(max(1,scale-1));//TODO: Screen resolution seems fixed at 640x480 (on QEMU at least). So we make the font smaller 139 | } -------------------------------------------------------------------------------- /kernel/graph/drivers/videocore/videocore.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "../gpu_driver.hpp" 4 | 5 | class VideoCoreGPUDriver : public GPUDriver { 6 | public: 7 | static VideoCoreGPUDriver* try_init(gpu_size preferred_screen_size); 8 | VideoCoreGPUDriver(){} 9 | bool init(gpu_size preferred_screen_size) override; 10 | 11 | void flush() override; 12 | 13 | void clear(color color) override; 14 | void draw_pixel(uint32_t x, uint32_t y, color color) override; 15 | void fill_rect(uint32_t x, uint32_t y, uint32_t width, uint32_t height, color color) override; 16 | void draw_line(uint32_t x0, uint32_t y0, uint32_t x1,uint32_t y1, color color) override; 17 | void draw_char(uint32_t x, uint32_t y, char c, uint32_t scale, uint32_t color) override; 18 | gpu_size get_screen_size() override; 19 | void draw_string(string s, uint32_t x, uint32_t y, uint32_t scale, uint32_t color) override; 20 | uint32_t get_char_size(uint32_t scale) override; 21 | ~VideoCoreGPUDriver() = default; 22 | 23 | private: 24 | gpu_size screen_size; 25 | uintptr_t framebuffer; 26 | uintptr_t back_framebuffer; 27 | 28 | void* page; 29 | 30 | uint8_t bpp; 31 | uint32_t stride; 32 | }; -------------------------------------------------------------------------------- /kernel/graph/drivers/virtio_gpu_pci/virtio_gpu_pci.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "virtio/virtio_pci.h" 4 | #include "../gpu_driver.hpp" 5 | 6 | class VirtioGPUDriver : public GPUDriver { 7 | public: 8 | static VirtioGPUDriver* try_init(gpu_size preferred_screen_size); 9 | VirtioGPUDriver(){} 10 | bool init(gpu_size preferred_screen_size) override; 11 | 12 | void flush() override; 13 | 14 | void clear(color color) override; 15 | void draw_pixel(uint32_t x, uint32_t y, color color) override; 16 | void fill_rect(uint32_t x, uint32_t y, uint32_t width, uint32_t height, color color) override; 17 | void draw_line(uint32_t x0, uint32_t y0, uint32_t x1,uint32_t y1, color color) override; 18 | void draw_char(uint32_t x, uint32_t y, char c, uint32_t scale, uint32_t color) override; 19 | gpu_size get_screen_size() override; 20 | void draw_string(string s, uint32_t x, uint32_t y, uint32_t scale, uint32_t color) override; 21 | uint32_t get_char_size(uint32_t scale) override; 22 | ~VirtioGPUDriver() = default; 23 | 24 | private: 25 | gpu_size screen_size; 26 | virtio_device gpu_dev; 27 | uintptr_t framebuffer; 28 | uint64_t framebuffer_size; 29 | 30 | gpu_size get_display_info(); 31 | bool create_2d_resource(gpu_size size); 32 | bool attach_backing(); 33 | bool set_scanout(); 34 | bool transfer_to_host(gpu_rect rect); 35 | 36 | bool scanout_found; 37 | uint64_t scanout_id; 38 | }; -------------------------------------------------------------------------------- /kernel/graph/font8x8_basic.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "types.h" 4 | 5 | static const uint8_t font8x8_basic[128][8] = { 6 | [' '] = {0,0,0,0,0,0,0,0}, 7 | ['!'] = {0x18,0x18,0x18,0x18,0x00,0x18,0x00,0x00}, 8 | ['"'] = {0x6c,0x6c,0x48,0x00,0x00,0x00,0x00,0x00}, 9 | ['#'] = {0x6c,0x6c,0xfe,0x6c,0xfe,0x6c,0x6c,0x00}, 10 | ['$'] = {0x18,0x3e,0x58,0x3c,0x1a,0x7c,0x18,0x00}, 11 | ['%'] = {0x00,0xc6,0xcc,0x18,0x30,0x66,0xc6,0x00}, 12 | ['&'] = {0x38,0x6c,0x38,0x76,0xdc,0xcc,0x76,0x00}, 13 | ['\''] = {0x30,0x30,0x60,0x00,0x00,0x00,0x00,0x00}, 14 | ['('] = {0x0c,0x18,0x30,0x30,0x30,0x18,0x0c,0x00}, 15 | [')'] = {0x30,0x18,0x0c,0x0c,0x0c,0x18,0x30,0x00}, 16 | ['*'] = {0x00,0x66,0x3c,0xff,0x3c,0x66,0x00,0x00}, 17 | ['+'] = {0x00,0x18,0x18,0x7e,0x18,0x18,0x00,0x00}, 18 | [','] = {0x00,0x00,0x00,0x00,0x30,0x30,0x60,0x00}, 19 | ['-'] = {0x00,0x00,0x00,0x7e,0x00,0x00,0x00,0x00}, 20 | ['.'] = {0x00,0x00,0x00,0x00,0x00,0x30,0x30,0x00}, 21 | ['/'] = {0x06,0x0c,0x18,0x30,0x60,0xc0,0x80,0x00}, 22 | ['0'] = {0x7c,0xc6,0xce,0xd6,0xe6,0xc6,0x7c,0x00}, 23 | ['1'] = {0x18,0x38,0x18,0x18,0x18,0x18,0x7e,0x00}, 24 | ['2'] = {0x7c,0xc6,0x0e,0x1c,0x70,0xc0,0xfe,0x00}, 25 | ['3'] = {0x7c,0xc6,0x06,0x3c,0x06,0xc6,0x7c,0x00}, 26 | ['4'] = {0x1c,0x3c,0x6c,0xcc,0xfe,0x0c,0x1e,0x00}, 27 | ['5'] = {0xfe,0xc0,0xfc,0x06,0x06,0xc6,0x7c,0x00}, 28 | ['6'] = {0x38,0x60,0xc0,0xfc,0xc6,0xc6,0x7c,0x00}, 29 | ['7'] = {0xfe,0xc6,0x0c,0x18,0x30,0x30,0x30,0x00}, 30 | ['8'] = {0x7c,0xc6,0xc6,0x7c,0xc6,0xc6,0x7c,0x00}, 31 | ['9'] = {0x7c,0xc6,0xc6,0x7e,0x06,0x0c,0x78,0x00}, 32 | [':'] = {0x00,0x30,0x30,0x00,0x00,0x30,0x30,0x00}, 33 | [';'] = {0x00,0x30,0x30,0x00,0x00,0x30,0x30,0x60}, 34 | ['<'] = {0x0c,0x18,0x30,0x60,0x30,0x18,0x0c,0x00}, 35 | ['='] = {0x00,0x00,0x7e,0x00,0x7e,0x00,0x00,0x00}, 36 | ['>'] = {0x30,0x18,0x0c,0x06,0x0c,0x18,0x30,0x00}, 37 | ['?'] = {0x7c,0xc6,0x0c,0x18,0x18,0x00,0x18,0x00}, 38 | ['@'] = {0x7c,0xc6,0xde,0xde,0xde,0xc0,0x78,0x00}, 39 | 40 | ['A'] = {0x38,0x6c,0xc6,0xfe,0xc6,0xc6,0xc6,0x00}, 41 | ['B'] = {0xfc,0x66,0x66,0x7c,0x66,0x66,0xfc,0x00}, 42 | ['C'] = {0x3c,0x66,0xc0,0xc0,0xc0,0x66,0x3c,0x00}, 43 | ['D'] = {0xf8,0x6c,0x66,0x66,0x66,0x6c,0xf8,0x00}, 44 | ['E'] = {0xfe,0x62,0x68,0x78,0x68,0x62,0xfe,0x00}, 45 | ['F'] = {0xfe,0x62,0x68,0x78,0x68,0x60,0xf0,0x00}, 46 | ['G'] = {0x3c,0x66,0xc0,0xde,0xc6,0x66,0x3e,0x00}, 47 | ['H'] = {0xc6,0xc6,0xc6,0xfe,0xc6,0xc6,0xc6,0x00}, 48 | ['I'] = {0x7e,0x18,0x18,0x18,0x18,0x18,0x7e,0x00}, 49 | ['J'] = {0x1e,0x0c,0x0c,0x0c,0xcc,0xcc,0x78,0x00}, 50 | ['K'] = {0xe6,0x66,0x6c,0x78,0x6c,0x66,0xe6,0x00}, 51 | ['L'] = {0xf0,0x60,0x60,0x60,0x62,0x66,0xfe,0x00}, 52 | ['M'] = {0xc6,0xee,0xfe,0xfe,0xd6,0xc6,0xc6,0x00}, 53 | ['N'] = {0xc6,0xe6,0xf6,0xde,0xce,0xc6,0xc6,0x00}, 54 | ['O'] = {0x7c,0xc6,0xc6,0xc6,0xc6,0xc6,0x7c,0x00}, 55 | ['P'] = {0x7C, 0x62, 0x62, 0x7C, 0x60, 0x60, 0x60, 0x00}, 56 | ['Q'] = {0x7C, 0x62, 0x62, 0x62, 0x7C, 0x06, 0x06, 0x00}, 57 | ['R'] = {0x7C, 0x62, 0x62, 0x7C, 0x6C, 0x66, 0x62, 0x00}, 58 | ['S'] = {0x3C, 0x62, 0x60, 0x3C, 0x06, 0x62, 0x3C, 0x00}, 59 | ['T'] = {0x7E, 0x5A, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00}, 60 | ['U'] = {0x62, 0x62, 0x62, 0x62, 0x62, 0x62, 0x3C, 0x00}, 61 | ['V'] = {0x62, 0x62, 0x62, 0x62, 0x62, 0x3C, 0x18, 0x00}, 62 | ['W'] = {0x62, 0x62, 0x62, 0x6A, 0x6A, 0x7E, 0x24, 0x00}, 63 | ['X'] = {0x62, 0x62, 0x34, 0x18, 0x34, 0x62, 0x62, 0x00}, 64 | ['Y'] = {0x66, 0x66, 0x66, 0x3C, 0x18, 0x18, 0x18, 0x00}, 65 | ['Z'] = {0x7E, 0x06, 0x0C, 0x18, 0x30, 0x60, 0x7E, 0x00}, 66 | 67 | ['a'] = {0x00, 0x00, 0x3C, 0x06, 0x3E, 0x66, 0x3E, 0x00}, 68 | ['b'] = {0x60, 0x60, 0x7C, 0x66, 0x66, 0x66, 0x7C, 0x00}, 69 | ['c'] = {0x00, 0x00, 0x3C, 0x66, 0x60, 0x66, 0x3C, 0x00}, 70 | ['d'] = {0x06, 0x06, 0x3E, 0x66, 0x66, 0x66, 0x3E, 0x00}, 71 | ['e'] = {0x00, 0x00, 0x3C, 0x66, 0x7E, 0x60, 0x3C, 0x00}, 72 | ['f'] = {0x0E, 0x18, 0x3E, 0x18, 0x18, 0x18, 0x18, 0x00}, 73 | ['g'] = {0x00, 0x00, 0x3E, 0x66, 0x66, 0x3E, 0x06, 0x3C}, 74 | ['h'] = {0x60, 0x60, 0x7C, 0x66, 0x66, 0x66, 0x66, 0x00}, 75 | ['i'] = {0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x3C, 0x00}, 76 | ['j'] = {0x0C, 0x00, 0x0C, 0x0C, 0x0C, 0x6C, 0x6C, 0x38}, 77 | ['k'] = {0x60, 0x60, 0x66, 0x6C, 0x78, 0x6C, 0x66, 0x00}, 78 | ['l'] = {0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3C, 0x00}, 79 | ['m'] = {0x00, 0x00, 0x6C, 0x7E, 0x7E, 0x6C, 0x6C, 0x00}, 80 | ['n'] = {0x00, 0x00, 0x7C, 0x66, 0x66, 0x66, 0x66, 0x00}, 81 | ['o'] = {0x00, 0x00, 0x3C, 0x66, 0x66, 0x66, 0x3C, 0x00}, 82 | ['p'] = {0x00, 0x00, 0x7C, 0x66, 0x66, 0x7C, 0x60, 0x60}, 83 | ['q'] = {0x00, 0x00, 0x3E, 0x66, 0x66, 0x3E, 0x06, 0x06}, 84 | ['r'] = {0x00, 0x00, 0x6C, 0x76, 0x60, 0x60, 0x60, 0x00}, 85 | ['s'] = {0x00, 0x00, 0x3E, 0x60, 0x3C, 0x06, 0x7C, 0x00}, 86 | ['t'] = {0x10, 0x30, 0x7C, 0x30, 0x30, 0x30, 0x1C, 0x00}, 87 | ['u'] = {0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x3E, 0x00}, 88 | ['v'] = {0x00, 0x00, 0x66, 0x66, 0x66, 0x3C, 0x18, 0x00}, 89 | ['w'] = {0x00, 0x00, 0x6C, 0x6C, 0x7E, 0x7E, 0x24, 0x00}, 90 | ['x'] = {0x00, 0x00, 0x66, 0x3C, 0x18, 0x3C, 0x66, 0x00}, 91 | ['y'] = {0x00, 0x00, 0x66, 0x66, 0x66, 0x3E, 0x06, 0x3C}, 92 | ['z'] = {0x00, 0x00, 0x7E, 0x0C, 0x18, 0x30, 0x7E, 0x00}, 93 | 94 | ['['] = {0x1c,0x18,0x18,0x18,0x18,0x18,0x1c,0x00}, 95 | ['\\'] = {0xc0,0x60,0x30,0x18,0x0c,0x06,0x02,0x00}, 96 | [']'] = {0x38,0x18,0x18,0x18,0x18,0x18,0x38,0x00}, 97 | ['^'] = {0x10,0x38,0x6c,0xc6,0x00,0x00,0x00,0x00}, 98 | ['_'] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff}, 99 | ['`'] = {0x30,0x18,0x0c,0x00,0x00,0x00,0x00,0x00}, 100 | ['{'] = {0x0e,0x0c,0x0c,0x38,0x0c,0x0c,0x0e,0x00}, 101 | ['|'] = {0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x00}, 102 | ['}'] = {0x70,0x30,0x30,0x1c,0x30,0x30,0x70,0x00}, 103 | ['~'] = {0x76,0xdc,0x00,0x00,0x00,0x00,0x00,0x00}, 104 | }; 105 | -------------------------------------------------------------------------------- /kernel/graph/font8x8_bridge.c: -------------------------------------------------------------------------------- 1 | #include "font8x8_basic.h" 2 | #include "font8x8_bridge.h" 3 | 4 | const uint8_t* get_font8x8(uint8_t c) { 5 | return font8x8_basic[c]; 6 | } -------------------------------------------------------------------------------- /kernel/graph/font8x8_bridge.h: -------------------------------------------------------------------------------- 1 | #ifdef __cplusplus 2 | extern "C" { 3 | #endif 4 | #include "types.h" 5 | 6 | const uint8_t* get_font8x8(uint8_t c); 7 | 8 | #ifdef __cplusplus 9 | } 10 | #endif -------------------------------------------------------------------------------- /kernel/graph/graphics.cpp: -------------------------------------------------------------------------------- 1 | #include "graphics.h" 2 | #include "console/kio.h" 3 | 4 | #include "drivers/virtio_gpu_pci/virtio_gpu_pci.hpp" 5 | #include "drivers/ramfb_driver/ramfb.hpp" 6 | #include "drivers/videocore/videocore.hpp" 7 | 8 | #include "std/std.hpp" 9 | #include "hw/hw.h" 10 | 11 | static gpu_size screen_size; 12 | static bool _gpu_ready; 13 | 14 | GPUDriver *gpu_driver; 15 | 16 | void gpu_init(gpu_size preferred_screen_size){ 17 | if (VirtioGPUDriver *vgd = VirtioGPUDriver::try_init(preferred_screen_size)){ 18 | gpu_driver = vgd; 19 | } else if (RamFBGPUDriver *rfb = RamFBGPUDriver::try_init(preferred_screen_size)){ 20 | gpu_driver = rfb; 21 | } else if (BOARD_TYPE == 2){ 22 | gpu_driver = VideoCoreGPUDriver::try_init(preferred_screen_size); 23 | } 24 | screen_size = preferred_screen_size; 25 | _gpu_ready = true; 26 | kprintf("Selected and initialized GPU %x", (uintptr_t)gpu_driver); 27 | } 28 | 29 | bool gpu_ready(){ 30 | return gpu_driver != nullptr && _gpu_ready; 31 | } 32 | 33 | void gpu_flush(){ 34 | if (!gpu_ready()) 35 | return; 36 | gpu_driver->flush(); 37 | } 38 | void gpu_clear(color color){ 39 | if (!gpu_ready()) 40 | return; 41 | gpu_driver->clear(color); 42 | } 43 | 44 | void gpu_draw_pixel(gpu_point p, color color){ 45 | if (!gpu_ready()) 46 | return; 47 | gpu_driver->draw_pixel(p.x,p.y,color); 48 | } 49 | 50 | void gpu_fill_rect(gpu_rect r, color color){ 51 | if (!gpu_ready()) 52 | return; 53 | gpu_driver->fill_rect(r.point.x,r.point.y,r.size.width,r.size.height,color); 54 | } 55 | 56 | void gpu_draw_line(gpu_point p0, gpu_point p1, uint32_t color){ 57 | if (!gpu_ready()) 58 | return; 59 | gpu_driver->draw_line(p0.x,p0.y,p1.x,p1.y,color); 60 | } 61 | void gpu_draw_char(gpu_point p, char c, uint32_t scale, uint32_t color){ 62 | if (!gpu_ready()) 63 | return; 64 | gpu_driver->draw_char(p.x,p.y,c,scale,color); 65 | } 66 | 67 | void gpu_draw_string(string s, gpu_point p, uint32_t scale, uint32_t color){ 68 | if (!gpu_ready()) 69 | return; 70 | gpu_driver->draw_string(s, p.x, p.y, scale, color); 71 | } 72 | 73 | uint32_t gpu_get_char_size(uint32_t scale){ 74 | if (!gpu_ready()) 75 | return 0; 76 | return gpu_driver->get_char_size(scale); 77 | } 78 | 79 | gpu_size gpu_get_screen_size(){ 80 | if (!gpu_ready()) 81 | return (gpu_size){0,0}; 82 | return gpu_driver->get_screen_size(); 83 | } -------------------------------------------------------------------------------- /kernel/graph/graphics.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #ifdef __cplusplus 4 | extern "C" { 5 | #endif 6 | 7 | #include "types.h" 8 | #include "ui/graphic_types.h" 9 | #include "std/string.h" 10 | 11 | void gpu_init(gpu_size preferred_screen_size); 12 | bool gpu_ready(); 13 | 14 | void gpu_flush(); 15 | 16 | void gpu_clear(color color); 17 | void gpu_draw_pixel(gpu_point p, color color); 18 | void gpu_fill_rect(gpu_rect r, color color); 19 | void gpu_draw_line(gpu_point p0, gpu_point p1, color color); 20 | void gpu_draw_char(gpu_point p, char c, uint32_t scale, uint32_t color); 21 | gpu_size gpu_get_screen_size(); 22 | void gpu_draw_string(string s, gpu_point p, uint32_t scale, uint32_t color); 23 | uint32_t gpu_get_char_size(uint32_t scale); 24 | 25 | #ifdef __cplusplus 26 | } 27 | #endif -------------------------------------------------------------------------------- /kernel/hw/hw.c: -------------------------------------------------------------------------------- 1 | #include "hw.h" 2 | #include "console/kio.h" 3 | #include "gpio.h" 4 | 5 | uint8_t BOARD_TYPE; 6 | uint8_t USE_DTB = 0; 7 | uint8_t USE_PCI = 0; 8 | uintptr_t RAM_START = 0; 9 | uintptr_t RAM_SIZE = 0; 10 | uintptr_t CRAM_START = 0; 11 | uintptr_t CRAM_END = 0; 12 | uintptr_t UART0_BASE = 0; 13 | uintptr_t XHCI_BASE = 0; 14 | uintptr_t MMIO_BASE = 0; 15 | uintptr_t GICD_BASE = 0; 16 | uintptr_t GICC_BASE = 0; 17 | uintptr_t SDHCI_BASE = 0; 18 | 19 | uint8_t RPI_BOARD; 20 | uint8_t GPIO_BASE; 21 | uint8_t GPIO_PIN_BASE; 22 | 23 | void detect_hardware(){ 24 | if (BOARD_TYPE == 1){ 25 | UART0_BASE = 0x9000000; 26 | MMIO_BASE = 0x10010000; 27 | CRAM_END = 0x60000000; 28 | RAM_START = 0x40000000; 29 | CRAM_START = 0x43600000; 30 | USE_PCI = 1; 31 | GICD_BASE = 0x08000000; 32 | GICC_BASE = 0x08010000; 33 | 34 | } else { 35 | uint32_t reg; 36 | asm volatile ("mrs %x0, midr_el1" : "=r" (reg)); 37 | uint32_t raspi = (reg >> 4) & 0xFFF; 38 | switch (raspi) { 39 | case 0xD08: //4B. Cortex A72 40 | MMIO_BASE = 0xFE000000; 41 | RPI_BOARD = 4; 42 | GPIO_PIN_BASE = 0x50; 43 | break; 44 | case 0xD0B: //5. Cortex A76 45 | MMIO_BASE = 0x107C000000UL; 46 | RPI_BOARD = 5; 47 | GPIO_PIN_BASE = 0x50; 48 | break; 49 | default: MMIO_BASE = 0x3F000000; break; 50 | } 51 | GPIO_BASE = MMIO_BASE + 0x200000; 52 | GICD_BASE = MMIO_BASE + 0x1841000; 53 | GICC_BASE = MMIO_BASE + 0x1842000; 54 | UART0_BASE = MMIO_BASE + 0x201000; 55 | SDHCI_BASE = MMIO_BASE + 0x300000; 56 | XHCI_BASE = MMIO_BASE + 0x9C0000; 57 | RAM_START = 0x10000000; 58 | CRAM_END = (MMIO_BASE - 0x10000000) & 0xF0000000; 59 | RAM_START = 0x10000000; 60 | CRAM_START = 0x13600000; 61 | reset_gpio(); 62 | } 63 | } 64 | 65 | void print_hardware(){ 66 | kprintf("Board type %i",BOARD_TYPE); 67 | } -------------------------------------------------------------------------------- /kernel/hw/hw.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | // #include "elfvirt.h" 4 | #include "types.h" 5 | 6 | extern uint8_t BOARD_TYPE; 7 | 8 | extern uint8_t USE_DTB; 9 | extern uint8_t USE_PCI; 10 | 11 | extern uintptr_t RAM_START; 12 | extern uintptr_t RAM_SIZE; 13 | extern uintptr_t CRAM_START; 14 | extern uintptr_t CRAM_END; 15 | 16 | extern uintptr_t UART0_BASE; 17 | extern uintptr_t XHCI_BASE; 18 | 19 | extern uintptr_t MMIO_BASE; 20 | 21 | extern uintptr_t GICD_BASE; 22 | extern uintptr_t GICC_BASE; 23 | 24 | extern uintptr_t SDHCI_BASE; 25 | 26 | extern uint8_t GPIO_BASE; 27 | 28 | extern uint8_t GPIO_PIN_BASE; 29 | 30 | extern uint8_t RPI_BOARD; 31 | 32 | void detect_hardware(); 33 | void print_hardware(); -------------------------------------------------------------------------------- /kernel/input/USBDevice.cpp: -------------------------------------------------------------------------------- 1 | #include "USBDevice.hpp" 2 | #include "USBKeyboard.hpp" 3 | #include "xhci_types.h" 4 | #include "console/kio.h" 5 | 6 | USBDevice::USBDevice(uint32_t capacity, uint8_t address) : address(address) { 7 | endpoints = IndexMap(capacity); 8 | }; 9 | 10 | void USBDevice::request_data(uint8_t endpoint_id, USBDriver *driver){ 11 | if (endpoint_id >= endpoints.max_size()) return;//TODO: check if it exists 12 | USBEndpoint *ep = endpoints[endpoint_id]; 13 | if (ep) 14 | ep->request_data(driver); 15 | } 16 | 17 | void USBDevice::process_data(uint8_t endpoint_id, USBDriver *driver){ 18 | if (endpoint_id >= endpoints.max_size()) return;//TODO: check if it exists 19 | USBEndpoint *ep = endpoints[endpoint_id]; 20 | if (ep) 21 | ep->process_data(driver); 22 | } 23 | 24 | void USBDevice::register_endpoint(uint8_t endpoint, xhci_device_types type, uint16_t packet_size){ 25 | if (endpoint >= endpoints.max_size()) return; 26 | USBEndpoint *newendpoint; 27 | switch (type){ 28 | case KEYBOARD: 29 | newendpoint = new USBKeyboard(address, endpoint, packet_size); 30 | break; 31 | default: return; 32 | } 33 | if (!newendpoint) return; 34 | endpoints.add(endpoint,newendpoint); 35 | } 36 | 37 | void USBDevice::poll_inputs(USBDriver *driver){ 38 | for (uint8_t i = 0; i < endpoints.max_size(); i++){ 39 | USBEndpoint *ep = endpoints[i]; 40 | if (ep && ep->type == KEYBOARD) 41 | ep->request_data(driver); 42 | } 43 | } -------------------------------------------------------------------------------- /kernel/input/USBDevice.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "types.h" 3 | #include "xhci_types.h" 4 | #include "std/std.hpp" 5 | #include "console/kio.h" 6 | 7 | class USBDriver; 8 | 9 | class USBEndpoint { 10 | public: 11 | USBEndpoint(uint8_t endpoint, xhci_device_types type, uint16_t packet_size): endpoint(endpoint), type(type), packet_size(packet_size) { } 12 | virtual void request_data(USBDriver *driver) = 0; 13 | 14 | virtual void process_data(USBDriver *driver) = 0; 15 | 16 | uint8_t endpoint; 17 | xhci_device_types type; 18 | uint16_t packet_size; 19 | }; 20 | 21 | class USBDevice { 22 | public: 23 | USBDevice(uint32_t capacity, uint8_t address); 24 | void request_data(uint8_t endpoint_id, USBDriver *driver); 25 | 26 | void process_data(uint8_t endpoint_id, USBDriver *driver); 27 | 28 | void register_endpoint(uint8_t endpoint, xhci_device_types type, uint16_t packet_size); 29 | 30 | void poll_inputs(USBDriver *driver); 31 | 32 | IndexMap endpoints; 33 | uint8_t address; 34 | }; -------------------------------------------------------------------------------- /kernel/input/USBKeyboard.cpp: -------------------------------------------------------------------------------- 1 | #include "USBKeyboard.hpp" 2 | #include "input_dispatch.h" 3 | #include "console/kio.h" 4 | #include "memory/page_allocator.h" 5 | #include "usb.hpp" 6 | 7 | void USBKeyboard::request_data(USBDriver *driver){ 8 | requesting = true; 9 | 10 | if (buffer == 0){ 11 | buffer = alloc_page(packet_size, true, true, true); 12 | } 13 | 14 | if (!driver->poll(slot_id, endpoint, buffer, packet_size)){ 15 | 16 | return; 17 | } 18 | 19 | if (!driver->use_interrupts){ 20 | process_keypress((keypress*)buffer); 21 | return; 22 | } 23 | } 24 | 25 | void USBKeyboard::process_data(USBDriver *driver){ 26 | if (!requesting){ 27 | return; 28 | } 29 | 30 | process_keypress((keypress*)buffer); 31 | 32 | request_data(driver); 33 | } 34 | 35 | void USBKeyboard::process_keypress(keypress *rkp){ 36 | keypress kp; 37 | if (is_new_keypress(rkp, &last_keypress) || repeated_keypresses > 3){ 38 | if (is_new_keypress(rkp, &last_keypress)) 39 | repeated_keypresses = 0; 40 | kp.modifier = rkp->modifier; 41 | // kprintf_raw("Mod: %i", kp.modifier); 42 | for (int i = 0; i < 6; i++){ 43 | kp.keys[i] = rkp->keys[i]; 44 | // kprintf_raw("Key [%i]: %i", i, kp.keys[i]); 45 | } 46 | last_keypress = kp; 47 | register_keypress(kp); 48 | } else 49 | repeated_keypresses++; 50 | } -------------------------------------------------------------------------------- /kernel/input/USBKeyboard.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "types.h" 4 | #include "USBDevice.hpp" 5 | #include "keypress.h" 6 | #include "xhci_types.h" 7 | 8 | class USBKeyboard: public USBEndpoint { 9 | public: 10 | USBKeyboard(uint8_t new_slot_id, uint8_t endpoint, uint16_t packet_size) : USBEndpoint(endpoint, KEYBOARD, packet_size), slot_id(new_slot_id) {} 11 | void request_data(USBDriver *driver) override; 12 | void process_data(USBDriver *driver) override; 13 | private: 14 | void process_keypress(keypress *rkp); 15 | trb* latest_ring; 16 | bool requesting = false; 17 | uint8_t slot_id; 18 | 19 | keypress last_keypress; 20 | 21 | int repeated_keypresses = 0; 22 | 23 | void* buffer; 24 | }; -------------------------------------------------------------------------------- /kernel/input/USBManager.cpp: -------------------------------------------------------------------------------- 1 | #include "USBManager.hpp" 2 | #include "USBDevice.hpp" 3 | #include "USBKeyboard.hpp" 4 | #include "console/kio.h" 5 | 6 | USBManager::USBManager(uint32_t capacity){ 7 | devices = IndexMap(capacity); 8 | }; 9 | 10 | void USBManager::register_device(uint8_t address){ 11 | if (address >= devices.max_size()) return; 12 | USBDevice *newdevice = new USBDevice(8,address); 13 | if (!newdevice) return; 14 | devices.add(address,newdevice); 15 | } 16 | 17 | void USBManager::register_endpoint(uint8_t slot_id, uint8_t endpoint, xhci_device_types type, uint16_t packet_size){ 18 | if (slot_id >= devices.max_size()) return; 19 | USBDevice *dev = devices[slot_id]; 20 | if (dev) 21 | dev->register_endpoint(endpoint, type, packet_size); 22 | } 23 | 24 | void USBManager::request_data(uint8_t slot_id, uint8_t endpoint_id, USBDriver *driver){ 25 | if (slot_id >= devices.max_size()) return;//TODO: check if it exists 26 | USBDevice *dev = devices[slot_id]; 27 | if (dev) 28 | dev->request_data(endpoint_id, driver); 29 | } 30 | 31 | void USBManager::process_data(uint8_t slot_id, uint8_t endpoint_id, USBDriver *driver){ 32 | if (slot_id >= devices.max_size()) return;//TODO: check if it exists 33 | USBDevice *dev = devices[slot_id]; 34 | if (dev) 35 | dev->process_data(endpoint_id, driver); 36 | } 37 | 38 | void USBManager::poll_inputs(USBDriver *driver){ 39 | for (uint8_t i = 0; i < devices.max_size(); i++){ 40 | USBDevice *device = devices[i]; 41 | if (device){ 42 | device->poll_inputs(driver); 43 | } 44 | } 45 | } -------------------------------------------------------------------------------- /kernel/input/USBManager.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "types.h" 3 | #include "xhci_types.h" 4 | #include "std/std.hpp" 5 | #include "USBDevice.hpp" 6 | 7 | class USBDriver; 8 | 9 | class USBManager { 10 | public: 11 | USBManager(uint32_t capacity); 12 | IndexMap devices; 13 | 14 | void register_device(uint8_t address); 15 | void register_endpoint(uint8_t slot_id, uint8_t endpoint, xhci_device_types type, uint16_t packet_size); 16 | void request_data(uint8_t slot_id, uint8_t endpoint_id, USBDriver *driver); 17 | void process_data(uint8_t slot_id, uint8_t endpoint_id, USBDriver *driver); 18 | void poll_inputs(USBDriver *driver); 19 | }; -------------------------------------------------------------------------------- /kernel/input/dwc2.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "usb.hpp" 4 | #include "std/indexmap.hpp" 5 | #include "xhci_types.h" 6 | 7 | typedef struct { 8 | uint32_t gotgctl; 9 | uint32_t gotgint; 10 | uint32_t gahbcfg; 11 | uint32_t gusbcfg; 12 | uint32_t grstctl; 13 | uint32_t gintsts; 14 | uint32_t gintmsk; 15 | uint32_t grxstsr; 16 | uint32_t grxstsp; 17 | uint32_t grxfsiz; 18 | uint32_t gnptxfsiz; 19 | uint32_t gnptxsts; 20 | } dwc2_regs; 21 | 22 | typedef struct { 23 | uint32_t hstcfg; 24 | uint32_t frminterval; 25 | uint32_t frmnum; 26 | uint32_t rsvd; 27 | uint32_t ptx_fifo; 28 | uint32_t allchan_int; 29 | uint32_t allchan_int_mask; 30 | uint32_t frmlst_base; 31 | uint32_t rsvd2[8]; 32 | uint32_t port; 33 | } dwc2_host; 34 | 35 | typedef struct { 36 | uint32_t cchar; 37 | uint32_t splt; 38 | uint32_t interrupt; 39 | uint32_t intmask; 40 | uint32_t xfer_size; 41 | uint32_t dma; 42 | uint32_t reserved[2]; 43 | uint32_t buf; 44 | } dwc2_host_channel; 45 | 46 | class DWC2Driver: public USBDriver { 47 | public: 48 | DWC2Driver() = default; 49 | bool init() override; 50 | bool request_sized_descriptor(uint8_t address, uint8_t endpoint, uint8_t rType, uint8_t request, uint8_t type, uint16_t descriptor_index, uint16_t wIndex, uint16_t descriptor_size, void *out_descriptor) override; 51 | uint8_t address_device(uint8_t address) override; 52 | bool configure_endpoint(uint8_t address, usb_endpoint_descriptor *endpoint, uint8_t configuration_value, xhci_device_types type) override; 53 | void handle_hub_routing(uint8_t hub, uint8_t port) override; 54 | bool poll(uint8_t address, uint8_t endpoint, void *out_buf, uint16_t size) override; 55 | void handle_interrupt() override; 56 | ~DWC2Driver() = default; 57 | private: 58 | dwc2_host_channel* get_channel(uint16_t channel); 59 | uint8_t assign_channel(uint8_t device, uint8_t endpoint, uint8_t ep_type); 60 | bool make_transfer(dwc2_host_channel *channel, bool in, uint8_t pid, sizedptr data); 61 | bool port_reset(uint32_t *port); 62 | uint16_t port_speed; 63 | dwc2_regs *dwc2; 64 | dwc2_host *host; 65 | uint8_t next_channel; 66 | uint8_t next_address; 67 | dwc2_host_channel *endpoint_channel; 68 | IndexMap channel_map; 69 | }; -------------------------------------------------------------------------------- /kernel/input/input_dispatch.cpp: -------------------------------------------------------------------------------- 1 | #include "input_dispatch.h" 2 | #include "process/process.h" 3 | #include "process/scheduler.h" 4 | #include "dwc2.hpp" 5 | #include "xhci.hpp" 6 | #include "hw/hw.h" 7 | #include "std/std.hpp" 8 | 9 | process_t* focused_proc; 10 | 11 | typedef struct { 12 | keypress kp; 13 | int pid; 14 | bool triggered; 15 | } shortcut; 16 | 17 | shortcut shortcuts[16]; 18 | 19 | uint16_t shortcut_count = 0; 20 | 21 | bool secure_mode = false; 22 | 23 | USBDriver *input_driver; 24 | 25 | void register_keypress(keypress kp) { 26 | if (!secure_mode){ 27 | for (int i = 0; i < shortcut_count; i++){ 28 | if (shortcuts[i].pid != -1 && !is_new_keypress(&shortcuts[i].kp, &kp)){ 29 | shortcuts[i].triggered = true; 30 | return; 31 | } 32 | } 33 | } 34 | 35 | if (!(uintptr_t)focused_proc) return; 36 | 37 | input_buffer_t* buf = &focused_proc->input_buffer; 38 | uint32_t next_index = (buf->write_index + 1) % INPUT_BUFFER_CAPACITY; 39 | 40 | buf->entries[buf->write_index] = kp; 41 | buf->write_index = next_index; 42 | 43 | if (buf->write_index == buf->read_index) 44 | buf->read_index = (buf->read_index + 1) % INPUT_BUFFER_CAPACITY; 45 | } 46 | 47 | uint16_t sys_subscribe_shortcut_current(keypress kp){ 48 | return sys_subscribe_shortcut(get_current_proc_pid(),kp); 49 | } 50 | 51 | uint16_t sys_subscribe_shortcut(uint16_t pid, keypress kp){ 52 | shortcuts[shortcut_count] = (shortcut){ 53 | .kp = kp, 54 | .pid = pid 55 | }; 56 | return shortcut_count++; 57 | } 58 | 59 | void sys_focus_current(){ 60 | sys_set_focus(get_current_proc_pid()); 61 | } 62 | 63 | void sys_set_focus(int pid){ 64 | focused_proc = get_proc_by_pid(pid); 65 | focused_proc->focused = true; 66 | } 67 | 68 | void sys_unset_focus(){ 69 | focused_proc->focused = false; 70 | focused_proc = 0; 71 | } 72 | 73 | void sys_set_secure(bool secure){ 74 | secure_mode = secure; 75 | } 76 | 77 | bool sys_read_input_current(keypress *out){ 78 | return sys_read_input(get_current_proc_pid(), out); 79 | } 80 | 81 | bool is_new_keypress(keypress* current, keypress* previous) { 82 | if (current->modifier != previous->modifier) return true; 83 | 84 | for (int i = 0; i < 6; i++) 85 | if (current->keys[i] != previous->keys[i]) return true; 86 | 87 | return false; 88 | } 89 | 90 | bool sys_read_input(int pid, keypress *out){ 91 | if (BOARD_TYPE == 2) 92 | input_driver->poll_inputs(); 93 | process_t *process = get_proc_by_pid(pid); 94 | if (process->input_buffer.read_index == process->input_buffer.write_index) return false; 95 | 96 | *out = process->input_buffer.entries[process->input_buffer.read_index]; 97 | process->input_buffer.read_index = (process->input_buffer.read_index + 1) % INPUT_BUFFER_CAPACITY; 98 | return true; 99 | } 100 | 101 | bool sys_shortcut_triggered_current(uint16_t sid){ 102 | return sys_shortcut_triggered(get_current_proc_pid(), sid); 103 | } 104 | 105 | bool sys_shortcut_triggered(uint16_t pid, uint16_t sid){ 106 | if (shortcuts[sid].pid == pid && shortcuts[sid].triggered){ 107 | shortcuts[sid].triggered = false; 108 | return true; 109 | } 110 | return false; 111 | } 112 | 113 | bool input_init(){ 114 | if (BOARD_TYPE == 2){ 115 | input_driver = new DWC2Driver();//TODO: QEMU & 3 Only 116 | return input_driver->init(); 117 | } else { 118 | input_driver = new XHCIDriver(); 119 | return input_driver->init(); 120 | } 121 | } 122 | 123 | void handle_input_interrupt(){ 124 | if (input_driver->use_interrupts) input_driver->handle_interrupt(); 125 | } -------------------------------------------------------------------------------- /kernel/input/input_dispatch.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "input_keycodes.h" 4 | #include "keypress.h" 5 | 6 | #ifdef __cplusplus 7 | extern "C" { 8 | #endif 9 | 10 | void register_keypress(keypress kp); 11 | uint16_t sys_subscribe_shortcut(uint16_t pid, keypress kp); 12 | uint16_t sys_subscribe_shortcut_current(keypress kp); 13 | void sys_set_focus(int pid); 14 | void sys_focus_current(); 15 | void sys_unset_focus(); 16 | 17 | ///A process can request for shortcuts and others to be disabled 18 | void sys_set_secure(bool secure); 19 | 20 | bool sys_read_input(int pid, keypress *out); 21 | bool sys_read_input_current(keypress *out); 22 | 23 | bool sys_shortcut_triggered_current(uint16_t sid); 24 | bool sys_shortcut_triggered(uint16_t pid, uint16_t sid); 25 | 26 | bool is_new_keypress(keypress* current, keypress* previous); 27 | 28 | bool input_init(); 29 | 30 | void handle_input_interrupt(); 31 | 32 | #ifdef __cplusplus 33 | } 34 | #endif -------------------------------------------------------------------------------- /kernel/input/usb.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "types.h" 4 | #include "keypress.h" 5 | #include "xhci_types.h" 6 | #include "USBManager.hpp" 7 | 8 | class USBDriver { 9 | public: 10 | USBDriver() = default; 11 | virtual bool init() = 0; 12 | bool request_descriptor(uint8_t address, uint8_t endpoint, uint8_t rType, uint8_t request, uint8_t type, uint16_t index, uint16_t wIndex, void *out_descriptor); 13 | virtual bool request_sized_descriptor(uint8_t address, uint8_t endpoint, uint8_t rType, uint8_t request, uint8_t type, uint16_t descriptor_index, uint16_t wIndex, uint16_t descriptor_size, void *out_descriptor) = 0; 14 | uint16_t packet_size(uint16_t speed); 15 | bool get_configuration(uint8_t address); 16 | void hub_enumerate(uint8_t address); 17 | virtual bool setup_device(uint8_t address, uint16_t port); 18 | virtual uint8_t address_device(uint8_t address) = 0; 19 | virtual bool configure_endpoint(uint8_t address, usb_endpoint_descriptor *endpoint, uint8_t configuration_value, xhci_device_types type) = 0; 20 | virtual void handle_hub_routing(uint8_t hub, uint8_t port) = 0; 21 | virtual bool poll(uint8_t address, uint8_t endpoint, void *out_buf, uint16_t size) = 0; 22 | void poll_inputs(); 23 | virtual void handle_interrupt() = 0; 24 | bool use_interrupts; 25 | ~USBDriver() = default; 26 | protected: 27 | void *mem_page; 28 | USBManager *usb_manager; 29 | bool verbose = false; 30 | }; -------------------------------------------------------------------------------- /kernel/input/xhci.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "usb.hpp" 4 | #include "xhci_types.h" 5 | 6 | typedef struct xhci_ring { 7 | trb* ring; 8 | uint8_t cycle_bit; 9 | uint32_t index; 10 | } xhci_ring; 11 | 12 | class XHCIDriver : public USBDriver { 13 | public: 14 | XHCIDriver() = default; 15 | bool init() override; 16 | bool request_sized_descriptor(uint8_t address, uint8_t endpoint, uint8_t rType, uint8_t request, uint8_t type, uint16_t descriptor_index, uint16_t wIndex, uint16_t descriptor_size, void *out_descriptor) override; 17 | uint8_t address_device(uint8_t address) override; 18 | bool configure_endpoint(uint8_t address, usb_endpoint_descriptor *endpoint, uint8_t configuration_value, xhci_device_types type) override; 19 | void handle_hub_routing(uint8_t hub, uint8_t port) override; 20 | bool poll(uint8_t address, uint8_t endpoint, void *out_buf, uint16_t size) override; 21 | bool setup_device(uint8_t address, uint16_t port) override; 22 | void handle_interrupt() override; 23 | ~XHCIDriver() = default; 24 | private: 25 | bool check_fatal_error(); 26 | bool enable_events(); 27 | 28 | bool port_reset(uint16_t port); 29 | 30 | bool issue_command(uint64_t param, uint32_t status, uint32_t control); 31 | void ring_doorbell(uint32_t slot, uint32_t endpoint); 32 | bool await_response(uint64_t command, uint32_t type); 33 | uint8_t get_ep_type(usb_endpoint_descriptor* descriptor); 34 | 35 | void make_ring_link_control(trb* ring, bool cycle); 36 | void make_ring_link(trb* ring, bool cycle); 37 | 38 | xhci_cap_regs* cap; 39 | xhci_op_regs* op; 40 | xhci_port_regs* ports; 41 | xhci_interrupter* interrupter; 42 | uintptr_t db_base; 43 | uintptr_t rt_base; 44 | uintptr_t* dcbaap; 45 | uint16_t max_device_slots; 46 | uint16_t max_ports; 47 | 48 | xhci_ring command_ring; 49 | xhci_ring event_ring; 50 | 51 | trb* last_event; 52 | 53 | IndexMap endpoint_map; 54 | IndexMap context_map; 55 | }; -------------------------------------------------------------------------------- /kernel/kernel.c: -------------------------------------------------------------------------------- 1 | #include "console/kio.h" 2 | #include "console/serial/uart.h" 3 | #include "graph/graphics.h" 4 | #include "hw/hw.h" 5 | #include "pci.h" 6 | #include "kstring.h" 7 | #include "console/kconsole/kconsole.h" 8 | #include "memory/mmu.h" 9 | #include "exceptions/exception_handler.h" 10 | #include "memory/kalloc.h" 11 | #include "exceptions/irq.h" 12 | #include "process/scheduler.h" 13 | #include "filesystem/disk.h" 14 | #include "kernel_processes/boot/bootprocess.h" 15 | #include "input/input_dispatch.h" 16 | #include "kernel_processes/monitor/monitor_processes.h" 17 | #include "networking/processes/net_proc.h" 18 | #include "memory/page_allocator.h" 19 | #include "networking/network.h" 20 | 21 | void kernel_main() { 22 | 23 | detect_hardware(); 24 | 25 | mmu_alloc(); 26 | // mmu_enable_verbose(); 27 | enable_uart(); 28 | kprintf_l("UART output enabled"); 29 | // enable_talloc_verbose(); 30 | 31 | set_exception_vectors(); 32 | kprintf_l("Exception vectors set"); 33 | 34 | print_hardware(); 35 | 36 | page_allocator_init(); 37 | // page_alloc_enable_verbose(); 38 | kprintf_l("Initializing kernel..."); 39 | 40 | init_main_process(); 41 | 42 | kprintf_l("Preparing for draw"); 43 | gpu_size screen_size = {1080,720}; 44 | 45 | irq_init(); 46 | kprintf("Interrupts initialized"); 47 | 48 | enable_interrupt(); 49 | 50 | kprintf_l("Initializing GPU"); 51 | 52 | gpu_init(screen_size); 53 | 54 | kprintf("GPU initialized"); 55 | 56 | kprintf("Initializing disk..."); 57 | 58 | // disk_verbose(); 59 | if (!find_disk()) 60 | panic("Disk initialization failure"); 61 | 62 | // xhci_enable_verbose(); 63 | if (!input_init()) 64 | panic("Input initialization error"); 65 | 66 | bool network_available = network_init(); 67 | 68 | mmu_init(); 69 | kprintf_l("MMU Mapped"); 70 | 71 | if (!disk_init()) 72 | panic("Disk read failure"); 73 | 74 | kprintf_l("Kernel initialization finished"); 75 | 76 | kprintf_l("Starting processes"); 77 | 78 | if (network_available) launch_net_process(); 79 | 80 | init_bootprocess(); 81 | 82 | kprintf_l("Starting scheduler"); 83 | 84 | disable_interrupt(); 85 | start_scheduler(); 86 | 87 | panic("Kernel did not activate any process"); 88 | 89 | } -------------------------------------------------------------------------------- /kernel/kernel_processes/boot/bootprocess.cpp: -------------------------------------------------------------------------------- 1 | #include "bootprocess_sm.hpp" 2 | #include "bootprocess.h" 3 | #include "../kprocess_loader.h" 4 | #include "console/kio.h" 5 | 6 | BootSM state_machine; 7 | 8 | extern "C" __attribute__((section(".text.kcoreprocesses"))) void eval_bootscreen() { 9 | while (1){ 10 | state_machine.eval_state(); 11 | } 12 | } 13 | 14 | extern "C" void init_bootprocess() { 15 | create_kernel_process("bootsm",eval_bootscreen); 16 | state_machine.initialize(); 17 | } 18 | -------------------------------------------------------------------------------- /kernel/kernel_processes/boot/bootprocess.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #ifdef __cplusplus 4 | extern "C" { 5 | #endif 6 | 7 | void init_bootprocess(); 8 | 9 | #ifdef __cplusplus 10 | } 11 | #endif -------------------------------------------------------------------------------- /kernel/kernel_processes/boot/bootprocess_sm.cpp: -------------------------------------------------------------------------------- 1 | #include "bootprocess_sm.hpp" 2 | #include "bootscreen.h" 3 | #include "login_screen.h" 4 | #include "../windows/windows.h" 5 | #include "console/kio.h" 6 | 7 | BootSM::BootSM(){ 8 | 9 | } 10 | 11 | void BootSM::initialize(){ 12 | AdvanceToState(Bootscreen); 13 | } 14 | 15 | BootSM::BootStates BootSM::eval_state(){ 16 | if (current_proc->state == process_t::process_state::STOPPED) 17 | AdvanceToState(GetNextState()); 18 | 19 | return current_state; 20 | } 21 | 22 | void BootSM::AdvanceToState(BootStates next_state){ 23 | switch (next_state){ 24 | case Bootscreen: 25 | current_proc = start_bootscreen(); 26 | break; 27 | case Login: 28 | current_proc = present_login(); 29 | break; 30 | case Desktop: 31 | current_proc = start_windows(); 32 | break; 33 | } 34 | current_state = next_state; 35 | } 36 | 37 | BootSM::BootStates BootSM::GetNextState(){ 38 | switch (current_state){ 39 | case Login: 40 | return Desktop; 41 | default: 42 | return Login; 43 | } 44 | } -------------------------------------------------------------------------------- /kernel/kernel_processes/boot/bootprocess_sm.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "types.h" 4 | #include "process/process.h" 5 | 6 | class BootSM { 7 | 8 | enum BootStates { 9 | Bootscreen, 10 | Login, 11 | Desktop 12 | }; 13 | 14 | public: 15 | BootSM(); 16 | 17 | void initialize(); 18 | 19 | BootStates eval_state(); 20 | 21 | private: 22 | BootStates current_state; 23 | process_t* current_proc; 24 | 25 | void AdvanceToState(BootStates next_state); 26 | BootStates GetNextState(); 27 | 28 | }; -------------------------------------------------------------------------------- /kernel/kernel_processes/boot/bootscreen.c: -------------------------------------------------------------------------------- 1 | #include "bootscreen.h" 2 | #include "../kprocess_loader.h" 3 | #include "console/kio.h" 4 | #include "graph/graphics.h" 5 | #include "std/string.h" 6 | #include "memory/kalloc.h" 7 | #include "theme/theme.h" 8 | #include "exceptions/exception_handler.h" 9 | #include "input/input_dispatch.h" 10 | #include "process/scheduler.h" 11 | #include "math/math.h" 12 | #include "syscalls/syscalls.h" 13 | 14 | __attribute__((section(".text.kcoreprocesses"))) 15 | void boot_draw_name(gpu_point screen_middle,int xoffset, int yoffset){ 16 | const char* name = BOOTSCREEN_TEXT; 17 | string s = string_l(name); 18 | int scale = 2; 19 | uint32_t char_size = gpu_get_char_size(scale); 20 | int mid_offset = ((s.length/BOOTSCREEN_NUM_LINES) * char_size)/2; 21 | int xo = screen_middle.x - mid_offset + xoffset; 22 | int yo = screen_middle.y + yoffset; 23 | gpu_fill_rect((gpu_rect){{xo,yo}, {char_size * (s.length/BOOTSCREEN_NUM_LINES), char_size * BOOTSCREEN_NUM_LINES}},BG_COLOR); 24 | gpu_draw_string(s, (gpu_point){xo, yo}, scale, 0xFFFFFF); 25 | free(s.data,s.mem_length); 26 | } 27 | 28 | __attribute__((section(".rodata.kcoreprocesses"))) 29 | const gpu_point offsets[BOOTSCREEN_NUM_SYMBOLS] = BOOTSCREEN_OFFSETS; 30 | 31 | __attribute__((section(".text.kcoreprocesses"))) 32 | gpu_point boot_calc_point(gpu_point offset, gpu_size screen_size, gpu_point screen_middle){ 33 | int xoff = (screen_size.width/BOOTSCREEN_DIV) * offset.x; 34 | int yoff = (screen_size.height/BOOTSCREEN_DIV) * offset.y; 35 | int xloc = BOOTSCREEN_PADDING + xoff; 36 | int yloc = BOOTSCREEN_PADDING + yoff; 37 | return (gpu_point){screen_middle.x + xloc - (abs(offset.x) == 1 ? BOOTSCREEN_ASYMM.x : 0), screen_middle.y + yloc - (abs(offset.y) == 1 ? BOOTSCREEN_ASYMM.y : 0)}; 38 | } 39 | 40 | void boot_draw_lines(gpu_point current_point, gpu_point next_point, gpu_size size, int num_lines, int separation){ 41 | int steps = 0; 42 | for (int j = 0; j < num_lines; j++) { 43 | gpu_point ccurrent = current_point; 44 | gpu_point cnext = next_point; 45 | if (current_point.x != 0 && current_point.x < size.width) 46 | ccurrent.x += (separation * j); 47 | if (next_point.x != 0 && next_point.x < size.width) 48 | cnext.x += (separation * j); 49 | if (current_point.y != 0 && current_point.y < size.height) 50 | ccurrent.y -= (separation * j); 51 | if (next_point.y != 0 && next_point.y < size.height) 52 | cnext.y -= (separation * j); 53 | int xlength = abs(ccurrent.x - cnext.x); 54 | int ylength = abs(ccurrent.y - cnext.y); 55 | int csteps = xlength > ylength ? xlength : ylength; 56 | if (csteps > steps) steps = csteps; 57 | } 58 | 59 | for (int i = 0; i <= steps; i++) { 60 | for (int j = 0; j < num_lines; j++){ 61 | gpu_point ccurrent = current_point; 62 | gpu_point cnext = next_point; 63 | if (current_point.x != 0 && current_point.x < size.width) 64 | ccurrent.x += (separation * j); 65 | if (next_point.x != 0 && next_point.x < size.width) 66 | cnext.x += (separation * j); 67 | if (current_point.y != 0 && current_point.y < size.height) 68 | ccurrent.y -= (separation * j); 69 | if (next_point.y != 0 && next_point.y < size.height) 70 | cnext.y -= (separation * j); 71 | int xlength = abs(ccurrent.x - cnext.x); 72 | int ylength = abs(ccurrent.y - cnext.y); 73 | int csteps = xlength > ylength ? xlength : ylength; 74 | if (csteps > i){ 75 | gpu_point interpolated = { 76 | lerp(i, ccurrent.x, cnext.x, csteps), 77 | lerp(i, ccurrent.y, cnext.y, csteps) 78 | }; 79 | gpu_draw_pixel(interpolated, 0xFFFFFF); 80 | } 81 | } 82 | keypress kp; 83 | if (sys_read_input_current(&kp)) 84 | if (kp.keys[0] != 0){ 85 | stop_current_process(); 86 | } 87 | gpu_flush(); 88 | // sleep(0); 89 | } 90 | } 91 | 92 | __attribute__((section(".text.kcoreprocesses"))) 93 | void bootscreen(){ 94 | disable_visual(); 95 | sys_focus_current(); 96 | while (1) 97 | { 98 | gpu_clear(BG_COLOR); 99 | gpu_size screen_size = gpu_get_screen_size(); 100 | gpu_point screen_middle = {screen_size.width/2,screen_size.height/2}; 101 | 102 | gpu_point current_point = boot_calc_point(offsets[BOOTSCREEN_NUM_SYMBOLS-1],screen_size,screen_middle); 103 | for (int i = 0; i < BOOTSCREEN_NUM_STEPS; i++){ 104 | gpu_point offset = offsets[i]; 105 | gpu_point next_point = boot_calc_point(offset,screen_size,screen_middle); 106 | boot_draw_name(screen_middle, 0, BOOTSCREEN_PADDING + screen_size.height/BOOTSCREEN_UPPER_Y_DIV + 10); 107 | boot_draw_lines(current_point, next_point, screen_size, BOOTSCREEN_REPEAT, 5); 108 | current_point = next_point; 109 | } 110 | sleep(1000); 111 | } 112 | } 113 | 114 | process_t* start_bootscreen(){ 115 | return create_kernel_process("bootscreen",bootscreen); 116 | } -------------------------------------------------------------------------------- /kernel/kernel_processes/boot/bootscreen.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #ifdef __cplusplus 4 | extern "C" { 5 | #endif 6 | #include "process/process.h" 7 | #include "types.h" 8 | 9 | process_t* start_bootscreen(); 10 | #ifdef __cplusplus 11 | } 12 | #endif -------------------------------------------------------------------------------- /kernel/kernel_processes/boot/login_screen.c: -------------------------------------------------------------------------------- 1 | #include "login_screen.h" 2 | #include "memory/kalloc.h" 3 | #include "graph/graphics.h" 4 | #include "input/input_dispatch.h" 5 | #include "../kprocess_loader.h" 6 | #include "theme/theme.h" 7 | #include "console/kio.h" 8 | #include "process/scheduler.h" 9 | #include "math/math.h" 10 | #include "std/string.h" 11 | #include "syscalls/syscalls.h" 12 | 13 | static const char hid_keycode_to_char[256] = { 14 | [0x04] = 'a', [0x05] = 'b', [0x06] = 'c', [0x07] = 'd', 15 | [0x08] = 'e', [0x09] = 'f', [0x0A] = 'g', [0x0B] = 'h', 16 | [0x0C] = 'i', [0x0D] = 'j', [0x0E] = 'k', [0x0F] = 'l', 17 | [0x10] = 'm', [0x11] = 'n', [0x12] = 'o', [0x13] = 'p', 18 | [0x14] = 'q', [0x15] = 'r', [0x16] = 's', [0x17] = 't', 19 | [0x18] = 'u', [0x19] = 'v', [0x1A] = 'w', [0x1B] = 'x', 20 | [0x1C] = 'y', [0x1D] = 'z', 21 | [0x1E] = '1', [0x1F] = '2', [0x20] = '3', [0x21] = '4', 22 | [0x22] = '5', [0x23] = '6', [0x24] = '7', [0x25] = '8', 23 | [0x26] = '9', [0x27] = '0', 24 | [0x28] = '\n', [0x2C] = ' ', [0x2D] = '-', [0x2E] = '=', 25 | [0x2F] = '[', [0x30] = ']', [0x31] = '\\', [0x33] = ';', 26 | [0x34] = '\'', [0x35] = '`', [0x36] = ',', [0x37] = '.', 27 | [0x38] = '/', 28 | }; 29 | 30 | bool keypress_contains(keypress *kp, char key, uint8_t modifier){ 31 | if (kp->modifier != modifier) return false;//TODO: This is not entirely accurate, some modifiers do not change key 32 | 33 | for (int i = 0; i < 6; i++) 34 | if (kp->keys[i] == key) 35 | return true; 36 | return false; 37 | } 38 | 39 | __attribute__((section(".text.kcoreprocesses"))) 40 | void login_screen(){ 41 | sys_focus_current(); 42 | sys_set_secure(true); 43 | char* buf = (char*)talloc(256); 44 | int len = 0; 45 | keypress old_kp; 46 | const char* name = BOOTSCREEN_TEXT; 47 | string title = string_l(name); 48 | string subtitle = string_l("Login"); 49 | while (1) 50 | { 51 | gpu_clear(BG_COLOR); 52 | gpu_size screen_size = gpu_get_screen_size(); 53 | gpu_point screen_middle = {screen_size.width/2,screen_size.height/2}; 54 | string s = string_repeat('*',min(len,20)); 55 | int scale = 2; 56 | uint32_t char_size = gpu_get_char_size(scale); 57 | int xo = screen_size.width / 3; 58 | int yo = screen_middle.y; 59 | int height = char_size * 2; 60 | 61 | gpu_draw_string(title, (gpu_point){screen_middle.x - ((title.length/2) * char_size), yo - char_size*9}, scale, 0xFFFFFF); 62 | gpu_draw_string(subtitle, (gpu_point){screen_middle.x - ((subtitle.length/2) * char_size), yo - char_size*6}, scale, 0xFFFFFF); 63 | 64 | gpu_fill_rect((gpu_rect){{xo,yo - char_size/2}, {screen_size.width / 3, height}},BG_COLOR+0x111111); 65 | gpu_draw_string(s, (gpu_point){xo, yo}, scale, 0xFFFFFF); 66 | keypress kp; 67 | if (sys_read_input_current(&kp)){ 68 | for (int i = 0; i < 6; i++){ 69 | char key = kp.keys[i]; 70 | if (hid_keycode_to_char[(uint8_t)key]){ 71 | if (key == KEY_ENTER){ 72 | if (strcmp(buf,default_pwd, false) == 0){ 73 | free(s.data,s.mem_length); 74 | free(title.data,title.mem_length); 75 | free(subtitle.data,subtitle.mem_length); 76 | sys_set_secure(false); 77 | stop_current_process(); 78 | } else 79 | break; 80 | } 81 | key = hid_keycode_to_char[(uint8_t)key];//Translate readables 82 | if (key != 0 && len < 256 && (!keypress_contains(&old_kp,kp.keys[i], kp.modifier) || !is_new_keypress(&old_kp, &kp))){ 83 | buf[len] = key; 84 | len++; 85 | } 86 | } 87 | if (kp.keys[i] == KEY_BACKSPACE){ 88 | if (len > 0) len--; 89 | buf[len] = '\0'; 90 | } 91 | } 92 | } 93 | 94 | old_kp = kp; 95 | gpu_flush(); 96 | free(s.data,s.mem_length); 97 | } 98 | } 99 | 100 | process_t* present_login(){ 101 | return create_kernel_process("login",login_screen); 102 | } -------------------------------------------------------------------------------- /kernel/kernel_processes/boot/login_screen.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "types.h" 4 | #include "process/process.h" 5 | 6 | #ifdef __cplusplus 7 | extern "C" { 8 | #endif 9 | process_t* present_login(); 10 | #ifdef __cplusplus 11 | } 12 | #endif -------------------------------------------------------------------------------- /kernel/kernel_processes/kprocess_loader.c: -------------------------------------------------------------------------------- 1 | #include "kprocess_loader.h" 2 | #include "console/kio.h" 3 | #include "process/scheduler.h" 4 | #include "memory/page_allocator.h" 5 | #include "exceptions/irq.h" 6 | 7 | process_t *create_kernel_process(const char *name, void (*func)()){ 8 | 9 | disable_interrupt(); 10 | 11 | process_t* proc = init_process(); 12 | 13 | name_process(proc, name); 14 | 15 | uint64_t stack_size = 0x1000; 16 | 17 | uintptr_t stack = (uintptr_t)alloc_page(stack_size, true, false, false); 18 | kprintf_raw("Stack size %x. Start %x", stack_size,stack); 19 | if (!stack) return 0; 20 | 21 | uintptr_t heap = (uintptr_t)alloc_page(stack_size, true, false, false); 22 | kprintf_raw("Heap %x", heap); 23 | if (!heap) return 0; 24 | 25 | proc->stack = (stack + stack_size); 26 | proc->stack_size = stack_size; 27 | 28 | proc->heap = heap; 29 | 30 | proc->sp = proc->stack; 31 | 32 | proc->pc = (uintptr_t)func; 33 | kprintf_raw("Kernel process %s allocated with address at %x, stack at %x, heap at %x", (uintptr_t)name, proc->pc, proc->sp, proc->heap); 34 | proc->spsr = 0x205; 35 | proc->state = READY; 36 | 37 | enable_interrupt(); 38 | 39 | return proc; 40 | } -------------------------------------------------------------------------------- /kernel/kernel_processes/kprocess_loader.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #ifdef __cplusplus 4 | extern "C" { 5 | #endif 6 | 7 | #include "types.h" 8 | #include "process/process.h" 9 | 10 | process_t *create_kernel_process(const char *name, void (*func)()); 11 | 12 | #ifdef __cplusplus 13 | } 14 | #endif -------------------------------------------------------------------------------- /kernel/kernel_processes/monitor/monitor_processes.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "process/process.h" 4 | 5 | #ifdef __cplusplus 6 | extern "C" { 7 | #endif 8 | 9 | process_t* start_process_monitor(); 10 | 11 | #ifdef __cplusplus 12 | } 13 | #endif -------------------------------------------------------------------------------- /kernel/kernel_processes/windows/desktop.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "types.h" 4 | #include "graph/graphics.h" 5 | #include "process/process.h" 6 | #include "ui/ui.hpp" 7 | #include "std/std.hpp" 8 | 9 | struct LaunchEntry { 10 | char* name; 11 | char* ext; 12 | char* path; 13 | }; 14 | 15 | class Desktop { 16 | public: 17 | Desktop(); 18 | 19 | void draw_desktop(); 20 | 21 | private: 22 | gpu_size tile_size; 23 | gpu_point selected; 24 | bool ready = false; 25 | bool rendered_full = false; 26 | process_t *active_proc; 27 | Label *single_label;// TODO: This is hardcoded, ew 28 | Label *extension_label;// TODO: This is hardcoded, ew 29 | Array entries; 30 | bool process_active = false; 31 | 32 | void draw_tile(uint32_t column, uint32_t row); 33 | bool await_gpu(); 34 | void draw_full(); 35 | void add_entry(char* name, char* ext, char* path); 36 | void activate_current(); 37 | uint16_t find_extension(char *path); 38 | }; -------------------------------------------------------------------------------- /kernel/kernel_processes/windows/window_manager.cpp: -------------------------------------------------------------------------------- 1 | #include "window_manager.hpp" 2 | #include "console/kio.h" 3 | #include "graph/graphics.h" 4 | #include "theme/theme.h" 5 | #include "../monitor/monitor_processes.h" 6 | #include "std/std.hpp" 7 | #include "windows.h" 8 | 9 | WindowManager::WindowManager(){ 10 | 11 | } 12 | 13 | void WindowManager::initialize(){ 14 | monitor_proc = start_process_monitor(); 15 | desktop = new Desktop(); 16 | } 17 | 18 | void WindowManager::manage_windows(){ 19 | if (paused) return; 20 | desktop->draw_desktop(); 21 | } 22 | 23 | //TODO: the window manager will need to handle gpu access from windows as well. Windows should work on their private FB and it should be written by the window manager into the real fb 24 | //Tho it'd be nice to avoid the double repetition of writing to private, then backbuffer, then main buffer, but that's gpu-driver-specific 25 | void WindowManager::pause(){ 26 | paused = true; 27 | screen_overlay = paused; 28 | } 29 | 30 | void WindowManager::resume(){ 31 | paused = false; 32 | screen_overlay = paused; 33 | } -------------------------------------------------------------------------------- /kernel/kernel_processes/windows/window_manager.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "types.h" 4 | #include "desktop.hpp" 5 | #include "process/process.h" 6 | 7 | class WindowManager { 8 | public: 9 | WindowManager(); 10 | 11 | void manage_windows(); 12 | void initialize(); 13 | 14 | void pause(); 15 | void resume(); 16 | 17 | private: 18 | Desktop *desktop; 19 | bool paused; 20 | process_t *monitor_proc; 21 | }; -------------------------------------------------------------------------------- /kernel/kernel_processes/windows/windows.cpp: -------------------------------------------------------------------------------- 1 | #include "windows.h" 2 | #include "graph/graphics.h" 3 | #include "../kprocess_loader.h" 4 | #include "theme/theme.h" 5 | #include "console/kio.h" 6 | #include "window_manager.hpp" 7 | 8 | WindowManager manager; 9 | 10 | bool screen_overlay; 11 | 12 | extern "C" __attribute__((section(".text.kcoreprocesses"))) void manage_windows(){ 13 | manager.initialize(); 14 | while (1) 15 | { 16 | manager.manage_windows(); 17 | } 18 | } 19 | 20 | __attribute__((section(".text.kcoreprocesses"))) 21 | void pause_window_draw(){ 22 | manager.pause(); 23 | } 24 | 25 | __attribute__((section(".text.kcoreprocesses"))) 26 | void resume_window_draw(){ 27 | manager.resume(); 28 | } 29 | 30 | extern "C" process_t* start_windows(){ 31 | return create_kernel_process("winmanager",manage_windows); 32 | } -------------------------------------------------------------------------------- /kernel/kernel_processes/windows/windows.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #ifdef __cplusplus 4 | extern "C" { 5 | #endif 6 | 7 | #include "types.h" 8 | #include "process/process.h" 9 | 10 | process_t* start_windows(); 11 | 12 | void pause_window_draw(); 13 | void resume_window_draw(); 14 | 15 | extern bool screen_overlay; 16 | 17 | #ifdef __cplusplus 18 | } 19 | #endif -------------------------------------------------------------------------------- /kernel/kstring.c: -------------------------------------------------------------------------------- 1 | #include "kstring.h" 2 | #include "memory/kalloc.h" 3 | #include "memory/memory_access.h" 4 | #include "std/string.h" 5 | #include "std/memfunctions.h" 6 | 7 | //TODO: we can most likely get rid of this class now and use string entirely 8 | static uint32_t compute_length(const char *s, uint32_t max_length) { 9 | uint32_t len = 0; 10 | while ((max_length == 0 || len < max_length) && s[len] != '\0') { 11 | len++; 12 | } 13 | return len; 14 | } 15 | 16 | kstring kstring_l(const char *literal) { 17 | uint32_t len = compute_length(literal, 0); 18 | char *buf = (char*)talloc(len+1); 19 | for (uint32_t i = 0; i < len; i++) 20 | buf[i] = literal[i]; 21 | buf[len] = 0; 22 | return (kstring){ .data = buf, .length = len }; 23 | } 24 | 25 | kstring kstring_repeat(char symbol, uint32_t amount){ 26 | char *buf = (char*)talloc(amount + 1); 27 | memset(buf, symbol, amount); 28 | buf[amount] = 0; 29 | return (kstring){ .data = buf, .length = amount }; 30 | } 31 | 32 | kstring kstring_tail(const char *array, uint32_t max_length){ 33 | uint32_t len = compute_length(array, 0); 34 | int offset = len-max_length; 35 | if (offset < 0) 36 | offset = 0; 37 | uint32_t adjusted_len = len - offset; 38 | char *buf = (char*)talloc(adjusted_len + 1); 39 | for (uint32_t i = offset; i < len; i++) 40 | buf[i-offset] = array[i]; 41 | buf[len-offset] = 0; 42 | return (kstring){ .data = buf, .length = adjusted_len }; 43 | } 44 | 45 | kstring kstring_ca_max(const char *array, uint32_t max_length) { 46 | uint32_t len = compute_length(array, max_length); 47 | char *buf = (char*)talloc(len + 1); 48 | for (uint32_t i = 0; i < len; i++) 49 | buf[i] = array[i]; 50 | buf[len] = 0; 51 | return (kstring){ .data = buf, .length = len }; 52 | } 53 | 54 | kstring kstring_c(const char c){ 55 | char *buf = (char*)talloc(2); 56 | buf[0] = c; 57 | buf[1] = 0; 58 | return (kstring){ .data = buf, .length = 1 }; 59 | } 60 | 61 | kstring kstring_from_hex(uint64_t value) { 62 | char *buf = (char*)talloc(18); 63 | uint32_t len = 0; 64 | buf[len++] = '0'; 65 | buf[len++] = 'x'; 66 | 67 | bool started = false; 68 | for (uint32_t i = 60;; i -= 4) { 69 | uint8_t nibble = (value >> i) & 0xF; 70 | char curr_char = nibble < 10 ? '0' + nibble : 'A' + (nibble - 10); 71 | if (started || curr_char != '0' || i == 0) { 72 | started = true; 73 | buf[len++] = curr_char; 74 | } 75 | if (i == 0) break; 76 | } 77 | 78 | buf[len] = 0; 79 | return (kstring){ .data = buf, .length = len }; 80 | } 81 | 82 | kstring kstring_from_bin(uint64_t value) { 83 | char *buf = (char*)talloc(67); 84 | uint32_t len = 0; 85 | buf[len++] = '0'; 86 | buf[len++] = 'b'; 87 | 88 | bool started = false; 89 | for (uint32_t i = 60;; i --) { 90 | char bit = (value >> i) & 1 ? '1' : '0'; 91 | if (started || bit != '0' || i == 0) { 92 | started = true; 93 | buf[len++] = bit; 94 | } 95 | if (i == 0) break; 96 | } 97 | 98 | buf[len] = 0; 99 | return (kstring){ .data = buf, .length = len }; 100 | } 101 | 102 | bool kstring_equals(kstring a, kstring b) { 103 | return strcmp(a.data,b.data, false) == 0; 104 | } 105 | 106 | kstring kstring_format_args(const char *fmt, const uint64_t *args, uint32_t arg_count) { 107 | char *buf = (char*)talloc(256); 108 | uint32_t len = 0; 109 | uint32_t arg_index = 0; 110 | 111 | for (uint32_t i = 0; fmt[i] && len < 255; i++) { 112 | if (fmt[i] == '%' && fmt[i+1]) { 113 | i++; 114 | if (arg_index >= arg_count) break; 115 | if (fmt[i] == 'x') { 116 | uint64_t val = args[arg_index++]; 117 | kstring hex = kstring_from_hex(val); 118 | for (uint32_t j = 0; j < hex.length && len < 255; j++) buf[len++] = hex.data[j]; 119 | temp_free(hex.data,hex.length); 120 | } else if (fmt[i] == 'b') { 121 | uint64_t val = args[arg_index++]; 122 | kstring bin = kstring_from_bin(val); 123 | for (uint32_t j = 0; j < bin.length && len < 255; j++) buf[len++] = bin.data[j]; 124 | temp_free(bin.data,bin.length); 125 | } else if (fmt[i] == 'c') { 126 | uint64_t val = args[arg_index++]; 127 | buf[len++] = (char)val; 128 | } else if (fmt[i] == 's') { 129 | const char *str = (const char *)(uintptr_t)args[arg_index++]; 130 | for (uint32_t j = 0; str[j] && len < 255; j++) buf[len++] = str[j]; 131 | } else if (fmt[i] == 'i') { 132 | uint64_t val = args[arg_index++]; 133 | char temp[21]; 134 | uint32_t temp_len = 0; 135 | bool negative = false; 136 | 137 | if ((int)val < 0) { 138 | negative = true; 139 | val = (uint64_t)(-(int)val); 140 | } 141 | 142 | do { 143 | temp[temp_len++] = '0' + (val % 10); 144 | val /= 10; 145 | } while (val && temp_len < 20); 146 | 147 | if (negative && temp_len < 20) { 148 | temp[temp_len++] = '-'; 149 | } 150 | 151 | for (int j = temp_len - 1; j >= 0 && len < 255; j--) { 152 | buf[len++] = temp[j]; 153 | } 154 | } else { 155 | buf[len++] = '%'; 156 | buf[len++] = fmt[i]; 157 | } 158 | } else { 159 | buf[len++] = fmt[i]; 160 | } 161 | } 162 | 163 | buf[len] = 0; 164 | return (kstring){ .data = buf, .length = len }; 165 | } -------------------------------------------------------------------------------- /kernel/kstring.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #ifdef __cplusplus 4 | extern "C" { 5 | #endif 6 | 7 | #include "types.h" 8 | 9 | typedef struct { 10 | char *data; 11 | uint32_t length; 12 | } kstring; 13 | 14 | #define kstring_format(fmt, ...) \ 15 | ({ \ 16 | uint64_t _args[] = { __VA_ARGS__ }; \ 17 | kstring_format_args((fmt), _args, sizeof(_args) / sizeof(_args[0])); \ 18 | }) 19 | 20 | kstring kstring_l(const char *literal); 21 | kstring kstring_ca_max(const char *array, uint32_t max_length); 22 | kstring kstring_c(const char c); 23 | kstring kstring_from_hex(uint64_t value); 24 | bool kstring_equals(kstring a, kstring b); 25 | kstring kstring_format_args(const char *fmt, const uint64_t *args, uint32_t arg_count); 26 | kstring kstring_tail(const char *array, uint32_t max_length); 27 | kstring kstring_repeat(char symbol, uint32_t amount); 28 | 29 | #ifdef __cplusplus 30 | } 31 | #endif -------------------------------------------------------------------------------- /kernel/linker.ld: -------------------------------------------------------------------------------- 1 | ENTRY(_start) 2 | 3 | SECTIONS { 4 | . = LOAD_ADDR; 5 | kernel_start = .; 6 | .boot . : { boot.o(.text) } 7 | .text : { 8 | *(EXCLUDE_FILE(shared/*.o) .text .text.[!p]*) 9 | } 10 | .data : { *(.data) } 11 | __bss_start = .; 12 | .bss : 13 | { 14 | bss = .; 15 | *(.bss) 16 | } 17 | . = ALIGN(4096); /* align to page size */ 18 | __bss_end = .; 19 | __bss_size = __bss_end - __bss_start; 20 | .vectors : { KEEP(*(.vectors)) } 21 | 22 | . = ALIGN(16); 23 | stack_bottom = .; 24 | .stack_fill : { FILL(0); . = . + 0x10000; } 25 | stack_top = .; 26 | 27 | . = ALIGN(4096); 28 | heap_bottom = .; 29 | .heap_fill : { FILL(0); . = . + 0x2000000; } 30 | heap_limit = .; 31 | 32 | .kcoreprocesses : ALIGN(8) { 33 | kcoreprocesses_rodata_start = .; 34 | KEEP(*(.rodata.kcoreprocesses)) 35 | KEEP(*(.data.kcoreprocesses)) 36 | kcoreprocesses_rodata_end = .; 37 | kcoreprocesses_start = .; 38 | KEEP(*(.text.kcoreprocesses)) 39 | kcoreprocesses_end = .; 40 | } 41 | . = ALIGN(0x200000); 42 | kcode_end = .; 43 | 44 | . = . + 0x200000; 45 | 46 | .shared : ALIGN(4096) { 47 | shared_start = .; 48 | KEEP(*(.shared)) 49 | KEEP(*(.text.shared)) 50 | KEEP(*shared/*.o(.text*)) 51 | 52 | . = ALIGN(8); 53 | BYTE(0); 54 | 55 | shared_end = .; 56 | } 57 | 58 | . = ALIGN(0x200000); 59 | kfull_end = .; 60 | } -------------------------------------------------------------------------------- /kernel/mailbox/mailbox.c: -------------------------------------------------------------------------------- 1 | #include "mailbox.h" 2 | 3 | int mailbox_call(volatile uint32_t* mbox, uint8_t channel) { 4 | uint32_t addr = ((uint32_t)(uintptr_t)mbox) & ~0xF; 5 | 6 | while (MBOX_STATUS & MBOX_FULL); 7 | MBOX_WRITE = addr | (channel & 0xF); 8 | 9 | while (1) { 10 | while (MBOX_STATUS & MBOX_EMPTY); 11 | uint32_t resp = MBOX_READ; 12 | if ((resp & 0xF) == channel && (resp & ~0xF) == addr) 13 | return mbox[1] == 0x80000000; 14 | } 15 | } -------------------------------------------------------------------------------- /kernel/mailbox/mailbox.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "types.h" 4 | #include "hw/hw.h" 5 | 6 | #define MAILBOX_BASE (MMIO_BASE + 0xB880) 7 | 8 | #define MBOX_READ (*(volatile uint32_t*)(MAILBOX_BASE + 0x00)) 9 | #define MBOX_STATUS (*(volatile uint32_t*)(MAILBOX_BASE + 0x18)) 10 | #define MBOX_WRITE (*(volatile uint32_t*)(MAILBOX_BASE + 0x20)) 11 | 12 | #define MBOX_FULL 0x80000000 13 | #define MBOX_EMPTY 0x40000000 14 | 15 | #ifdef __cplusplus 16 | extern "C" { 17 | #endif 18 | int mailbox_call(volatile uint32_t* mbox, uint8_t channel); 19 | #ifdef __cplusplus 20 | } 21 | #endif -------------------------------------------------------------------------------- /kernel/memory/dma.c: -------------------------------------------------------------------------------- 1 | #include "dma.h" 2 | #include "memory/kalloc.h" 3 | 4 | void dma_read(void* dest, uint32_t size, uint64_t pointer) { 5 | uint8_t* d = (uint8_t*)dest; 6 | for (uint32_t i = 0; i < size; i++) { 7 | d[i] = *(volatile uint8_t*)(uintptr_t)(pointer + i); 8 | } 9 | } -------------------------------------------------------------------------------- /kernel/memory/dma.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "types.h" 4 | 5 | void dma_read(void* dest, uint32_t size, uint64_t pointer); -------------------------------------------------------------------------------- /kernel/memory/kalloc.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "types.h" 4 | #include "memory/memory_types.h" 5 | 6 | #ifdef __cplusplus 7 | extern "C" { 8 | #endif 9 | uint64_t talloc(uint64_t size); 10 | void temp_free(void* ptr, uint64_t size); 11 | void enable_talloc_verbose(); 12 | #ifdef __cplusplus 13 | } 14 | #endif 15 | 16 | uint64_t mem_get_kmem_start(); 17 | uint64_t mem_get_kmem_end(); 18 | uint64_t get_total_ram(); 19 | uint64_t get_total_user_ram(); 20 | uint64_t get_user_ram_start(); 21 | uint64_t get_user_ram_end(); 22 | uint64_t get_shared_start(); 23 | uint64_t get_shared_end(); 24 | 25 | uint64_t alloc_mmio_region(uint64_t size); 26 | 27 | bool is_mmio_allocated(uint64_t addr); -------------------------------------------------------------------------------- /kernel/memory/memory_access.c: -------------------------------------------------------------------------------- 1 | #include "memory_access.h" 2 | 3 | uint8_t read8(uintptr_t addr) { 4 | return *(volatile uint8_t*)addr; 5 | } 6 | 7 | void write8(uintptr_t addr, uint8_t value) { 8 | *(volatile uint8_t*)addr = value; 9 | } 10 | 11 | uint16_t read16(uintptr_t addr) { 12 | return *(volatile uint16_t*)addr; 13 | } 14 | 15 | void write16(uintptr_t addr, uint16_t value) { 16 | *(volatile uint16_t*)addr = value; 17 | } 18 | 19 | uint32_t read32(uintptr_t addr) { 20 | return *(volatile uint32_t*)addr; 21 | } 22 | 23 | void write32(uintptr_t addr, uint32_t value) { 24 | *(volatile uint32_t*)addr = value; 25 | } 26 | 27 | uint64_t read64(uintptr_t addr) { 28 | return *(volatile uint64_t*)addr; 29 | } 30 | 31 | void write64(uintptr_t addr, uint64_t value) { 32 | *(volatile uint64_t*)addr = value; 33 | } 34 | 35 | void write(uint64_t addr, uint64_t value) { 36 | write64(addr, value); 37 | } 38 | 39 | uint64_t read(uint64_t addr) { 40 | return read64(addr); 41 | } -------------------------------------------------------------------------------- /kernel/memory/memory_access.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "types.h" 4 | 5 | uint8_t read8(uintptr_t addr); 6 | void write8(uintptr_t addr, uint8_t value); 7 | uint16_t read16(uintptr_t addr); 8 | void write16(uintptr_t addr, uint16_t value); 9 | uint32_t read32(uintptr_t addr); 10 | void write32(uintptr_t addr, uint32_t value); 11 | uint64_t read64(uintptr_t addr); 12 | void write64(uintptr_t addr, uint64_t value); 13 | void write(uint64_t addr, uint64_t value); 14 | uint64_t read(uint64_t addr); 15 | void write_barrier(); -------------------------------------------------------------------------------- /kernel/memory/memory_types.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "types.h" 4 | 5 | typedef struct FreeBlock { 6 | uint64_t size; 7 | struct FreeBlock* next; 8 | } FreeBlock; 9 | 10 | typedef struct mem_page { 11 | struct mem_page *next; 12 | FreeBlock *free_list; 13 | uint64_t next_free_mem_ptr; 14 | uint64_t size; 15 | } mem_page; -------------------------------------------------------------------------------- /kernel/memory/mmu.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "types.h" 4 | 5 | #define GRANULE_4KB 0x1000 6 | #define GRANULE_2MB 0x200000 7 | 8 | void mmu_alloc(); 9 | void mmu_init(); 10 | #ifdef __cplusplus 11 | extern "C" { 12 | #endif 13 | void register_device_memory(uint64_t va, uint64_t pa); 14 | void register_device_memory_2mb(uint64_t va, uint64_t pa); 15 | void register_proc_memory(uint64_t va, uint64_t pa, bool kernel); 16 | #ifdef __cplusplus 17 | } 18 | #endif 19 | void debug_mmu_address(uint64_t va); 20 | void mmu_enable_verbose(); 21 | 22 | void mmu_unmap(uint64_t va, uint64_t pa); -------------------------------------------------------------------------------- /kernel/memory/page_allocator.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "types.h" 4 | #include "memory_types.h" 5 | 6 | #define ALIGN_4KB 0x1000 7 | #define ALIGN_16B 0x10 8 | #define ALIGN_64B 0x40 9 | 10 | void page_alloc_enable_verbose(); 11 | void page_allocator_init(); 12 | 13 | #ifdef __cplusplus 14 | extern "C" { 15 | #endif 16 | void* alloc_page(uint64_t size, bool kernel, bool device, bool full); 17 | void free_page(void* ptr, uint64_t size); 18 | 19 | void* allocate_in_page(void *page, uint64_t size, uint16_t alignment, bool kernel, bool device); 20 | void free_from_page(void* ptr, uint64_t size); 21 | 22 | void free_sized(sizedptr ptr); 23 | 24 | #ifdef __cplusplus 25 | } 26 | #endif -------------------------------------------------------------------------------- /kernel/networking/drivers/net_driver.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "types.h" 4 | #include "std/string.h" 5 | #include "ui/graphic_types.h" 6 | #include "net/network_types.h" 7 | 8 | class NetDriver { 9 | public: 10 | NetDriver(){} 11 | virtual bool init() = 0; 12 | 13 | virtual sizedptr allocate_packet(size_t size) = 0; 14 | 15 | virtual sizedptr handle_receive_packet() = 0; 16 | 17 | virtual void handle_sent_packet() = 0; 18 | 19 | virtual void enable_verbose() = 0; 20 | 21 | virtual void send_packet(sizedptr packet) = 0; 22 | 23 | virtual void get_mac(network_connection_ctx *context) = 0; 24 | 25 | virtual ~NetDriver() = default; 26 | 27 | uint16_t header_size; 28 | }; -------------------------------------------------------------------------------- /kernel/networking/drivers/virtio_net_pci/virtio_net_pci.hpp: -------------------------------------------------------------------------------- 1 | #include "../net_driver.hpp" 2 | #include "virtio/virtio_pci.h" 3 | #include "net/network_types.h" 4 | 5 | class VirtioNetDriver : public NetDriver { 6 | public: 7 | static VirtioNetDriver* try_init(); 8 | 9 | VirtioNetDriver(){} 10 | 11 | bool init() override; 12 | 13 | sizedptr allocate_packet(size_t size) override; 14 | 15 | sizedptr handle_receive_packet() override; 16 | void handle_sent_packet() override; 17 | 18 | void enable_verbose() override; 19 | 20 | void send_packet(sizedptr packet) override; 21 | 22 | void get_mac(network_connection_ctx *context) override; 23 | 24 | ~VirtioNetDriver() = default; 25 | 26 | private: 27 | bool verbose = false; 28 | uint16_t last_used_receive_idx = 0; 29 | uint16_t last_used_sent_idx = 0; 30 | virtio_device vnp_net_dev; 31 | }; -------------------------------------------------------------------------------- /kernel/networking/network.cpp: -------------------------------------------------------------------------------- 1 | #include "network.h" 2 | #include "network_dispatch.hpp" 3 | #include "std/allocator.hpp" 4 | #include "process/scheduler.h" 5 | 6 | NetworkDispatch *dispatch; 7 | 8 | bool network_init(){ 9 | dispatch = new NetworkDispatch(); 10 | return dispatch->init(); 11 | } 12 | 13 | void network_handle_download_interrupt(){ 14 | return dispatch->handle_download_interrupt(); 15 | } 16 | 17 | void network_handle_upload_interrupt(){ 18 | return dispatch->handle_upload_interrupt(); 19 | } 20 | 21 | 22 | bool network_bind_port(uint16_t port, uint16_t process){ 23 | return dispatch->bind_port(port, process); 24 | } 25 | 26 | bool network_unbind_port(uint16_t port, uint16_t process){ 27 | return dispatch->unbind_port(port, process); 28 | } 29 | 30 | bool network_bind_port_current(uint16_t port){ 31 | return dispatch->bind_port(port, get_current_proc_pid()); 32 | } 33 | 34 | bool network_unbind_port_current(uint16_t port){ 35 | return dispatch->unbind_port(port, get_current_proc_pid()); 36 | } 37 | 38 | void network_send_packet(NetProtocol protocol, uint16_t port, network_connection_ctx *destination, void* payload, uint16_t payload_len){ 39 | return dispatch->send_packet(protocol, port, destination, payload, payload_len); 40 | } 41 | 42 | bool network_read_packet(sizedptr *packet, uint16_t process){ 43 | return dispatch->read_packet(packet, process); 44 | } 45 | 46 | bool network_read_packet_current(sizedptr *packet){ 47 | return dispatch->read_packet(packet, get_current_proc_pid()); 48 | } 49 | 50 | network_connection_ctx* network_get_context(){ 51 | return dispatch->get_context(); 52 | } -------------------------------------------------------------------------------- /kernel/networking/network.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #ifdef __cplusplus 4 | extern "C" { 5 | #endif 6 | 7 | #include "types.h" 8 | #include "net/network_types.h" 9 | 10 | #define NET_IRQ 32 11 | 12 | bool network_init(); 13 | void network_handle_download_interrupt(); 14 | void network_handle_upload_interrupt(); 15 | bool network_bind_port(uint16_t port, uint16_t process); 16 | bool network_unbind_port(uint16_t port, uint16_t process); 17 | void network_send_packet(NetProtocol protocol, uint16_t port, network_connection_ctx *destination, void* payload, uint16_t payload_len); 18 | 19 | bool network_bind_port_current(uint16_t port); 20 | bool network_unbind_port_current(uint16_t port); 21 | 22 | bool network_read_packet(sizedptr *packet, uint16_t process); 23 | bool network_read_packet_current(sizedptr *packet); 24 | 25 | network_connection_ctx* network_get_context(); 26 | 27 | #ifdef __cplusplus 28 | } 29 | #endif -------------------------------------------------------------------------------- /kernel/networking/network_dispatch.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "net/network_types.h" 4 | #include "types.h" 5 | #include "std/indexmap.hpp" 6 | #include "drivers/net_driver.hpp" 7 | 8 | class NetworkDispatch { 9 | public: 10 | NetworkDispatch(); 11 | bool init(); 12 | bool bind_port(uint16_t port, uint16_t process); 13 | bool unbind_port(uint16_t port, uint16_t process); 14 | void handle_upload_interrupt(); 15 | void handle_download_interrupt(); 16 | //TODO: use sizedptr 17 | void send_packet(NetProtocol protocol, uint16_t port, network_connection_ctx *destination, void* payload, uint16_t payload_len); 18 | bool read_packet(sizedptr *Packet, uint16_t process); 19 | 20 | network_connection_ctx* get_context(); 21 | 22 | private: 23 | IndexMap ports; 24 | NetDriver *driver; 25 | 26 | NetDriver* select_driver(); 27 | 28 | sizedptr allocate_packet(size_t size); 29 | network_connection_ctx context; 30 | }; -------------------------------------------------------------------------------- /kernel/networking/processes/net_proc.c: -------------------------------------------------------------------------------- 1 | #include "net_proc.h" 2 | #include "kernel_processes/kprocess_loader.h" 3 | #include "net/network_types.h" 4 | #include "process/scheduler.h" 5 | #include "console/kio.h" 6 | #include "net/udp.h" 7 | #include "net/dhcp.h" 8 | #include "std/memfunctions.h" 9 | #include "networking/network.h" 10 | #include "syscalls/syscalls.h" 11 | #include "math/math.h" 12 | #include "net/tcp.h" 13 | #include "net/http.h" 14 | #include "net/ipv4.h" 15 | #include "net/eth.h" 16 | 17 | network_connection_ctx server; 18 | 19 | bool find_server(){ 20 | bind_port(7777); 21 | server = (network_connection_ctx){ 22 | .ip = (192 << 24) | (168 << 16) | (1 << 8) | 255, 23 | .mac = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, 24 | .port = 8080, 25 | }; 26 | 27 | size_t payload_size = 5; 28 | char hw[5] = {'h','e','l','l','o'}; 29 | 30 | send_packet(UDP, 7777, &server, hw, payload_size); 31 | 32 | sizedptr pack; 33 | 34 | while (!read_packet(&pack)); 35 | 36 | memcpy((void*)&server.mac, (void*)eth_get_source(pack.ptr), 6); 37 | 38 | server.ip = ipv4_get_source(pack.ptr + sizeof(eth_hdr_t)); 39 | 40 | sizedptr payload = udp_parse_packet_payload(pack.ptr); 41 | 42 | uint8_t *content = (uint8_t*)payload.ptr; 43 | 44 | kprintf("PAYLOAD: %s",(uintptr_t)string_ca_max(content, payload.size).data); 45 | 46 | unbind_port(7777); 47 | 48 | return strcmp(content, "world", false) == 0; 49 | } 50 | 51 | void test_network(){ 52 | if (!find_server()){ 53 | kprintf("Could not find update server"); 54 | return; 55 | } 56 | bind_port(8888); 57 | 58 | server.port = 80; 59 | 60 | sizedptr http = request_http_data(GET, &server, 8888); 61 | 62 | if (http.ptr != 0){ 63 | kprintf("Parsing payload"); 64 | sizedptr payload = http_get_payload(http); 65 | string content = http_get_chunked_payload(payload); 66 | printf("Received payload %s",(uintptr_t)content.data); 67 | } 68 | 69 | unbind_port(8888); 70 | } 71 | 72 | uint32_t negotiate_dhcp(){ 73 | kprintf("Sending DHCP request"); 74 | network_connection_ctx *ctx = network_get_context(); 75 | dhcp_request request = (dhcp_request){ 76 | .mac = 0, 77 | .offered_ip = 0, 78 | .server_ip = 0, 79 | }; 80 | memcpy(request.mac, ctx->mac, 6); 81 | send_packet(DHCP, 53, ctx, &request, sizeof(dhcp_request)); 82 | 83 | sizedptr ptr; 84 | 85 | dhcp_packet *payload; 86 | 87 | for (int i = 5; i >= 0; i--){ 88 | while (!read_packet(&ptr));//TODO. Timeout. Opt 89 | kprintf("Received DHCP response"); 90 | payload = dhcp_parse_packet_payload(ptr.ptr); 91 | uint16_t opt_index = dhcp_parse_option(payload, 53); 92 | if (payload->options[opt_index + 2] == 2) 93 | break; 94 | if (i == 0) 95 | return 60000; 96 | } 97 | 98 | uint32_t local_ip = __builtin_bswap32(payload->yiaddr); 99 | kprintf("Received local IP %i.%i.%i.%i",(local_ip >> 24) & 0xFF,(local_ip >> 16) & 0xFF,(local_ip >> 8) & 0xFF,(local_ip >> 0) & 0xFF); 100 | request.offered_ip = payload->yiaddr; 101 | 102 | uint16_t serv_index = dhcp_parse_option(payload, 54); 103 | memcpy((void*)&request.server_ip, (void*)(payload->options + serv_index + 2), min(4,payload->options[serv_index+1])); 104 | 105 | uint16_t lease_index = dhcp_parse_option(payload, 51); 106 | uint32_t lease_time; 107 | memcpy((void*)&lease_time, (void*)(payload->options + lease_index + 2), min(4,payload->options[lease_index+1])); 108 | 109 | lease_time /= 2; 110 | 111 | send_packet(DHCP, 53, ctx, &request, sizeof(dhcp_request)); 112 | 113 | for (int i = 5; i >= 0; i--){ 114 | while (!read_packet(&ptr)); 115 | kprintf("Received DHCP response");//TODO. Timeout. Opt 116 | payload = dhcp_parse_packet_payload(ptr.ptr); 117 | uint16_t opt_index = dhcp_parse_option(payload, 53); 118 | if (payload->options[opt_index + 2] == 5) 119 | break; 120 | if (i == 0) 121 | return 60000; 122 | } 123 | 124 | kprintf("DHCP negotiation finished. Lease %i",lease_time); 125 | 126 | //We can parse options for 127 | //DHCP Server identifier 128 | //Subnet mask 129 | //Router (3) 130 | //DNS (8 bytes) (6) 131 | //TODO: Make subsequent DHCP requests (renewals and requests) directed to the server 132 | ctx->ip = local_ip; 133 | 134 | test_network(); 135 | 136 | return lease_time; 137 | } 138 | 139 | void dhcp_daemon(){ 140 | bind_port(68); 141 | while (true){ 142 | uint32_t await = negotiate_dhcp(); 143 | if (await == 0) break; 144 | kprintf("DHCP Negotiated for %i",await); 145 | sleep(await); 146 | } 147 | bind_port(68); 148 | stop_current_process(); 149 | } 150 | 151 | process_t* launch_net_process(){ 152 | return create_kernel_process("dhcp_daemon",dhcp_daemon); 153 | } -------------------------------------------------------------------------------- /kernel/networking/processes/net_proc.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "process/process.h" 4 | 5 | process_t* launch_net_process(); -------------------------------------------------------------------------------- /kernel/pci.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "types.h" 4 | 5 | #ifdef __cplusplus 6 | extern "C" { 7 | #endif 8 | 9 | #define MSI_OFFSET 50 10 | 11 | typedef struct { 12 | uint64_t base_addr; 13 | uint64_t size; 14 | } pci_device_mmio; 15 | 16 | uint64_t find_pci_device(uint32_t vendor_id, uint32_t device_id); 17 | uint64_t pci_get_bar_address(uint64_t base, uint8_t offset, uint8_t index); 18 | uint64_t pci_setup_bar(uint64_t pci_addr, uint32_t bar_index, uint64_t *mmio_start, uint64_t *mmio_size); 19 | 20 | void pci_enable_device(uint64_t pci_addr); 21 | void pci_register(uint64_t mmio_addr, uint64_t mmio_size); 22 | 23 | void pci_enable_verbose(); 24 | 25 | bool pci_setup_msi(uint64_t pci_addr, uint8_t irq_vector); 26 | 27 | uint8_t pci_setup_interrupts(uint64_t pci_addr, uint8_t irq_line, uint8_t amount); 28 | 29 | typedef struct { 30 | uint32_t addr_offset; 31 | uint8_t irq_num; 32 | } msix_irq_line; 33 | 34 | bool pci_setup_msix(uint64_t pci_addr, msix_irq_line* irq_lines, uint8_t line_size); 35 | 36 | #ifdef __cplusplus 37 | } 38 | #endif -------------------------------------------------------------------------------- /kernel/process/context_switch.S: -------------------------------------------------------------------------------- 1 | .global save_context 2 | save_context: 3 | // x0: pointer to process_t 4 | 5 | // Save general-purpose registers x1-x30 (excluding x0 which holds the pointer) 6 | stp x1, x2, [x0, #(8 * 0)] 7 | stp x3, x4, [x0, #(8 * 2)] 8 | stp x5, x6, [x0, #(8 * 4)] 9 | stp x7, x8, [x0, #(8 * 6)] 10 | stp x9, x10, [x0, #(8 * 8)] 11 | stp x11, x12, [x0, #(8 * 10)] 12 | stp x13, x14, [x0, #(8 * 12)] 13 | stp x15, x16, [x0, #(8 * 14)] 14 | stp x17, x18, [x0, #(8 * 16)] 15 | stp x19, x20, [x0, #(8 * 18)] 16 | stp x21, x22, [x0, #(8 * 20)] 17 | stp x23, x24, [x0, #(8 * 22)] 18 | stp x25, x26, [x0, #(8 * 24)] 19 | stp x27, x28, [x0, #(8 * 26)] 20 | stp x29, x30, [x0, #(8 * 28)] 21 | 22 | // Save SP 23 | str x11, [x0, #(8 * 31)] 24 | 25 | //Save status bits 26 | and x10, x10, 0xFFF 27 | str x10, [x0, #(8 * 33)] 28 | 29 | ret 30 | 31 | .global save_pc_interrupt 32 | save_pc_interrupt: 33 | // x0: pointer to process_t 34 | 35 | mrs x1, elr_el1 36 | str x1, [x0, #(8 * 32)]//PC 37 | 38 | ret 39 | 40 | .global restore_context 41 | restore_context: 42 | // x0: pointer to process_t 43 | 44 | // Restore general-purpose registers x1-x30 45 | ldp x1, x2, [x0, #(8 * 0)] 46 | ldp x3, x4, [x0, #(8 * 2)] 47 | ldp x5, x6, [x0, #(8 * 4)] 48 | ldp x7, x8, [x0, #(8 * 6)] 49 | ldp x9, x10, [x0, #(8 * 8)] 50 | ldp x11, x12, [x0, #(8 * 10)] 51 | ldp x13, x14, [x0, #(8 * 12)] 52 | ldp x15, x16, [x0, #(8 * 14)] 53 | ldp x17, x18, [x0, #(8 * 16)] 54 | ldp x19, x20, [x0, #(8 * 18)] 55 | ldp x21, x22, [x0, #(8 * 20)] 56 | ldp x23, x24, [x0, #(8 * 22)] 57 | ldp x25, x26, [x0, #(8 * 24)] 58 | ldp x27, x28, [x0, #(8 * 26)] 59 | ldp x29, x30, [x0, #(8 * 28)] 60 | 61 | ldr x11, [x0, #(8 * 31)] 62 | mov sp, x11 63 | msr sp_el0, x11 64 | mov x29, x11 65 | ldr x10, [x0, #(8 * 33)] 66 | msr spsr_el1, x10 67 | 68 | ldr x11, [x0, #(8 * 32)] 69 | msr elr_el1, x11 70 | 71 | mov x0, x15 72 | mov x1, x14 73 | mov x30, x12 74 | mov x2, x9 75 | mov x3, x16 76 | 77 | eret -------------------------------------------------------------------------------- /kernel/process/loading/elf_file.c: -------------------------------------------------------------------------------- 1 | #include "elf_file.h" 2 | #include "console/kio.h" 3 | #include "process_loader.h" 4 | 5 | typedef struct elf_header { 6 | char magic[4];//should be " ELF" 7 | uint8_t architecture; 8 | uint8_t endianness; 9 | uint8_t header_version; 10 | uint8_t ABI; 11 | uint64_t padding; 12 | uint16_t type;//1 relocatable, 2 executable, 3 shared, 4 core 13 | uint16_t instruction_set;//Expect 0xB7 = arm 14 | uint16_t elf_version; 15 | uint64_t program_entry_offset; 16 | uint64_t program_header_offset; 17 | uint64_t section_header_offset; 18 | uint32_t flags;// 19 | uint16_t header_size; 20 | uint16_t program_header_entry_size; 21 | uint16_t program_header_num_entries; 22 | uint16_t section_entry_size; 23 | uint16_t section_num_entries; 24 | uint16_t string_table_section_index; 25 | 26 | } elf_header; 27 | 28 | typedef struct elf_program_header { 29 | uint32_t segment_type; 30 | uint32_t flags; 31 | uint64_t p_offset; 32 | uint64_t p_vaddr; 33 | uint64_t p_paddr; 34 | uint64_t p_filez; 35 | uint64_t p_memsz; 36 | uint64_t alignment; 37 | } elf_program_header; 38 | 39 | process_t* load_elf_file(const char *name, void* file){ 40 | elf_header *header = (elf_header*)file; 41 | 42 | if (header->magic[0] != 0x7f){ 43 | kprintf("Failed to read header file"); 44 | return 0; 45 | } 46 | 47 | kprintf("ELF FILE VERSION %x HEADER VERSION %x (%x)",header->elf_version,header->header_version,header->header_size); 48 | kprintf("FILE %i for %x",header->type, header->instruction_set); 49 | kprintf("ENTRY %x - %i",header->program_entry_offset); 50 | kprintf("HEADER %x - %i * %i vs %i",header->program_header_offset, header->program_header_entry_size,header->program_header_num_entries,sizeof(elf_program_header)); 51 | elf_program_header* first_program_header = (elf_program_header*)((uint8_t *)file + header->program_header_offset); 52 | kprintf("program takes up %x, begins at %x, and is %b, %b",first_program_header->p_filez, first_program_header->p_offset, first_program_header->segment_type, first_program_header->flags); 53 | kprintf("SECTION %x - %i * %i",header->section_header_offset, header->section_entry_size,header->section_num_entries); 54 | kprintf("First instruction %x", *(uint64_t*)(file + header->program_entry_offset)); 55 | 56 | return create_process(name, (void*)(file + first_program_header->p_offset), first_program_header->p_filez, header->program_entry_offset); 57 | } -------------------------------------------------------------------------------- /kernel/process/loading/elf_file.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #ifdef __cplusplus 4 | extern "C" { 5 | #endif 6 | 7 | #include "types.h" 8 | #include "process/process.h" 9 | 10 | process_t* load_elf_file(const char *name, void* file); 11 | 12 | #ifdef __cplusplus 13 | } 14 | #endif -------------------------------------------------------------------------------- /kernel/process/loading/process_loader.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #ifdef __cplusplus 4 | extern "C" { 5 | #endif 6 | #include "types.h" 7 | #include "process/process.h" 8 | 9 | process_t* create_process(char *name, void *content, uint64_t content_size, uintptr_t entry); 10 | void translate_enable_verbose(); 11 | #ifdef __cplusplus 12 | } 13 | #endif -------------------------------------------------------------------------------- /kernel/process/process.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #ifdef __cplusplus 4 | extern "C" { 5 | #endif 6 | 7 | #include "types.h" 8 | #include "keypress.h" 9 | #include "net/network_types.h" 10 | 11 | #define INPUT_BUFFER_CAPACITY 64 12 | #define PACKET_BUFFER_CAPACITY 128 13 | 14 | typedef struct { 15 | volatile uint32_t write_index; 16 | volatile uint32_t read_index; 17 | keypress entries[INPUT_BUFFER_CAPACITY]; 18 | } input_buffer_t; 19 | 20 | typedef struct { 21 | volatile uint32_t write_index; 22 | volatile uint32_t read_index; 23 | sizedptr entries[PACKET_BUFFER_CAPACITY]; 24 | } packet_buffer_t; 25 | 26 | #define MAX_PROC_NAME_LENGTH 256 27 | 28 | typedef struct { 29 | //We use the addresses of these variables to save and restore process state 30 | uint64_t regs[31]; // x0–x30 31 | uintptr_t sp; 32 | uintptr_t pc; 33 | uint64_t spsr; 34 | //Not used in process saving 35 | uint16_t id; 36 | uintptr_t stack; 37 | uint64_t stack_size; 38 | uintptr_t heap; 39 | bool focused; 40 | enum process_state { STOPPED, READY, RUNNING, BLOCKED } state; 41 | input_buffer_t input_buffer; 42 | packet_buffer_t packet_buffer; 43 | char name[MAX_PROC_NAME_LENGTH]; 44 | } process_t; 45 | 46 | #ifdef __cplusplus 47 | } 48 | #endif -------------------------------------------------------------------------------- /kernel/process/scheduler.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "types.h" 4 | #include "process/process.h" 5 | 6 | typedef enum { 7 | INTERRUPT, 8 | YIELD, 9 | HALT, 10 | } ProcSwitchReason; 11 | 12 | #define MAX_PROCS 16 13 | 14 | void switch_proc(ProcSwitchReason reason); 15 | void start_scheduler(); 16 | void save_context_registers(); 17 | void save_return_address_interrupt(); 18 | void init_main_process(); 19 | process_t* init_process(); 20 | void save_syscall_return(uint64_t value); 21 | void process_restore(); 22 | 23 | void stop_process(uint16_t pid); 24 | void stop_current_process(); 25 | 26 | void name_process(process_t *proc, const char *name); 27 | 28 | void sleep_process(uint64_t msec); 29 | void wake_processes(); 30 | 31 | #ifdef __cplusplus 32 | extern "C" { 33 | #endif 34 | 35 | process_t* get_current_proc(); 36 | process_t* get_proc_by_pid(uint16_t pid); 37 | uint16_t get_current_proc_pid(); 38 | 39 | uintptr_t get_current_heap(); 40 | bool get_current_privilege(); 41 | #ifdef __cplusplus 42 | } 43 | #endif 44 | 45 | uint16_t process_count(); 46 | process_t *get_all_processes(); 47 | 48 | extern uint64_t ksp; -------------------------------------------------------------------------------- /kernel/process/syscall.c: -------------------------------------------------------------------------------- 1 | #include "syscall.h" 2 | #include "console/kio.h" 3 | #include "exceptions/exception_handler.h" 4 | #include "console/serial/uart.h" 5 | #include "exceptions/irq.h" 6 | #include "process/scheduler.h" 7 | #include "memory/page_allocator.h" 8 | #include "graph/graphics.h" 9 | #include "memory/memory_access.h" 10 | #include "input/input_dispatch.h" 11 | #include "kernel_processes/windows/windows.h" 12 | #include "std/memfunctions.h" 13 | #include "std/string.h" 14 | #include "exceptions/timer.h" 15 | #include "networking/network.h" 16 | 17 | void sync_el0_handler_c(){ 18 | save_context_registers(); 19 | save_return_address_interrupt(); 20 | 21 | if (ksp > 0) 22 | asm volatile ("mov sp, %0" :: "r"(ksp)); 23 | uint64_t x0; 24 | asm volatile ("mov %0, x15" : "=r"(x0)); 25 | uint64_t x1; 26 | asm volatile ("mov %0, x14" : "=r"(x1)); 27 | uint64_t x2; 28 | asm volatile ("mov %0, x9" : "=r"(x2)); 29 | uint64_t x3; 30 | asm volatile ("mov %0, x16" : "=r"(x3)); 31 | uint64_t x4; 32 | asm volatile ("mov %0, x4" : "=r"(x4)); 33 | uint64_t x29; 34 | asm volatile ("mov %0, x13" : "=r"(x29)); 35 | uint64_t x30; 36 | asm volatile ("mov %0, x12" : "=r"(x30)); 37 | uint64_t elr; 38 | asm volatile ("mrs %0, elr_el1" : "=r"(elr)); 39 | uint64_t spsr; 40 | asm volatile ("mrs %0, spsr_el1" : "=r"(spsr)); 41 | 42 | uint64_t currentEL; 43 | asm volatile ("mov %0, x18" : "=r"(currentEL)); 44 | 45 | uint64_t sp_el; 46 | asm volatile ("mov %0, x11" : "=r"(sp_el)); 47 | 48 | uint64_t esr; 49 | asm volatile ("mrs %0, esr_el1" : "=r"(esr)); 50 | 51 | uint64_t ec = (esr >> 26) & 0x3F; 52 | uint64_t iss = esr & 0xFFFFFF; 53 | 54 | 55 | uint64_t result = 0; 56 | if (ec == 0x15) { 57 | switch (iss) 58 | { 59 | case 0: 60 | void* page_ptr = (void*)get_current_heap(); 61 | if ((uintptr_t)page_ptr == 0x0){ 62 | handle_exception_with_info("Wrong process heap state", iss); 63 | } 64 | result = (uintptr_t)allocate_in_page(page_ptr, x0, ALIGN_16B, get_current_privilege(), false); 65 | break; 66 | case 1: 67 | free_from_page((void*)x0, x1); 68 | break; 69 | case 3: 70 | kprintf_l((const char *)x0); 71 | break; 72 | 73 | case 5: 74 | keypress *kp = (keypress*)x0; 75 | result = sys_read_input_current(kp); 76 | break; 77 | 78 | case 10: 79 | if (!screen_overlay) 80 | gpu_clear(x0); 81 | break; 82 | 83 | case 11: 84 | if (!screen_overlay) 85 | gpu_draw_pixel(*(gpu_point*)x0,x1); 86 | break; 87 | 88 | case 12: 89 | if (!screen_overlay) 90 | gpu_draw_line(*(gpu_point*)x0,*(gpu_point*)x1,x2); 91 | break; 92 | 93 | case 13: 94 | if (!screen_overlay) 95 | gpu_fill_rect(*(gpu_rect*)x0,x1); 96 | break; 97 | 98 | case 14: 99 | if (!screen_overlay) 100 | gpu_draw_char(*(gpu_point*)x0,(char)x1,x2,x3); 101 | break; 102 | 103 | case 15: 104 | if (!screen_overlay){ 105 | gpu_draw_string(*(string *)x0,*(gpu_point*)x1,x2,x3); 106 | } 107 | break; 108 | 109 | case 20: 110 | if (!screen_overlay) 111 | gpu_flush(); 112 | break; 113 | 114 | case 21: 115 | result = (uintptr_t)allocate_in_page((void*)get_current_heap(), sizeof(gpu_size), ALIGN_16B, get_current_privilege(), false); 116 | gpu_size size = gpu_get_screen_size(); 117 | memcpy((void*)result, &size, sizeof(gpu_size)); 118 | break; 119 | 120 | case 22: 121 | result = gpu_get_char_size(x0); 122 | break; 123 | 124 | case 30: 125 | sleep_process(x0); 126 | break; 127 | 128 | case 33: 129 | stop_current_process(); 130 | break; 131 | 132 | case 40: 133 | result = timer_now_msec(); 134 | break; 135 | 136 | case 51: 137 | result = network_bind_port(x0, get_current_proc_pid()); 138 | break; 139 | 140 | case 52: 141 | result = network_unbind_port(x0, get_current_proc_pid()); 142 | break; 143 | 144 | case 53: 145 | network_connection_ctx *ctx = (network_connection_ctx*)x2; 146 | void* payload = (void*)x3; 147 | network_send_packet(x0, x1, ctx, payload, x4); 148 | break; 149 | 150 | case 54: 151 | sizedptr *ptr = (sizedptr*)x0; 152 | result = network_read_packet_current(ptr); 153 | break; 154 | 155 | default: 156 | handle_exception_with_info("Unknown syscall", iss); 157 | break; 158 | } 159 | } else { 160 | //We could handle more exceptions now, such as x25 (unmasked x96) = data abort 161 | if (currentEL == 1) 162 | handle_exception_with_info("UNEXPECTED EXCEPTION",ec); 163 | else { 164 | uint64_t far; 165 | asm volatile ("mrs %0, far_el1" : "=r"(far)); 166 | kprintf("Process has crashed. ESR: %x. ELR: %x. FAR: %x", esr, elr, far); 167 | stop_current_process(); 168 | } 169 | } 170 | save_syscall_return(result); 171 | process_restore(); 172 | } 173 | 174 | -------------------------------------------------------------------------------- /kernel/process/syscall.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "types.h" 4 | 5 | -------------------------------------------------------------------------------- /kernel/process/syscall_as.S: -------------------------------------------------------------------------------- 1 | .global sync_el0_handler_as 2 | 3 | //TODO: Rethink the registers used to be sequential both here and in context_switch and exception_vectors_as 4 | sync_el0_handler_as: 5 | msr daifset, #2//Disable interrupts 6 | mov x15, x0 7 | mov x14, x1 8 | mov x9, x2 9 | mov x16, x3 10 | mov x13, x29 11 | mov x12, x30 12 | mrs x10, spsr_el1 13 | lsr x18, x10, #2 14 | and x18, x18, #0b11 15 | 16 | cmp x18, #1 17 | b.eq 1f 18 | cmp x18, #0 19 | b.eq 2f 20 | 21 | b 3f 22 | 23 | 1: mov x11, sp 24 | b 3f 25 | 26 | 2: mrs x11, sp_el0 27 | 28 | 3: 29 | b sync_el0_handler_c 30 | eret -------------------------------------------------------------------------------- /kernel/theme/RedactedOS.h: -------------------------------------------------------------------------------- 1 | #define BOOTSCREEN_TEXT "[REDACTED] Operating System" 2 | 3 | #define BOOTSCREEN_NUM_SYMBOLS 8 4 | #define BOOTSCREEN_NUM_STEPS 7 5 | 6 | #define BOOTSCREEN_NUM_LINES 1 7 | 8 | #define BOOTSCREEN_REPEAT 15 9 | 10 | #define BOOTSCREEN_DIV 10 11 | 12 | #define BOOTSCREEN_OFFSETS {\ 13 | {-4,-2},\ 14 | {-3,-1},\ 15 | {-1,-1},\ 16 | {0,-1},\ 17 | {0,3},\ 18 | {1,3},\ 19 | {5,3},\ 20 | {-5,-2},\ 21 | } 22 | 23 | #define BOOTSCREEN_ASYMM (gpu_point){0,0} 24 | #define BOOTSCREEN_PADDING 0 25 | 26 | #define BOOTSCREEN_INNER_X_CONST 30 27 | #define BOOTSCREEN_OUTER_X_DIV 3 28 | #define BOOTSCREEN_UPPER_Y_DIV 3 29 | #define BOOTSCREEN_LOWER_Y_CONST 30 30 | 31 | #define PANIC_TEXT "FATAL ERROR" 32 | 33 | #define BG_COLOR 0x222233 34 | 35 | #define default_pwd "hi" -------------------------------------------------------------------------------- /kernel/theme/theme.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "RedactedOS.h" -------------------------------------------------------------------------------- /kernel/virtio/virtio_pci.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "types.h" 4 | 5 | #ifdef __cplusplus 6 | extern "C" { 7 | #endif 8 | 9 | #define VIRTQ_DESC_F_NEXT 1 10 | #define VIRTQ_DESC_F_WRITE 2 11 | 12 | typedef struct virtio_pci_common_cfg { 13 | uint32_t device_feature_select; 14 | uint32_t device_feature; 15 | uint32_t driver_feature_select; 16 | uint32_t driver_feature; 17 | uint16_t msix_config; 18 | uint16_t num_queues; 19 | uint8_t device_status; 20 | uint8_t config_generation; 21 | uint16_t queue_select; 22 | uint16_t queue_size; 23 | uint16_t queue_msix_vector; 24 | uint16_t queue_enable; 25 | uint16_t queue_notify_off; 26 | uint64_t queue_desc; 27 | uint64_t queue_driver; 28 | uint64_t queue_device; 29 | uint16_t queue_notify_data; 30 | uint16_t queue_reset; 31 | }__attribute__((packed)) virtio_pci_common_cfg; 32 | 33 | struct virtq_desc { 34 | uint64_t addr; 35 | uint32_t len; 36 | uint16_t flags; 37 | uint16_t next; 38 | } __attribute__((packed)); 39 | 40 | struct virtq_avail { 41 | uint16_t flags; 42 | uint16_t idx; 43 | uint16_t ring[]; 44 | } __attribute__((packed)); 45 | 46 | struct virtq_used_elem { 47 | uint32_t id; 48 | uint32_t len; 49 | } __attribute__((packed)); 50 | 51 | struct virtq_used { 52 | uint16_t flags; 53 | uint16_t idx; 54 | struct virtq_used_elem ring[128]; 55 | } __attribute__((packed)); 56 | 57 | typedef struct virtio_device { 58 | struct virtio_pci_common_cfg* common_cfg; 59 | uint8_t* notify_cfg; 60 | uint8_t* device_cfg; 61 | uint8_t* isr_cfg; 62 | uint32_t notify_off_multiplier; 63 | void *memory_page; 64 | } virtio_device; 65 | 66 | void virtio_set_feature_mask(uint32_t mask); 67 | void virtio_enable_verbose(); 68 | void virtio_get_capabilities(virtio_device *dev, uint64_t pci_addr, uint64_t *mmio_start, uint64_t *mmio_size); 69 | bool virtio_init_device(virtio_device *dev); 70 | bool virtio_send(virtio_device *dev, uint64_t desc, uint64_t avail, uint64_t used, uint64_t cmd, uint32_t cmd_len, uint64_t resp, uint32_t resp_len, uint8_t flags); 71 | bool virtio_send2(virtio_device *dev, uint64_t desc, uint64_t avail, uint64_t used, uint64_t cmd, uint32_t cmd_len, uint64_t resp, uint32_t resp_len, uint8_t flags); 72 | bool virtio_send_1d(virtio_device *dev, uint64_t cmd, uint32_t cmd_len); 73 | void virtio_add_buffer(virtio_device *dev, uint16_t index, uint64_t buf, uint32_t buf_len); 74 | uint32_t select_queue(virtio_device *dev, uint32_t index); 75 | 76 | #ifdef __cplusplus 77 | } 78 | #endif -------------------------------------------------------------------------------- /run_raspi: -------------------------------------------------------------------------------- 1 | #/!bin/sh 2 | 3 | echo "Running raspi emulator" 4 | 5 | ARGS="" 6 | if [ "$1" = "debug" ]; then 7 | ARGS="-monitor unix:/tmp/qemu-monitor-socket,server,nowait -s -S" 8 | fi 9 | 10 | OS_TYPE="$(uname)" 11 | 12 | if [[ "$OS_TYPE" == "Darwin" ]]; then 13 | NETARG="vmnet-bridged,id=net0,ifname=en0" 14 | PRIVILEGE="sudo" 15 | elif [[ "$OS_TYPE" == "Linux" ]]; then 16 | NETARG="user,id=net0" 17 | PRIVILEGE="" 18 | else 19 | echo "Unknown OS: $OS_TYPE" >&2 20 | exit 1 21 | fi 22 | 23 | $PRIVILEGE qemu-system-aarch64 \ 24 | -M raspi4b \ 25 | -kernel kernel.img \ 26 | -display sdl \ 27 | -device sd-card,drive=sd -drive id=sd,format=raw,file=disk.img,if=none \ 28 | -netdev $NETARG \ 29 | -serial mon:stdio \ 30 | -device usb-kbd \ 31 | -d guest_errors \ 32 | $ARGS 33 | -------------------------------------------------------------------------------- /run_virt: -------------------------------------------------------------------------------- 1 | #/!bin/sh 2 | 3 | echo "Running virt emulator" 4 | 5 | ARGS="" 6 | if [ "$1" = "debug" ]; then 7 | ARGS="-monitor unix:/tmp/qemu-monitor-socket,server,nowait -s -S" 8 | fi 9 | 10 | MSI_CAPABILITIES="" 11 | 12 | XHCI_CAPABILITIES="$(qemu-system-aarch64 -device qemu-xhci,help)" 13 | 14 | if echo "$XHCI_CAPABILITIES" | grep -q "msi "; then 15 | MSI_CAPABILITIES="msi=on,msix=off," 16 | fi 17 | 18 | OS_TYPE="$(uname)" 19 | 20 | if [[ "$OS_TYPE" == "Darwin" ]]; then 21 | NETARG="vmnet-bridged,id=net0,ifname=en0" 22 | PRIVILEGE="sudo" 23 | elif [[ "$OS_TYPE" == "Linux" ]]; then 24 | NETARG="user,id=net0" 25 | PRIVILEGE="" 26 | else 27 | echo "Unknown OS: $OS_TYPE" >&2 28 | exit 1 29 | fi 30 | 31 | $PRIVILEGE qemu-system-aarch64 \ 32 | -M virt \ 33 | -cpu cortex-a72 \ 34 | -m 512M \ 35 | -kernel kernel.elf \ 36 | -device virtio-gpu-pci \ 37 | -display sdl \ 38 | -netdev $NETARG \ 39 | -device virtio-net-pci,netdev=net0 \ 40 | -serial mon:stdio \ 41 | -drive file=disk.img,if=none,format=raw,id=hd0 \ 42 | -device virtio-blk-pci,drive=hd0 \ 43 | -device qemu-xhci,${MSI_CAPABILITIES}id=usb \ 44 | -device usb-kbd,bus=usb.0 \ 45 | -d guest_errors \ 46 | $ARGS -------------------------------------------------------------------------------- /rundebug: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | MODE="raspi" 4 | ARGS=() 5 | 6 | for arg in "$@"; do 7 | case $arg in 8 | MODE=*) MODE="${arg#MODE=}" ;; 9 | *) ARGS+=("$arg") ;; 10 | esac 11 | done 12 | 13 | osascript < b ? a : b; 13 | } 14 | 15 | static inline int abs(int n){ 16 | return n < 0 ? -n : n; 17 | } 18 | 19 | static inline int sign(int x) { 20 | return x < 0 ? -1 : 1; 21 | } 22 | 23 | static inline int lerp(int i, int start, int end, int steps) { 24 | return start + (end - start) * i / steps; 25 | } 26 | 27 | #ifdef __cplusplus 28 | } 29 | #endif -------------------------------------------------------------------------------- /shared/net/arp.c: -------------------------------------------------------------------------------- 1 | #include "arp.h" 2 | #include "eth.h" 3 | #include "std/memfunctions.h" 4 | 5 | void create_arp_packet(uintptr_t p, uint8_t* src_mac, uint32_t src_ip, uint8_t* dst_mac, uint32_t dst_ip, bool is_request){ 6 | p = create_eth_packet(p, src_mac, is_request ? (uint8_t[]){0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF} : dst_mac, 0x806); 7 | 8 | arp_hdr_t* arp = (arp_hdr_t*)p; 9 | 10 | arp->htype = __builtin_bswap16(1); 11 | arp->ptype = __builtin_bswap16(0x0800); 12 | arp->hlen = 6; 13 | arp->plen = 4; 14 | arp->opcode = __builtin_bswap16(is_request ? 1 : 2); 15 | memcpy(arp->sender_mac, src_mac, 6); 16 | arp->sender_ip = __builtin_bswap32(src_ip); 17 | memcpy(arp->target_mac, dst_mac, 6); 18 | arp->target_ip = __builtin_bswap32(dst_ip); 19 | } 20 | 21 | void arp_populate_response(network_connection_ctx *ctx, arp_hdr_t* arp){ 22 | memcpy(ctx->mac, arp->sender_mac, 6); 23 | ctx->ip = arp->sender_ip; 24 | } 25 | 26 | bool arp_should_handle(arp_hdr_t *arp, uint32_t ip){ 27 | return __builtin_bswap32(arp->target_ip) == ip; 28 | } -------------------------------------------------------------------------------- /shared/net/arp.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #ifdef __cplusplus 4 | extern "C" { 5 | #endif 6 | 7 | #include "types.h" 8 | #include "net/network_types.h" 9 | 10 | typedef struct __attribute__((packed)) arp_hdr_t { 11 | uint16_t htype; 12 | uint16_t ptype; 13 | uint8_t hlen; 14 | uint8_t plen; 15 | uint16_t opcode; 16 | uint8_t sender_mac[6]; 17 | uint32_t sender_ip; 18 | uint8_t target_mac[6]; 19 | uint32_t target_ip; 20 | } arp_hdr_t; 21 | 22 | void create_arp_packet(uintptr_t p, uint8_t* src_mac, uint32_t src_ip, uint8_t* dst_mac, uint32_t dst_ip, bool is_request); 23 | bool arp_should_handle(arp_hdr_t *arp, uint32_t ip); 24 | void arp_populate_response(network_connection_ctx *ctx, arp_hdr_t* arp); 25 | 26 | #ifdef __cplusplus 27 | } 28 | #endif -------------------------------------------------------------------------------- /shared/net/checksums.c: -------------------------------------------------------------------------------- 1 | #include "network_types.h" 2 | 3 | uint16_t checksum16(uint16_t *data, size_t len) { 4 | uint32_t sum = 0; 5 | for (int i = 0; i < len; i++) sum += data[i]; 6 | while (sum >> 16) sum = (sum & 0xFFFF) + (sum >> 16); 7 | return ~sum; 8 | } 9 | 10 | uint16_t checksum16_pipv4( 11 | uint32_t src_ip, 12 | uint32_t dst_ip, 13 | uint8_t protocol, 14 | const uint8_t* payload, 15 | uint16_t length 16 | ) { 17 | uint32_t sum = 0; 18 | 19 | sum += (src_ip >> 16) & 0xFFFF; 20 | sum += src_ip & 0xFFFF; 21 | sum += (dst_ip >> 16) & 0xFFFF; 22 | sum += dst_ip & 0xFFFF; 23 | sum += protocol; 24 | sum += length; 25 | 26 | for (uint16_t i = 0; i + 1 < length; i += 2) 27 | sum += (payload[i] << 8) | payload[i + 1]; 28 | 29 | if (length & 1) 30 | sum += payload[length - 1] << 8; 31 | 32 | while (sum >> 16) 33 | sum = (sum & 0xFFFF) + (sum >> 16); 34 | 35 | return ~sum; 36 | } -------------------------------------------------------------------------------- /shared/net/dhcp.c: -------------------------------------------------------------------------------- 1 | #include "dhcp.h" 2 | #include "std/memfunctions.h" 3 | 4 | void create_dhcp_packet(uintptr_t p, dhcp_request *payload){ 5 | network_connection_ctx source = (network_connection_ctx){ 6 | .port = 68, 7 | }; 8 | network_connection_ctx destination = (network_connection_ctx){ 9 | .ip = (255 << 24) | (255 << 16) | (255 << 8) | 255, 10 | .mac = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, 11 | .port = 67, 12 | }; 13 | dhcp_packet packet = (dhcp_packet){ 14 | .op = 1,//request 15 | .htype = 1,//Ethernet 16 | .hlen = 6,//Mac length 17 | .hops = 0, 18 | .xid = 372,//Transaction ID: Static, could be random 19 | .secs = 0, 20 | .flags = __builtin_bswap16(0x8000),//Broadcast 21 | .ciaddr = 0, 22 | .yiaddr = 0, 23 | .siaddr = 0, 24 | .giaddr = 0, 25 | }; 26 | memcpy(packet.chaddr, payload->mac, 6); 27 | memcpy(source.mac, payload->mac, 6); 28 | 29 | packet.options[0] = 0x63; // magic 30 | packet.options[1] = 0x82; 31 | packet.options[2] = 0x53; 32 | packet.options[3] = 0x63; // magic 33 | 34 | packet.options[4] = 53; // DHCP type 35 | packet.options[5] = 1; // length 36 | if (payload->server_ip != 0 && payload->offered_ip != 0){ 37 | packet.options[6] = 3; // DHCPREQUEST 38 | 39 | packet.options[7] = 50; 40 | packet.options[8] = 4; 41 | memcpy(&packet.options[9], &payload->offered_ip, 4); 42 | 43 | packet.options[13] = 54; 44 | packet.options[14] = 4; 45 | memcpy(&packet.options[15], &payload->server_ip, 4); 46 | packet.options[19] = 255; 47 | } else { 48 | packet.options[6] = 1; // DHCPDISCOVER 49 | 50 | packet.options[7] = 255; // END 51 | } 52 | 53 | create_udp_packet(p, source, destination, (sizedptr){(uintptr_t)&packet, sizeof(dhcp_packet)}); 54 | } 55 | 56 | dhcp_packet* dhcp_parse_packet_payload(uintptr_t ptr){ 57 | sizedptr sptr = udp_parse_packet_payload(ptr); 58 | return (dhcp_packet*)sptr.ptr; 59 | } 60 | 61 | uint16_t dhcp_parse_option(dhcp_packet *pack, uint16_t option){ 62 | for (int i = 0; i < 312; i++) 63 | if (pack->options[i] == option) return i; 64 | 65 | return 0; 66 | } -------------------------------------------------------------------------------- /shared/net/dhcp.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #ifdef __cplusplus 4 | extern "C" { 5 | #endif 6 | 7 | #include "types.h" 8 | #include "net/network_types.h" 9 | #include "net/udp.h" 10 | 11 | typedef struct __attribute__((packed)) dhcp_packet { 12 | uint8_t op; 13 | uint8_t htype; 14 | uint8_t hlen; 15 | uint8_t hops; 16 | uint32_t xid; 17 | uint16_t secs; 18 | uint16_t flags; 19 | uint32_t ciaddr; 20 | uint32_t yiaddr; 21 | uint32_t siaddr; 22 | uint32_t giaddr; 23 | uint8_t chaddr[16]; 24 | uint8_t sname[64]; 25 | uint8_t file[128]; 26 | uint8_t options[312]; 27 | } dhcp_packet; 28 | 29 | typedef struct dhcp_request { 30 | uint8_t mac[6]; 31 | uint32_t server_ip; 32 | uint32_t offered_ip; 33 | } dhcp_request; 34 | 35 | #define DHCP_SIZE sizeof(eth_hdr_t) + sizeof(ipv4_hdr_t) + sizeof(udp_hdr_t) + sizeof(dhcp_packet) 36 | 37 | void create_dhcp_packet(uintptr_t p, dhcp_request *data); 38 | dhcp_packet* dhcp_parse_packet_payload(uintptr_t ptr); 39 | uint16_t dhcp_parse_option(dhcp_packet *pack, uint16_t option); 40 | 41 | #ifdef __cplusplus 42 | } 43 | #endif -------------------------------------------------------------------------------- /shared/net/eth.c: -------------------------------------------------------------------------------- 1 | #include "eth.h" 2 | #include "std/memfunctions.h" 3 | 4 | uintptr_t create_eth_packet(uintptr_t p, uint8_t src_mac[6], uint8_t dst_mac[6], uint16_t type){ 5 | eth_hdr_t* eth = (eth_hdr_t*)p; 6 | memcpy(eth->src_mac, src_mac, 6); 7 | memcpy(eth->dst_mac, dst_mac, 6); 8 | eth->ethertype = __builtin_bswap16(type); 9 | return p + sizeof(eth_hdr_t); 10 | } 11 | 12 | uint16_t eth_parse_packet_type(uintptr_t ptr){ 13 | eth_hdr_t* eth = (eth_hdr_t*)ptr; 14 | 15 | ptr += sizeof(eth_hdr_t); 16 | 17 | return __builtin_bswap16(eth->ethertype); 18 | } 19 | 20 | uintptr_t eth_get_source(uintptr_t ptr){ 21 | eth_hdr_t* eth = (eth_hdr_t*)ptr; 22 | return (uintptr_t)ð->src_mac; 23 | } -------------------------------------------------------------------------------- /shared/net/eth.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #ifdef __cplusplus 4 | extern "C" { 5 | #endif 6 | 7 | #include "types.h" 8 | #include "net/network_types.h" 9 | 10 | typedef struct __attribute__((packed)) eth_hdr_t { 11 | uint8_t dst_mac[6]; 12 | uint8_t src_mac[6]; 13 | uint16_t ethertype; 14 | } eth_hdr_t; 15 | 16 | uint16_t eth_parse_packet_type(uintptr_t ptr); 17 | uintptr_t create_eth_packet(uintptr_t ptr, uint8_t src_mac[6], uint8_t dst_mac[6], uint16_t type); 18 | uintptr_t eth_get_source(uintptr_t ptr); 19 | 20 | #ifdef __cplusplus 21 | } 22 | #endif -------------------------------------------------------------------------------- /shared/net/http.c: -------------------------------------------------------------------------------- 1 | #include "http.h" 2 | #include "std/string.h" 3 | #include "tcp.h" 4 | #include "syscalls/syscalls.h" 5 | #include "ipv4.h" 6 | #include "std/memfunctions.h" 7 | 8 | string make_http_request(HTTPRequest request, char *domain, char *agent){ 9 | //TODO: request instead of hardcoded GET 10 | return string_format("GET / HTTP/1.1\r\nHost: %s\r\nUser-Agent: %s\r\nAccept: */*\r\n\r\n",domain, agent); 11 | } 12 | 13 | sizedptr http_data_transfer(network_connection_ctx *dest, sizedptr payload, uint16_t port, tcp_data *data, uint8_t retry, uint32_t orig_seq, uint32_t orig_ack){ 14 | if (retry == 5){ 15 | printf("Exceeded max number of retries"); 16 | return (sizedptr){0}; 17 | } 18 | 19 | data->sequence = orig_seq; 20 | data->ack = orig_ack; 21 | data->flags = (1 << PSH_F) | (1 << ACK_F); 22 | 23 | data->payload = payload; 24 | 25 | tcp_send(port, dest, data); 26 | 27 | data->flags = (1 << ACK_F); 28 | 29 | uint8_t resp; 30 | do { 31 | resp = tcp_check_response(data, 0); 32 | if (resp == TCP_OK) 33 | break; 34 | if (resp == TCP_RESET)//We don't reset, we ignore irrelevant packets (or we could parse them tbh) 35 | continue; 36 | if (resp == TCP_RETRY) 37 | return http_data_transfer(dest, payload, port, data, retry+1, orig_seq, orig_ack); 38 | } while (1); 39 | 40 | data->flags = (1 << PSH_F) | (1 << ACK_F); 41 | 42 | sizedptr http_content; 43 | 44 | resp = tcp_check_response(data, &http_content); 45 | if (resp == TCP_RETRY){ 46 | sleep(1000); 47 | return http_data_transfer(dest, payload, port, data, retry+1, orig_seq, orig_ack); 48 | } else if (resp == TCP_RESET){ 49 | tcp_reset(port, dest, data); 50 | return (sizedptr){0}; 51 | } 52 | 53 | data->payload = (sizedptr){0}; 54 | 55 | data->flags = (1 << ACK_F); 56 | tcp_send(port, dest, data); 57 | 58 | return http_content; 59 | } 60 | 61 | sizedptr request_http_data(HTTPRequest request, network_connection_ctx *dest, uint16_t port){ 62 | tcp_data data = (tcp_data){ 63 | .window = UINT16_MAX, 64 | }; 65 | 66 | printf("TCP Handshake"); 67 | 68 | if (!tcp_handskake(dest, 8888, &data, 0)){ 69 | printf("TCP Handshake Error"); 70 | return (sizedptr){0}; 71 | } 72 | 73 | string serverstr = ipv4_to_string(dest->ip); 74 | string req = make_http_request(request, serverstr.data, "redactedos/0.0.1"); 75 | 76 | free(serverstr.data, serverstr.mem_length); 77 | 78 | printf("HTTP Request"); 79 | 80 | //TODO: more chunked support 81 | 82 | sizedptr http_response = http_data_transfer(dest, (sizedptr){(uintptr_t)req.data, req.length}, port, &data, 0, data.sequence, data.ack); 83 | 84 | printf("TCP End"); 85 | 86 | free(req.data, req.mem_length); 87 | 88 | if (!tcp_close(dest, 8888, &data, 0, data.sequence, data.ack)){ 89 | printf("TCP Connnection not closed"); 90 | return (sizedptr){0}; 91 | } 92 | 93 | return http_response; 94 | } 95 | 96 | sizedptr http_get_payload(sizedptr header){ 97 | if (header.ptr && header.size > 0){ 98 | int start = strindex((char*)header.ptr, "\r\n\r\n"); 99 | if (start < header.size){ 100 | return (sizedptr){header.ptr + start + 4,header.size-start-4}; 101 | } 102 | } 103 | return (sizedptr){0,0}; 104 | } 105 | 106 | string http_get_chunked_payload(sizedptr chunk){ 107 | //TODO: allow finding 0 to know when we're done reading the payload 108 | if (chunk.ptr && chunk.size > 0){ 109 | int sizetrm = strindex((char*)chunk.ptr, "\r\n"); 110 | uint64_t chunk_size = parse_hex_u64((char*)chunk.ptr,sizetrm); 111 | return string_ca_max((char*)(chunk.ptr + sizetrm + 2),chunk_size); 112 | } 113 | return (string){0}; 114 | } -------------------------------------------------------------------------------- /shared/net/http.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "tcp.h" 4 | #include "types.h" 5 | #include "network_types.h" 6 | #include "std/string.h" 7 | 8 | typedef enum HTTPRequest { 9 | GET, 10 | POST, 11 | PUT, 12 | DELETE 13 | } HTTPRequest; 14 | 15 | sizedptr request_http_data(HTTPRequest request, network_connection_ctx *dest, uint16_t port); 16 | sizedptr http_get_payload(sizedptr header); 17 | string http_get_chunked_payload(sizedptr chunk); -------------------------------------------------------------------------------- /shared/net/icmp.c: -------------------------------------------------------------------------------- 1 | #include "icmp.h" 2 | #include "net/udp.h" 3 | #include "net/eth.h" 4 | #include "net/ipv4.h" 5 | #include "std/memfunctions.h" 6 | 7 | void create_icmp_packet(uintptr_t p, network_connection_ctx source, network_connection_ctx destination, icmp_data* data){ 8 | p = create_eth_packet(p, source.mac, destination.mac, 0x800); 9 | 10 | p = create_ipv4_packet(p, sizeof(icmp_packet), 0x01, source.ip, destination.ip); 11 | 12 | icmp_packet *packet = (icmp_packet*)p; 13 | 14 | packet->type = __builtin_bswap16(data->response ? 0 : 8); 15 | packet->seq = __builtin_bswap16(data->seq); 16 | packet->id = __builtin_bswap16(data->id); 17 | memcpy(packet->payload, data->payload, 56); 18 | packet->checksum = checksum16((uint16_t*)packet, sizeof(icmp_packet)); 19 | } 20 | 21 | uint16_t icmp_get_sequence(icmp_packet *packet){ 22 | return __builtin_bswap16(packet->seq); 23 | } 24 | 25 | uint16_t icmp_get_id(icmp_packet *packet){ 26 | return __builtin_bswap16(packet->id); 27 | } 28 | 29 | void icmp_copy_payload(void* dest, icmp_packet *packet){ 30 | memcpy(dest, packet->payload, 56); 31 | } -------------------------------------------------------------------------------- /shared/net/icmp.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #ifdef __cplusplus 4 | extern "C" { 5 | #endif 6 | 7 | #include "types.h" 8 | #include "net/network_types.h" 9 | 10 | typedef struct __attribute__((packed)) icmp_packet { 11 | uint8_t type; 12 | uint8_t code; 13 | uint16_t checksum; 14 | uint16_t id; 15 | uint16_t seq; 16 | uint8_t payload[56]; 17 | } icmp_packet; 18 | 19 | typedef struct icmp_data { 20 | uint8_t response; 21 | uint16_t seq; 22 | uint16_t id; 23 | uint8_t payload[56]; 24 | } icmp_data; 25 | 26 | void create_icmp_packet(uintptr_t p, network_connection_ctx source, network_connection_ctx destination, icmp_data *data); 27 | uint16_t icmp_get_sequence(icmp_packet *packet); 28 | uint16_t icmp_get_id(icmp_packet *packet); 29 | void icmp_copy_payload(void* dest, icmp_packet *packet); 30 | 31 | #ifdef __cplusplus 32 | } 33 | #endif -------------------------------------------------------------------------------- /shared/net/ipv4.c: -------------------------------------------------------------------------------- 1 | #include "ipv4.h" 2 | #include "console/kio.h" 3 | #include "network_types.h" 4 | #include "std/string.h" 5 | #include "std/memfunctions.h" 6 | 7 | uintptr_t create_ipv4_packet(uintptr_t p, uint32_t payload_len, uint8_t protocol, uint32_t source_ip, uint32_t destination_ip){ 8 | ipv4_hdr_t* ip = (ipv4_hdr_t*)p; 9 | ip->version_ihl = 0x45; 10 | ip->dscp_ecn = 0; 11 | ip->total_length = __builtin_bswap16(sizeof(ipv4_hdr_t) + payload_len); 12 | ip->identification = 0; 13 | ip->flags_frag_offset = __builtin_bswap16(0x4000); 14 | ip->ttl = 64; 15 | ip->protocol = protocol; 16 | ip->src_ip = __builtin_bswap32(source_ip); 17 | ip->dst_ip = __builtin_bswap32(destination_ip); 18 | ip->header_checksum = checksum16((uint16_t*)ip, 10); 19 | return p + sizeof(ipv4_hdr_t); 20 | } 21 | 22 | uint8_t ipv4_get_protocol(uintptr_t ptr){ 23 | return ((ipv4_hdr_t*)ptr)->protocol; 24 | } 25 | 26 | void ipv4_populate_response(network_connection_ctx *ctx, eth_hdr_t *eth, ipv4_hdr_t* ipv4){ 27 | ctx->ip = __builtin_bswap32(ipv4->src_ip); 28 | memcpy(ctx->mac, eth->src_mac, 6); 29 | } 30 | 31 | string ipv4_to_string(uint32_t ip){ 32 | return string_format("%i.%i.%i.%i",(ip >> 24) & 0xFF,(ip >> 16) & 0xFF,(ip >> 8) & 0xFF,(ip >> 0) & 0xFF); 33 | } 34 | 35 | uint32_t ipv4_get_source(uintptr_t ptr){ 36 | return __builtin_bswap32(((ipv4_hdr_t*)ptr)->src_ip); 37 | } -------------------------------------------------------------------------------- /shared/net/ipv4.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #ifdef __cplusplus 4 | extern "C" { 5 | #endif 6 | 7 | #include "types.h" 8 | #include "net/network_types.h" 9 | #include "std/string.h" 10 | #include "eth.h" 11 | 12 | typedef struct __attribute__((packed)) ipv4_hdr_t { 13 | uint8_t version_ihl; 14 | uint8_t dscp_ecn; 15 | uint16_t total_length; 16 | uint16_t identification; 17 | uint16_t flags_frag_offset; 18 | uint8_t ttl; 19 | uint8_t protocol; 20 | uint16_t header_checksum; 21 | uint32_t src_ip; 22 | uint32_t dst_ip; 23 | } ipv4_hdr_t; 24 | 25 | uint8_t ipv4_get_protocol(uintptr_t ptr); 26 | uintptr_t create_ipv4_packet(uintptr_t p, uint32_t payload_len, uint8_t protocol, uint32_t source_ip, uint32_t destination_ip); 27 | void ipv4_populate_response(network_connection_ctx *ctx, eth_hdr_t *eth, ipv4_hdr_t* ipv4); 28 | string ipv4_to_string(uint32_t ip); 29 | uint32_t ipv4_get_source(uintptr_t ptr); 30 | 31 | #ifdef __cplusplus 32 | } 33 | #endif -------------------------------------------------------------------------------- /shared/net/network_types.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #ifdef __cplusplus 4 | extern "C" { 5 | #endif 6 | 7 | #include "types.h" 8 | 9 | typedef enum NetProtocol { 10 | UDP, 11 | DHCP, 12 | ARP, 13 | TCP, 14 | ICMP 15 | } NetProtocol; 16 | 17 | uint16_t checksum16(uint16_t *data, size_t len); 18 | 19 | uint16_t checksum16_pipv4(uint32_t src_ip, uint32_t dst_ip, uint8_t protocol, const uint8_t* payload, uint16_t length); 20 | 21 | typedef struct network_connection_ctx { 22 | uint16_t port; 23 | uint32_t ip; 24 | uint8_t mac[6]; 25 | } network_connection_ctx; 26 | 27 | #ifdef __cplusplus 28 | } 29 | #endif -------------------------------------------------------------------------------- /shared/net/tcp.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #ifdef __cplusplus 4 | extern "C" { 5 | #endif 6 | 7 | #include "types.h" 8 | #include "net/network_types.h" 9 | 10 | #define FIN_F 0 11 | #define SYN_F 1 12 | #define RST_F 2 13 | #define PSH_F 3 14 | #define ACK_F 4 15 | #define URG_F 5 16 | #define ECE_F 6 17 | #define CWR_F 7 18 | 19 | //TODO: more response types. Indicate why we reset or retry instead of just that 20 | #define TCP_RESET 2 21 | #define TCP_RETRY 1 22 | #define TCP_OK 0 23 | 24 | typedef struct __attribute__((packed)) tcp_hdr_t { 25 | uint16_t src_port; 26 | uint16_t dst_port; 27 | uint32_t sequence; 28 | uint32_t ack; 29 | uint8_t data_offset_reserved;// upper offset, lower reserved 30 | uint8_t flags; 31 | uint16_t window; 32 | uint16_t checksum; 33 | uint16_t urgent_ptr; 34 | } tcp_hdr_t; 35 | 36 | typedef struct tcp_data { 37 | uint32_t sequence; 38 | uint32_t ack; 39 | uint8_t padding; 40 | uint8_t flags; 41 | uint16_t window; 42 | sizedptr options; 43 | sizedptr payload; 44 | uint32_t expected_ack; 45 | } tcp_data; 46 | 47 | void create_tcp_packet(uintptr_t p, network_connection_ctx source, network_connection_ctx destination, sizedptr payload); 48 | size_t calc_tcp_size(uint16_t payload_len); 49 | uint16_t tcp_parse_packet(uintptr_t ptr); 50 | sizedptr tcp_parse_packet_payload(uintptr_t ptr); 51 | 52 | void tcp_send(uint16_t port, network_connection_ctx *destination, tcp_data* data); 53 | void tcp_reset(uint16_t port, network_connection_ctx *destination, tcp_data* data); 54 | bool expect_response(sizedptr *pack); 55 | uint8_t tcp_check_response(tcp_data *data, sizedptr *out); 56 | bool tcp_handskake(network_connection_ctx *dest, uint16_t port, tcp_data *data, uint8_t retry); 57 | bool tcp_close(network_connection_ctx *dest, uint16_t port, tcp_data *data, uint8_t retry, uint32_t orig_seq, uint32_t orig_ack); 58 | 59 | #ifdef __cplusplus 60 | } 61 | #endif -------------------------------------------------------------------------------- /shared/net/udp.c: -------------------------------------------------------------------------------- 1 | #include "udp.h" 2 | #include "console/kio.h" 3 | #include "net/network_types.h" 4 | #include "syscalls/syscalls.h" 5 | #include "eth.h" 6 | #include "ipv4.h" 7 | 8 | void create_udp_packet(uintptr_t p, network_connection_ctx source, network_connection_ctx destination, sizedptr payload){ 9 | p = create_eth_packet(p, source.mac, destination.mac, 0x800); 10 | 11 | p = create_ipv4_packet(p, sizeof(udp_hdr_t) + payload.size, 0x11, source.ip, destination.ip); 12 | 13 | udp_hdr_t* udp = (udp_hdr_t*)p; 14 | udp->src_port = __builtin_bswap16(source.port); 15 | udp->dst_port = __builtin_bswap16(destination.port); 16 | udp->length = __builtin_bswap16(sizeof(udp_hdr_t) + payload.size); 17 | 18 | p += sizeof(udp_hdr_t); 19 | 20 | uint8_t* data = (uint8_t*)p; 21 | uint8_t* payload_c = (uint8_t*)payload.ptr; 22 | for (size_t i = 0; i < payload.size; i++) data[i] = payload_c[i]; 23 | 24 | udp->checksum = __builtin_bswap16(checksum16_pipv4(source.ip,destination.ip,0x11,(uint8_t*)udp,sizeof(udp_hdr_t) + payload.size)); 25 | 26 | } 27 | 28 | uint16_t udp_parse_packet(uintptr_t ptr){ 29 | udp_hdr_t* udp = (udp_hdr_t*)ptr; 30 | ptr += sizeof(udp_hdr_t); 31 | uint16_t port = __builtin_bswap16(udp->dst_port); 32 | return port; 33 | } 34 | 35 | sizedptr udp_parse_packet_payload(uintptr_t ptr){ 36 | eth_hdr_t* eth = (eth_hdr_t*)ptr; 37 | 38 | ptr += sizeof(eth_hdr_t); 39 | 40 | if (__builtin_bswap16(eth->ethertype) == 0x800){ 41 | ipv4_hdr_t* ip = (ipv4_hdr_t*)ptr; 42 | uint32_t srcip = __builtin_bswap32(ip->src_ip); 43 | ptr += sizeof(ipv4_hdr_t); 44 | if (ip->protocol == 0x11){ 45 | udp_hdr_t* udp = (udp_hdr_t*)ptr; 46 | ptr += sizeof(udp_hdr_t); 47 | uint16_t payload_len = __builtin_bswap16(udp->length) - sizeof(udp_hdr_t); 48 | return (sizedptr){ptr,payload_len}; 49 | } 50 | } 51 | 52 | return (sizedptr){0,0}; 53 | } -------------------------------------------------------------------------------- /shared/net/udp.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #ifdef __cplusplus 4 | extern "C" { 5 | #endif 6 | 7 | #include "types.h" 8 | #include "net/network_types.h" 9 | 10 | typedef struct __attribute__((packed)) udp_hdr_t { 11 | uint16_t src_port; 12 | uint16_t dst_port; 13 | uint16_t length; 14 | uint16_t checksum; 15 | } udp_hdr_t; 16 | 17 | void create_udp_packet(uintptr_t p, network_connection_ctx source, network_connection_ctx destination, sizedptr payload); 18 | uint16_t udp_parse_packet(uintptr_t ptr); 19 | sizedptr udp_parse_packet_payload(uintptr_t ptr); 20 | 21 | #ifdef __cplusplus 22 | } 23 | #endif -------------------------------------------------------------------------------- /shared/std/allocator.cpp: -------------------------------------------------------------------------------- 1 | #include "allocator.hpp" 2 | #include "syscalls/syscalls.h" 3 | #include "console/kio.h" 4 | 5 | void* operator new(size_t size) { 6 | return (void*)malloc(size); 7 | } 8 | 9 | void* operator new[](size_t size) { 10 | return (void*)malloc(size); 11 | } 12 | 13 | //TODO: We'll need to implement an unsized version of these, and keep track of size ourselves 14 | 15 | void operator delete(void* ptr, size_t size) noexcept { 16 | free(ptr,size); 17 | } 18 | void operator delete[](void* ptr, size_t size) noexcept { 19 | free(ptr,size); 20 | } -------------------------------------------------------------------------------- /shared/std/allocator.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "types.h" 4 | 5 | void* operator new(size_t size); 6 | void* operator new[](size_t size); 7 | void operator delete(void* ptr, size_t size) noexcept; 8 | void operator delete[](void* ptr, size_t size) noexcept; -------------------------------------------------------------------------------- /shared/std/args.h: -------------------------------------------------------------------------------- 1 | typedef __builtin_va_list va_list; 2 | #define va_start(ap, last) __builtin_va_start(ap, last) 3 | #define va_arg(ap, type) __builtin_va_arg(ap, type) 4 | #define va_end(ap) __builtin_va_end(ap) -------------------------------------------------------------------------------- /shared/std/array.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "types.h" 4 | 5 | #include "allocator.hpp" 6 | #include "syscalls/syscalls.h" 7 | #include "process/scheduler.h" 8 | #include "memory/page_allocator.h" 9 | 10 | template 11 | class Array { 12 | public: 13 | 14 | Array() : items(0), count(0), capacity(0) { 15 | } 16 | 17 | Array(uint32_t capacity) : count(0), capacity(capacity) { 18 | if (capacity == 0) { 19 | items = 0; 20 | return; 21 | } 22 | void *mem = (void*)malloc(sizeof(T) * capacity); 23 | items = reinterpret_cast(mem); 24 | } 25 | 26 | ~Array() { 27 | if (count == 0) return; 28 | for (uint32_t i = 0; i < count; i++) 29 | items[i].~T(); 30 | ::operator delete(items, sizeof(T) * count); 31 | } 32 | 33 | bool add(const T& value) { 34 | if (count >= capacity) return false; 35 | items[count] = value; 36 | count++; 37 | return true; 38 | } 39 | 40 | T& operator[](uint32_t i) { return items[i]; } 41 | const T& operator[](uint32_t i) const { return items[i]; } 42 | uint32_t size() const { return count; } 43 | uint32_t max_size() const { return capacity; } 44 | 45 | T* items; 46 | 47 | //TODO: we could make arrays expandable as linked lists of various arrays with a fixed capacity. Essentially once you reach capacity, you allocate (and point to) another array which can be accessed sequentially 48 | private: 49 | uint32_t count; 50 | uint32_t capacity; 51 | }; -------------------------------------------------------------------------------- /shared/std/indexmap.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "types.h" 4 | 5 | #include "allocator.hpp" 6 | #include "syscalls/syscalls.h" 7 | #include "process/scheduler.h" 8 | #include "memory/page_allocator.h" 9 | 10 | template 11 | class IndexMap { 12 | public: 13 | 14 | IndexMap() : items(0), count(0), capacity(0) { 15 | } 16 | 17 | IndexMap(uint32_t capacity) : count(0), capacity(capacity) { 18 | if (capacity == 0) { 19 | items = 0; 20 | return; 21 | } 22 | void *mem = (void*)malloc(sizeof(T) * capacity); 23 | items = reinterpret_cast(mem); 24 | } 25 | 26 | ~IndexMap() { 27 | //TODO: Deallocation has not been changed since this code was copied off Array 28 | if (count == 0) return; 29 | for (uint32_t i = 0; i < count; i++) 30 | items[i].~T(); 31 | ::operator delete(items, sizeof(T) * count); 32 | } 33 | 34 | bool add(const uint32_t index, const T& value) { 35 | if (count >= capacity) return false; 36 | items[index] = value; 37 | count++; 38 | return true; 39 | } 40 | 41 | //TODO: we need a function for checking if a value exists 42 | T& operator[](uint32_t i) { return items[i]; } 43 | const T& operator[](uint32_t i) const { return items[i]; } 44 | uint32_t size() const { return count; } 45 | uint32_t max_size() const { return capacity; } 46 | 47 | T* items; 48 | 49 | //TODO: we could make arrays expandable as linked lists of various arrays with a fixed capacity. Essentially once you reach capacity, you allocate (and point to) another array which can be accessed sequentially 50 | private: 51 | uint32_t count; 52 | uint32_t capacity; 53 | }; -------------------------------------------------------------------------------- /shared/std/memfunctions.c: -------------------------------------------------------------------------------- 1 | #include "memfunctions.h" 2 | 3 | int memcmp(const void *s1, const void *s2, unsigned long n) { 4 | const unsigned char *a = s1; 5 | const unsigned char *b = s2; 6 | for (unsigned long i = 0; i < n; i++) { 7 | if (a[i] != b[i]) return a[i] - b[i]; 8 | } 9 | return 0; 10 | } 11 | 12 | void *memset(void *dest, int val, unsigned long count) { 13 | unsigned char *ptr = dest; 14 | while (count--) { 15 | *ptr++ = (unsigned char)val; 16 | } 17 | return dest; 18 | } 19 | 20 | void *memcpy(void *dest, const void *src, uint64_t n) { 21 | uint64_t *d64 = (uint64_t *)dest; 22 | const uint64_t *s64 = (const uint64_t *)src; 23 | 24 | uint64_t blocks = n / 32; 25 | for (uint64_t i = 0; i < blocks; i++) { 26 | d64[0] = s64[0]; 27 | d64[1] = s64[1]; 28 | d64[2] = s64[2]; 29 | d64[3] = s64[3]; 30 | d64 += 4; 31 | s64 += 4; 32 | } 33 | 34 | uint64_t remaining = (n % 32) / 8; 35 | for (uint64_t i = 0; i < remaining; i++) { 36 | d64[i] = s64[i]; 37 | } 38 | 39 | uint8_t *d8 = (uint8_t *)(d64 + remaining); 40 | const uint8_t *s8 = (const uint8_t *)(s64 + remaining); 41 | for (uint64_t i = 0; i < n % 8; i++) d8[i] = s8[i]; 42 | 43 | return dest; 44 | } -------------------------------------------------------------------------------- /shared/std/memfunctions.h: -------------------------------------------------------------------------------- 1 | #ifdef __cplusplus 2 | extern "C" { 3 | #endif 4 | 5 | #include "types.h" 6 | 7 | int memcmp(const void *s1, const void *s2, unsigned long n); 8 | void *memset(void *dest, int val, unsigned long count); 9 | void *memcpy(void *dest, const void *src, uint64_t n); 10 | 11 | #ifdef __cplusplus 12 | } 13 | #endif -------------------------------------------------------------------------------- /shared/std/std.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "allocator.hpp" 4 | #include "array.hpp" 5 | #include "indexmap.hpp" -------------------------------------------------------------------------------- /shared/std/string.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "types.h" 4 | #include "args.h" 5 | 6 | #ifdef __cplusplus 7 | extern "C" { 8 | #endif 9 | 10 | typedef struct { 11 | char *data; 12 | uint32_t length; 13 | uint32_t mem_length; 14 | } string; 15 | 16 | typedef struct string_list { 17 | uint32_t count; 18 | char array[]; 19 | } string_list; 20 | 21 | string string_l( char *literal); 22 | string string_ca_max( char *array, uint32_t max_length); 23 | string string_c( char c); 24 | string string_from_hex(uint64_t value); 25 | bool string_equals(string a, string b); 26 | string string_format( char *fmt, ...); 27 | string string_format_va( char *fmt, va_list args); 28 | string string_tail( char *array, uint32_t max_length); 29 | string string_repeat(char symbol, uint32_t amount); 30 | 31 | char tolower(char c); 32 | int strcmp( char *a, char *b, bool case_insensitive); 33 | bool strcont( char *a, char *b); 34 | int strstart(char *a, char *b, bool case_insensitive); 35 | int strend( char *a, char *b, bool case_insensitive); 36 | int strindex( char *a, char *b); 37 | 38 | uint64_t parse_hex_u64(char* str, size_t size); 39 | 40 | bool utf16tochar( uint16_t* str_in, char* out_str, size_t max_len); 41 | 42 | #ifdef __cplusplus 43 | } 44 | #endif -------------------------------------------------------------------------------- /shared/syscalls/syscalls.c: -------------------------------------------------------------------------------- 1 | #include "syscalls.h" 2 | #include "std/string.h" 3 | 4 | void printf(const char *fmt, ...){ 5 | va_list args; 6 | va_start(args, fmt); 7 | string str = string_format_va(fmt, args); 8 | va_end(args); 9 | printl(str.data); 10 | free(str.data, str.mem_length); 11 | } -------------------------------------------------------------------------------- /shared/syscalls/syscalls.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "types.h" 4 | #include "ui/graphic_types.h" 5 | #include "keypress.h" 6 | #include "std/string.h" 7 | #include "net/network_types.h" 8 | 9 | #ifdef __cplusplus 10 | extern "C" { 11 | #endif 12 | 13 | extern void printl(const char *str); 14 | 15 | extern uintptr_t malloc(size_t size); 16 | extern void free(void *ptr, size_t size); 17 | 18 | extern bool read_key(keypress *kp); 19 | 20 | extern void sleep(uint64_t time); 21 | extern void halt(); 22 | 23 | extern void clear_screen(color color); 24 | extern void gpu_flush_data(); 25 | 26 | extern gpu_size* gpu_screen_size(); 27 | extern uint32_t gpu_char_size(uint32_t scale); 28 | 29 | extern void draw_primitive_pixel(gpu_point *p, color color); 30 | extern void draw_primitive_line(gpu_point *p0, gpu_point *p1, color color); 31 | extern void draw_primitive_rect(gpu_rect *r, color color); 32 | extern void draw_primitive_char(gpu_point *p, char c, uint32_t scale, uint32_t color); 33 | extern void draw_primitive_string(string *text, gpu_point *p, uint32_t scale, uint32_t color); 34 | 35 | extern uint64_t get_time(); 36 | 37 | extern bool bind_port(uint16_t port); 38 | extern bool unbind_port(uint16_t port); 39 | extern void send_packet(NetProtocol protocol, uint16_t port, network_connection_ctx *destination, void* payload, uint16_t payload_len); 40 | extern bool read_packet(sizedptr *ptr); 41 | 42 | void printf(const char *fmt, ...); 43 | 44 | #ifdef __cplusplus 45 | } 46 | #endif -------------------------------------------------------------------------------- /shared/syscalls/syscalls_as.S: -------------------------------------------------------------------------------- 1 | .macro syscall_def name:req, id:req 2 | .global \name 3 | .type \name, %function 4 | \name: 5 | svc #\id 6 | ret 7 | .endm 8 | 9 | syscall_def malloc, 0 10 | syscall_def free, 1 11 | 12 | syscall_def printl, 3 13 | 14 | syscall_def read_key, 5 15 | syscall_def register_shortcut, 6 16 | syscall_def read_shortcut, 7 17 | 18 | //Primitives 19 | syscall_def clear_screen, 10 20 | syscall_def draw_primitive_pixel, 11 21 | syscall_def draw_primitive_line, 12 22 | syscall_def draw_primitive_rect, 13 23 | syscall_def draw_primitive_char, 14 24 | syscall_def draw_primitive_string, 15 25 | 26 | //GPU commands 27 | syscall_def gpu_flush_data, 20 28 | syscall_def gpu_screen_size, 21 29 | syscall_def gpu_char_size, 21 30 | 31 | syscall_def sleep, 30 32 | syscall_def process_yield, 31 33 | // syscall_def process_await, 32 34 | syscall_def halt, 33 35 | 36 | //Time commands 37 | syscall_def get_time, 40 38 | 39 | //Network commands 40 | syscall_def bind_port, 51 41 | syscall_def unbind_port, 52 42 | syscall_def send_packet, 53 43 | syscall_def read_packet, 54 -------------------------------------------------------------------------------- /shared/types.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #ifndef asm 4 | #define asm __asm__ 5 | #endif 6 | 7 | #ifdef __cplusplus 8 | extern "C" { 9 | #endif 10 | 11 | 12 | 13 | typedef unsigned int uint32_t; 14 | typedef long unsigned int size_t; 15 | typedef unsigned long uint64_t; 16 | typedef unsigned long uintptr_t; 17 | typedef unsigned short uint16_t; 18 | typedef unsigned char uint8_t; 19 | 20 | #define UINT64_MAX 0xFFFFFFFFFFFFFFFFULL 21 | #define UINT16_MAX 0xFFFF 22 | 23 | typedef int int32_t; 24 | typedef long int64_t; 25 | typedef long intptr_t; 26 | typedef short int16_t; 27 | typedef char int8_t; 28 | 29 | typedef struct sizedptr { 30 | uintptr_t ptr; 31 | size_t size; 32 | } sizedptr; 33 | 34 | #define NULL 0 35 | 36 | #ifdef __cplusplus 37 | } 38 | #else 39 | 40 | typedef unsigned int bool; 41 | 42 | #define true 1 43 | #define false 0 44 | 45 | #endif -------------------------------------------------------------------------------- /shared/ui/UIElement.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "types.h" 4 | #include "graphic_types.h" 5 | 6 | class UIElement { 7 | public: 8 | gpu_rect rect; 9 | void render(); 10 | }; -------------------------------------------------------------------------------- /shared/ui/draw/draw.c: -------------------------------------------------------------------------------- 1 | #include "draw.h" 2 | #include "graph/font8x8_bridge.h" 3 | #include "kstring.h" 4 | 5 | #define line_height char_size + 2 6 | 7 | uint32_t stride = 0; 8 | uint32_t max_width, max_height; 9 | 10 | gpu_rect dirty_rects[MAX_DIRTY_RECTS]; 11 | uint32_t dirty_count = 0; 12 | bool full_redraw = false; 13 | 14 | int try_merge(gpu_rect* a, gpu_rect* b) { 15 | uint32_t ax2 = a->point.x + a->size.width; 16 | uint32_t ay2 = a->point.y + a->size.height; 17 | uint32_t bx2 = b->point.x + b->size.width; 18 | uint32_t by2 = b->point.y + b->size.height; 19 | 20 | if (a->point.x > bx2 || b->point.x > ax2 || a->point.y > by2 || b->point.y > ay2) 21 | return false; 22 | 23 | uint32_t min_x = a->point.x < b->point.x ? a->point.x : b->point.x; 24 | uint32_t min_y = a->point.y < b->point.y ? a->point.y : b->point.y; 25 | uint32_t max_x = ax2 > bx2 ? ax2 : bx2; 26 | uint32_t max_y = ay2 > by2 ? ay2 : by2; 27 | 28 | a->point.x = min_x; 29 | a->point.y = min_y; 30 | a->size.width = max_x - min_x; 31 | a->size.height = max_y - min_y; 32 | 33 | return true; 34 | } 35 | 36 | void mark_dirty(uint32_t x, uint32_t y, uint32_t w, uint32_t h) { 37 | if (full_redraw) return; 38 | 39 | if (x >= max_width || y >= max_height) 40 | return; 41 | 42 | if (x + w > max_width) 43 | w = max_width - x; 44 | 45 | if (y + h > max_height) 46 | h = max_height - y; 47 | 48 | if (w == 0 || h == 0) 49 | return; 50 | 51 | gpu_rect new_rect = { x, y, w, h }; 52 | 53 | for (uint32_t i = 0; i < dirty_count; i++) 54 | if (try_merge(&dirty_rects[i], &new_rect)) 55 | return; 56 | 57 | if (dirty_count < MAX_DIRTY_RECTS) 58 | dirty_rects[dirty_count++] = new_rect; 59 | else 60 | full_redraw = true; 61 | } 62 | 63 | void fb_clear(uint32_t* fb, uint32_t color) { 64 | for (uint32_t i = 0; i < max_width * max_height; i++) { 65 | fb[i] = color; 66 | } 67 | full_redraw = true; 68 | } 69 | 70 | void fb_draw_pixel(uint32_t* fb, uint32_t x, uint32_t y, color color){ 71 | if (x >= max_width || y >= max_height) return; 72 | fb[y * (stride / 4) + x] = color; 73 | //TODO: for some reason, calling mark_dirty from here crashes. Calling it from just outside this function does not. Something to do with merge. Need to investigate. 74 | } 75 | 76 | void fb_fill_rect(uint32_t* fb, uint32_t x, uint32_t y, uint32_t width, uint32_t height, color color){ 77 | for (uint32_t dy = 0; dy < height; dy++) { 78 | for (uint32_t dx = 0; dx < width; dx++) { 79 | fb_draw_pixel(fb, x + dx, y + dy, color); 80 | } 81 | } 82 | mark_dirty(x,y,width,height); 83 | } 84 | 85 | gpu_rect fb_draw_line(uint32_t* fb, uint32_t x0, uint32_t y0, uint32_t x1, uint32_t y1, color color){ 86 | int dx = (x1 > x0) ? (x1 - x0) : (x0 - x1); 87 | int sx = (x0 < x1) ? 1 : -1; 88 | int dy = (y1 > y0) ? (y1 - y0) : (y0 - y1); 89 | int sy = (y0 < y1) ? 1 : -1; 90 | int err = (dx > dy ? dx : -dy) / 2, e2; 91 | 92 | for (;;) { 93 | fb_draw_pixel(fb, x0, y0, color); 94 | if (x0 == x1 && y0 == y1) break; 95 | e2 = err; 96 | if (e2 > -dx) { err -= dy; x0 += sx; } 97 | if (e2 < dy) { err += dx; y0 += sy; } 98 | } 99 | 100 | int min_x = (x0 < x1) ? x0 : x1; 101 | int min_y = (y0 < y1) ? y0 : y1; 102 | int max_x = (x0 > x1) ? x0 : x1; 103 | int max_y = (y0 > y1) ? y0 : y1; 104 | 105 | mark_dirty(min_x,min_y,max_x - min_x + 1,max_y - min_y + 1); 106 | 107 | return (gpu_rect) { {min_x, min_y}, {max_x - min_x + 1, max_y - min_y + 1}}; 108 | } 109 | 110 | void fb_draw_char(uint32_t* fb, uint32_t x, uint32_t y, char c, uint32_t scale, uint32_t color){ 111 | const uint8_t* glyph = get_font8x8((uint8_t)c); 112 | for (uint32_t row = 0; row < (8 * scale); row++) { 113 | uint8_t bits = glyph[row/scale]; 114 | for (uint32_t col = 0; col < (8 * scale); col++) { 115 | if (bits & (1 << (7 - (col / scale)))) { 116 | fb_draw_pixel(fb, x + col, y + row, color); 117 | } 118 | } 119 | } 120 | mark_dirty(x,y,8*scale,8*scale); 121 | } 122 | 123 | gpu_size fb_draw_string(uint32_t* fb, string s, uint32_t x0, uint32_t y0, uint32_t scale, uint32_t color){ 124 | int char_size = fb_get_char_size(scale); 125 | int str_length = s.length; 126 | 127 | uint32_t xoff = 0; 128 | uint32_t xSize = 0; 129 | uint32_t xRowSize = 0; 130 | uint32_t ySize = line_height; 131 | for (int i = 0; i < str_length; i++){ 132 | char c = s.data[i]; 133 | if (c == '\n'){ 134 | y0 += line_height; 135 | ySize += line_height; 136 | if (xRowSize > xSize) 137 | xSize = xRowSize; 138 | xRowSize = 0; 139 | xoff = 0; 140 | } else { 141 | fb_draw_char(fb, x0 + (xoff * char_size),y0,c,scale, color); 142 | xoff++; 143 | xRowSize += char_size; 144 | } 145 | } 146 | if (xRowSize > xSize) 147 | xSize = xRowSize; 148 | 149 | mark_dirty(x0,y0,xSize,ySize); 150 | 151 | return (gpu_size){xSize,ySize}; 152 | } 153 | 154 | uint32_t fb_get_char_size(uint32_t scale){ 155 | return 8 * scale; 156 | } 157 | 158 | void fb_set_stride(uint32_t new_stride){ 159 | stride = new_stride; 160 | } 161 | 162 | void fb_set_bounds(uint32_t width, uint32_t height){ 163 | max_width = width; 164 | max_height = height; 165 | } -------------------------------------------------------------------------------- /shared/ui/draw/draw.h: -------------------------------------------------------------------------------- 1 | #ifdef __cplusplus 2 | extern "C" { 3 | #endif 4 | 5 | #include "types.h" 6 | #include "ui/graphic_types.h" 7 | #include "std/string.h" 8 | 9 | int try_merge(gpu_rect* a, gpu_rect* b); 10 | void mark_dirty(uint32_t x, uint32_t y, uint32_t w, uint32_t h); 11 | 12 | //TODO: to make this a more robust drawing library available without syscall, unify dirty_rects, fb pointer, stride and size into a context structure 13 | 14 | void fb_clear(uint32_t* fb, uint32_t color); 15 | void fb_draw_pixel(uint32_t* fb, uint32_t x, uint32_t y, color color); 16 | void fb_fill_rect(uint32_t* fb, uint32_t x, uint32_t y, uint32_t width, uint32_t height, color color); 17 | gpu_rect fb_draw_line(uint32_t* fb, uint32_t x0, uint32_t y0, uint32_t x1, uint32_t y1, color color); 18 | void fb_draw_char(uint32_t* fb, uint32_t x, uint32_t y, char c, uint32_t scale, uint32_t color); 19 | gpu_size fb_draw_string(uint32_t* fb, string s, uint32_t x, uint32_t y, uint32_t scale, uint32_t color); 20 | uint32_t fb_get_char_size(uint32_t scale); 21 | 22 | void fb_set_stride(uint32_t new_stride); 23 | void fb_set_bounds(uint32_t width, uint32_t height); 24 | 25 | #define MAX_DIRTY_RECTS 64 26 | 27 | extern gpu_rect dirty_rects[MAX_DIRTY_RECTS]; 28 | extern uint32_t dirty_count; 29 | extern bool full_redraw; 30 | 31 | #ifdef __cplusplus 32 | } 33 | #endif -------------------------------------------------------------------------------- /shared/ui/graphic_types.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #ifdef __cplusplus 4 | extern "C" { 5 | #endif 6 | 7 | typedef uint32_t color; 8 | 9 | typedef struct { 10 | uint32_t x; 11 | uint32_t y; 12 | }__attribute__((packed)) gpu_point; 13 | 14 | typedef struct { 15 | uint32_t width; 16 | uint32_t height; 17 | }__attribute__((packed)) gpu_size; 18 | 19 | typedef struct { 20 | gpu_point point; 21 | gpu_size size; 22 | }__attribute__((packed)) gpu_rect; 23 | 24 | #ifdef __cplusplus 25 | } 26 | #endif -------------------------------------------------------------------------------- /shared/ui/label.cpp: -------------------------------------------------------------------------------- 1 | #include "label.hpp" 2 | #include "graph/graphics.h" 3 | #include "console/kio.h" 4 | 5 | Label::Label(){ 6 | 7 | } 8 | 9 | void Label::render(){ 10 | gpu_fill_rect(rect, background_color); 11 | gpu_draw_string(content, calculate_label_pos(), scale, text_color); 12 | } 13 | 14 | gpu_size Label::calculate_label_size(){ 15 | int num_lines = 1; 16 | int num_chars = 0; 17 | int local_num_chars = 0; 18 | for (unsigned int i = 0; i < content.length; i++){ 19 | if (content.data[i] == '\n'){ 20 | if (local_num_chars > num_chars) 21 | num_chars = local_num_chars; 22 | num_lines++; 23 | local_num_chars = 0; 24 | } 25 | else 26 | local_num_chars++; 27 | } 28 | if (local_num_chars > num_chars) 29 | num_chars = local_num_chars; 30 | unsigned int size = gpu_get_char_size(scale); 31 | return (gpu_size){size * num_chars, size * num_lines}; 32 | } 33 | 34 | gpu_point Label::calculate_label_pos(){ 35 | gpu_point point = rect.point; 36 | switch (horz_alignment) 37 | { 38 | case Trailing: 39 | point.x = (rect.point.x + rect.size.width) - calculate_label_size().width; 40 | break; 41 | case HorizontalCenter: 42 | point.x = (rect.point.x + (rect.size.width/2)) - (calculate_label_size().width/2); 43 | break; 44 | default: 45 | break; 46 | } 47 | 48 | switch (vert_alignment) 49 | { 50 | case Bottom: 51 | point.y = (rect.point.y + rect.size.height) - calculate_label_size().height; 52 | break; 53 | case VerticalCenter: 54 | point.y = (rect.point.y + (rect.size.height/2)) - (calculate_label_size().height/2); 55 | break; 56 | default: 57 | break; 58 | } 59 | 60 | return point; 61 | } 62 | 63 | void Label::set_bg_color(color bg){ 64 | this->background_color = bg; 65 | } 66 | 67 | void Label::set_text_color(color txt){ 68 | this->text_color = txt; 69 | } 70 | 71 | void Label::set_text(string text){ 72 | this->content = text; 73 | } 74 | 75 | void Label::set_font_size(unsigned int size){ 76 | this->scale = size; 77 | } 78 | 79 | void Label::set_alignment(HorizontalAlignment horizontal_alignment,VerticalAlignment vertical_alignment){ 80 | horz_alignment = horizontal_alignment; 81 | vert_alignment = vertical_alignment; 82 | } 83 | 84 | void Label::adapt_to_size(){ 85 | rect.size = calculate_label_size(); 86 | } -------------------------------------------------------------------------------- /shared/ui/label.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "UIElement.hpp" 4 | #include "std/string.h" 5 | 6 | enum HorizontalAlignment : int { 7 | Leading = 1 << 1, 8 | HorizontalCenter = 1 << 2, 9 | Trailing = 1 << 3, 10 | }; 11 | 12 | enum VerticalAlignment : int { 13 | Top = 1 << 1, 14 | Bottom = 1 << 2, 15 | VerticalCenter = 1 << 3 16 | }; 17 | 18 | class Label: UIElement { 19 | public: 20 | Label(); 21 | gpu_rect rect; 22 | void set_text(string text); 23 | void set_bg_color(color bg); 24 | void set_text_color(color txt); 25 | void set_font_size(unsigned int size); 26 | void set_alignment(HorizontalAlignment horizontal_alignment,VerticalAlignment vertical_alignment); 27 | void render(); 28 | void adapt_to_size(); 29 | private: 30 | string content; 31 | color background_color; 32 | color text_color; 33 | VerticalAlignment vert_alignment = VerticalAlignment::Top; 34 | HorizontalAlignment horz_alignment = HorizontalAlignment::Leading; 35 | gpu_point calculate_label_pos(); 36 | gpu_size calculate_label_size(); 37 | unsigned int scale = 1; 38 | }; -------------------------------------------------------------------------------- /shared/ui/ui.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "graphic_types.h" 4 | #include "UIElement.hpp" 5 | #include "label.hpp" -------------------------------------------------------------------------------- /user/Makefile: -------------------------------------------------------------------------------- 1 | ARCH= aarch64-none-elf 2 | CC = $(ARCH)-gcc 3 | LD = $(ARCH)-ld 4 | OBJCOPY = $(ARCH)-objcopy 5 | 6 | CFLAGS = -g -O0 -std=c17 -nostdlib -ffreestanding -Wall -Wextra -mcpu=cortex-a72 -I. -I../shared -Wno-unused-parameter 7 | LDFLAGS = -T $(shell ls *.ld) 8 | 9 | C_SRC = $(shell find . -name '*.c') 10 | CPP_SRC = $(shell find . -name '*.cpp') 11 | OBJ = $(C_SRC:.c=.o) $(CPP_SRC:.cpp=.o) 12 | 13 | NAME = $(shell basename "$$PWD") 14 | TARGET = $(NAME).bin 15 | ELF = $(NAME).elf 16 | LOCATION = ../fs/redos/user/ 17 | 18 | all: $(TARGET) 19 | 20 | $(TARGET): $(OBJ) 21 | $(LD) $(LDFLAGS) -o $(LOCATION)$(ELF) $(OBJ) ../shared/libshared.a 22 | $(OBJCOPY) -O binary $(LOCATION)$(ELF) $(LOCATION)$(TARGET) 23 | 24 | %.o: %.S 25 | $(CC) $(CFLAGS) -c $< -o $@ 26 | 27 | %.o: %.c 28 | $(CC) $(CFLAGS) -c $< -o $@ 29 | 30 | %.o: %.cpp 31 | $(CC) $(CFLAGS) -c $< -o $@ 32 | 33 | clean: 34 | rm -f $(shell find . -name '*.o') $(TARGET) -------------------------------------------------------------------------------- /user/default_process.c: -------------------------------------------------------------------------------- 1 | #include "default_process.h" 2 | #include "types.h" 3 | #include "syscalls/syscalls.h" 4 | #include "input_keycodes.h" 5 | #include "std/string.h" 6 | 7 | void proc_func() { 8 | uint64_t j = 0; 9 | gpu_size* size = gpu_screen_size(); 10 | gpu_rect rect = (gpu_rect){{10,10},{size->width-20,size->height-20}}; 11 | while (1) { 12 | keypress kp; 13 | printf("Print console test %f", (get_time()/1000.f)); 14 | while (read_key(&kp)){ 15 | if (kp.keys[0] == KEY_ESC) 16 | halt(); 17 | } 18 | clear_screen(0xFFFFFF); 19 | draw_primitive_rect(&rect, 0x222233); 20 | string s = string_l("Print screen test"); 21 | draw_primitive_string(&s,&rect.point,2, 0xFFFFFF); 22 | free(s.data,s.mem_length); 23 | gpu_flush_data(); 24 | } 25 | } -------------------------------------------------------------------------------- /user/default_process.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | void proc_func(); -------------------------------------------------------------------------------- /user/linker.ld: -------------------------------------------------------------------------------- 1 | ENTRY(proc_func) 2 | 3 | SECTIONS { 4 | . = 0x1000; 5 | 6 | .text : { 7 | *(.text .text.*) 8 | } 9 | 10 | .rodata : { 11 | *(.rodata .rodata.*) 12 | } 13 | 14 | .data : { 15 | *(.data .data.*) 16 | } 17 | 18 | .bss : { 19 | __bss_start = .; 20 | *(.bss .bss.* COMMON) 21 | __bss_end = .; 22 | } 23 | 24 | /DISCARD/ : { 25 | *(.comment .note .eh_frame) 26 | } 27 | } -------------------------------------------------------------------------------- /virt.dtb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/differrari/RedactedOS/706f8645212deff1d6fe44147294ccf965e59041/virt.dtb --------------------------------------------------------------------------------