├── .gitignore ├── LICENSE ├── Makefile ├── README.md ├── disk0.img ├── disk1.img ├── extlibs └── Makefile ├── image.iso ├── iso_root └── .gitignore ├── limine.cfg ├── ovmf ├── OVMF_CODE-pure-efi.fd └── OVMF_VARS-pure-efi.fd └── source ├── Makefile ├── apps ├── kshell.cpp └── kshell.hpp ├── drivers ├── audio │ └── pcspk │ │ ├── pcspk.cpp │ │ └── pcspk.hpp ├── block │ ├── ahci │ │ ├── ahci.cpp │ │ └── ahci.hpp │ ├── ata │ │ ├── ata.cpp │ │ └── ata.hpp │ └── drivemgr │ │ ├── drivemgr.cpp │ │ └── drivemgr.hpp ├── display │ ├── framebuffer │ │ ├── framebuffer.cpp │ │ └── framebuffer.hpp │ ├── serial │ │ ├── serial.cpp │ │ └── serial.hpp │ ├── ssfn │ │ ├── ssfn.cpp │ │ └── ssfn.hpp │ └── terminal │ │ ├── printf_config.cpp │ │ ├── terminal.cpp │ │ └── terminal.hpp ├── fs │ ├── devfs │ │ ├── dev │ │ │ ├── null.cpp │ │ │ ├── null.hpp │ │ │ ├── random.cpp │ │ │ ├── random.hpp │ │ │ ├── tty.cpp │ │ │ ├── tty.hpp │ │ │ ├── zero.cpp │ │ │ └── zero.hpp │ │ ├── devfs.cpp │ │ └── devfs.hpp │ ├── ilar │ │ ├── ilar.cpp │ │ └── ilar.hpp │ ├── initrd │ │ ├── initrd.cpp │ │ └── initrd.hpp │ ├── tmpfs │ │ ├── tmpfs.cpp │ │ └── tmpfs.hpp │ └── ustar │ │ ├── ustar.cpp │ │ └── ustar.hpp ├── net │ ├── e1000 │ │ ├── e1000.cpp │ │ └── e1000.hpp │ ├── nicmgr │ │ ├── nicmgr.cpp │ │ └── nicmgr.hpp │ ├── rtl8139 │ │ ├── rtl8139.cpp │ │ └── rtl8139.hpp │ └── rtl8169 │ │ ├── rtl8169.cpp │ │ └── rtl8169.hpp ├── ps2 │ ├── kbscancodetable │ │ ├── kbscancodetable.cpp │ │ └── kbscancodetable.hpp │ ├── ps2.cpp │ └── ps2.hpp └── vmware │ ├── vmware.cpp │ └── vmware.hpp ├── initrd ├── bin │ └── crash ├── binlink ├── prog ├── prog1 ├── test └── testlink ├── kernel ├── kernel.cpp ├── kernel.hpp ├── main.cpp └── main.hpp ├── lib ├── alloc.cpp ├── alloc.hpp ├── bitmap.cpp ├── bitmap.hpp ├── buddy.cpp ├── buddy.hpp ├── cpu.cpp ├── cpu.hpp ├── cpu.inc ├── cxxabi.cpp ├── cxxabi.hpp ├── elf.h ├── elf.hpp ├── errno.cpp ├── errno.hpp ├── function.hpp ├── io.cpp ├── io.hpp ├── liballoc.cpp ├── liballoc.hpp ├── list.hpp ├── lock.cpp ├── lock.hpp ├── log.cpp ├── log.hpp ├── math.cpp ├── math.hpp ├── memory.asm ├── memory.cpp ├── memory.hpp ├── mmio.cpp ├── mmio.hpp ├── net.hpp ├── panic.cpp ├── panic.hpp ├── pty.cpp ├── pty.hpp ├── reboot.hpp ├── ring.hpp ├── shared_ptr.hpp ├── slab.cpp ├── slab.hpp ├── string.cpp ├── string.hpp ├── timer.cpp ├── timer.hpp └── vector.hpp ├── linker.ld ├── misc ├── bg.bmp ├── unifont.bin └── unifont.sfn ├── system ├── acpi │ ├── acpi.cpp │ └── acpi.hpp ├── cpu │ ├── apic │ │ ├── apic.cpp │ │ └── apic.hpp │ ├── gdt │ │ ├── gdt.cpp │ │ └── gdt.hpp │ ├── idt │ │ ├── idt.asm │ │ ├── idt.cpp │ │ └── idt.hpp │ ├── pic │ │ ├── pic.cpp │ │ └── pic.hpp │ ├── smp │ │ ├── smp.cpp │ │ └── smp.hpp │ └── syscall │ │ ├── syscall.asm │ │ ├── syscall.cpp │ │ └── syscall.hpp ├── mm │ ├── pmm │ │ ├── pmm.cpp │ │ └── pmm.hpp │ └── vmm │ │ ├── vmm.cpp │ │ └── vmm.hpp ├── net │ ├── arp │ │ ├── arp.cpp │ │ └── arp.hpp │ ├── ethernet │ │ ├── ethernet.cpp │ │ └── ethernet.hpp │ ├── icmpv4 │ │ ├── icmpv4.cpp │ │ └── icmpv4.hpp │ └── ipv4 │ │ ├── ipv4.cpp │ │ └── ipv4.hpp ├── pci │ ├── pci.cpp │ ├── pci.hpp │ ├── pcidesc.cpp │ └── pcidesc.hpp ├── sched │ ├── hpet │ │ ├── hpet.cpp │ │ └── hpet.hpp │ ├── pit │ │ ├── pit.cpp │ │ └── pit.hpp │ ├── rtc │ │ ├── rtc.cpp │ │ └── rtc.hpp │ └── scheduler │ │ ├── scheduler.cpp │ │ └── scheduler.hpp ├── trace │ ├── trace.cpp │ └── trace.hpp ├── ubsan │ ├── ubsan.cpp │ └── ubsan.hpp └── vfs │ ├── vfs.cpp │ └── vfs.hpp └── wrappers ├── assert.h ├── climits ├── cstdarg ├── cstring ├── ctype.h ├── functional ├── math.h ├── stdio.h ├── stdlib.h ├── string └── string.h /.gitignore: -------------------------------------------------------------------------------- 1 | .vscode -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | ROOTDIR := $(shell dirname $(realpath $(firstword $(MAKEFILE_LIST)))) 2 | SOURCEDIR := $(ROOTDIR)/source 3 | 4 | all: libs 5 | @$(MAKE) -sC $(SOURCEDIR) clean 6 | @$(MAKE) -sC $(SOURCEDIR) 7 | 8 | bios: libs 9 | @$(MAKE) -sC $(SOURCEDIR) clean 10 | @$(MAKE) -sC $(SOURCEDIR) bios 11 | 12 | vnc: libs 13 | @$(MAKE) -sC $(SOURCEDIR) clean 14 | @$(MAKE) -sC $(SOURCEDIR) vnc 15 | 16 | libs: 17 | @$(MAKE) -sC $(ROOTDIR)/extlibs 18 | 19 | clean: 20 | @$(MAKE) -sC $(SOURCEDIR) clean 21 | @rm -f $(ROOTDIR)/log.txt 22 | 23 | distclean: clean 24 | @$(MAKE) -sC $(ROOTDIR)/extlibs clean -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Kernel project 2 | Note: This kernel is archived, please see: https://github.com/ilobilo/ilobilix 3 | 4 | My first os built from scratch\ 5 | Contributors are welcome 6 | 7 | ## [LICENSE](LICENSE) 8 | 9 | ## TODO 10 | 11 | ### System 12 | - [x] GDT 13 | - [x] IDT 14 | - [x] TSS 15 | - [x] PCI 16 | - [x] PCIe 17 | - [x] MSI 18 | - [ ] MSI-X 19 | 20 | ### Memory 21 | - [x] PMM 22 | - [x] VMM 23 | - [x] Heap 24 | 25 | ### ACPI 26 | - [x] ACPI 27 | - [x] LAPIC 28 | - [x] IOAPIC 29 | - [x] Shutdown 30 | - [x] Reboot 31 | 32 | ### Device drivers 33 | #### Audio 34 | - [x] PC speaker 35 | - [ ] AC97 36 | - [ ] SB16 37 | 38 | #### I/O 39 | - [x] PS/2 Keyboard 40 | - [x] PS/2 Mouse 41 | - [x] COM 42 | 43 | #### VMs 44 | - [x] VMWare Tools 45 | - [ ] VBox Guest Additions 46 | - [ ] Virtio 47 | 48 | #### Storage 49 | - [ ] FDC 50 | - [x] IDE 51 | - [x] SATA 52 | - [ ] NVMe 53 | - [ ] Virtio block 54 | 55 | #### Network 56 | - [x] RTL8139 57 | - [x] RTL8169 (Broken) 58 | - [x] E1000 59 | - [ ] Virtio network 60 | 61 | #### USB 62 | - [ ] UHCI 63 | - [ ] OHCI 64 | - [ ] EHCI 65 | - [ ] XHCI 66 | 67 | ### Timers 68 | - [x] HPET 69 | - [x] PIT 70 | - [x] RTC 71 | - [x] LAPIC Timer 72 | 73 | ### Tasking 74 | - [x] SMP 75 | - [x] Scheduling 76 | - [ ] IPC 77 | 78 | ### Partition tables 79 | - [x] MBR 80 | - [x] GPT 81 | 82 | ### Filesystems 83 | - [x] VFS (Based on Vinix) 84 | - [x] TMPFS 85 | - [x] DEVFS 86 | - [x] Initrd 87 | - [ ] Echfs 88 | - [ ] SFS 89 | - [ ] Ext2 90 | - [ ] Fat32 91 | - [ ] ISO9660 92 | - [ ] NTFS 93 | 94 | ### Userspace 95 | - [x] System calls 96 | - [x] ELF 97 | - [ ] Signals 98 | - [ ] Userspace 99 | - [ ] Libc 100 | - [ ] Bash 101 | - [ ] Coreutils 102 | 103 | ### Network stack 104 | - [x] Ethernet 105 | - [x] ARP 106 | - [x] IPv4 107 | - [ ] IPv4 fragmentation support 108 | - [x] ICMPv4 109 | - [ ] TCP 110 | - [ ] UDP 111 | - [ ] DHCP 112 | - [ ] HTTP 113 | - [ ] Telnet 114 | - [ ] SSL 115 | 116 | ## Building And Running 117 | 118 | Make sure you have following programs installed: 119 | * Clang 120 | * lld 121 | * llvm 122 | * Make 123 | * Nasm 124 | * Qemu x86-64 125 | * Xorriso 126 | * Wget 127 | * Tar 128 | 129 | If you have Debian based system (Ubuntu, linux mint, Pop_os! etc) you can install them with this command:\ 130 | ```sudo apt install clang lld make nasm qemu-system-x86 xorriso wget tar``` 131 | 132 | Follow these steps to build and run the os 133 | 1. Clone this repo with:\ 134 | ``git clone --single-branch --branch=master --depth=1 https://github.com/ilobilo/kernel`` 135 | 136 | 2. Go to the root directory of cloned repo and run:\ 137 | ``make -j$(nproc --all)`` For UEFI mode\ 138 | ``make bios -j$(nproc --all)`` For BIOS mode 139 | 140 | If you, for some reason, are on Termux, run this command instead and connect to ``127.0.0.1:5901`` with VNC viewer:\ 141 | ``make vnc -j$(nproc --all)`` 142 | 143 | ### Options 144 | * ``USEILAR=1``: Use ILAR archive format for initrd instead of USTAR (requires libboost-iostreams-dev) 145 | * ``NOUBSAN=1``: Turn off UBSAN 146 | * ``NOCLEAN=1``: Don't clean the source after compiling 147 | * ``NORUN=1``: Don't run the kernel, just compile 148 | * ``DEBUG=1``: Turn off kvm and enable qemu logging 149 | 150 | ## Discord server 151 | https://discord.gg/fM5GK3RpS7 152 | 153 | ## Resources used: 154 | * Osdev wiki: https://wiki.osdev.org 155 | * Osdev discord server: https://discord.gg/RnCtsqD 156 | * PonchoOS: https://github.com/Absurdponcho/PonchoOS 157 | * Poncho discord server: https://discord.gg/N2Dpwpu4qT 158 | * Limine: https://github.com/limine-bootloader/limine 159 | * Vinix: https://github.com/vlang/vinix 160 | * Lyre: https://github.com/lyre-os/lyre 161 | * Polaris: https://github.com/NSG650/Polaris 162 | * Ilar: https://github.com/ilobilo/ilar 163 | * Printf: https://github.com/eyalroz/printf 164 | * Scalable Screen Font: https://gitlab.com/bztsrc/scalable-font2 165 | * Liballoc: https://github.com/blanham/liballoc 166 | * CWalk: https://github.com/likle/cwalk 167 | * String: https://github.com/cocoz1/cpp-string 168 | * Cxxshim: https://github.com/managarm/cxxshim 169 | * Unifont: https://ftp.gnu.org/gnu/unifont/unifont-14.0.02 170 | -------------------------------------------------------------------------------- /disk0.img: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ilobilo/kernel/e85ed7ec06901c40b339769cfc7236b6b094a9f3/disk0.img -------------------------------------------------------------------------------- /disk1.img: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ilobilo/kernel/e85ed7ec06901c40b339769cfc7236b6b094a9f3/disk1.img -------------------------------------------------------------------------------- /extlibs/Makefile: -------------------------------------------------------------------------------- 1 | EXTLIBDIR := $(shell dirname $(realpath $(firstword $(MAKEFILE_LIST)))) 2 | ROOTDIR := $(shell dirname $(EXTLIBDIR)) 3 | 4 | all: $(EXTLIBDIR)/lai $(EXTLIBDIR)/ilar $(EXTLIBDIR)/cwalk $(EXTLIBDIR)/printf $(EXTLIBDIR)/limine $(EXTLIBDIR)/cxxshim $(EXTLIBDIR)/scalable-font2 5 | 6 | $(EXTLIBDIR)/lai: 7 | echo "Downloading lai" 8 | git clone --single-branch --branch=master --depth=1 https://github.com/managarm/lai || echo "\e[31mFailed to download lai!\e[0m" 9 | 10 | $(EXTLIBDIR)/ilar: 11 | ifdef USEILAR 12 | @echo "Downloading ilar" 13 | @git clone --single-branch --branch=master --depth=1 https://github.com/ilobilo/ilar || echo "\e[31mFailed to download ilar!\e[0m" 14 | $(MAKE) -sC $(EXTLIBDIR)/ilar 15 | endif 16 | 17 | $(EXTLIBDIR)/cwalk: 18 | echo "Downloading cwalk" 19 | git clone --single-branch --branch=master --depth=1 https://github.com/likle/cwalk || echo "\e[31mFailed to download cwalk!\e[0m" 20 | 21 | $(EXTLIBDIR)/printf: 22 | echo "Downloading printf" 23 | git clone --single-branch --branch=master --depth=1 https://github.com/eyalroz/printf || echo "\e[31mFailed to download printf!\e[0m" 24 | 25 | $(EXTLIBDIR)/limine: 26 | @echo "Downloading limine" 27 | @git clone --single-branch --branch=v3.0-branch-binary --depth=1 https://github.com/limine-bootloader/limine || echo "\e[31mFailed to download limine!\e[0m" 28 | $(MAKE) -sC $(EXTLIBDIR)/limine 29 | 30 | $(EXTLIBDIR)/cxxshim: 31 | echo "Downloading cxxshim" 32 | git clone --single-branch --branch=master --depth=1 https://github.com/managarm/cxxshim || echo "\e[31mFailed to download cxxshim!\e[0m" 33 | 34 | $(EXTLIBDIR)/scalable-font2: 35 | echo "Downloading scalable-font2" 36 | git clone --single-branch --branch=master --depth=1 https://gitlab.com/bztsrc/scalable-font2 || echo "\e[31mFailed to download ssfn!\e[0m" 37 | 38 | clean: 39 | rm -rf $(EXTLIBDIR)/lai $(EXTLIBDIR)/ilar $(EXTLIBDIR)/cwalk $(EXTLIBDIR)/printf $(EXTLIBDIR)/limine $(EXTLIBDIR)/cxxshim $(EXTLIBDIR)/scalable-font2 -------------------------------------------------------------------------------- /image.iso: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ilobilo/kernel/e85ed7ec06901c40b339769cfc7236b6b094a9f3/image.iso -------------------------------------------------------------------------------- /iso_root/.gitignore: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ilobilo/kernel/e85ed7ec06901c40b339769cfc7236b6b094a9f3/iso_root/.gitignore -------------------------------------------------------------------------------- /limine.cfg: -------------------------------------------------------------------------------- 1 | TIMEOUT=0 2 | 3 | SERIAL=yes 4 | VERBOSE=yes 5 | 6 | TERM_PALETTE=000000;E83336;31DE56;624726;005DFF;C740F4;20C7FF;A3ADBF # ;001740;FFFFFF 7 | TERM_BACKGROUND=A0000000 8 | TERM_FOREGROUND=FFFFFFFF 9 | 10 | TERM_WALLPAPER=boot:///bg.bmp 11 | TERM_WALLPAPER_STYLE=stretched 12 | 13 | TERM_FONT=boot:///unifont.bin 14 | 15 | :Kernel Project 16 | 17 | PROTOCOL=limine 18 | 19 | KERNEL_PATH=boot:///kernel.elf 20 | KERNEL_CMDLINE=initrd 21 | 22 | MODULE_PATH=$boot:///initrd.img.gz 23 | MODULE_CMDLINE=initrd 24 | 25 | MODULE_PATH=boot:///unifont.sfn 26 | MODULE_CMDLINE=sfn 27 | 28 | KASLR=no -------------------------------------------------------------------------------- /ovmf/OVMF_CODE-pure-efi.fd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ilobilo/kernel/e85ed7ec06901c40b339769cfc7236b6b094a9f3/ovmf/OVMF_CODE-pure-efi.fd -------------------------------------------------------------------------------- /ovmf/OVMF_VARS-pure-efi.fd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ilobilo/kernel/e85ed7ec06901c40b339769cfc7236b6b094a9f3/ovmf/OVMF_VARS-pure-efi.fd -------------------------------------------------------------------------------- /source/apps/kshell.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2021-2022 ilobilo 2 | 3 | #pragma once 4 | 5 | namespace kernel::apps::kshell { 6 | 7 | void run(); 8 | } -------------------------------------------------------------------------------- /source/drivers/audio/pcspk/pcspk.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2021-2022 ilobilo 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | namespace kernel::drivers::audio::pcspk { 9 | 10 | new_lock(pcspk_lock); 11 | 12 | void play(uint64_t freq) 13 | { 14 | uint64_t divisor = 1193180 / freq; 15 | 16 | outb(0x43, 0xB6); 17 | 18 | uint8_t l = static_cast(divisor); 19 | uint8_t h = static_cast(divisor >> 8); 20 | 21 | outb(0x42, l); 22 | outb(0x42, h); 23 | 24 | outb(0x61, inb(0x61) | 0x3); 25 | } 26 | 27 | void stop() 28 | { 29 | outb(0x61, inb(0x61) & 0xFC); 30 | } 31 | 32 | void beep(uint64_t freq, uint64_t msec) 33 | { 34 | lockit(pcspk_lock); 35 | 36 | play(freq); 37 | timer::msleep(msec); 38 | stop(); 39 | } 40 | } -------------------------------------------------------------------------------- /source/drivers/audio/pcspk/pcspk.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2021-2022 ilobilo 2 | 3 | #pragma once 4 | 5 | #include 6 | 7 | namespace kernel::drivers::audio::pcspk { 8 | 9 | enum notes 10 | { 11 | A0 = 28, 12 | AS0 = 29, 13 | B0 = 31, 14 | 15 | C1 = 33, 16 | CS1 = 35, 17 | D1 = 37, 18 | DS1 = 39, 19 | E1 = 41, 20 | F1 = 44, 21 | FS1 = 46, 22 | G1 = 49, 23 | GS1 = 52, 24 | A1 = 55, 25 | AS1 = 58, 26 | B1 = 62, 27 | 28 | C2 = 65, 29 | CS2 = 69, 30 | D2 = 73, 31 | DS2 = 78, 32 | E2 = 82, 33 | F2 = 87, 34 | FS2 = 92, 35 | G2 = 98, 36 | GS2 = 104, 37 | A2 = 110, 38 | AS2 = 117, 39 | B2 = 123, 40 | 41 | C3 = 131, 42 | CS3 = 139, 43 | D3 = 147, 44 | DS3 = 156, 45 | E3 = 165, 46 | F3 = 175, 47 | FS3 = 185, 48 | G3 = 196, 49 | GS3 = 208, 50 | A3 = 220, 51 | AS3 = 233, 52 | B3 = 247, 53 | 54 | C4 = 262, 55 | CS4 = 277, 56 | D4 = 294, 57 | DS4 = 311, 58 | E4 = 330, 59 | F4 = 349, 60 | FS4 = 370, 61 | G4 = 392, 62 | GS4 = 415, 63 | A4 = 440, 64 | AS4 = 466, 65 | B4 = 494, 66 | 67 | C5 = 523, 68 | CS5 = 554, 69 | D5 = 587, 70 | DS5 = 622, 71 | E5 = 659, 72 | F5 = 698, 73 | FS5 = 739, 74 | G5 = 783, 75 | GS5 = 830, 76 | A5 = 880, 77 | AS5 = 932, 78 | B5 = 987, 79 | 80 | C6 = 1046, 81 | CS6 = 1108, 82 | D6 = 1174, 83 | DS6 = 1244, 84 | E6 = 1318, 85 | F6 = 1396, 86 | FS6 = 1479, 87 | G6 = 1567, 88 | GS6 = 1661, 89 | A6 = 1760, 90 | AS6 = 1864, 91 | B6 = 1975, 92 | 93 | DefaultNote = 800, 94 | }; 95 | 96 | enum durations 97 | { 98 | Whole = 1600, 99 | Half = Whole / 2, 100 | Quarter = Half / 2, 101 | Eighth = Quarter / 2, 102 | Sixteenth = Eighth / 2, 103 | 104 | DefaultDur = 200, 105 | }; 106 | 107 | void play(uint64_t freq); 108 | void stop(); 109 | void beep(uint64_t freq, uint64_t msec); 110 | } -------------------------------------------------------------------------------- /source/drivers/block/drivemgr/drivemgr.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2021-2022 ilobilo 2 | 3 | #pragma once 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | using namespace kernel::system; 12 | 13 | namespace kernel::drivers::block::drivemgr { 14 | 15 | static constexpr uint64_t GPT_SIGNATURE = 0x5452415020494645; 16 | static constexpr uint64_t SECTOR_SIZE = 512; 17 | 18 | enum type_t 19 | { 20 | NVME, 21 | SATA, 22 | SATAPI, 23 | ATA, 24 | ATAPI 25 | }; 26 | 27 | enum partFlags 28 | { 29 | PRESENT, 30 | BOOTABLE, 31 | EFISYS 32 | }; 33 | 34 | struct [[gnu::packed]] MBRPart 35 | { 36 | uint8_t Flags; 37 | uint8_t CHSFirst[3]; 38 | uint8_t Type; 39 | uint8_t CHSLast[3]; 40 | uint32_t LBAFirst; 41 | uint32_t Sectors; 42 | }; 43 | 44 | struct [[gnu::packed]] MBRHdr 45 | { 46 | uint8_t Bootstrap[440]; 47 | uint32_t UniqueID; 48 | uint16_t Reserved; 49 | MBRPart Partitions[4]; 50 | uint8_t Signature[2]; 51 | }; 52 | 53 | struct [[gnu::packed]] GPTPart 54 | { 55 | uint64_t TypeLow; 56 | uint64_t TypeHigh; 57 | uint64_t GUIDLow; 58 | uint64_t GUIDHigh; 59 | uint64_t StartLBA; 60 | uint64_t EndLBA; 61 | uint64_t Attributes; 62 | char Label[72]; 63 | }; 64 | 65 | struct [[gnu::packed]] GPTHdr 66 | { 67 | uint64_t Signature; 68 | uint32_t Revision; 69 | uint32_t HdrSize; 70 | uint32_t HdrCRC32; 71 | uint32_t Reserved; 72 | uint64_t LBA; 73 | uint64_t ALTLBA; 74 | uint64_t FirstBlock; 75 | uint64_t LastBlock; 76 | uint64_t GUIDLow; 77 | uint64_t GUIDHigh; 78 | uint64_t PartLBA; 79 | uint32_t PartCount; 80 | uint32_t EntrySize; 81 | uint32_t PartCRC32; 82 | }; 83 | 84 | struct partTable 85 | { 86 | MBRHdr mbr; 87 | GPTHdr gpt; 88 | }; 89 | 90 | struct Partition; 91 | struct Drive : vfs::resource_t 92 | { 93 | uint8_t *buffer = nullptr; 94 | 95 | partTable parttable; 96 | vector partitions; 97 | uint64_t sectors; 98 | type_t type; 99 | }; 100 | 101 | struct Partition : vfs::resource_t 102 | { 103 | uint64_t start; 104 | uint64_t sectors; 105 | uint64_t flags; 106 | vfs::resource_t *parent; 107 | 108 | int64_t read(void *handle, uint8_t *buffer, uint64_t offset, uint64_t size) 109 | { 110 | if (offset + size > this->sectors * this->parent->stat.blksize) 111 | { 112 | size = this->sectors * this->parent->stat.blksize - offset; 113 | } 114 | return this->parent->read(handle, buffer, this->start + offset, size); 115 | } 116 | 117 | int64_t write(void *handle, uint8_t *buffer, uint64_t offset, uint64_t size) 118 | { 119 | if (offset + size > this->sectors * this->parent->stat.blksize) 120 | { 121 | size = this->sectors * this->parent->stat.blksize - offset; 122 | } 123 | return this->parent->write(handle, buffer, this->start + offset, size); 124 | } 125 | 126 | int ioctl(void *handle, uint64_t request, void *argp) 127 | { 128 | return this->parent->ioctl(handle, request, argp); 129 | } 130 | bool grow(void *handle, size_t new_size) 131 | { 132 | return this->parent->grow(handle, new_size); 133 | } 134 | void unref(void *handle) 135 | { 136 | this->parent->unref(handle); 137 | } 138 | void link(void *handle) 139 | { 140 | } 141 | void unlink(void *handle) 142 | { 143 | } 144 | void *mmap(uint64_t page, int flags) 145 | { 146 | return this->parent->mmap(page, flags); 147 | } 148 | }; 149 | 150 | extern bool initialised; 151 | extern vector drives; 152 | 153 | void init(); 154 | } -------------------------------------------------------------------------------- /source/drivers/display/framebuffer/framebuffer.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2021-2022 ilobilo 2 | 3 | #pragma once 4 | 5 | #include 6 | #include 7 | 8 | namespace kernel::drivers::display::framebuffer { 9 | 10 | extern limine_framebuffer **framebuffers; 11 | extern limine_framebuffer *main_frm; 12 | extern uint64_t frm_count; 13 | 14 | void putpix(uint64_t x, uint64_t y, uint32_t colour, limine_framebuffer *frm = main_frm); 15 | void putpix(uint64_t x, uint64_t y, uint32_t r, uint32_t g, uint64_t b, limine_framebuffer *frm = main_frm); 16 | uint32_t getpix(uint64_t x, uint64_t y, limine_framebuffer *frm = main_frm); 17 | 18 | void drawline(uint64_t x0, uint64_t y0, uint64_t x1, uint64_t y1, uint32_t colour, limine_framebuffer *frm = main_frm); 19 | 20 | void drawrectangle(uint64_t x, uint64_t y, uint64_t w, uint64_t h, uint32_t colour, limine_framebuffer *frm = main_frm); 21 | void drawfilledrectangle(uint64_t x, uint64_t y, uint64_t w, uint64_t h, uint32_t colour, limine_framebuffer *frm = main_frm); 22 | 23 | void drawcircle(uint64_t xm, uint64_t ym, uint64_t r, uint32_t colour, limine_framebuffer *frm = main_frm); 24 | void drawfilledcircle(uint64_t cx, uint64_t cy, uint64_t radius, uint32_t colour, limine_framebuffer *frm = main_frm); 25 | 26 | void drawovercursor(uint8_t cursor[], point pos, uint32_t colour, bool back, limine_framebuffer *frm = main_frm); 27 | void clearcursor(uint8_t cursor[], point pos, limine_framebuffer *frm = main_frm); 28 | 29 | void init(); 30 | } -------------------------------------------------------------------------------- /source/drivers/display/serial/serial.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2021-2022 ilobilo 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | using namespace kernel::drivers::fs; 14 | using namespace kernel::system::cpu; 15 | using namespace kernel::system; 16 | 17 | namespace kernel::drivers::display::serial { 18 | 19 | struct ttys_res : pty_res 20 | { 21 | COMS thiscom; 22 | 23 | ttys_res(COMS _thiscom) : pty_res(0, 0), thiscom(_thiscom) { } 24 | 25 | int print(const char *fmt, ...) 26 | { 27 | va_list args; 28 | va_start(args, fmt); 29 | int ret = vfctprintf(printc, reinterpret_cast(this->thiscom), fmt, args); 30 | va_end(args); 31 | 32 | return ret; 33 | } 34 | }; 35 | 36 | bool initialised = false; 37 | ttys_res *current_ttys = nullptr; 38 | new_lock(serial_lock); 39 | 40 | static bool is_transmit_empty(COMS com = COM1) 41 | { 42 | return inb(com + 5) & 0x20; 43 | } 44 | 45 | static bool received(COMS com = COM1) 46 | { 47 | uint8_t status = inb(com + 5); 48 | return (status != 0xFF) && (status & 1); 49 | } 50 | 51 | static char read(COMS com = COM1) 52 | { 53 | while (!received()); 54 | return inb(com); 55 | } 56 | 57 | void printc(char c, void *arg) 58 | { 59 | while (!is_transmit_empty()); 60 | outb(reinterpret_cast(arg), c); 61 | } 62 | 63 | int print(COMS com, const char *fmt, ...) 64 | { 65 | lockit(serial_lock); 66 | 67 | va_list args; 68 | va_start(args, fmt); 69 | int ret = vfctprintf(&printc, reinterpret_cast(com), fmt, args); 70 | va_end(args); 71 | 72 | return ret; 73 | } 74 | 75 | void newline(COMS com) 76 | { 77 | print(com, "\n"); 78 | } 79 | 80 | static void com1_handler(registers_t *) 81 | { 82 | char c = read(COM1); 83 | if (c == 0) return; 84 | current_ttys->add_char(c); 85 | } 86 | 87 | static void com2_handler(registers_t *) 88 | { 89 | char c = read(COM2); 90 | if (c == 0) return; 91 | current_ttys->add_char(c); 92 | } 93 | 94 | static void initport(COMS com) 95 | { 96 | outb(com + 1, 0x00); 97 | outb(com + 3, 0x80); 98 | outb(com + 0, 0x01); 99 | outb(com + 1, 0x00); 100 | outb(com + 3, 0x03); 101 | outb(com + 2, 0xC7); 102 | outb(com + 4, 0x0B); 103 | 104 | print(com, "\033[0m\n"); 105 | } 106 | 107 | void early_init() 108 | { 109 | initport(COM1); 110 | initport(COM2); 111 | 112 | idt::register_interrupt_handler(idt::IRQ4, com1_handler); 113 | idt::register_interrupt_handler(idt::IRQ3, com2_handler); 114 | 115 | outb(COM1 + 1, 0x01); 116 | outb(COM2 + 1, 0x01); 117 | } 118 | 119 | void init() 120 | { 121 | if (initialised) return; 122 | 123 | ttys_res *res = new ttys_res(COM1); 124 | devfs::add(res, "ttyS0"); 125 | 126 | current_ttys = res; 127 | 128 | res = new ttys_res(COM2); 129 | devfs::add(res, "ttyS1"); 130 | 131 | initialised = true; 132 | } 133 | } -------------------------------------------------------------------------------- /source/drivers/display/serial/serial.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2021-2022 ilobilo 2 | 3 | #pragma once 4 | 5 | namespace kernel::drivers::display::serial { 6 | 7 | enum COMS 8 | { 9 | COM1 = 0x3F8, 10 | COM2 = 0x2F8, 11 | COM3 = 0x3E8, 12 | COM4 = 0x2E8 13 | }; 14 | 15 | extern bool initialised; 16 | 17 | void printc(char c, void *arg = nullptr); 18 | int print(COMS com, const char *fmt, ...); 19 | void newline(COMS com = COM1); 20 | 21 | void early_init(); 22 | void init(); 23 | } -------------------------------------------------------------------------------- /source/drivers/display/ssfn/ssfn.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2021-2022 ilobilo 2 | 3 | #include 4 | #include 5 | #define SSFN_CONSOLEBITMAP_TRUECOLOR 6 | #define SSFN_CONSOLEBITMAP_CONTROL 7 | #define __THROW 8 | #include 9 | 10 | namespace kernel::drivers::display::ssfn { 11 | 12 | uint32_t bgcolour; 13 | uint32_t fgcolour = 0xFFFFFF; 14 | point pos = { 0, 0 }; 15 | 16 | void putc(char c, void *arg) 17 | { 18 | ssfn_putc(c); 19 | } 20 | 21 | void setcolour(uint64_t fg, uint64_t bg) 22 | { 23 | bgcolour = bg; 24 | fgcolour = fg; 25 | 26 | ssfn_dst.fg = fgcolour; 27 | ssfn_dst.bg = bgcolour; 28 | } 29 | 30 | void setpos(uint64_t x, uint64_t y) 31 | { 32 | pos.X = ssfn_dst.x = x * 8; 33 | pos.Y = ssfn_dst.y = y * 16; 34 | } 35 | 36 | void resetpos() 37 | { 38 | pos.X = ssfn_dst.x = 0; 39 | pos.Y = ssfn_dst.y = 0; 40 | } 41 | 42 | void printf(const char *fmt, ...) 43 | { 44 | va_list args; 45 | va_start(args, fmt); 46 | vfctprintf(&putc, nullptr, fmt, args); 47 | va_end(args); 48 | } 49 | 50 | void init(uint64_t sfn) 51 | { 52 | ssfn_src = reinterpret_cast(sfn); 53 | 54 | ssfn_dst.ptr = reinterpret_cast(framebuffer::main_frm->address); 55 | ssfn_dst.w = framebuffer::main_frm->width; 56 | ssfn_dst.h = framebuffer::main_frm->height; 57 | ssfn_dst.p = framebuffer::main_frm->pitch; 58 | ssfn_dst.x = ssfn_dst.y = pos.X = pos.Y = 0; 59 | ssfn_dst.fg = fgcolour; 60 | } 61 | } -------------------------------------------------------------------------------- /source/drivers/display/ssfn/ssfn.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2021-2022 ilobilo 2 | 3 | #pragma once 4 | 5 | #include 6 | 7 | namespace kernel::drivers::display::ssfn { 8 | 9 | extern uint64_t bgcolour; 10 | extern uint64_t fgcolour; 11 | extern point pos; 12 | 13 | void setcolour(uint64_t fg = fgcolour, uint64_t bg = bgcolour); 14 | 15 | void setpos(uint64_t x, uint64_t y); 16 | void resetpos(); 17 | 18 | void printf(const char *fmt, ...); 19 | void printfat(uint64_t x, uint64_t y, const char *fmt, ...); 20 | 21 | void init(uint64_t sfn); 22 | } -------------------------------------------------------------------------------- /source/drivers/display/terminal/printf_config.cpp: -------------------------------------------------------------------------------- 1 | #define PRINTF_SUPPORT_EXPONENTIAL_SPECIFIERS 0 2 | #define PRINTF_ALIAS_STANDARD_FUNCTION_NAMES 1 3 | #define PRINTF_SUPPORT_DECIMAL_SPECIFIERS 0 4 | #include -------------------------------------------------------------------------------- /source/drivers/display/terminal/terminal.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2021-2022 ilobilo 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | using namespace kernel::drivers::fs::dev; 12 | using namespace kernel::drivers::audio; 13 | 14 | namespace kernel::drivers::display::terminal { 15 | 16 | static point pos = { 0, 0 }; 17 | new_lock(term_lock); 18 | char *resetcolour = "\033[0m"_c; 19 | 20 | limine_terminal **terminals; 21 | limine_terminal *main_term; 22 | uint64_t term_count; 23 | 24 | void init() 25 | { 26 | terminals = terminal_request.response->terminals; 27 | main_term = terminals[0]; 28 | term_count = terminal_request.response->terminal_count; 29 | } 30 | 31 | #pragma region Print 32 | void print(const char *str, limine_terminal *term) 33 | { 34 | lockit(term_lock); 35 | if (terminal_request.response == nullptr || term == nullptr) return; 36 | terminal_request.response->write(term, str, strlen(str)); 37 | } 38 | 39 | void printi(int num, limine_terminal *term) 40 | { 41 | if (num != 0) 42 | { 43 | char temp[10]; 44 | int i = 0; 45 | if (num < 0) 46 | { 47 | printc('-'); 48 | num = -num; 49 | } 50 | if (num <= 0) 51 | { 52 | temp[i++] = '8'; 53 | num = -(num / 10); 54 | } 55 | while (num > 0) 56 | { 57 | temp[i++] = num % 10 + '0'; 58 | num /= 10; 59 | } 60 | while (--i >= 0) printc(temp[i], term); 61 | } 62 | else printc('0', term); 63 | } 64 | 65 | void printc(char c, limine_terminal *term) 66 | { 67 | char str[] = { c, 0 }; 68 | print(str, term); 69 | } 70 | #pragma endregion Print 71 | 72 | #pragma region Clear 73 | void reset(limine_terminal *term) 74 | { 75 | lockit(term_lock); 76 | if (terminal_request.response == nullptr || term == nullptr) return; 77 | terminal_request.response->write(term, "", LIMINE_TERMINAL_FULL_REFRESH); 78 | } 79 | 80 | void clear(const char *ansii_colour, limine_terminal *term) 81 | { 82 | // reset(term); 83 | print(ansii_colour, term); 84 | print("\033[H\033[2J", term); 85 | } 86 | #pragma endregion Clear 87 | 88 | #pragma region CursorCtrl 89 | void cursor_up(int lines, limine_terminal *term) 90 | { 91 | printf(term, "\033[%dA", lines); 92 | } 93 | void cursor_down(int lines, limine_terminal *term) 94 | { 95 | printf(term, "\033[%dB", lines); 96 | } 97 | void cursor_right(int lines, limine_terminal *term) 98 | { 99 | printf(term, "\033[%dC", lines); 100 | } 101 | void cursor_left(int lines, limine_terminal *term) 102 | { 103 | printf(term, "\033[%dD", lines); 104 | } 105 | #pragma endregion CursorCtrl 106 | 107 | #pragma region Misc 108 | void center(const char *text, limine_terminal *term) 109 | { 110 | for (uint64_t i = 0; i < term->columns / 2 - strlen(text) / 2; i++) printc(' '); 111 | print(text); 112 | for (uint64_t i = 0; i < term->columns / 2 - strlen(text) / 2; i++) printc(' '); 113 | } 114 | 115 | void callback(limine_terminal *term, uint64_t type, uint64_t first, uint64_t second, uint64_t third) 116 | { 117 | switch (type) 118 | { 119 | case LIMINE_TERMINAL_CB_BELL: 120 | pcspk::beep(800, 200); 121 | break; 122 | case LIMINE_TERMINAL_CB_POS_REPORT: 123 | pos.X = first; 124 | pos.Y = second; 125 | break; 126 | case LIMINE_TERMINAL_CB_KBD_LEDS: 127 | switch (first) 128 | { 129 | case 0: 130 | tty::current_tty->scrollock = false; 131 | tty::current_tty->numlock = false; 132 | tty::current_tty->capslock = false; 133 | break; 134 | case 1: 135 | tty::current_tty->scrollock = true; 136 | break; 137 | case 2: 138 | tty::current_tty->numlock = true; 139 | break; 140 | case 3: 141 | tty::current_tty->capslock = true; 142 | break; 143 | } 144 | ps2::update_leds(); 145 | break; 146 | } 147 | } 148 | 149 | point getpos(limine_terminal *term) 150 | { 151 | print("\033[6n", term); 152 | return pos; 153 | } 154 | 155 | #pragma endregion Misc 156 | } 157 | 158 | void putchar_(char character) 159 | { 160 | kernel::drivers::display::terminal::printc(character); 161 | } -------------------------------------------------------------------------------- /source/drivers/display/terminal/terminal.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2021-2022 ilobilo 2 | 3 | #pragma once 4 | 5 | #define PRINTF_ALIAS_STANDARD_FUNCTION_NAMES 1 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | static inline int printf(limine_terminal *term, const char *format, ...); 13 | 14 | namespace kernel::drivers::display::terminal { 15 | 16 | extern bool initialised; 17 | extern char *resetcolour; 18 | 19 | extern limine_terminal **terminals; 20 | extern limine_terminal *main_term; 21 | extern uint64_t term_count; 22 | 23 | void print(const char *string, limine_terminal *term = main_term); 24 | void printi(int i, limine_terminal *term = main_term); 25 | void printc(char c, limine_terminal *term = main_term); 26 | 27 | void init(); 28 | 29 | void cursor_up(int lines = 1, limine_terminal *term = main_term), cursor_down(int lines = 1, limine_terminal *term = main_term), cursor_right(int lines = 1, limine_terminal *term = main_term), cursor_left(int lines = 1, limine_terminal *term = main_term); 30 | 31 | void reset(limine_terminal *term = main_term); 32 | void clear(const char *ansii_colour = "\033[0m", limine_terminal *term = main_term); 33 | void center(const char *text, limine_terminal *term = main_term); 34 | 35 | void callback(limine_terminal *term, uint64_t type, uint64_t first, uint64_t second, uint64_t third); 36 | point getpos(limine_terminal *term = main_term); 37 | 38 | static void check(const char *message, auto init, int64_t args, bool &ok, bool shouldinit = true, limine_terminal *term = main_term) 39 | { 40 | printf(term, "\033[1m[\033[21m*\033[0m\033[1m]\033[21m %s", message); 41 | 42 | if (shouldinit) reinterpret_cast(init)(args); 43 | 44 | printf(term, "\033[2G\033[%s\033[0m\033[%dG\033[1m[\033[21m \033[%s\033[0m \033[1m]\033[21m", (ok ? "32m*" : "31m*"), term->columns - 5, (ok ? "32mOK" : "31m!!")); 45 | } 46 | } 47 | 48 | static inline int vprintf(limine_terminal *term, const char *fmt, va_list args) 49 | { 50 | auto printc = reinterpret_cast(kernel::drivers::display::terminal::printc); 51 | int ret = vfctprintf(printc, term, fmt, args); 52 | 53 | return ret; 54 | } 55 | 56 | static inline int printf(limine_terminal *term, const char *fmt, ...) 57 | { 58 | va_list args; 59 | va_start(args, fmt); 60 | int ret = vprintf(term, fmt, args); 61 | va_end(args); 62 | 63 | return ret; 64 | } -------------------------------------------------------------------------------- /source/drivers/fs/devfs/dev/null.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2021-2022 ilobilo 2 | 3 | #include 4 | #include 5 | 6 | namespace kernel::drivers::fs::dev::null { 7 | 8 | bool initialised = false; 9 | 10 | int64_t null_res::read(void *handle, uint8_t *buffer, uint64_t offset, uint64_t size) 11 | { 12 | return 0; 13 | } 14 | 15 | int64_t null_res::write(void *handle, uint8_t *buffer, uint64_t offset, uint64_t size) 16 | { 17 | return size; 18 | } 19 | 20 | int null_res::ioctl(void *handle, uint64_t request, void *argp) 21 | { 22 | return vfs::default_ioctl(handle, request, argp); 23 | } 24 | 25 | bool null_res::grow(void *handle, size_t new_size) 26 | { 27 | return false; 28 | } 29 | 30 | void null_res::unref(void *handle) 31 | { 32 | this->refcount--; 33 | } 34 | 35 | void null_res::link(void *handle) 36 | { 37 | this->stat.nlink++; 38 | } 39 | 40 | void null_res::unlink(void *handle) 41 | { 42 | this->stat.nlink--; 43 | } 44 | 45 | void *null_res::mmap(uint64_t page, int flags) 46 | { 47 | return nullptr; 48 | } 49 | 50 | void init() 51 | { 52 | if (initialised) return; 53 | 54 | null_res *res = new null_res; 55 | 56 | res->stat.size = 0; 57 | res->stat.blocks = 0; 58 | res->stat.blksize = 0x1000; 59 | res->stat.rdev = vfs::dev_new_id(); 60 | res->stat.mode = 0666 | vfs::ifchr; 61 | res->can_mmap = true; 62 | 63 | devfs::add(res, "null"); 64 | 65 | initialised = true; 66 | } 67 | } -------------------------------------------------------------------------------- /source/drivers/fs/devfs/dev/null.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2021-2022 ilobilo 2 | 3 | #pragma once 4 | 5 | #include 6 | 7 | using namespace kernel::system; 8 | 9 | namespace kernel::drivers::fs::dev::null { 10 | 11 | struct null_res : vfs::resource_t 12 | { 13 | int64_t read(void *handle, uint8_t *buffer, uint64_t offset, uint64_t size); 14 | int64_t write(void *handle, uint8_t *buffer, uint64_t offset, uint64_t size); 15 | int ioctl(void *handle, uint64_t request, void *argp); 16 | bool grow(void *handle, size_t new_size); 17 | void unref(void *handle); 18 | void link(void *handle); 19 | void unlink(void *handle); 20 | void *mmap(uint64_t page, int flags); 21 | }; 22 | 23 | extern bool initialised; 24 | void init(); 25 | } -------------------------------------------------------------------------------- /source/drivers/fs/devfs/dev/random.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2021-2022 ilobilo 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | using namespace kernel::system::mm; 10 | 11 | namespace kernel::drivers::fs::dev::random { 12 | 13 | bool initialised = false; 14 | 15 | int64_t random_res::read(void *handle, uint8_t *buffer, uint64_t offset, uint64_t size) 16 | { 17 | if (size == 0) return 0; 18 | for (size_t i = 0; i < size; i++) 19 | { 20 | buffer[i] = rand() % 0xFF + 1; 21 | } 22 | return size; 23 | } 24 | 25 | int64_t random_res::write(void *handle, uint8_t *buffer, uint64_t offset, uint64_t size) 26 | { 27 | return size; 28 | } 29 | 30 | int random_res::ioctl(void *handle, uint64_t request, void *argp) 31 | { 32 | return vfs::default_ioctl(handle, request, argp); 33 | } 34 | 35 | bool random_res::grow(void *handle, size_t new_size) 36 | { 37 | return false; 38 | } 39 | 40 | void random_res::unref(void *handle) 41 | { 42 | this->refcount--; 43 | } 44 | 45 | void random_res::link(void *handle) 46 | { 47 | this->stat.nlink++; 48 | } 49 | 50 | void random_res::unlink(void *handle) 51 | { 52 | this->stat.nlink--; 53 | } 54 | 55 | void *random_res::mmap(uint64_t page, int flags) 56 | { 57 | return pmm::alloc(); 58 | } 59 | 60 | void init() 61 | { 62 | if (initialised) return; 63 | 64 | random_res *res = new random_res; 65 | 66 | res->stat.size = 0; 67 | res->stat.blocks = 0; 68 | res->stat.blksize = 0x1000; 69 | res->stat.rdev = vfs::dev_new_id(); 70 | res->stat.mode = 0666 | vfs::ifchr; 71 | res->can_mmap = true; 72 | 73 | devfs::add(res, "random"); 74 | devfs::add(res, "urandom"); 75 | 76 | initialised = true; 77 | } 78 | } -------------------------------------------------------------------------------- /source/drivers/fs/devfs/dev/random.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2021-2022 ilobilo 2 | 3 | #pragma once 4 | 5 | #include 6 | 7 | using namespace kernel::system; 8 | 9 | namespace kernel::drivers::fs::dev::random { 10 | 11 | struct random_res : vfs::resource_t 12 | { 13 | int64_t read(void *handle, uint8_t *buffer, uint64_t offset, uint64_t size); 14 | int64_t write(void *handle, uint8_t *buffer, uint64_t offset, uint64_t size); 15 | int ioctl(void *handle, uint64_t request, void *argp); 16 | bool grow(void *handle, size_t new_size); 17 | void unref(void *handle); 18 | void link(void *handle); 19 | void unlink(void *handle); 20 | void *mmap(uint64_t page, int flags); 21 | }; 22 | 23 | extern bool initialised; 24 | void init(); 25 | } -------------------------------------------------------------------------------- /source/drivers/fs/devfs/dev/tty.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2021-2022 ilobilo 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | namespace kernel::drivers::fs::dev::tty { 9 | 10 | bool initialised = false; 11 | tty_res *current_tty = nullptr; 12 | 13 | void init() 14 | { 15 | if (initialised) return; 16 | 17 | for (size_t i = 0; i < terminal::term_count; i++) 18 | { 19 | tty_res *tty = new tty_res(terminal::terminals[i]); 20 | 21 | std::string ttyname("tty"); 22 | ttyname.push_back(i + '0'); 23 | devfs::add(tty, ttyname); 24 | if (current_tty == nullptr) current_tty = tty; 25 | } 26 | 27 | initialised = true; 28 | } 29 | } -------------------------------------------------------------------------------- /source/drivers/fs/devfs/dev/tty.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2021-2022 ilobilo 2 | 3 | #pragma once 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | using namespace kernel::drivers; 10 | using namespace kernel::system; 11 | 12 | namespace kernel::drivers::fs::dev::tty { 13 | 14 | struct tty_res : pty_res 15 | { 16 | limine_terminal *thisterm; 17 | 18 | tty_res(limine_terminal *_thisterm) : pty_res(_thisterm->rows, _thisterm->columns), thisterm(_thisterm) { } 19 | 20 | int print(const char *fmt, ...) 21 | { 22 | va_list args; 23 | va_start(args, fmt); 24 | int ret = vprintf(this->thisterm, fmt, args); 25 | va_end(args); 26 | 27 | return ret; 28 | } 29 | }; 30 | 31 | extern bool initialised; 32 | extern tty_res *current_tty; 33 | 34 | void init(); 35 | } -------------------------------------------------------------------------------- /source/drivers/fs/devfs/dev/zero.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2021-2022 ilobilo 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | namespace kernel::drivers::fs::dev::zero { 8 | 9 | bool initialised = false; 10 | 11 | int64_t zero_res::read(void *handle, uint8_t *buffer, uint64_t offset, uint64_t size) 12 | { 13 | memset(buffer, 0, size); 14 | return 0; 15 | } 16 | 17 | int64_t zero_res::write(void *handle, uint8_t *buffer, uint64_t offset, uint64_t size) 18 | { 19 | return size; 20 | } 21 | 22 | int zero_res::ioctl(void *handle, uint64_t request, void *argp) 23 | { 24 | return vfs::default_ioctl(handle, request, argp); 25 | } 26 | 27 | bool zero_res::grow(void *handle, size_t new_size) 28 | { 29 | return false; 30 | } 31 | 32 | void zero_res::unref(void *handle) 33 | { 34 | this->refcount--; 35 | } 36 | 37 | void zero_res::link(void *handle) 38 | { 39 | this->stat.nlink++; 40 | } 41 | 42 | void zero_res::unlink(void *handle) 43 | { 44 | this->stat.nlink--; 45 | } 46 | 47 | void *zero_res::mmap(uint64_t page, int flags) 48 | { 49 | return malloc(0x1000); 50 | } 51 | 52 | void init() 53 | { 54 | if (initialised) return; 55 | 56 | zero_res *res = new zero_res; 57 | 58 | res->stat.size = 0; 59 | res->stat.blocks = 0; 60 | res->stat.blksize = 0x1000; 61 | res->stat.rdev = vfs::dev_new_id(); 62 | res->stat.mode = 0666 | vfs::ifchr; 63 | 64 | devfs::add(res, "zero"); 65 | 66 | initialised = true; 67 | } 68 | } -------------------------------------------------------------------------------- /source/drivers/fs/devfs/dev/zero.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2021-2022 ilobilo 2 | 3 | #pragma once 4 | 5 | #include 6 | 7 | using namespace kernel::system; 8 | 9 | namespace kernel::drivers::fs::dev::zero { 10 | 11 | struct zero_res : vfs::resource_t 12 | { 13 | int64_t read(void *handle, uint8_t *buffer, uint64_t offset, uint64_t size); 14 | int64_t write(void *handle, uint8_t *buffer, uint64_t offset, uint64_t size); 15 | int ioctl(void *handle, uint64_t request, void *argp); 16 | bool grow(void *handle, size_t new_size); 17 | void unref(void *handle); 18 | void link(void *handle); 19 | void unlink(void *handle); 20 | void *mmap(uint64_t page, int flags); 21 | }; 22 | 23 | extern bool initialised; 24 | void init(); 25 | } -------------------------------------------------------------------------------- /source/drivers/fs/devfs/devfs.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2021-2022 ilobilo 2 | 3 | #pragma once 4 | 5 | #include 6 | 7 | using namespace kernel::system; 8 | 9 | namespace kernel::drivers::fs::devfs { 10 | 11 | struct devfs_fs : vfs::filesystem_t 12 | { 13 | void init(); 14 | void populate(vfs::fs_node_t *node); 15 | vfs::fs_node_t *mount(vfs::fs_node_t *parent, vfs::fs_node_t *source, std::string dest); 16 | vfs::fs_node_t *symlink(vfs::fs_node_t *parent, std::string source, std::string dest); 17 | vfs::fs_node_t *create(vfs::fs_node_t *parent, std::string name, int mode); 18 | vfs::fs_node_t *link(vfs::fs_node_t *parent, std::string name, vfs::fs_node_t *old); 19 | }; 20 | 21 | struct devfs_res : vfs::resource_t 22 | { 23 | uint8_t *storage; 24 | uint64_t cap; 25 | 26 | int64_t read(void *handle, uint8_t *buffer, uint64_t offset, uint64_t size); 27 | int64_t write(void *handle, uint8_t *buffer, uint64_t offset, uint64_t size); 28 | int ioctl(void *handle, uint64_t request, void *argp); 29 | bool grow(void *handle, size_t new_size); 30 | void unref(void *handle); 31 | void link(void *handle); 32 | void unlink(void *handle); 33 | void *mmap(uint64_t page, int flags); 34 | }; 35 | 36 | extern bool initialised; 37 | extern devfs_fs *devfs; 38 | 39 | bool add(vfs::resource_t *res, std::string name); 40 | 41 | void init(); 42 | } -------------------------------------------------------------------------------- /source/drivers/fs/ilar/ilar.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2021-2022 ilobilo 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | using namespace kernel::system::mm; 13 | using namespace kernel::system; 14 | 15 | namespace kernel::drivers::fs::ilar { 16 | 17 | bool initialised = false; 18 | 19 | void init(uint64_t module) 20 | { 21 | log("Initialising ILAR"); 22 | 23 | if (initialised) 24 | { 25 | warn("ILAR has already been initialised!\n"); 26 | return; 27 | } 28 | 29 | auto initrd_mod = reinterpret_cast(module); 30 | uint64_t base = reinterpret_cast(initrd_mod->address); 31 | uint64_t top = base + initrd_mod->size; 32 | uint64_t address = base; 33 | 34 | fileheader *file = reinterpret_cast(address); 35 | if (strcmp(file->signature, ILAR_SIGNATURE)) 36 | { 37 | error("ILAR: Invalid signature!\n"); 38 | return; 39 | } 40 | 41 | while (true) 42 | { 43 | uint64_t size = file->size; 44 | uint32_t mode = file->mode; 45 | std::string name(file->name); 46 | std::string link(file->link); 47 | if (name[0] == '/') name.erase(0, 1); 48 | if (link[0] == '/') link.erase(0, 1); 49 | 50 | vfs::fs_node_t *node = nullptr; 51 | switch (file->type) 52 | { 53 | case ILAR_DIRECTORY: 54 | node = vfs::create(vfs::fs_root, name, mode | vfs::ifdir); 55 | if (node == nullptr) 56 | { 57 | error("ILAR: Could not create directory %s", name.c_str()); 58 | goto next; 59 | } 60 | break; 61 | case ILAR_REGULAR: 62 | { 63 | node = vfs::create(vfs::fs_root, name, mode | vfs::ifreg); 64 | if (node == nullptr) 65 | { 66 | error("ILAR: Could not create file %s", name.c_str()); 67 | goto next; 68 | } 69 | uint8_t *buffer = reinterpret_cast(address + sizeof(fileheader)); 70 | if (node->res->write(nullptr, buffer, 0, size) == -1) 71 | { 72 | error("ILAR: Could not write to file %s", name.c_str()); 73 | goto next; 74 | } 75 | break; 76 | } 77 | case ILAR_SYMLINK: 78 | node = vfs::symlink(vfs::fs_root, name, link); 79 | if (node == nullptr) 80 | { 81 | error("Initrd: Could not create symlink %s", name.c_str()); 82 | goto next; 83 | } 84 | break; 85 | } 86 | 87 | next: 88 | address += sizeof(fileheader) + file->size; 89 | 90 | file = reinterpret_cast(address); 91 | if (strcmp(file->signature, ILAR_SIGNATURE) || address >= top) break; 92 | } 93 | 94 | pmm::free(reinterpret_cast(ALIGN_DOWN(base - hhdm_offset, 0x1000)), ALIGN_UP(initrd_mod->size, 0x1000) / 0x1000); 95 | 96 | serial::newline(); 97 | initialised = true; 98 | } 99 | } -------------------------------------------------------------------------------- /source/drivers/fs/ilar/ilar.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2021-2022 ilobilo 2 | 3 | #pragma once 4 | 5 | #include 6 | #include 7 | 8 | namespace kernel::drivers::fs::ilar { 9 | 10 | static constexpr size_t PATH_LENGTH = 128; 11 | static constexpr char ILAR_SIGNATURE[] = "ILAR"; 12 | 13 | enum filetypes 14 | { 15 | ILAR_REGULAR = 0, 16 | ILAR_DIRECTORY = 1, 17 | ILAR_SYMLINK = 2 18 | }; 19 | 20 | struct [[gnu::packed]] fileheader 21 | { 22 | char signature[5]; 23 | char name[PATH_LENGTH]; 24 | char link[PATH_LENGTH]; 25 | uint64_t size; 26 | uint8_t type; 27 | uint32_t mode; 28 | }; 29 | 30 | extern bool initialised; 31 | 32 | void init(uint64_t module); 33 | } -------------------------------------------------------------------------------- /source/drivers/fs/initrd/initrd.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2021-2022 ilobilo 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | namespace kernel::drivers::fs::initrd { 8 | 9 | bool initialised = false; 10 | 11 | void init(uint64_t module) 12 | { 13 | ilar::init(module); 14 | if (ilar::initialised == false) 15 | { 16 | ustar::init(module); 17 | if (ustar::initialised == false) return; 18 | } 19 | 20 | initialised = true; 21 | } 22 | } -------------------------------------------------------------------------------- /source/drivers/fs/initrd/initrd.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2021-2022 ilobilo 2 | 3 | #pragma once 4 | 5 | #include 6 | 7 | namespace kernel::drivers::fs::initrd { 8 | 9 | extern bool initialised; 10 | void init(uint64_t module); 11 | } -------------------------------------------------------------------------------- /source/drivers/fs/tmpfs/tmpfs.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2021-2022 ilobilo 2 | 3 | #pragma once 4 | 5 | #include 6 | 7 | using namespace kernel::system; 8 | 9 | namespace kernel::drivers::fs::tmpfs { 10 | 11 | struct tmpfs_fs : vfs::filesystem_t 12 | { 13 | uint64_t inode_counter = 0; 14 | uint64_t dev_id = 0; 15 | 16 | void init(); 17 | void populate(vfs::fs_node_t *node); 18 | vfs::fs_node_t *mount(vfs::fs_node_t *parent, vfs::fs_node_t *source, std::string dest); 19 | vfs::fs_node_t *symlink(vfs::fs_node_t *parent, std::string source, std::string dest); 20 | vfs::fs_node_t *create(vfs::fs_node_t *parent, std::string name, int mode); 21 | vfs::fs_node_t *link(vfs::fs_node_t *parent, std::string name, vfs::fs_node_t *old); 22 | }; 23 | 24 | struct tmpfs_res : vfs::resource_t 25 | { 26 | uint8_t *storage; 27 | uint64_t cap; 28 | 29 | int64_t read(void *handle, uint8_t *buffer, uint64_t offset, uint64_t size); 30 | int64_t write(void *handle, uint8_t *buffer, uint64_t offset, uint64_t size); 31 | int ioctl(void *handle, uint64_t request, void *argp); 32 | bool grow(void *handle, size_t new_size); 33 | void unref(void *handle); 34 | void link(void *handle); 35 | void unlink(void *handle); 36 | void *mmap(uint64_t page, int flags); 37 | }; 38 | 39 | extern bool initialised; 40 | extern tmpfs_fs *tmpfs; 41 | 42 | void init(); 43 | } -------------------------------------------------------------------------------- /source/drivers/fs/ustar/ustar.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2021-2022 ilobilo 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | using namespace kernel::system::mm; 13 | using namespace kernel::system; 14 | 15 | namespace kernel::drivers::fs::ustar { 16 | 17 | bool initialised = false; 18 | 19 | uint64_t oct2dec(const char *s) 20 | { 21 | uint64_t ret = 0; 22 | while (*s) 23 | { 24 | ret *= 8; 25 | ret += *s - '0'; 26 | s++; 27 | } 28 | return ret; 29 | } 30 | 31 | void init(uint64_t module) 32 | { 33 | log("Initialising USTAR"); 34 | 35 | if (initialised) 36 | { 37 | warn("USTAR has already been initialised!\n"); 38 | return; 39 | } 40 | 41 | auto initrd_mod = reinterpret_cast(module); 42 | uint64_t base = reinterpret_cast(initrd_mod->address); 43 | uint64_t top = base + initrd_mod->size; 44 | uint64_t address = base; 45 | 46 | while (true) 47 | { 48 | file_header_t *header = reinterpret_cast(address); 49 | if (strcmp(header->signature, "ustar") || address >= top) break; 50 | 51 | uint64_t size = oct2dec(header->size); 52 | uint64_t mode = oct2dec(header->mode); 53 | std::string name(header->name); 54 | std::string link(header->link); 55 | 56 | vfs::fs_node_t *node = nullptr; 57 | if (name == "./") goto next; 58 | 59 | switch (header->typeflag[0]) 60 | { 61 | case DIRECTORY: 62 | node = vfs::create(vfs::fs_root, name, mode | vfs::ifdir); 63 | if (node == nullptr) 64 | { 65 | error("USTAR: Could not create directory %s", name.c_str()); 66 | goto next; 67 | } 68 | break; 69 | case REGULAR_FILE: 70 | { 71 | node = vfs::create(vfs::fs_root, name, mode | vfs::ifreg); 72 | if (node == nullptr) 73 | { 74 | error("USTAR: Could not create file %s", name.c_str()); 75 | goto next; 76 | } 77 | uint8_t *buffer = reinterpret_cast(reinterpret_cast(header) + 512); 78 | if (node->res->write(nullptr, buffer, 0, size) == -1) 79 | { 80 | error("USTAR: Could not write to file %s", name.c_str()); 81 | goto next; 82 | } 83 | break; 84 | } 85 | case SYMLINK: 86 | node = vfs::symlink(vfs::fs_root, name, link); 87 | if (node == nullptr) 88 | { 89 | error("USTAR: Could not create symlink %s", name.c_str()); 90 | goto next; 91 | } 92 | break; 93 | } 94 | 95 | node->res->stat.uid = oct2dec(header->uid); 96 | node->res->stat.gid = oct2dec(header->gid); 97 | 98 | next: 99 | address += 512 + ALIGN_UP(size, 512); 100 | } 101 | 102 | pmm::free(reinterpret_cast(ALIGN_DOWN(base - hhdm_offset, 0x1000)), ALIGN_UP(initrd_mod->size, 0x1000) / 0x1000); 103 | 104 | serial::newline(); 105 | initialised = true; 106 | } 107 | } -------------------------------------------------------------------------------- /source/drivers/fs/ustar/ustar.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2021-2022 ilobilo 2 | 3 | #pragma once 4 | 5 | #include 6 | 7 | namespace kernel::drivers::fs::ustar { 8 | 9 | enum filetypes 10 | { 11 | REGULAR_FILE = '0', 12 | HARDLINK = '1', 13 | SYMLINK = '2', 14 | CHARDEV = '3', 15 | BLOCKDEV = '4', 16 | DIRECTORY = '5', 17 | FIFO = '6' 18 | }; 19 | 20 | struct file_header_t 21 | { 22 | char name[100]; 23 | char mode[8]; 24 | char uid[8]; 25 | char gid[8]; 26 | char size[12]; 27 | char mtime[12]; 28 | char chksum[8]; 29 | char typeflag[1]; 30 | char link[100]; 31 | char signature[6]; 32 | char version[2]; 33 | char owner[32]; 34 | char group[32]; 35 | char dev_maj[8]; 36 | char dev_min[8]; 37 | char prefix[155]; 38 | }; 39 | 40 | extern bool initialised; 41 | 42 | void init(uint64_t module); 43 | } -------------------------------------------------------------------------------- /source/drivers/net/e1000/e1000.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2021-2022 ilobilo 2 | 3 | #pragma once 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | using namespace kernel::system; 11 | 12 | namespace kernel::drivers::net::e1000 { 13 | 14 | #define TSTA_DD (1 << 0) 15 | #define TSTA_EC (1 << 1) 16 | #define TSTA_LC (1 << 2) 17 | #define LSTA_TU (1 << 3) 18 | #define ECTRL_SLU 0x40 19 | 20 | enum regs 21 | { 22 | REG_CTRL = 0x0000, 23 | REG_STATUS = 0x0008, 24 | REG_EEPROM = 0x0014, 25 | REG_CTRL_EXT = 0x0018, 26 | REG_IMASK = 0x00D0, 27 | REG_RCTRL = 0x0100, 28 | REG_RXDESCLO = 0x2800, 29 | REG_RXDESCHI = 0x2804, 30 | REG_RXDESCLEN = 0x2808, 31 | REG_RXDESCHEAD = 0x2810, 32 | REG_RXDESCTAIL = 0x2818, 33 | REG_TCTRL = 0x0400, 34 | REG_TXDESCLO = 0x3800, 35 | REG_TXDESCHI = 0x3804, 36 | REG_TXDESCLEN = 0x3808, 37 | REG_TXDESCHEAD = 0x3810, 38 | REG_TXDESCTAIL = 0x3818, 39 | REG_RDTR = 0x2820, 40 | REG_RXDCTL = 0x3828, 41 | REG_RADV = 0x282C, 42 | REG_RSRPD = 0x2C00, 43 | REG_TIPG = 0x0410, 44 | }; 45 | 46 | enum rctl 47 | { 48 | RCTL_EN = (1 << 1), 49 | RCTL_SBP = (1 << 2), 50 | RCTL_UPE = (1 << 3), 51 | RCTL_MPE = (1 << 4), 52 | RCTL_LPE = (1 << 5), 53 | RCTL_LBM_NONE = (0 << 6), 54 | RCTL_LBM_PHY = (3 << 6), 55 | RCTL_RDMTS_HALF = (0 << 8), 56 | RCTL_RDMTS_QUARTER = (1 << 8), 57 | RCTL_RDMTS_EIGHTH = (2 << 8), 58 | RCTL_MO_36 = (0 << 12), 59 | RCTL_MO_35 = (1 << 12), 60 | RCTL_MO_34 = (2 << 12), 61 | RCTL_MO_32 = (3 << 12), 62 | RCTL_BAM = (1 << 15), 63 | RCTL_VFE = (1 << 18), 64 | RCTL_CFIEN = (1 << 19), 65 | RCTL_CFI = (1 << 20), 66 | RCTL_DPF = (1 << 22), 67 | RCTL_PMCF = (1 << 23), 68 | RCTL_SECRC = (1 << 26), 69 | RCTL_BSIZE_256 = (3 << 16), 70 | RCTL_BSIZE_512 = (2 << 16), 71 | RCTL_BSIZE_1024 = (1 << 16), 72 | RCTL_BSIZE_2048 = (0 << 16), 73 | RCTL_BSIZE_4096 = ((3 << 16) | (1 << 25)), 74 | RCTL_BSIZE_8192 = ((2 << 16) | (1 << 25)), 75 | RCTL_BSIZE_16384 = ((1 << 16) | (1 << 25)) 76 | }; 77 | 78 | enum tctl 79 | { 80 | TCTL_EN = (1 << 1), 81 | TCTL_PSP = (1 << 3), 82 | TCTL_CT_SHIFT = 4, 83 | TCTL_COLD_SHIFT = 12, 84 | TCTL_SWXOFF = (1 << 22), 85 | TCTL_RTLC = (1 << 24) 86 | }; 87 | 88 | enum cmd 89 | { 90 | CMD_EOP = (1 << 0), 91 | CMD_IFCS = (1 << 1), 92 | CMD_IC = (1 << 2), 93 | CMD_RS = (1 << 3), 94 | CMD_RPS = (1 << 4), 95 | CMD_VLE = (1 << 6), 96 | CMD_IDE = (1 << 7) 97 | }; 98 | 99 | static constexpr uint8_t E1000_NUM_RX_DESC = 32; 100 | static constexpr uint8_t E1000_NUM_TX_DESC = 8; 101 | 102 | static constexpr uint32_t E1000_RX_BUFF_SIZE = 8192; 103 | 104 | struct [[gnu::packed]] RXDesc 105 | { 106 | uint64_t addr; 107 | uint16_t length; 108 | uint16_t checksum; 109 | uint8_t status; 110 | uint8_t errors; 111 | uint16_t special; 112 | }; 113 | 114 | struct [[gnu::packed]] TXDesc 115 | { 116 | uint64_t addr; 117 | uint16_t length; 118 | uint8_t cso; 119 | uint8_t cmd; 120 | uint8_t status; 121 | uint8_t css; 122 | uint16_t special; 123 | }; 124 | 125 | class E1000 : public nicmgr::NIC 126 | { 127 | private: 128 | pci::pcidevice_t *pcidevice; 129 | lock_t lock; 130 | 131 | uint8_t BARType = 0; 132 | uint16_t IOBase = 0; 133 | uint64_t MEMBase = 0; 134 | 135 | RXDesc *rxdescs[E1000_NUM_RX_DESC]; 136 | TXDesc *txdescs[E1000_NUM_TX_DESC]; 137 | uint16_t rxcurr = 0; 138 | uint16_t txcurr = 0; 139 | 140 | void rxinit(); 141 | void txinit(); 142 | 143 | bool eeprom = false; 144 | bool detecteeprom(); 145 | uint32_t readeeprom(uint8_t addr); 146 | void read_mac(); 147 | 148 | void outcmd(uint16_t addr, uint32_t val); 149 | uint32_t incmd(uint16_t addr); 150 | 151 | void intenable(); 152 | 153 | public: 154 | bool initialised = false; 155 | uint8_t id; 156 | 157 | void send(void *data, uint64_t length); 158 | void receive(); 159 | 160 | uint32_t status(); 161 | void irq_reset(uint32_t stat); 162 | 163 | void startlink(); 164 | void start(); 165 | 166 | E1000(pci::pcidevice_t *pcidevice, uint8_t id); 167 | }; 168 | 169 | extern bool initialised; 170 | extern vector devices; 171 | 172 | void init(); 173 | } -------------------------------------------------------------------------------- /source/drivers/net/nicmgr/nicmgr.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2021-2022 ilobilo 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | namespace kernel::drivers::net::nicmgr { 14 | 15 | bool initialised = false; 16 | vector nics; 17 | 18 | static uint8_t next = 50; 19 | void addCard(NIC *card, type_t type) 20 | { 21 | log("Registering NIC #%zu", nics.size()); 22 | nics.push_back(card); 23 | nics.front()->type = type; 24 | nics.front()->uniqueid = rand() % (RAND_MAX + 1 - 10000) + 10000; 25 | 26 | // Temporarily hardcode IPv4 addresses 27 | // NIC 0 IPv4 = 192.168.0.50 28 | // NIC 0 IPv4 = 192.168.0.51 29 | // NIC 0 IPv4 = 192.168.0.52 30 | // ... 31 | 32 | card->IPv4 = { 192, 168, 0, next++ }; 33 | } 34 | 35 | void addRTL8139() 36 | { 37 | if (!rtl8139::initialised) return; 38 | for (size_t i = 0; i < rtl8139::devices.size(); i++) 39 | { 40 | addCard(rtl8139::devices[i], RTL8139); 41 | sprintf(nics.front()->name, "RTL8139 #%zu", i); 42 | } 43 | } 44 | 45 | void addRTL8169() 46 | { 47 | if (!rtl8169::initialised) return; 48 | for (size_t i = 0; i < rtl8169::devices.size(); i++) 49 | { 50 | addCard(rtl8169::devices[i], RTL8169); 51 | sprintf(nics.front()->name, "RTL8169 #%zu", i); 52 | } 53 | } 54 | 55 | void addE1000() 56 | { 57 | if (!e1000::initialised) return; 58 | for (size_t i = 0; i < e1000::devices.size(); i++) 59 | { 60 | addCard(e1000::devices[i], E1000); 61 | sprintf(nics.front()->name, "E1000 #%zu", i); 62 | } 63 | } 64 | 65 | void init() 66 | { 67 | log("Initialising NIC manager"); 68 | 69 | if (initialised) 70 | { 71 | warn("NIC manager has already been initialised!\n"); 72 | return; 73 | } 74 | 75 | addRTL8139(); 76 | addRTL8169(); 77 | addE1000(); 78 | 79 | serial::newline(); 80 | initialised = true; 81 | } 82 | } -------------------------------------------------------------------------------- /source/drivers/net/nicmgr/nicmgr.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2021-2022 ilobilo 2 | 3 | #pragma once 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | namespace kernel::drivers::net::nicmgr { 11 | 12 | enum type_t 13 | { 14 | RTL8139, 15 | RTL8169, 16 | E1000 17 | }; 18 | 19 | struct NIC 20 | { 21 | char name[32] = "New NIC"; 22 | macaddr MAC; 23 | ipv4addr IPv4; 24 | type_t type; 25 | uint64_t uniqueid; 26 | bool debug = NET_DEBUG; 27 | 28 | virtual void send(void *data, uint64_t length) 29 | { 30 | error("Send function for this device is not available!"); 31 | } 32 | }; 33 | 34 | extern bool initialised; 35 | extern vector nics; 36 | 37 | void init(); 38 | } -------------------------------------------------------------------------------- /source/drivers/net/rtl8139/rtl8139.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2021-2022 ilobilo 2 | 3 | #pragma once 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | using namespace kernel::system; 11 | 12 | namespace kernel::drivers::net::rtl8139 { 13 | 14 | enum regs 15 | { 16 | REG_ID_0 = 0x00, 17 | REG_ID_1 = 0x01, 18 | REG_ID_2 = 0x02, 19 | REG_ID_3 = 0x03, 20 | REG_ID_4 = 0x04, 21 | REG_ID_5 = 0x05, 22 | REG_TSD_0 = 0x10, 23 | REG_TSD_1 = 0x14, 24 | REG_TSD_2 = 0x18, 25 | REG_TSD_3 = 0x1C, 26 | REG_TSAD_0 = 0x20, 27 | REG_TSAD_1 = 0x24, 28 | REG_TSAD_2 = 0x28, 29 | REG_TSAD_3 = 0x2C, 30 | REG_RBSTART = 0x30, 31 | REG_CR = 0x37, 32 | REG_CAPR = 0x38, 33 | REG_IMR = 0x3C, 34 | REG_ISR = 0x3E, 35 | REG_RCR = 0x44, 36 | REG_CONFIG1 = 0x52 37 | }; 38 | 39 | enum cmd 40 | { 41 | CMD_BUFF_EMPTY = (1 << 0), 42 | CMD_TX_ENABLE = (1 << 2), 43 | CMD_RX_ENABLE = (1 << 3), 44 | CMD_RESET = (1 << 4) 45 | }; 46 | 47 | enum intmask 48 | { 49 | IMR_RECEIVE_OK = (1 << 0), 50 | IMR_RECEIVE_ERROR = (1 << 1), 51 | IMR_TRANSMIT_OK = (1 << 2), 52 | IMR_TRANSMIT_ERROR = (1 << 3), 53 | IMR_RX_OVERFLOW = (1 << 4), 54 | IMR_LINK_CHANGE = (1 << 5), 55 | IMR_RX_FIFO_OVERFLOW = (1 << 6), 56 | IMR_CABLE_LENGTH_CHANGE = (1 << 13), 57 | IMR_TIME_OUT = (1 << 14), 58 | IMR_SYSTEM_ERROR = (1 << 15) 59 | }; 60 | 61 | enum intstat 62 | { 63 | IST_RECEIVE_OK = (1 << 0), 64 | IST_RECEIVE_ERR = (1 << 1), 65 | IST_TRANSMIT_OK = (1 << 2), 66 | IST_TRANSMIT_ERR = (1 << 3), 67 | IST_RX_BUFF_OVER = (1 << 4), 68 | IST_LINK_CHANGE = (1 << 5), 69 | IST_RX_FIFO_OVER = (1 << 6), 70 | IST_CABLE_LENGTH_CHANGE = (1 << 13), 71 | IST_TIME_OUT = (1 << 14), 72 | IST_SYSTEM_ERROR = (1 << 15), 73 | }; 74 | 75 | enum rxconf 76 | { 77 | RCR_PHYS_ADDR_PACKETS = (1 << 0), 78 | RCR_PHYS_MATCH_PACKETS = (1 << 1), 79 | RCR_MULTICAST_PACKETS = (1 << 2), 80 | RCR_BROADCAST_PACKETS = (1 << 3), 81 | RCR_RUNT_PACKETS = (1 << 4), 82 | RCR_ERROR_PACKETS = (1 << 5), 83 | RCR_EEPROM_SELECT = (1 << 6), 84 | RCR_WRAP = (1 << 7), 85 | }; 86 | 87 | class RTL8139 : public nicmgr::NIC 88 | { 89 | private: 90 | pci::pcidevice_t *pcidevice; 91 | lock_t lock; 92 | 93 | uint8_t BARType = 0; 94 | uint16_t IOBase = 0; 95 | uint64_t MEMBase = 0; 96 | 97 | uint8_t *RXBuffer = nullptr; 98 | uint32_t current_packet = 0; 99 | 100 | uint8_t TSAD[4] = { REG_TSAD_0, REG_TSAD_1, REG_TSAD_2, REG_TSAD_3 }; 101 | uint8_t TSD[4] = { REG_TSD_0, REG_TSD_1, REG_TSD_2, REG_TSD_3 }; 102 | size_t txcurr = 0; 103 | 104 | void outb(uint16_t addr, uint8_t val); 105 | void outw(uint16_t addr, uint16_t val); 106 | void outl(uint16_t addr, uint32_t val); 107 | 108 | uint8_t inb(uint16_t addr); 109 | uint16_t inw(uint16_t addr); 110 | uint32_t inl(uint16_t addr); 111 | 112 | public: 113 | bool initialised = false; 114 | uint8_t id; 115 | 116 | void send(void *data, uint64_t length); 117 | void receive(); 118 | 119 | void reset(); 120 | void start(); 121 | 122 | uint16_t status(); 123 | void irq_reset(); 124 | 125 | void read_mac(); 126 | 127 | RTL8139(pci::pcidevice_t *pcidevice, uint8_t id); 128 | }; 129 | 130 | extern bool initialised; 131 | extern vector devices; 132 | 133 | void init(); 134 | } -------------------------------------------------------------------------------- /source/drivers/net/rtl8169/rtl8169.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2021-2022 ilobilo 2 | 3 | #pragma once 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | using namespace kernel::system; 11 | 12 | namespace kernel::drivers::net::rtl8169 { 13 | 14 | enum regs 15 | { 16 | REG_ID_0 = 0x00, 17 | REG_ID_1 = 0x01, 18 | REG_ID_2 = 0x02, 19 | REG_ID_3 = 0x03, 20 | REG_ID_4 = 0x04, 21 | REG_ID_5 = 0x05, 22 | REG_TNPDS_1 = 0x20, 23 | REG_TNPDS_2 = 0x24, 24 | REG_CR = 0x37, 25 | REG_TPPOLL = 0x38, 26 | REG_IMR = 0x3C, 27 | REG_ISR = 0x3E, 28 | REG_TCR = 0x40, 29 | REG_RCR = 0x44, 30 | REG_9346CR = 0x50, 31 | REG_CONFIG1 = 0x52, 32 | REG_RMS = 0xDA, 33 | REG_RDSAR_1 = 0xE4, 34 | REG_RDSAR_2 = 0xE8, 35 | REG_ETTHR = 0xEC 36 | }; 37 | 38 | enum cmd 39 | { 40 | CMD_TX_ENABLE = (1 << 2), 41 | CMD_RX_ENABLE = (1 << 3), 42 | CMD_RESET = (1 << 4) 43 | }; 44 | 45 | enum intstat 46 | { 47 | IST_RECEIVE_OK = (1 << 0), 48 | IST_RECEIVE_ERR = (1 << 1), 49 | IST_TRANSMIT_OK = (1 << 2), 50 | IST_TRANSMIT_ERR = (1 << 3), 51 | IST_RX_UNAVAIL = (1 << 4), 52 | IST_LINK_CHANGE = (1 << 5), 53 | IST_RX_FIFO_OVER = (1 << 6), 54 | IST_TX_UNAVAIL = (1 << 7), 55 | IST_SOFT_INT = (1 << 8), 56 | IST_TIME_OUT = (1 << 14), 57 | IST_SYSTEM_ERROR = (1 << 15), 58 | }; 59 | 60 | enum desc 61 | { 62 | RTL8169_OWN = (1 << 31), 63 | RTL8169_EOR = (1 << 30), 64 | RTL8169_FFR = (1 << 29), 65 | RTL8169_LFR = (1 << 28) 66 | }; 67 | 68 | static constexpr uint8_t RTL8169_NUM_RX_DESC = 32; 69 | static constexpr uint8_t RTL8169_NUM_TX_DESC = 8; 70 | 71 | static constexpr uint32_t RTL8169_RX_BUFF_SIZE = 8192; 72 | 73 | struct [[gnu::packed]] Desc 74 | { 75 | uint32_t command; 76 | uint32_t vlan; 77 | uint64_t buffer; 78 | }; 79 | 80 | class RTL8169 : public nicmgr::NIC 81 | { 82 | private: 83 | pci::pcidevice_t *pcidevice; 84 | lock_t lock; 85 | 86 | uint8_t BARType = 0; 87 | uint16_t IOBase = 0; 88 | uint64_t MEMBase = 0; 89 | 90 | Desc *rxdescs[RTL8169_NUM_RX_DESC]; 91 | Desc *txdescs[RTL8169_NUM_TX_DESC]; 92 | 93 | uint16_t rxcurr = 0; 94 | uint16_t txcurr = 0; 95 | 96 | void outb(uint16_t addr, uint8_t val); 97 | void outw(uint16_t addr, uint16_t val); 98 | void outl(uint16_t addr, uint32_t val); 99 | 100 | uint8_t inb(uint16_t addr); 101 | uint16_t inw(uint16_t addr); 102 | uint32_t inl(uint16_t addr); 103 | 104 | void rxinit(); 105 | void txinit(); 106 | 107 | public: 108 | bool initialised = false; 109 | uint8_t id; 110 | 111 | void send(void *data, uint64_t length); 112 | void receive(); 113 | 114 | void reset(); 115 | void start(); 116 | 117 | uint16_t status(); 118 | void irq_reset(uint16_t status); 119 | 120 | void read_mac(); 121 | 122 | RTL8169(pci::pcidevice_t *pcidevice, uint8_t id); 123 | }; 124 | 125 | extern bool initialised; 126 | extern vector devices; 127 | 128 | void init(); 129 | } -------------------------------------------------------------------------------- /source/drivers/ps2/kbscancodetable/kbscancodetable.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2021-2022 ilobilo 2 | 3 | #pragma once 4 | 5 | #include 6 | 7 | #define NUM_KEYS 256 8 | #define MAX_NUM_FUNC 256 9 | #define MAX_NUM_KEYMAPS 256 10 | 11 | #define KEY(t, v) (((t) << 8) | (v)) 12 | #define KEY_TYPE(x) ((x) >> 8) 13 | #define KEY_VALUE(x) ((x) & 0xff) 14 | 15 | enum keygs 16 | { 17 | KG_SHIFT = 0, 18 | KG_CTRL = 2, 19 | KG_ALT = 3, 20 | KG_ALTGR = 1, 21 | KG_SHIFTL = 4, 22 | KG_KANASHIFT = 4, 23 | KG_SHIFTR = 5, 24 | KG_CTRLL = 6, 25 | KG_CTRLR = 7 26 | }; 27 | 28 | enum key_types 29 | { 30 | KEY_TYPE_LATIN = 0, 31 | KEY_TYPE_FN = 1, 32 | KEY_TYPE_SPEC = 2, 33 | KEY_TYPE_PAD = 3, 34 | KEY_TYPE_DEAD = 4, 35 | KEY_TYPE_CONS = 5, 36 | KEY_TYPE_CUR = 6, 37 | KEY_TYPE_SHIFT = 7, 38 | KEY_TYPE_META = 8, 39 | KEY_TYPE_ASCII = 9, 40 | KEY_TYPE_LOCK = 10, 41 | KEY_TYPE_LETTER = 11, 42 | KEY_TYPE_SLOCK = 12, 43 | KEY_TYPE_DEAD2 = 13, 44 | KEY_TYPE_BRL = 14 45 | }; 46 | 47 | enum keys 48 | { 49 | KEY_SHIFT = KEY(KEY_TYPE_SHIFT, KG_SHIFT), 50 | KEY_CTRL = KEY(KEY_TYPE_SHIFT, KG_CTRL), 51 | KEY_ALT = KEY(KEY_TYPE_SHIFT, KG_ALT), 52 | KEY_ALTGR = KEY(KEY_TYPE_SHIFT, KG_ALTGR), 53 | KEY_SHIFTL = KEY(KEY_TYPE_SHIFT, KG_SHIFTL), 54 | KEY_SHIFTR = KEY(KEY_TYPE_SHIFT, KG_SHIFTR), 55 | KEY_CTRLL = KEY(KEY_TYPE_SHIFT, KG_CTRLL), 56 | KEY_CTRLR = KEY(KEY_TYPE_SHIFT, KG_CTRLR), 57 | 58 | KEY_P0 = KEY(KEY_TYPE_PAD, 0), 59 | KEY_P1 = KEY(KEY_TYPE_PAD, 1), 60 | KEY_P2 = KEY(KEY_TYPE_PAD, 2), 61 | KEY_P3 = KEY(KEY_TYPE_PAD, 3), 62 | KEY_P4 = KEY(KEY_TYPE_PAD, 4), 63 | KEY_P5 = KEY(KEY_TYPE_PAD, 5), 64 | KEY_P6 = KEY(KEY_TYPE_PAD, 6), 65 | KEY_P7 = KEY(KEY_TYPE_PAD, 7), 66 | KEY_P8 = KEY(KEY_TYPE_PAD, 8), 67 | KEY_P9 = KEY(KEY_TYPE_PAD, 9), 68 | 69 | KEY_PCOMMA = KEY(KEY_TYPE_PAD, 15), 70 | KEY_PDOT = KEY(KEY_TYPE_PAD, 16), 71 | 72 | KEY_FIND = KEY(KEY_TYPE_FN, 20), 73 | KEY_INSERT = KEY(KEY_TYPE_FN, 21), 74 | KEY_REMOVE = KEY(KEY_TYPE_FN, 22), 75 | KEY_SELECT = KEY(KEY_TYPE_FN, 23), 76 | KEY_PGUP = KEY(KEY_TYPE_FN, 24), 77 | KEY_PGDN = KEY(KEY_TYPE_FN, 25), 78 | 79 | KEY_DOWN = KEY(KEY_TYPE_CUR, 0), 80 | KEY_LEFT = KEY(KEY_TYPE_CUR, 1), 81 | KEY_RIGHT = KEY(KEY_TYPE_CUR, 2), 82 | KEY_UP = KEY(KEY_TYPE_CUR, 3) 83 | }; 84 | 85 | extern uint16_t plain_map[NUM_KEYS]; 86 | extern uint16_t shift_map[NUM_KEYS]; 87 | extern uint16_t altgr_map[NUM_KEYS]; 88 | extern uint16_t ctrl_map[NUM_KEYS]; 89 | extern uint16_t shift_ctrl_map[NUM_KEYS]; 90 | extern uint16_t alt_map[NUM_KEYS]; 91 | extern uint16_t ctrl_alt_map[NUM_KEYS]; 92 | 93 | extern uint16_t *key_maps[MAX_NUM_KEYMAPS]; 94 | 95 | extern char *func_table[MAX_NUM_FUNC]; -------------------------------------------------------------------------------- /source/drivers/ps2/ps2.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2021-2022 ilobilo 2 | 3 | #pragma once 4 | 5 | #include 6 | #include 7 | 8 | namespace kernel::drivers::ps2 { 9 | 10 | static constexpr uint64_t PS2_MAX_TIMEOUT = 1000; 11 | static constexpr uint64_t PS2_MAX_RESENDS = 10; 12 | static constexpr uint8_t PS2_KBD_SCANCODE = 2; 13 | 14 | static constexpr uint64_t KBD_BUFFSIZE = 1024; 15 | 16 | static constexpr uint8_t PS2_X_SIGN = 0b00010000; 17 | static constexpr uint8_t PS2_Y_SIGN = 0b00100000; 18 | static constexpr uint8_t PS2_X_OVER = 0b01000000; 19 | static constexpr uint8_t PS2_Y_OVER = 0b10000000; 20 | 21 | enum mousestate 22 | { 23 | PS2_NONE = 0b00000000, 24 | PS2_LEFT = 0b00000001, 25 | PS2_MIDDLE = 0b00000100, 26 | PS2_RIGHT = 0b00000010, 27 | }; 28 | 29 | enum devices 30 | { 31 | PS2_DEVICE_NONE = 0, 32 | PS2_DEVICE_FIRST = 1, 33 | PS2_DEVICE_SECOND = 2 34 | }; 35 | 36 | enum ioports 37 | { 38 | PS2_PORT_DATA = 0x60, 39 | PS2_PORT_STATUS = 0x64, 40 | PS2_PORT_COMMAND = 0x64, 41 | }; 42 | 43 | enum status 44 | { 45 | PS2_OUTPUT_FULL = (1 << 0), 46 | PS2_INPUT_FULL = (1 << 1), 47 | PS2_MOUSE_BYTE = (1 << 5) 48 | }; 49 | 50 | enum mousetype 51 | { 52 | PS2_MOUSE_NORMAL = 0, 53 | PS2_MOUSE_SCROLL = 3, 54 | PS2_MOUSE_5_BUTTON = 4 55 | }; 56 | 57 | enum cmds 58 | { 59 | PS2_DISABLE_FIRST = 0xAD, 60 | PS2_ENABLE_FIRST = 0xAE, 61 | PS2_TEST_FIRST = 0xAB, 62 | PS2_DISABLE_SECOND = 0xA7, 63 | PS2_ENABLE_SECOND = 0xA8, 64 | PS2_WRITE_SECOND = 0xD4, 65 | PS2_TEST_SECOND = 0xA9, 66 | PS2_TEST_CONTROLER = 0xAA, 67 | PS2_READ_CONFIG = 0x20, 68 | PS2_WRITE_CONFIG = 0x60 69 | }; 70 | 71 | enum config 72 | { 73 | PS2_FIRST_IRQ_MASK = (1 << 0), 74 | PS2_SECOND_IRQ_MASK = (1 << 1), 75 | PS2_SECOND_CLOCK = (1 << 5), 76 | PS2_TRANSLATION = (1 << 6) 77 | }; 78 | 79 | enum kbdcmd 80 | { 81 | PS2_KEYBOARD_REPEAT = 0xF3, 82 | PS2_KEYBOARD_SET_LEDS = 0xED, 83 | PS2_KEYBOARD_SCANCODE_SET = 0xF0 84 | }; 85 | 86 | enum mousecmd 87 | { 88 | PS2_MOUSE_DEFAULTS = 0xF6, 89 | PS2_MOUSE_SAMPLE_RATE = 0xF3, 90 | PS2_MOUSE_READ = 0xEB, 91 | PS2_MOUSE_RESOLUTION = 0xE8 92 | }; 93 | 94 | enum cmd 95 | { 96 | PS2_DEVICE_RESET = 0xFF, 97 | PS2_DEVICE_DISABLE = 0xF5, 98 | PS2_DEVICE_ENABLE = 0xF4, 99 | PS2_DEVICE_IDENTIFY = 0xF2 100 | }; 101 | 102 | extern bool initialised; 103 | extern bool kbdinitialised; 104 | extern bool mouseinitialised; 105 | 106 | extern bool mousevmware; 107 | 108 | extern point mousepos; 109 | extern point mouseposold; 110 | extern uint32_t mousebordercol; 111 | extern uint32_t mouseinsidecol; 112 | 113 | mousestate getmousestate(); 114 | 115 | void mousedraw(); 116 | void mouseclear(); 117 | 118 | void update_leds(); 119 | 120 | void reboot(); 121 | void init(); 122 | } -------------------------------------------------------------------------------- /source/drivers/vmware/vmware.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2021-2022 ilobilo 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | using namespace kernel::drivers::display; 8 | 9 | namespace kernel::drivers::vmware { 10 | 11 | bool initialised = false; 12 | 13 | void send(CMD &cmd) 14 | { 15 | cmd.magic = VMWARE_MAGIC; 16 | cmd.port = VMWARE_PORT; 17 | asm volatile("in %%dx, %0" : "+a"(cmd.ax), "+b"(cmd.bx), "+c"(cmd.cx), "+d"(cmd.dx), "+S"(cmd.si), "+D"(cmd.di)); 18 | } 19 | 20 | bool is_vmware_backdoor() 21 | { 22 | CMD cmd; 23 | cmd.bx = ~VMWARE_MAGIC; 24 | cmd.command = CMD_GETVERSION; 25 | send(cmd); 26 | 27 | if (cmd.bx != VMWARE_MAGIC || cmd.ax == 0xFFFFFFFF) return false; 28 | return true; 29 | } 30 | 31 | int buttons; 32 | ps2::mousestate getmousestate() 33 | { 34 | if (buttons & 0x20) return ps2::mousestate::PS2_LEFT; 35 | if (buttons & 0x10) return ps2::mousestate::PS2_RIGHT; 36 | if (buttons & 0x08) return ps2::mousestate::PS2_MIDDLE; 37 | return ps2::mousestate::PS2_NONE; 38 | } 39 | 40 | void handle_mouse() 41 | { 42 | CMD cmd; 43 | 44 | cmd.bx = 0; 45 | cmd.command = CMD_ABSPOINTER_STATUS; 46 | send(cmd); 47 | 48 | if (cmd.ax == 0xFFFF0000) 49 | { 50 | mouse_relative(); 51 | mouse_absolute(); 52 | return; 53 | } 54 | 55 | if ((cmd.ax & 0xFFFF) < 4) return; 56 | 57 | cmd.bx = 4; 58 | cmd.command = CMD_ABSPOINTER_DATA; 59 | send(cmd); 60 | 61 | buttons = (cmd.ax & 0xFFFF); 62 | ps2::mousepos.X = (cmd.bx * framebuffer::main_frm->width) / 0xFFFF; 63 | ps2::mousepos.Y = (cmd.cx * framebuffer::main_frm->height) / 0xFFFF; 64 | 65 | ps2::mouseclear(); 66 | 67 | static bool circle = false; 68 | switch(ps2::getmousestate()) 69 | { 70 | case ps2::PS2_LEFT: 71 | if (circle) framebuffer::drawfilledcircle(ps2::mousepos.X, ps2::mousepos.Y, 5, 0xff0000); 72 | else framebuffer::drawfilledrectangle(ps2::mousepos.X, ps2::mousepos.Y, 10, 10, 0xff0000); 73 | break; 74 | case ps2::PS2_MIDDLE: 75 | if (circle) circle = false; 76 | else circle = true; 77 | break; 78 | case ps2::PS2_RIGHT: 79 | if (circle) framebuffer::drawfilledcircle(ps2::mousepos.X, ps2::mousepos.Y, 5, 0xdd56f5); 80 | else framebuffer::drawfilledrectangle(ps2::mousepos.X, ps2::mousepos.Y, 10, 10, 0xdd56f5); 81 | break; 82 | default: 83 | break; 84 | } 85 | 86 | ps2::mousedraw(); 87 | ps2::mouseposold = ps2::mousepos; 88 | } 89 | 90 | void mouse_absolute() 91 | { 92 | CMD cmd; 93 | 94 | cmd.bx = ABSPOINTER_ENABLE; 95 | cmd.command = CMD_ABSPOINTER_COMMAND; 96 | send(cmd); 97 | 98 | cmd.bx = 0; 99 | cmd.command = CMD_ABSPOINTER_STATUS; 100 | send(cmd); 101 | 102 | cmd.bx = 1; 103 | cmd.command = CMD_ABSPOINTER_DATA; 104 | send(cmd); 105 | 106 | cmd.bx = ABSPOINTER_ABSOLUTE; 107 | cmd.command = CMD_ABSPOINTER_COMMAND; 108 | send(cmd); 109 | 110 | ps2::mousevmware = true; 111 | } 112 | 113 | void mouse_relative() 114 | { 115 | CMD cmd; 116 | 117 | cmd.bx = ABSPOINTER_RELATIVE; 118 | cmd.command = CMD_ABSPOINTER_COMMAND; 119 | send(cmd); 120 | 121 | ps2::mousevmware = false; 122 | } 123 | 124 | void init() 125 | { 126 | log("Initialising VMWare tools"); 127 | 128 | if (initialised) 129 | { 130 | warn("VMWare tools have already been initialised!\n"); 131 | return; 132 | } 133 | if (!is_vmware_backdoor()) 134 | { 135 | error("VMWare backdoor is not available!\n"); 136 | return; 137 | } 138 | 139 | mouse_absolute(); 140 | 141 | serial::newline(); 142 | initialised = true; 143 | } 144 | } -------------------------------------------------------------------------------- /source/drivers/vmware/vmware.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2021-2022 ilobilo 2 | 3 | #pragma once 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | using namespace kernel::drivers::ps2; 10 | 11 | namespace kernel::drivers::vmware { 12 | 13 | static constexpr uint32_t VMWARE_MAGIC = 0x564D5868; 14 | static constexpr uint16_t VMWARE_PORT = 0x5658; 15 | 16 | static constexpr uint16_t CMD_GETVERSION = 10; 17 | static constexpr uint16_t CMD_ABSPOINTER_DATA = 39; 18 | static constexpr uint16_t CMD_ABSPOINTER_STATUS = 40; 19 | static constexpr uint16_t CMD_ABSPOINTER_COMMAND = 41; 20 | 21 | static constexpr uint32_t ABSPOINTER_ENABLE = 0x45414552; 22 | static constexpr uint32_t ABSPOINTER_RELATIVE = 0xF5; 23 | static constexpr uint32_t ABSPOINTER_ABSOLUTE = 0x53424152; 24 | 25 | struct CMD 26 | { 27 | union { 28 | uint32_t ax; 29 | uint32_t magic; 30 | }; 31 | union { 32 | uint32_t bx; 33 | size_t size; 34 | }; 35 | union { 36 | uint32_t cx; 37 | uint16_t command; 38 | }; 39 | union { 40 | uint32_t dx; 41 | uint16_t port; 42 | }; 43 | uint32_t si; 44 | uint32_t di; 45 | }; 46 | 47 | extern bool initialised; 48 | 49 | void vmware_send(CMD *cmd); 50 | bool is_vmware_backdoor(); 51 | 52 | void handle_mouse(); 53 | 54 | ps2::mousestate getmousestate(); 55 | 56 | void mouse_absolute(); 57 | void mouse_relative(); 58 | 59 | void init(); 60 | } -------------------------------------------------------------------------------- /source/initrd/bin/crash: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ilobilo/kernel/e85ed7ec06901c40b339769cfc7236b6b094a9f3/source/initrd/bin/crash -------------------------------------------------------------------------------- /source/initrd/binlink: -------------------------------------------------------------------------------- 1 | bin -------------------------------------------------------------------------------- /source/initrd/prog: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ilobilo/kernel/e85ed7ec06901c40b339769cfc7236b6b094a9f3/source/initrd/prog -------------------------------------------------------------------------------- /source/initrd/prog1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ilobilo/kernel/e85ed7ec06901c40b339769cfc7236b6b094a9f3/source/initrd/prog1 -------------------------------------------------------------------------------- /source/initrd/test: -------------------------------------------------------------------------------- 1 | test text goes here 123 -------------------------------------------------------------------------------- /source/initrd/testlink: -------------------------------------------------------------------------------- 1 | test -------------------------------------------------------------------------------- /source/kernel/kernel.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2021-2022 ilobilo 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | using namespace kernel::drivers::display; 16 | 17 | uint8_t *kernel_stack; 18 | const char *cmdline; 19 | uint64_t hhdm_offset; 20 | 21 | #if LVL5_PAGING 22 | volatile limine_5_level_paging_request _5_level_paging_request 23 | { 24 | .id = LIMINE_5_LEVEL_PAGING_REQUEST, 25 | .revision = 0, 26 | .response = nullptr 27 | }; 28 | #endif 29 | 30 | volatile limine_terminal_request terminal_request 31 | { 32 | .id = LIMINE_TERMINAL_REQUEST, 33 | .revision = 0, 34 | .response = nullptr, 35 | .callback = terminal::callback 36 | }; 37 | 38 | volatile limine_framebuffer_request framebuffer_request 39 | { 40 | .id = LIMINE_FRAMEBUFFER_REQUEST, 41 | .revision = 0, 42 | .response = nullptr 43 | }; 44 | 45 | volatile limine_smp_request smp_request 46 | { 47 | .id = LIMINE_SMP_REQUEST, 48 | .revision = 0, 49 | .response = nullptr, 50 | .flags = (1 << 0) 51 | }; 52 | 53 | volatile limine_memmap_request memmap_request 54 | { 55 | .id = LIMINE_MEMMAP_REQUEST, 56 | .revision = 0, 57 | .response = nullptr 58 | }; 59 | 60 | volatile limine_rsdp_request rsdp_request 61 | { 62 | .id = LIMINE_RSDP_REQUEST, 63 | .revision = 0, 64 | .response = nullptr 65 | }; 66 | 67 | volatile limine_module_request module_request 68 | { 69 | .id = LIMINE_MODULE_REQUEST, 70 | .revision = 0, 71 | .response = nullptr 72 | }; 73 | 74 | volatile limine_kernel_file_request kernel_file_request 75 | { 76 | .id = LIMINE_KERNEL_FILE_REQUEST, 77 | .revision = 0, 78 | .response = nullptr 79 | }; 80 | 81 | volatile limine_boot_time_request boot_time_request 82 | { 83 | .id = LIMINE_BOOT_TIME_REQUEST, 84 | .revision = 0, 85 | .response = nullptr 86 | }; 87 | 88 | volatile limine_hhdm_request hhdm_request 89 | { 90 | .id = LIMINE_HHDM_REQUEST, 91 | .revision = 0, 92 | .response = nullptr 93 | }; 94 | 95 | volatile limine_kernel_address_request kernel_address_request 96 | { 97 | .id = LIMINE_KERNEL_ADDRESS_REQUEST, 98 | .revision = 0, 99 | .response = nullptr 100 | }; 101 | 102 | volatile limine_stack_size_request stack_size_request 103 | { 104 | .id = LIMINE_STACK_SIZE_REQUEST, 105 | .revision = 0, 106 | .response = nullptr, 107 | .stack_size = STACK_SIZE 108 | }; 109 | 110 | limine_file *find_module(const char *name) 111 | { 112 | for (size_t i = 0; i < module_request.response->module_count; i++) 113 | { 114 | if (!strcmp(module_request.response->modules[i]->cmdline, name)) 115 | { 116 | return module_request.response->modules[i]; 117 | } 118 | } 119 | return nullptr; 120 | } 121 | 122 | extern "C" void _start() 123 | { 124 | asm volatile ("movq %%rsp, %0" : "=r"(kernel_stack)); 125 | 126 | enableSSE(); 127 | enableSMEP(); 128 | enableSMAP(); 129 | enableUMIP(); 130 | enablePAT(); 131 | 132 | serial::early_init(); 133 | 134 | assert(terminal_request.response, "Could not get terminal response!"); 135 | terminal::init(); 136 | 137 | assert(framebuffer_request.response, "Could not get framebuffer response!"); 138 | framebuffer::init(); 139 | 140 | assert(smp_request.response, "Could not get smp response!"); 141 | assert(memmap_request.response, "Could not get memmap response!"); 142 | assert(rsdp_request.response, "Could not get rsdp response!"); 143 | assert(module_request.response, "Could not get module response!"); 144 | assert(kernel_file_request.response, "Could not get kernel file response!"); 145 | assert(boot_time_request.response, "Could not get boot time response!"); 146 | assert(hhdm_request.response, "Could not get hhdm response!"); 147 | assert(kernel_address_request.response, "Could not get kernel address response!"); 148 | assert(stack_size_request.response, "Could not get stack size response!"); 149 | 150 | cmdline = kernel_file_request.response->kernel_file->cmdline; 151 | hhdm_offset = hhdm_request.response->offset; 152 | 153 | kernel::main(); 154 | 155 | while (true) asm volatile ("hlt"); 156 | } -------------------------------------------------------------------------------- /source/kernel/kernel.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2021-2022 ilobilo 2 | 3 | #pragma once 4 | 5 | #include 6 | 7 | static constexpr uint64_t STACK_SIZE = 0x4000; 8 | extern uint8_t *kernel_stack; 9 | extern const char *cmdline; 10 | extern uint64_t hhdm_offset; 11 | 12 | #if LVL5_PAGING 13 | extern volatile limine_5_level_paging_request _5_level_paging_request; 14 | #endif 15 | extern volatile limine_terminal_request terminal_request; 16 | extern volatile limine_framebuffer_request framebuffer_request; 17 | extern volatile limine_smp_request smp_request; 18 | extern volatile limine_memmap_request memmap_request; 19 | extern volatile limine_rsdp_request rsdp_request; 20 | extern volatile limine_module_request module_request; 21 | extern volatile limine_kernel_file_request kernel_file_request; 22 | extern volatile limine_boot_time_request boot_time_request; 23 | extern volatile limine_hhdm_request hhdm_request; 24 | extern volatile limine_kernel_address_request kernel_address_request; 25 | 26 | limine_file *find_module(const char *name); -------------------------------------------------------------------------------- /source/kernel/main.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2021-2022 ilobilo 2 | 3 | #pragma once 4 | 5 | namespace kernel { 6 | 7 | void main(); 8 | } -------------------------------------------------------------------------------- /source/lib/alloc.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | BuddyAlloc buddyheap; 5 | SlabAlloc slabheap; 6 | 7 | void *malloc(size_t size) 8 | { 9 | switch (defalloc) 10 | { 11 | case LIBALLOC: 12 | // return liballoc_calloc(1, size); 13 | return liballoc_malloc(size); 14 | break; 15 | case BUDDY: 16 | // return buddyheap.calloc(1, size); 17 | return buddyheap.malloc(size); 18 | break; 19 | case SLAB: 20 | // return slabheap.calloc(1, size); 21 | return slabheap.malloc(size); 22 | break; 23 | } 24 | panic("No default allocator!"); 25 | return nullptr; 26 | } 27 | 28 | void *calloc(size_t num, size_t size) 29 | { 30 | switch (defalloc) 31 | { 32 | case LIBALLOC: 33 | return liballoc_calloc(num, size); 34 | break; 35 | case BUDDY: 36 | return buddyheap.calloc(num, size); 37 | break; 38 | case SLAB: 39 | return slabheap.calloc(num, size); 40 | break; 41 | } 42 | panic("No default allocator!"); 43 | return nullptr; 44 | } 45 | 46 | void *realloc(void *ptr, size_t size) 47 | { 48 | switch (defalloc) 49 | { 50 | case LIBALLOC: 51 | return liballoc_realloc(ptr, size); 52 | break; 53 | case BUDDY: 54 | return buddyheap.realloc(ptr, size); 55 | break; 56 | case SLAB: 57 | return slabheap.realloc(ptr, size); 58 | break; 59 | } 60 | panic("No default allocator!"); 61 | return nullptr; 62 | } 63 | 64 | void free(void *ptr) 65 | { 66 | switch (defalloc) 67 | { 68 | case LIBALLOC: 69 | return liballoc_free(ptr); 70 | break; 71 | case BUDDY: 72 | return buddyheap.free(ptr); 73 | break; 74 | case SLAB: 75 | return slabheap.free(ptr); 76 | break; 77 | } 78 | panic("No default allocator!"); 79 | return; 80 | } 81 | size_t allocsize(void *ptr) 82 | { 83 | switch (defalloc) 84 | { 85 | case LIBALLOC: 86 | return liballoc_allocsize(ptr); 87 | break; 88 | case BUDDY: 89 | return buddyheap.allocsize(ptr); 90 | break; 91 | case SLAB: 92 | return slabheap.allocsize(ptr); 93 | break; 94 | } 95 | panic("No default allocator!"); 96 | return 0; 97 | } 98 | 99 | 100 | namespace std 101 | { 102 | enum class align_val_t: size_t {}; 103 | } 104 | 105 | void *operator new(size_t size) 106 | { 107 | return malloc(size); 108 | } 109 | 110 | void *operator new(size_t size, std::align_val_t alignment) 111 | { 112 | return malloc(ALIGN_UP(size, static_cast(alignment))); 113 | } 114 | 115 | void *operator new[](size_t size) 116 | { 117 | return malloc(size); 118 | } 119 | 120 | void *operator new[](size_t size, std::align_val_t alignment) 121 | { 122 | return malloc(ALIGN_UP(size, static_cast(alignment))); 123 | } 124 | 125 | void operator delete(void *ptr) 126 | { 127 | free(ptr); 128 | } 129 | 130 | void operator delete(void *ptr, std::align_val_t alignment) 131 | { 132 | free(ptr); 133 | } 134 | 135 | void operator delete[](void *ptr) 136 | { 137 | free(ptr); 138 | } 139 | 140 | void operator delete[](void *ptr, std::align_val_t alignment) 141 | { 142 | free(ptr); 143 | } -------------------------------------------------------------------------------- /source/lib/alloc.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2021-2022 ilobilo 2 | 3 | #pragma once 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | enum allocs 12 | { 13 | LIBALLOC, 14 | BUDDY, 15 | SLAB 16 | }; 17 | 18 | static allocs defalloc = SLAB; 19 | 20 | extern BuddyAlloc buddyheap; 21 | extern SlabAlloc slabheap; 22 | 23 | extern "C" void *malloc(size_t size); 24 | extern "C" void *calloc(size_t num, size_t size); 25 | extern "C" void *realloc(void *ptr, size_t size); 26 | extern "C" void free(void *ptr); 27 | size_t allocsize(void *ptr); 28 | 29 | template 30 | static inline type malloc(size_t size) 31 | { 32 | return reinterpret_cast(malloc(size)); 33 | } 34 | 35 | template 36 | static inline type calloc(size_t num, size_t size) 37 | { 38 | return reinterpret_cast(calloc(num, size)); 39 | } 40 | 41 | template 42 | static inline type realloc(void *ptr, size_t size) 43 | { 44 | return reinterpret_cast(realloc(ptr, size)); 45 | } -------------------------------------------------------------------------------- /source/lib/bitmap.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2021-2022 ilobilo 2 | 3 | #include 4 | 5 | bool Bitmap::operator[](uint64_t index) 6 | { 7 | return Get(index); 8 | } 9 | 10 | bool Bitmap::Get(uint64_t index) 11 | { 12 | uint64_t bytei = index / 8; 13 | uint8_t biti = index % 8; 14 | uint8_t bitindexer = 0b10000000 >> biti; 15 | if ((buffer[bytei] & bitindexer) > 0) return true; 16 | return false; 17 | } 18 | 19 | bool Bitmap::Set(uint64_t index, bool value) 20 | { 21 | uint64_t bytei = index / 8; 22 | uint8_t biti = index % 8; 23 | uint8_t bitindexer = 0b10000000 >> biti; 24 | buffer[bytei] &= ~bitindexer; 25 | if (value) buffer[bytei] |= bitindexer; 26 | return true; 27 | } -------------------------------------------------------------------------------- /source/lib/bitmap.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2021-2022 ilobilo 2 | 3 | #pragma once 4 | 5 | #include 6 | #include 7 | 8 | struct Bitmap 9 | { 10 | uint8_t *buffer = nullptr; 11 | bool operator[](uint64_t index); 12 | bool Set(uint64_t index, bool value); 13 | bool Get(uint64_t index); 14 | }; -------------------------------------------------------------------------------- /source/lib/buddy.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2021-2022 ilobilo 2 | 3 | #pragma once 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | static constexpr uint64_t INIT_PAGES = 1024; 10 | 11 | struct BuddyBlock 12 | { 13 | size_t size; 14 | bool free; 15 | }; 16 | 17 | class BuddyAlloc 18 | { 19 | private: 20 | BuddyBlock *head = nullptr; 21 | BuddyBlock *tail = nullptr; 22 | void *data = nullptr; 23 | lock_t lock; 24 | 25 | BuddyBlock *next(BuddyBlock *block); 26 | BuddyBlock *split(BuddyBlock *block, size_t size); 27 | 28 | BuddyBlock *find_best(size_t size); 29 | size_t required_size(size_t size); 30 | void coalescence(); 31 | 32 | public: 33 | bool debug = false; 34 | 35 | void init(); 36 | 37 | void *malloc(size_t size); 38 | void *calloc(size_t num, size_t size); 39 | void *realloc(void *ptr, size_t size); 40 | void free(void *ptr); 41 | 42 | size_t allocsize(void *ptr); 43 | }; -------------------------------------------------------------------------------- /source/lib/cpu.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2021-2022 ilobilo 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | uint64_t rdmsr(uint32_t msr) 10 | { 11 | uint32_t edx, eax; 12 | asm volatile("rdmsr" : "=a"(eax), "=d"(edx) : "c"(msr) : "memory"); 13 | return (static_cast(edx) << 32) | eax; 14 | } 15 | 16 | void wrmsr(uint32_t msr, uint64_t value) 17 | { 18 | uint32_t edx = value >> 32; 19 | uint32_t eax = static_cast(value); 20 | asm volatile("wrmsr" : : "a"(eax), "d"(edx), "c"(msr) : "memory"); 21 | } 22 | 23 | void set_kernel_gs(uint64_t addr) 24 | { 25 | wrmsr(0xC0000102, addr); 26 | } 27 | 28 | uint64_t get_kernel_gs() 29 | { 30 | return rdmsr(0xC0000102); 31 | } 32 | 33 | void set_gs(uint64_t addr) 34 | { 35 | wrmsr(0xC0000101, addr); 36 | } 37 | 38 | uint64_t get_gs() 39 | { 40 | return rdmsr(0xC0000101); 41 | } 42 | 43 | void set_fs(uint64_t addr) 44 | { 45 | wrmsr(0xC0000100, addr); 46 | } 47 | 48 | uint64_t get_fs() 49 | { 50 | return rdmsr(0xC0000100); 51 | } 52 | 53 | void write_cr(uint64_t reg, uint64_t val) 54 | { 55 | switch (reg) 56 | { 57 | case 0: 58 | asm volatile ("mov %0, %%cr0" :: "r" (val) : "memory"); 59 | break; 60 | case 2: 61 | asm volatile ("mov %0, %%cr2" :: "r" (val) : "memory"); 62 | break; 63 | case 3: 64 | asm volatile ("mov %0, %%cr3" :: "r" (val) : "memory"); 65 | break; 66 | case 4: 67 | asm volatile ("mov %0, %%cr4" :: "r" (val) : "memory"); 68 | break; 69 | } 70 | } 71 | 72 | uint64_t read_cr(uint64_t reg) 73 | { 74 | uint64_t cr; 75 | switch (reg) 76 | { 77 | case 0: 78 | asm volatile ("mov %%cr0, %0" : "=r" (cr) :: "memory"); 79 | break; 80 | case 2: 81 | asm volatile ("mov %%cr2, %0" : "=r" (cr) :: "memory"); 82 | break; 83 | case 3: 84 | asm volatile ("mov %%cr3, %0" : "=r" (cr) :: "memory"); 85 | break; 86 | case 4: 87 | asm volatile ("mov %%cr4, %0" : "=r" (cr) :: "memory"); 88 | break; 89 | } 90 | return cr; 91 | } 92 | 93 | void wrxcr(uint32_t i, uint64_t value) 94 | { 95 | uint32_t edx = value >> 32; 96 | uint32_t eax = static_cast(value); 97 | asm volatile ("xsetbv" : : "a"(eax), "d"(edx), "c"(i) : "memory"); 98 | } 99 | 100 | static uint64_t rfbm = ~0ull; 101 | static uint32_t rfbm_low = rfbm & 0xFFFF'FFFF; 102 | static uint32_t rfbm_high = (rfbm >> 32) & 0xFFFF'FFFF; 103 | 104 | void xsaveopt(uint8_t *region) 105 | { 106 | asm volatile ("xsaveopt64 (%0)" : : "r"(region), "a"(rfbm_low), "d"(rfbm_high) : "memory"); 107 | } 108 | 109 | void xsave(uint8_t *region) 110 | { 111 | asm volatile ("xsaveq (%0)" : : "r"(region), "a"(rfbm_low), "d"(rfbm_high) : "memory"); 112 | } 113 | 114 | void xrstor(uint8_t *region) 115 | { 116 | asm volatile ("xrstorq (%0)" : : "r"(region), "a"(rfbm_low), "d"(rfbm_high) : "memory"); 117 | } 118 | 119 | void fxsave(uint8_t *region) 120 | { 121 | asm volatile ("fxsaveq (%0)" : : "r"(region) : "memory"); 122 | } 123 | 124 | void fxrstor(uint8_t *region) 125 | { 126 | asm volatile ("fxrstorq (%0)" : : "r"(region) : "memory"); 127 | } 128 | 129 | void invlpg(uint64_t addr) 130 | { 131 | asm volatile ("invlpg (%0)" : : "r"(addr)); 132 | } 133 | 134 | void enableSSE() 135 | { 136 | write_cr(0, (read_cr(0) & ~(1 << 2)) | (1 << 1)); 137 | write_cr(4, read_cr(4) | (3 << 9)); 138 | } 139 | 140 | void enableSMEP() 141 | { 142 | uint32_t a = 0, b = 0, c = 0, d = 0; 143 | if (__get_cpuid(7, &a, &b, &c, &d)) 144 | { 145 | if (b & CPUID_SMEP) 146 | { 147 | write_cr(4, read_cr(4) | (1 << 20)); 148 | } 149 | } 150 | } 151 | 152 | void enableSMAP() 153 | { 154 | uint32_t a = 0, b = 0, c = 0, d = 0; 155 | if (__get_cpuid(7, &a, &b, &c, &d)) 156 | { 157 | if (b & CPUID_SMAP) 158 | { 159 | write_cr(4, read_cr(4) | (1 << 21)); 160 | asm volatile ("clac"); 161 | } 162 | } 163 | } 164 | 165 | void enableUMIP() 166 | { 167 | uint32_t a = 0, b = 0, c = 0, d = 0; 168 | if (__get_cpuid(7, &a, &b, &c, &d)) 169 | { 170 | if (c & CPUID_UMIP) 171 | { 172 | write_cr(4, read_cr(4) | (1 << 11)); 173 | } 174 | } 175 | } 176 | 177 | void enablePAT() 178 | { 179 | wrmsr(0x277, WriteBack | (Uncachable << 8) | (WriteCombining << 16)); 180 | } -------------------------------------------------------------------------------- /source/lib/cpu.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2021-2022 ilobilo 2 | 3 | #pragma once 4 | 5 | #include 6 | 7 | static constexpr uint64_t CPUID_INVARIANT_TSC = (1 << 8); 8 | static constexpr uint64_t CPUID_TSC_DEADLINE = (1 << 24); 9 | static constexpr uint64_t CPUID_SMEP = (1 << 7); 10 | static constexpr uint64_t CPUID_SMAP = (1 << 20); 11 | static constexpr uint64_t CPUID_UMIP = (1 << 2); 12 | static constexpr uint64_t CPUID_X2APIC = (1 << 21); 13 | static constexpr uint64_t CPUID_GBPAGE = (1 << 26); 14 | 15 | enum PAT 16 | { 17 | Uncachable = 0x00, 18 | WriteCombining = 0x01, 19 | WriteThrough = 0x04, 20 | WriteProtected = 0x05, 21 | WriteBack = 0x06, 22 | Uncached = 0x07 23 | }; 24 | 25 | struct [[gnu::packed]] registers_t 26 | { 27 | uint64_t r15, r14, r13, r12, r11, r10, r9, r8; 28 | uint64_t rbp, rdi, rsi, rdx, rcx, rbx, rax; 29 | uint64_t int_no, error_code, rip, cs, rflags, rsp, ss; 30 | }; 31 | 32 | uint64_t rdmsr(uint32_t msr); 33 | void wrmsr(uint32_t msr, uint64_t value); 34 | 35 | void set_kernel_gs(uint64_t addr); 36 | uint64_t get_kernel_gs(); 37 | 38 | void set_gs(uint64_t addr); 39 | uint64_t get_gs(); 40 | 41 | void set_fs(uint64_t addr); 42 | uint64_t get_fs(); 43 | 44 | void write_cr(uint64_t reg, uint64_t val); 45 | uint64_t read_cr(uint64_t reg); 46 | 47 | void wrxcr(uint32_t i, uint64_t value); 48 | 49 | void xsaveopt(uint8_t *region); 50 | void xsave(uint8_t *region); 51 | void xrstor(uint8_t *region); 52 | void fxsave(uint8_t *region); 53 | void fxrstor(uint8_t *region); 54 | 55 | void invlpg(uint64_t addr); 56 | 57 | void enableSSE(); 58 | void enableSMEP(); 59 | void enableSMAP(); 60 | void enableUMIP(); 61 | void enablePAT(); 62 | 63 | #define read_gs(offset) \ 64 | ({ \ 65 | uint64_t value; \ 66 | asm volatile("movq %%gs:[" #offset "], %0" : "=r"(value) : : "memory"); \ 67 | value; \ 68 | }) -------------------------------------------------------------------------------- /source/lib/cpu.inc: -------------------------------------------------------------------------------- 1 | ; Copyright (C) 2021-2022 ilobilo 2 | 3 | %macro pushall 0 4 | push rax 5 | push rbx 6 | push rcx 7 | push rdx 8 | push rsi 9 | push rdi 10 | push rbp 11 | push r8 12 | push r9 13 | push r10 14 | push r11 15 | push r12 16 | push r13 17 | push r14 18 | push r15 19 | %endmacro 20 | 21 | %macro popall 0 22 | pop r15 23 | pop r14 24 | pop r13 25 | pop r12 26 | pop r11 27 | pop r10 28 | pop r9 29 | pop r8 30 | pop rbp 31 | pop rdi 32 | pop rsi 33 | pop rdx 34 | pop rcx 35 | pop rbx 36 | pop rax 37 | %endmacro -------------------------------------------------------------------------------- /source/lib/cxxabi.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | extern "C" { 7 | 8 | atexit_func_entry_t __atexit_funcs[ATEXIT_MAX_FUNCS]; 9 | uarch_t __atexit_func_count = 0; 10 | 11 | void *__dso_handle = 0; 12 | 13 | int __cxa_atexit(void (*func)(void *), void *objptr, void *dso) 14 | { 15 | if (__atexit_func_count >= ATEXIT_MAX_FUNCS) return -1; 16 | 17 | __atexit_funcs[__atexit_func_count].destructor_func = func; 18 | __atexit_funcs[__atexit_func_count].obj_ptr = objptr; 19 | __atexit_funcs[__atexit_func_count].dso_handle = dso; 20 | __atexit_func_count++; 21 | 22 | return 0; 23 | }; 24 | 25 | void __cxa_finalize(void *func) 26 | { 27 | uarch_t i = __atexit_func_count; 28 | if (func == nullptr) 29 | { 30 | while (i--) 31 | { 32 | if (__atexit_funcs[i].destructor_func) 33 | { 34 | (*__atexit_funcs[i].destructor_func)(__atexit_funcs[i].obj_ptr); 35 | } 36 | } 37 | return; 38 | } 39 | 40 | while (i--) 41 | { 42 | if (__atexit_funcs[i].destructor_func == func) 43 | { 44 | (*__atexit_funcs[i].destructor_func)(__atexit_funcs[i].obj_ptr); 45 | __atexit_funcs[i].destructor_func = 0; 46 | }; 47 | }; 48 | }; 49 | 50 | namespace __cxxabiv1 51 | { 52 | int __cxa_guard_acquire(uint64_t *guard) 53 | { 54 | reinterpret_cast(guard)->lock(); 55 | return static_cast(reinterpret_cast(guard)); 56 | } 57 | void __cxa_guard_release(uint64_t *guard) 58 | { 59 | reinterpret_cast(guard)->unlock(); 60 | } 61 | void __cxa_guard_abort(uint64_t *guard) 62 | { 63 | panic("__cxa_guard_abort was called!"); 64 | } 65 | } 66 | 67 | void __cxa_pure_virtual() 68 | { 69 | panic("Pure virtual function called!"); 70 | } 71 | } -------------------------------------------------------------------------------- /source/lib/cxxabi.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | static constexpr uint64_t ATEXIT_MAX_FUNCS = 128; 6 | 7 | extern "C" { 8 | 9 | using uarch_t = unsigned; 10 | 11 | struct atexit_func_entry_t 12 | { 13 | void (*destructor_func)(void*); 14 | void *obj_ptr; 15 | void *dso_handle; 16 | }; 17 | 18 | } -------------------------------------------------------------------------------- /source/lib/elf.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2021-2022 ilobilo 2 | 3 | #pragma once 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | using namespace kernel::system::mm; 15 | using namespace kernel::system; 16 | 17 | struct Auxval 18 | { 19 | uint64_t entry; 20 | uint64_t phdr; 21 | uint64_t phent; 22 | uint64_t phnum; 23 | }; 24 | 25 | static inline auto elf_load(vmm::Pagemap *pagemap, vfs::resource_t *res, uint64_t base) 26 | { 27 | struct ret { Auxval auxval; std::string ld_path; }; 28 | ret null { Auxval { 0, 0, 0, 0 }, "" }; 29 | 30 | std::shared_ptr header(new Elf64_Ehdr); 31 | res->read(nullptr, reinterpret_cast(header.get()), 0, sizeof(Elf64_Ehdr)); 32 | 33 | if (memcmp(header->e_ident, ELFMAG, 4)) 34 | { 35 | error("ELF: Invalid magic!"); 36 | return null; 37 | } 38 | 39 | if (header->e_ident[EI_CLASS] != ELFCLASS64 40 | || header->e_ident[EI_DATA] != ELFDATA2LSB 41 | || header->e_ident[EI_OSABI] != ELFOSABI_SYSV 42 | || header->e_machine != 0x3E) 43 | { 44 | error("ELF: Unsupported ELF file!"); 45 | return null; 46 | } 47 | 48 | Auxval auxval 49 | { 50 | .entry = base + header->e_entry, 51 | .phdr = 0, 52 | .phent = sizeof(Elf64_Phdr), 53 | .phnum = header->e_phnum 54 | }; 55 | 56 | std::string ld_path(""); 57 | for (size_t i = 0; i < header->e_phnum; i++) 58 | { 59 | std::shared_ptr phdr(new Elf64_Phdr); 60 | res->read(nullptr, reinterpret_cast(phdr.get()), header->e_phoff + sizeof(Elf64_Phdr) * i, sizeof(Elf64_Phdr)); 61 | 62 | switch (phdr->p_type) 63 | { 64 | case PT_INTERP: 65 | ld_path.resize(phdr->p_filesz); 66 | res->read(nullptr, reinterpret_cast(ld_path.data()), phdr->p_offset, phdr->p_filesz); 67 | break; 68 | case PT_PHDR: 69 | auxval.phdr = base + phdr->p_vaddr; 70 | break; 71 | case PT_LOAD: 72 | { 73 | uint64_t misalign = (phdr->p_vaddr & (vmm::page_size - 1)); 74 | uint64_t pages = DIV_ROUNDUP(misalign + phdr->p_memsz, vmm::page_size); 75 | void *addr = pmm::alloc(pages); 76 | if (addr == nullptr) 77 | { 78 | error("ELF: Could not allocate memory!"); 79 | return null; 80 | } 81 | 82 | uint64_t vaddr = base + phdr->p_vaddr; 83 | uint64_t paddr = reinterpret_cast(addr); 84 | 85 | pagemap->mapRange(vaddr, paddr, pages * vmm::page_size, vmm::ProtRead | vmm::ProtExec | (phdr->p_flags & PF_W ? vmm::ProtWrite : 0), vmm::MapAnon); 86 | 87 | uint8_t *buffer = reinterpret_cast(reinterpret_cast(addr) + misalign + hhdm_offset); 88 | res->read(0, buffer, phdr->p_offset, phdr->p_filesz); 89 | break; 90 | } 91 | } 92 | } 93 | return ret { auxval, ld_path }; 94 | } -------------------------------------------------------------------------------- /source/lib/errno.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2021-2022 ilobilo 2 | 3 | #include 4 | 5 | void errno_set(errno_t err) 6 | { 7 | if (this_thread()) this_thread()->err = err; 8 | else this_cpu->err = err; 9 | } 10 | 11 | errno_t errno_get() 12 | { 13 | if (this_thread()) return this_thread()->err; 14 | return this_cpu->err; 15 | } -------------------------------------------------------------------------------- /source/lib/errno.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2021-2022 ilobilo 2 | 3 | #pragma once 4 | 5 | enum errno_t 6 | { 7 | EDOM = 1, 8 | EILSEQ = 2, 9 | ERANGE = 3, 10 | E2BIG = 1001, 11 | EACCES = 1002, 12 | EADDRINUSE = 1003, 13 | EADDRNOTAVAIL = 1004, 14 | EAFNOSUPPORT = 1005, 15 | EAGAIN = 1006, 16 | EALREADY = 1007, 17 | EBADF = 1008, 18 | EBADMSG = 1009, 19 | EBUSY = 1010, 20 | ECANCELED = 1011, 21 | ECHILD = 1012, 22 | ECONNABORTED = 1013, 23 | ECONNREFUSED = 1014, 24 | ECONNRESET = 1015, 25 | EDEADLK = 1016, 26 | EDESTADDRREQ = 1017, 27 | EDQUOT = 1018, 28 | EEXIST = 1019, 29 | EFAULT = 1020, 30 | EFBIG = 1021, 31 | EHOSTUNREACH = 1022, 32 | EIDRM = 1023, 33 | EINPROGRESS = 1024, 34 | EINTR = 1025, 35 | EINVAL = 1026, 36 | EIO = 1027, 37 | EISCONN = 1028, 38 | EISDIR = 1029, 39 | ELOOP = 1030, 40 | EMFILE = 1031, 41 | EMLINK = 1032, 42 | EMSGSIZE = 1034, 43 | EMULTIHOP = 1035, 44 | ENAMETOOLONG = 1036, 45 | ENETDOWN = 1037, 46 | ENETRESET = 1038, 47 | ENETUNREACH = 1039, 48 | ENFILE = 1040, 49 | ENOBUFS = 1041, 50 | ENODEV = 1042, 51 | ENOENT = 1043, 52 | ENOEXEC = 1044, 53 | ENOLCK = 1045, 54 | ENOLINK = 1046, 55 | ENOMEM = 1047, 56 | ENOMSG = 1048, 57 | ENOPROTOOPT = 1049, 58 | ENOSPC = 1050, 59 | ENOSYS = 1051, 60 | ENOTCONN = 1052, 61 | ENOTDIR = 1053, 62 | ENOTEMPTY = 1054, 63 | ENOTRECOVERABLE = 1055, 64 | ENOTSOCK = 1056, 65 | ENOTSUP = 1057, 66 | ENOTTY = 1058, 67 | ENXIO = 1059, 68 | EOPNOTSUPP = 1060, 69 | EOVERFLOW = 1061, 70 | EOWNERDEAD = 1062, 71 | EPERM = 1063, 72 | EPIPE = 1064, 73 | EPROTO = 1065, 74 | EPROTONOSUPPORT = 1066, 75 | EPROTOTYPE = 1067, 76 | EROFS = 1068, 77 | ESPIPE = 1069, 78 | ESRCH = 1070, 79 | ESTALE = 1071, 80 | ETIMEDOUT = 1072, 81 | ETXTBSY = 1073, 82 | EWOULDBLOCK = EAGAIN, 83 | EXDEV = 1075, 84 | ENODATA = 1076, 85 | ETIME = 1077, 86 | ENOKEY = 1078, 87 | ESHUTDOWN = 1079, 88 | EHOSTDOWN = 1080, 89 | EBADFD = 1081 90 | }; 91 | 92 | void errno_set(errno_t err); 93 | errno_t errno_get(); -------------------------------------------------------------------------------- /source/lib/function.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2021-2022 ilobilo 2 | 3 | #pragma once 4 | 5 | template 6 | class function; 7 | 8 | template 9 | class function 10 | { 11 | public: 12 | function() { }; 13 | 14 | template 15 | function(func t) : callable_(new callableFunc(t)) { } 16 | 17 | ~function() 18 | { 19 | delete this->callable_; 20 | } 21 | 22 | template 23 | function &operator=(func t) 24 | { 25 | this->callable_ = new callableFunc(t); 26 | return *this; 27 | } 28 | 29 | retval operator()(Args ...args) const 30 | { 31 | return this->callable_->invoke(args...); 32 | } 33 | 34 | private: 35 | class callable { 36 | public: 37 | virtual ~callable() = default; 38 | virtual retval invoke(Args...) = 0; 39 | }; 40 | 41 | template 42 | class callableFunc : public callable { 43 | public: 44 | callableFunc(const func &t) : t_(t) { } 45 | ~callableFunc() override = default; 46 | 47 | retval invoke(Args ...args) override 48 | { 49 | return t_(args...); 50 | } 51 | 52 | private: 53 | func t_; 54 | }; 55 | 56 | callable *callable_; 57 | }; 58 | 59 | namespace std 60 | { 61 | template 62 | using function = ::function; 63 | } -------------------------------------------------------------------------------- /source/lib/io.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2021-2022 ilobilo 2 | 3 | #include 4 | #include 5 | 6 | void outb(uint16_t port, uint8_t val) 7 | { 8 | asm volatile ("outb %0, %1" : : "a"(val), "Nd"(port)); 9 | } 10 | 11 | void outw(uint16_t port, uint16_t val) 12 | { 13 | asm volatile("outw %w0, %w1" : : "a" (val), "Nd" (port)); 14 | } 15 | 16 | void outl(uint16_t port, uint32_t val) 17 | { 18 | asm volatile("outl %0, %w1" : : "a" (val), "Nd" (port)); 19 | } 20 | 21 | uint8_t inb(uint16_t port) 22 | { 23 | uint8_t data; 24 | asm volatile("inb %w1, %b0" : "=a" (data) : "Nd" (port)); 25 | return data; 26 | } 27 | 28 | uint16_t inw(uint16_t port) 29 | { 30 | uint16_t data; 31 | asm volatile("inw %w1, %w0" : "=a" (data) : "Nd" (port)); 32 | return data; 33 | } 34 | 35 | uint32_t inl(uint16_t port) 36 | { 37 | uint32_t data; 38 | asm volatile("inl %w1, %0" : "=a" (data) : "Nd" (port)); 39 | return data; 40 | } 41 | 42 | void io_wait(void) 43 | { 44 | asm volatile ("outb %%al, $0x80" : : "a"(0)); 45 | } -------------------------------------------------------------------------------- /source/lib/io.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2021-2022 ilobilo 2 | 3 | #pragma once 4 | 5 | #include 6 | 7 | void outb(uint16_t port, uint8_t val); 8 | void outw(uint16_t port, uint16_t val); 9 | void outl(uint16_t port, uint32_t val); 10 | 11 | uint8_t inb(uint16_t port); 12 | uint16_t inw(uint16_t port); 13 | uint32_t inl(uint16_t port); 14 | 15 | void io_wait(); -------------------------------------------------------------------------------- /source/lib/liballoc.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | struct boundary_tag 7 | { 8 | uint64_t magic; 9 | uint64_t size; 10 | uint64_t real_size; 11 | int index; 12 | 13 | struct boundary_tag *split_left; 14 | struct boundary_tag *split_right; 15 | 16 | struct boundary_tag *next; 17 | struct boundary_tag *prev; 18 | }; 19 | 20 | void *liballoc_malloc(size_t); 21 | void *liballoc_realloc(void*, size_t); 22 | void *liballoc_calloc(size_t, size_t); 23 | void liballoc_free(void*); 24 | size_t liballoc_allocsize(void*); -------------------------------------------------------------------------------- /source/lib/list.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2021-2022 ilobilo 2 | 3 | #pragma once 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | template 11 | class list 12 | { 13 | private: 14 | vector keys; 15 | vector values; 16 | type null = type(); 17 | 18 | public: 19 | volatile bool on = false; 20 | 21 | void init() 22 | { 23 | if (this->on) return; 24 | this->keys.init(); 25 | this->values.init(); 26 | on = true; 27 | } 28 | 29 | void init(size_t size) 30 | { 31 | if (on) return; 32 | this->keys.init(size); 33 | this->values.init(size); 34 | on = true; 35 | } 36 | 37 | void destroy() 38 | { 39 | if (!on) return; 40 | this->keys.destroy(); 41 | this->values.destroy(); 42 | on = false; 43 | } 44 | 45 | void push_back(const type &value, std::string key = "") 46 | { 47 | if (!on) this->init(); 48 | this->keys.push_back(key); 49 | this->values.push_back(value); 50 | } 51 | 52 | void pop_back() 53 | { 54 | if (!on) return; 55 | this->keys.pop_back(); 56 | this->values.pop_back(); 57 | } 58 | 59 | size_t find(type item) 60 | { 61 | return this->values.find(item); 62 | } 63 | 64 | void remove(size_t pos) 65 | { 66 | if (!on) return; 67 | this->keys.remove(pos); 68 | this->values.remove(pos); 69 | } 70 | 71 | type &operator[](size_t pos) 72 | { 73 | return this->values[pos]; 74 | } 75 | 76 | type &operator[](std::string key) 77 | { 78 | for (size_t i = 0; i < this->keys.size(); i++) 79 | { 80 | if (this->keys[i] == key) return this->values[i]; 81 | } 82 | return this->null; 83 | } 84 | 85 | type &at(size_t pos) 86 | { 87 | return this->values[pos]; 88 | } 89 | 90 | type &front() 91 | { 92 | return this->values.front(); 93 | } 94 | 95 | type &back() 96 | { 97 | return this->values.back(); 98 | } 99 | 100 | type *begin() 101 | { 102 | return this->values.begin(); 103 | } 104 | 105 | type *end() 106 | { 107 | return this->values.end(); 108 | } 109 | 110 | type *data() 111 | { 112 | return this->values.data(); 113 | } 114 | 115 | const type *cbegin() 116 | { 117 | return this->values.cbegin(); 118 | } 119 | 120 | const type *cend() 121 | { 122 | return this->values.cend(); 123 | } 124 | 125 | size_t size() 126 | { 127 | return this->values.size(); 128 | } 129 | 130 | size_t max_size() 131 | { 132 | return this->values.max_size(); 133 | } 134 | 135 | void resize(size_t size) 136 | { 137 | if (!on) this->init(); 138 | this->keys.resize(size); 139 | this->values.resize(size); 140 | } 141 | 142 | void expand(size_t size) 143 | { 144 | if (!on) this->init(); 145 | this->keys.expand(size); 146 | this->values.expand(size); 147 | } 148 | 149 | void insert(size_t pos, std::string key, const type &value) 150 | { 151 | if (!on) this->init(); 152 | this->keys.insert(pos, key); 153 | this->values.insert(pos, value); 154 | } 155 | }; -------------------------------------------------------------------------------- /source/lib/lock.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2021-2022 ilobilo 2 | 3 | #include 4 | #include 5 | 6 | void lock_t::lock() 7 | { 8 | while (__atomic_test_and_set(&this->locked, __ATOMIC_ACQUIRE)); 9 | } 10 | 11 | void lock_t::unlock() 12 | { 13 | __atomic_clear(&this->locked, __ATOMIC_RELEASE); 14 | } 15 | 16 | bool lock_t::test() 17 | { 18 | return this->locked; 19 | } -------------------------------------------------------------------------------- /source/lib/lock.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2021-2022 ilobilo 2 | 3 | #pragma once 4 | 5 | #include 6 | 7 | class lock_t 8 | { 9 | private: 10 | volatile bool locked = false; 11 | 12 | public: 13 | void lock(); 14 | void unlock(); 15 | bool test(); 16 | }; 17 | 18 | class lockit 19 | { 20 | private: 21 | lock_t *lock; 22 | public: 23 | lockit(lock_t &lock) 24 | { 25 | this->lock = &lock; 26 | lock.lock(); 27 | } 28 | ~lockit() 29 | { 30 | lock->unlock(); 31 | } 32 | }; 33 | 34 | #define new_lock(name) static lock_t name; 35 | 36 | #define CONCAT_IMPL(x, y) x##y 37 | #define CONCAT(x, y) CONCAT_IMPL(x, y) 38 | 39 | #define lockit(name) lockit CONCAT(lock##_, __COUNTER__)(name) -------------------------------------------------------------------------------- /source/lib/log.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2021-2022 ilobilo 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | using namespace kernel::drivers::display; 8 | 9 | new_lock(log_lock); 10 | 11 | int log(const char *fmt, ...) 12 | { 13 | lockit(log_lock); 14 | 15 | va_list args; 16 | va_start(args, fmt); 17 | int ret = vfctprintf(serial::printc, reinterpret_cast(serial::COM1), "[\033[32mINFO\033[0m] ", args); 18 | ret += vfctprintf(serial::printc, reinterpret_cast(serial::COM1), fmt, args); 19 | ret += vfctprintf(serial::printc, reinterpret_cast(serial::COM1), "\n", args); 20 | va_end(args); 21 | 22 | return ret; 23 | } 24 | 25 | int warn(const char *fmt, ...) 26 | { 27 | lockit(log_lock); 28 | 29 | va_list args; 30 | va_start(args, fmt); 31 | int ret = vfctprintf(serial::printc, reinterpret_cast(serial::COM1), "[\033[33mWARN\033[0m] ", args); 32 | ret += vfctprintf(serial::printc, reinterpret_cast(serial::COM1), fmt, args); 33 | ret += vfctprintf(serial::printc, reinterpret_cast(serial::COM1), "\n", args); 34 | va_end(args); 35 | 36 | return ret; 37 | } 38 | 39 | int error(const char *fmt, ...) 40 | { 41 | lockit(log_lock); 42 | 43 | va_list args; 44 | va_start(args, fmt); 45 | int ret = vfctprintf(serial::printc, reinterpret_cast(serial::COM1), "[\033[31mERROR\033[0m] ", args); 46 | ret += vfctprintf(serial::printc, reinterpret_cast(serial::COM1), fmt, args); 47 | ret += vfctprintf(serial::printc, reinterpret_cast(serial::COM1), "\n", args); 48 | va_end(args); 49 | 50 | return ret; 51 | } -------------------------------------------------------------------------------- /source/lib/log.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2021-2022 ilobilo 2 | 3 | #pragma once 4 | 5 | #include 6 | 7 | using namespace kernel::drivers::display; 8 | 9 | int log(const char *fmt, ...); 10 | int warn(const char *fmt, ...); 11 | int error(const char *fmt, ...); -------------------------------------------------------------------------------- /source/lib/math.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2021-2022 ilobilo 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | using namespace kernel::system::sched; 8 | 9 | static unsigned long next = 1; 10 | 11 | int pow(int base, int exp) 12 | { 13 | int result = 1; 14 | for (; exp > 0; exp--) result *= base; 15 | return result; 16 | } 17 | 18 | int abs(int num) 19 | { 20 | return num < 0 ? -num : num; 21 | } 22 | 23 | int sign(int num) 24 | { 25 | return (num > 0) ? 1 : ((num < 0) ? -1 : 0); 26 | } 27 | 28 | uint64_t jdn(uint8_t days, uint8_t months, uint16_t years) 29 | { 30 | return (1461 * (years + 4800 + (months - 14) / 12)) / 4 + (367 * (months - 2 - 12 * ((months - 14) / 12))) / 12 - (3 * ((years + 4900 + (months - 14) / 12) / 100)) / 4 + days - 32075; 31 | } 32 | 33 | uint64_t rand() 34 | { 35 | next = next * 1103515245 + 12345; 36 | return next / 65536 % RAND_MAX; 37 | } 38 | 39 | void srand(uint64_t seed) 40 | { 41 | next = seed; 42 | } 43 | 44 | [[gnu::constructor]] void runsrand() 45 | { 46 | srand((rtc::epoch() / rtc::time() - rtc::second() + rtc::minute()) % RAND_MAX - rtc::hour()); 47 | } 48 | 49 | uint64_t oct2dec(int oct) 50 | { 51 | int dec = 0, temp = 0; 52 | while (oct != 0) 53 | { 54 | dec = dec + (oct % 10) * pow(8, temp); 55 | temp++; 56 | oct = oct / 10; 57 | } 58 | return dec; 59 | } 60 | 61 | int intlen(int n) 62 | { 63 | int digits = 0; 64 | if (n <= 0) 65 | { 66 | n = -n; 67 | ++digits; 68 | } 69 | while (n) 70 | { 71 | n /= 10; 72 | ++digits; 73 | } 74 | return digits; 75 | } -------------------------------------------------------------------------------- /source/lib/math.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2021-2022 ilobilo 2 | 3 | #pragma once 4 | 5 | #include 6 | #include 7 | 8 | static constexpr uint64_t RAND_MAX = 32768; 9 | 10 | #define DIV_ROUNDUP(A, B) \ 11 | ({ \ 12 | typeof(A) _a_ = A; \ 13 | typeof(B) _b_ = B; \ 14 | (_a_ + (_b_ - 1)) / _b_; \ 15 | }) 16 | 17 | #define ALIGN_UP(A, B) \ 18 | ({ \ 19 | typeof(A) _a__ = A; \ 20 | typeof(B) _b__ = B; \ 21 | DIV_ROUNDUP(_a__, _b__) * _b__; \ 22 | }) 23 | 24 | #define ALIGN_DOWN(A, B) \ 25 | ({ \ 26 | typeof(A) _a_ = A; \ 27 | typeof(B) _b_ = B; \ 28 | (_a_ / _b_) * _b_; \ 29 | }) 30 | 31 | #define POWER_OF_2(var) (!((var) & ((var) - 1))) 32 | 33 | #define TO_POWER_OF_2(var) \ 34 | ({ \ 35 | typeof(var) i = (var) - 1; \ 36 | while (i & i - 1) i = i & i - 1; \ 37 | i <<= 1; \ 38 | }) 39 | 40 | #define ALIGN_UP_2(align, var) \ 41 | ({ \ 42 | typeof(var) a = (var); \ 43 | while (a % (align) || !POWER_OF_2(a)) \ 44 | { \ 45 | a++; \ 46 | a = TO_POWER_OF_2(a); \ 47 | } \ 48 | a; \ 49 | }) 50 | 51 | struct point 52 | { 53 | size_t X = 0; 54 | size_t Y = 0; 55 | }; 56 | 57 | extern "C" int pow(int base, int exponent); 58 | extern "C" int abs(int num); 59 | extern "C" int sign(int num); 60 | 61 | uint64_t jdn(uint8_t days, uint8_t months, uint16_t years); 62 | 63 | extern "C" uint64_t rand(); 64 | extern "C" void srand(uint64_t seed); 65 | 66 | uint64_t oct2dec(int n); 67 | int intlen(int n); -------------------------------------------------------------------------------- /source/lib/memory.asm: -------------------------------------------------------------------------------- 1 | memcpy: 2 | mov rcx, rdx 3 | mov rax, rdi 4 | rep movsb 5 | ret 6 | [GLOBAL memcpy] 7 | 8 | memset: 9 | push rdi 10 | mov rax, rsi 11 | mov rcx, rdx 12 | rep stosb 13 | pop rax 14 | ret 15 | [GLOBAL memset] 16 | 17 | memmove: 18 | mov rcx, rdx 19 | mov rax, rdi 20 | 21 | cmp rdi, rsi 22 | ja .copy_backwards 23 | 24 | rep movsb 25 | jmp .done 26 | 27 | .copy_backwards: 28 | lea rdi, [rdi + rcx - 1] 29 | lea rsi, [rsi + rcx - 1] 30 | std 31 | rep movsb 32 | cld 33 | 34 | .done: 35 | ret 36 | [GLOBAL memmove] 37 | 38 | memcmp: 39 | mov rcx, rdx 40 | repe cmpsb 41 | jecxz .equal 42 | 43 | mov al, byte [rdi - 1] 44 | sub al, byte [rsi - 1] 45 | movsx rax, al 46 | jmp .done 47 | 48 | .equal: 49 | xor eax, eax 50 | 51 | .done: 52 | ret 53 | [GLOBAL memcmp] -------------------------------------------------------------------------------- /source/lib/memory.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2021-2022 ilobilo 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | uint64_t getmemsize() 8 | { 9 | static uint64_t meminbytes = 0; 10 | if (meminbytes > 0) return meminbytes; 11 | 12 | for (size_t i = 0; i < memmap_request.response->entry_count; i++) 13 | { 14 | if (memmap_request.response->entries[i]->type != LIMINE_MEMMAP_USABLE) continue; 15 | 16 | meminbytes += memmap_request.response->entries[i]->length; 17 | } 18 | 19 | return meminbytes; 20 | } 21 | 22 | bool arraycmp(uint8_t *a1, uint8_t *a2, size_t length) 23 | { 24 | for (size_t i = 0; i < length; i++) 25 | { 26 | if (a1[i] != a2[i]) return false; 27 | } 28 | return true; 29 | } -------------------------------------------------------------------------------- /source/lib/memory.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2021-2022 ilobilo 2 | 3 | #pragma once 4 | 5 | #include 6 | #include 7 | 8 | uint64_t getmemsize(); 9 | 10 | bool arraycmp(uint8_t *a1, uint8_t *a2, size_t length); 11 | 12 | extern "C" void *memcpy(void *dest, const void *src, size_t len); 13 | extern "C" int memcmp(const void *ptr1, const void *ptr2, size_t len); 14 | extern "C" void *memset(void *dest, int ch, size_t n); 15 | extern "C" void *memmove(void *dest, const void *src, size_t len); -------------------------------------------------------------------------------- /source/lib/mmio.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2021-2022 ilobilo 2 | 3 | #include 4 | 5 | void mmoutb(void *addr, uint8_t value) 6 | { 7 | asm volatile("mov %1, %0" : "=m"(BYTE_PTR(addr)) : "r"(value) : "memory"); 8 | } 9 | 10 | void mmoutw(void *addr, uint16_t value) 11 | { 12 | asm volatile("mov %1, %0" : "=m"(WORD_PTR(addr)) : "r"(value) : "memory"); 13 | } 14 | 15 | void mmoutl(void *addr, uint32_t value) 16 | { 17 | asm volatile("mov %1, %0" : "=m"(DWORD_PTR(addr)) : "r"(value) : "memory"); 18 | } 19 | 20 | void mmoutq(void *addr, uint64_t value) 21 | { 22 | asm volatile("mov %1, %0" : "=m"(QWORD_PTR(addr)) : "r"(value) : "memory"); 23 | } 24 | 25 | uint8_t mminb(void *addr) 26 | { 27 | uint8_t ret; 28 | asm volatile("mov %1, %0" : "=r"(ret) : "m"(BYTE_PTR(addr)) : "memory"); 29 | return ret; 30 | } 31 | 32 | uint16_t mminw(void *addr) 33 | { 34 | uint16_t ret; 35 | asm volatile("mov %1, %0" : "=r"(ret) : "m"(WORD_PTR(addr)) : "memory"); 36 | return ret; 37 | } 38 | 39 | uint32_t mminl(void *addr) 40 | { 41 | uint32_t ret; 42 | asm volatile("mov %1, %0" : "=r"(ret) : "m"(DWORD_PTR(addr)) : "memory"); 43 | return ret; 44 | } 45 | 46 | uint64_t mminq(void *addr) 47 | { 48 | uint64_t ret; 49 | asm volatile("mov %1, %0" : "=r"(ret) : "m"(QWORD_PTR(addr)) : "memory"); 50 | return ret; 51 | } -------------------------------------------------------------------------------- /source/lib/mmio.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2021-2022 ilobilo 2 | 3 | #pragma once 4 | 5 | #include 6 | 7 | #define FLAT_PTR(PTR) (*reinterpret_cast(PTR)) 8 | #define BYTE_PTR(PTR) (*reinterpret_cast(PTR)) 9 | #define WORD_PTR(PTR) (*reinterpret_cast(PTR)) 10 | #define DWORD_PTR(PTR) (*reinterpret_cast(PTR)) 11 | #define QWORD_PTR(PTR) (*reinterpret_cast(PTR)) 12 | 13 | void mmoutb(void *addr, uint8_t value); 14 | void mmoutw(void *addr, uint16_t value); 15 | void mmoutl(void *addr, uint32_t value); 16 | void mmoutq(void *addr, uint64_t value); 17 | 18 | uint8_t mminb(void *addr); 19 | uint16_t mminw(void *addr); 20 | uint32_t mminl(void *addr); 21 | uint64_t mminq(void *addr); -------------------------------------------------------------------------------- /source/lib/net.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2021-2022 ilobilo 2 | 3 | #pragma once 4 | 5 | #include 6 | #include 7 | 8 | static inline uint16_t htons(uint16_t num) 9 | { 10 | return __builtin_bswap16(num); 11 | } 12 | static inline uint16_t ntohs(uint16_t num) 13 | { 14 | return __builtin_bswap16(num); 15 | } 16 | 17 | static inline uint32_t htonl(uint32_t num) 18 | { 19 | return __builtin_bswap32(num); 20 | } 21 | static inline uint32_t ntohl(uint32_t num) 22 | { 23 | return __builtin_bswap32(num); 24 | } 25 | 26 | static inline uint64_t htonq(uint64_t num) 27 | { 28 | return __builtin_bswap64(num); 29 | } 30 | static inline uint64_t ntohq(uint64_t num) 31 | { 32 | return __builtin_bswap64(num); 33 | } 34 | 35 | template 36 | struct bigendian 37 | { 38 | type value; 39 | 40 | bigendian() : value(0) { } 41 | bigendian(const type &_value) : value(_value) { } 42 | 43 | bigendian &operator=(const type &_value) 44 | { 45 | switch (sizeof(type)) 46 | { 47 | case sizeof(uint64_t): 48 | this->value = htonq(_value); 49 | break; 50 | case sizeof(uint32_t): 51 | this->value = htonl(_value); 52 | break; 53 | case sizeof(uint16_t): 54 | this->value = htons(_value); 55 | break; 56 | case sizeof(uint8_t): 57 | this->value = _value; 58 | break; 59 | } 60 | return *this; 61 | } 62 | 63 | inline constexpr operator type() const 64 | { 65 | switch (sizeof(type)) 66 | { 67 | case sizeof(uint64_t): 68 | return htonq(this->value); 69 | case sizeof(uint32_t): 70 | return htonl(this->value); 71 | case sizeof(uint16_t): 72 | return htons(this->value); 73 | case sizeof(uint8_t): 74 | return this->value; 75 | } 76 | return 0; 77 | } 78 | }; 79 | 80 | struct [[gnu::packed]] ipv4addr 81 | { 82 | uint8_t addr[4]; 83 | 84 | ipv4addr() { }; 85 | ipv4addr(uint8_t first, uint8_t second, uint8_t third, uint8_t fourth) 86 | { 87 | this->addr[0] = first; 88 | this->addr[1] = second; 89 | this->addr[2] = third; 90 | this->addr[3] = fourth; 91 | } 92 | 93 | ipv4addr(uint8_t *addr) 94 | { 95 | if (addr == nullptr) return; 96 | *this->addr = *addr; 97 | } 98 | 99 | ipv4addr &operator=(const uint8_t *addr) 100 | { 101 | if (addr == nullptr) return *this; 102 | *this->addr = *addr; 103 | return *this; 104 | } 105 | 106 | bool operator==(uint8_t *addr) 107 | { 108 | return !memcmp(this->addr, addr, 4); 109 | } 110 | 111 | bool operator==(ipv4addr &addr) 112 | { 113 | return !memcmp(this->addr, addr.addr, 4); 114 | } 115 | 116 | uint8_t &operator[](size_t pos) 117 | { 118 | return this->addr[pos]; 119 | } 120 | }; 121 | 122 | struct [[gnu::packed]] macaddr 123 | { 124 | uint8_t addr[6]; 125 | 126 | macaddr() { }; 127 | macaddr(uint8_t first, uint8_t second, uint8_t third, uint8_t fourth, uint8_t fifth, uint8_t sixth) 128 | { 129 | this->addr[0] = first; 130 | this->addr[1] = second; 131 | this->addr[2] = third; 132 | this->addr[3] = fourth; 133 | this->addr[4] = fifth; 134 | this->addr[5] = sixth; 135 | } 136 | 137 | macaddr(uint8_t *addr) 138 | { 139 | if (addr == nullptr) return; 140 | *this->addr = *addr; 141 | } 142 | 143 | macaddr &operator=(uint8_t *addr) 144 | { 145 | if (addr == nullptr) return *this; 146 | *this->addr = *addr; 147 | return *this; 148 | } 149 | 150 | bool operator==(uint8_t *addr) 151 | { 152 | return !memcmp(this->addr, addr, 6); 153 | } 154 | 155 | bool operator==(macaddr &addr) 156 | { 157 | return !memcmp(this->addr, addr.addr, 6); 158 | } 159 | 160 | uint8_t &operator[](size_t pos) 161 | { 162 | return this->addr[pos]; 163 | } 164 | }; 165 | 166 | static inline bigendian checksum(void *addr, size_t size) 167 | { 168 | uint16_t *ptr = static_cast(addr); 169 | size_t count = size; 170 | uint32_t checksum = 0; 171 | 172 | while (count >= 2) 173 | { 174 | checksum += *ptr++; 175 | count -= 2; 176 | } 177 | 178 | checksum = (checksum & 0xFFFF) + (checksum >> 16); 179 | if (checksum > UINT16_MAX) checksum += 1; 180 | 181 | bigendian ret; 182 | ret.value = ~checksum; 183 | return ret; 184 | } -------------------------------------------------------------------------------- /source/lib/panic.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2021-2022 ilobilo 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | namespace kernel::system::sched::scheduler 9 | { 10 | void kill(); 11 | } 12 | 13 | [[noreturn]] void panic(const char *message, const char *func, std::source_location location) 14 | { 15 | error("PANIC: %s", message); 16 | error("File: %s", location.file()); 17 | error("Function: %s", func); 18 | error("Line: %u", location.line()); 19 | error("Column: %u", location.column()); 20 | error("System halted!\n"); 21 | 22 | printf("\n[\033[31mPANIC\033[0m] %s", message); 23 | printf("\n[\033[31mPANIC\033[0m] File: %s", location.file()); 24 | printf("\n[\033[31mPANIC\033[0m] Function: %s", func); 25 | printf("\n[\033[31mPANIC\033[0m] Line: %u", location.line()); 26 | printf("\n[\033[31mPANIC\033[0m] Column: %u", location.column()); 27 | printf("\n[\033[31mPANIC\033[0m] System halted!\n"); 28 | 29 | kernel::system::sched::scheduler::kill(); 30 | while (true) asm volatile ("cli; hlt"); 31 | } 32 | 33 | [[noreturn]] extern "C" void panic(const char *message, const char *file, const char *func, int line) 34 | { 35 | error("PANIC: %s", message); 36 | error("File: %s", file); 37 | error("Function: %s", func); 38 | error("Line: %d", line); 39 | error("System halted!\n"); 40 | 41 | printf("\n[\033[31mPANIC\033[0m] %s", message); 42 | printf("\n[\033[31mPANIC\033[0m] File: %s", file); 43 | printf("\n[\033[31mPANIC\033[0m] Function: %s", func); 44 | printf("\n[\033[31mPANIC\033[0m] Line: %d", line); 45 | printf("\n[\033[31mPANIC\033[0m] System halted!\n"); 46 | 47 | kernel::system::sched::scheduler::kill(); 48 | while (true) asm volatile ("cli; hlt"); 49 | } -------------------------------------------------------------------------------- /source/lib/panic.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2021-2022 ilobilo 2 | 3 | #pragma once 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | // [[noreturn]] void panic(const char *message, const char *func, std::source_location location); 10 | [[noreturn]] extern "C" void panic(const char *message, const char *file, const char *func, int line); 11 | 12 | // #define panic(msg) panic((msg), __PRETTY_FUNCTION__, std::source_location::current()) 13 | #define panic(msg) panic((msg), __FILE__, __PRETTY_FUNCTION__, __LINE__) 14 | 15 | #define ASSERT_MSG(x, msg) (!(x) ? panic(msg) : static_cast(const_cast(msg))) 16 | #define ASSERT_NOMSG(x) (!(x) ? panic("Assertion failed: " #x) : static_cast(x)) 17 | #define GET_MACRO(_1, _2, NAME, ...) NAME 18 | 19 | #define assert(...) GET_MACRO(__VA_ARGS__, ASSERT_MSG, ASSERT_NOMSG)(__VA_ARGS__) -------------------------------------------------------------------------------- /source/lib/pty.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2021-2022 ilobilo 2 | 3 | #pragma once 4 | 5 | #include 6 | #include 7 | 8 | using namespace kernel::system; 9 | 10 | static constexpr uint8_t nccs = 32; 11 | 12 | enum requests 13 | { 14 | TCGETS = 0x5401, 15 | TCSETS = 0x5402, 16 | TCSETSW = 0x5403, 17 | TCSETSF = 0x5404, 18 | TIOCGWINSZ = 0x5413, 19 | TIOCSWINSZ = 0x5414, 20 | }; 21 | 22 | enum input_modes 23 | { 24 | BRKINT = 0000001, 25 | ICRNL = 0000002, 26 | IGNBRK = 0000004, 27 | IGNCR = 0000010, 28 | IGNPAR = 0000020, 29 | INLCR = 0000040, 30 | INPCK = 0000100, 31 | ISTRIP = 0000200, 32 | IUCLC = 0000400, 33 | IXANY = 0001000, 34 | IXOFF = 0002000, 35 | IXON = 0004000, 36 | PARMRK = 0010000 37 | }; 38 | 39 | enum output_modes 40 | { 41 | OPOST = 0000001, 42 | OLCUC = 0000002, 43 | ONLCR = 0000004, 44 | OCRNL = 0000010, 45 | ONOCR = 0000020, 46 | ONLRET = 0000040, 47 | OFILL = 0000100, 48 | OFDEL = 0000200, 49 | NLDLY = 0000400, 50 | NL0 = 0000000, 51 | NL1 = 0000400, 52 | CRDLY = 0003000, 53 | CR0 = 0000000, 54 | CR1 = 0001000, 55 | CR2 = 0002000, 56 | CR3 = 0003000, 57 | TABDLY = 0014000, 58 | TAB0 = 0000000, 59 | TAB1 = 0004000, 60 | TAB2 = 0010000, 61 | TAB3 = 0014000, 62 | BSDLY = 0020000, 63 | BS0 = 0000000, 64 | BS1 = 0020000, 65 | FFDLY = 0100000, 66 | FF0 = 0000000, 67 | FF1 = 0100000, 68 | VTDLY = 0040000, 69 | VT0 = 0000000, 70 | VT1 = 0040000 71 | }; 72 | 73 | enum baud_rates 74 | { 75 | B0 = 0000000, 76 | B50 = 0000001, 77 | B75 = 0000002, 78 | B110 = 0000003, 79 | B134 = 0000004, 80 | B150 = 0000005, 81 | B200 = 0000006, 82 | B300 = 0000007, 83 | B600 = 0000010, 84 | B1200 = 0000011, 85 | B1800 = 0000012, 86 | B2400 = 0000013, 87 | B4800 = 0000014, 88 | B9600 = 0000015, 89 | B19200 = 0000016, 90 | B38400 = 0000017 91 | }; 92 | 93 | enum control_modes 94 | { 95 | CSIZE = 0000060, 96 | CS5 = 0000000, 97 | CS6 = 0000020, 98 | CS7 = 0000040, 99 | CS8 = 0000060, 100 | CSTOPB = 0000100, 101 | CREAD = 0000200, 102 | PARENB = 0000400, 103 | PARODD = 0001000, 104 | HUPCL = 0002000, 105 | CLOCAL = 0004000 106 | }; 107 | 108 | enum local_modes 109 | { 110 | ISIG = 0000001, 111 | ICANON = 0000002, 112 | XCASE = 0000004, 113 | ECHO = 0000010, 114 | ECHOE = 0000020, 115 | ECHOK = 0000040, 116 | ECHONL = 0000100, 117 | NOFLSH = 0000200, 118 | TOSTOP = 0000400, 119 | IEXTEN = 0001000 120 | }; 121 | 122 | enum ccs 123 | { 124 | VEOF = 1, 125 | VEOL = 2, 126 | VERASE = 3, 127 | VINTR = 4, 128 | VKILL = 5, 129 | VMIN = 6, 130 | VQUIT = 7, 131 | VSTART = 8, 132 | VSTOP = 9, 133 | VSUSP = 10, 134 | VTIME = 11, 135 | VLNEXT = 12, 136 | VWERASE = 13 137 | }; 138 | 139 | struct winsize 140 | { 141 | uint16_t ws_row; 142 | uint16_t ws_col; 143 | uint16_t ws_xpixel; 144 | uint16_t ws_ypixel; 145 | }; 146 | 147 | struct termios 148 | { 149 | uint32_t c_iflag; 150 | uint32_t c_oflag; 151 | uint32_t c_cflag; 152 | uint32_t c_lflag; 153 | uint8_t c_cc[nccs]; 154 | }; 155 | 156 | struct pty_res : vfs::resource_t 157 | { 158 | lock_t read_lock; 159 | lock_t write_lock; 160 | ringbuffer buff; 161 | ringbuffer bigbuff; 162 | bool decckm = false; 163 | winsize wsize; 164 | termios tios; 165 | 166 | union 167 | { 168 | struct 169 | { 170 | bool capslock : 1; 171 | bool numlock : 1; 172 | bool scrollock : 1; 173 | uint8_t rsv0: 5; 174 | }; 175 | uint8_t leds; 176 | }; 177 | uint8_t lastleds; 178 | 179 | uint8_t lockstate; 180 | uint8_t slockstate; 181 | 182 | union 183 | { 184 | struct 185 | { 186 | bool shift : 1; 187 | uint8_t rsv1 : 1; 188 | bool ctrl : 1; 189 | bool alt : 1; 190 | uint8_t rsv2 : 4; 191 | }; 192 | uint8_t shiftstate; 193 | }; 194 | 195 | virtual int print(const char *fmt, ...) 196 | { 197 | return 0; 198 | } 199 | 200 | int64_t read(void *handle, uint8_t *buffer, uint64_t offset, uint64_t size); 201 | int64_t write(void *handle, uint8_t *buffer, uint64_t offset, uint64_t size); 202 | int ioctl(void *handle, uint64_t request, void *argp); 203 | bool grow(void *handle, size_t new_size); 204 | void unref(void *handle); 205 | void link(void *handle); 206 | void unlink(void *handle); 207 | void *mmap(uint64_t page, int flags); 208 | 209 | void add_char(char c); 210 | void add_str(const char *str); 211 | std::string getline(); 212 | 213 | pty_res(uint16_t rows, uint64_t columns); 214 | }; -------------------------------------------------------------------------------- /source/lib/reboot.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2021-2022 ilobilo 2 | 3 | #pragma once 4 | 5 | #define LINUX_REBOOT_MAGIC1 0xFEE1DEAD 6 | #define LINUX_REBOOT_MAGIC2 672274793 7 | #define LINUX_REBOOT_MAGIC2A 85072278 8 | #define LINUX_REBOOT_MAGIC2B 369367448 9 | #define LINUX_REBOOT_MAGIC2C 537993216 10 | 11 | #define LINUX_REBOOT_CMD_RESTART 0x01234567 12 | #define LINUX_REBOOT_CMD_HALT 0xCDEF0123 13 | #define LINUX_REBOOT_CMD_CAD_ON 0x89ABCDEF 14 | #define LINUX_REBOOT_CMD_CAD_OFF 0x00000000 15 | #define LINUX_REBOOT_CMD_POWER_OFF 0x4321FEDC 16 | #define LINUX_REBOOT_CMD_RESTART2 0xA1B2C3D4 17 | #define LINUX_REBOOT_CMD_SW_SUSPEND 0xD000FCE2 18 | #define LINUX_REBOOT_CMD_KEXEC 0x45584543 -------------------------------------------------------------------------------- /source/lib/ring.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2021-2022 ilobilo 2 | 3 | #pragma once 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | static constexpr uint64_t default_ring_size = 0x1000; 10 | 11 | template 12 | class ringbuffer 13 | { 14 | private: 15 | lock_t lock; 16 | type *buffer = nullptr; 17 | uint64_t head = 0; 18 | uint64_t tail = 0; 19 | size_t cap = 0; 20 | bool isfull = false; 21 | 22 | public: 23 | ringbuffer(size_t cap) 24 | { 25 | this->cap = cap; 26 | this->buffer = new type[cap]; 27 | } 28 | ringbuffer() 29 | { 30 | this->cap = default_ring_size; 31 | this->buffer = new type[default_ring_size]; 32 | } 33 | ~ringbuffer() 34 | { 35 | delete[] this->buffer; 36 | } 37 | 38 | void put(type item) 39 | { 40 | lockit(this->lock); 41 | 42 | buffer[this->head] = item; 43 | 44 | if (this->isfull) this->tail = (this->tail + 1) % this->cap; 45 | this->head = (this->head + 1) % this->cap; 46 | this->isfull = this->head == this->tail; 47 | } 48 | 49 | type get(bool remove = true) 50 | { 51 | lockit(this->lock); 52 | 53 | if (this->empty()) return 0; 54 | 55 | type val = this->buffer[this->tail]; 56 | if (remove == false) return val; 57 | 58 | this->isfull = false; 59 | this->tail = (this->tail + 1) % this->cap; 60 | 61 | return val; 62 | } 63 | 64 | type get_back(bool remove = true) 65 | { 66 | lockit(this->lock); 67 | 68 | if (this->empty()) return 0; 69 | 70 | type val = this->buffer[this->head - 1]; 71 | if (remove == false) return val; 72 | 73 | this->isfull = false; 74 | this->head = (this->head - 1) % this->cap; 75 | 76 | return val; 77 | } 78 | 79 | void clear() 80 | { 81 | lockit(this->lock); 82 | 83 | this->head = this->tail; 84 | this->isfull = false; 85 | } 86 | 87 | bool empty() 88 | { 89 | return (this->isfull == false && this->head == this->tail); 90 | } 91 | 92 | bool full() 93 | { 94 | return this->isfull; 95 | } 96 | 97 | size_t capacity() 98 | { 99 | return this->cap; 100 | } 101 | 102 | size_t size() 103 | { 104 | lockit(this->lock); 105 | 106 | size_t size = this->cap; 107 | if (this->isfull == false) 108 | { 109 | if (this->head >= this->tail) size = this->head - this->tail; 110 | else size = this->cap + this->head - this->tail; 111 | } 112 | 113 | return size; 114 | } 115 | 116 | void copyto(ringbuffer &newring) 117 | { 118 | size_t s = this->size(); 119 | for (size_t i = 0; i < s; i++) 120 | { 121 | newring.put(this->buffer[i]); 122 | } 123 | } 124 | }; -------------------------------------------------------------------------------- /source/lib/shared_ptr.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2021-2022 ilobilo 2 | 3 | #pragma once 4 | 5 | #include 6 | 7 | template 8 | class shared_ptr 9 | { 10 | private: 11 | type *ptr = nullptr; 12 | uint32_t *refCount = nullptr; 13 | 14 | void __cleanup__() 15 | { 16 | (*refCount)--; 17 | if (*refCount == 0) 18 | { 19 | if (ptr != nullptr) delete ptr; 20 | delete refCount; 21 | } 22 | } 23 | 24 | public: 25 | shared_ptr() : ptr(nullptr), refCount(new uint32_t(0)) { } 26 | shared_ptr(type *ptr) : ptr(ptr), refCount(new uint32_t(1)) { } 27 | 28 | shared_ptr(const shared_ptr &obj) 29 | { 30 | this->ptr = obj.ptr; 31 | this->refCount = obj.refCount; 32 | if (nullptr != obj.ptr) 33 | { 34 | (*this->refCount)++; 35 | } 36 | } 37 | 38 | shared_ptr &operator=(const shared_ptr &obj) 39 | { 40 | __cleanup__(); 41 | 42 | this->ptr = obj.ptr; 43 | this->refCount = obj.refCount; 44 | if (nullptr != obj.ptr) 45 | { 46 | (*this->refCount)++; 47 | } 48 | } 49 | 50 | // shared_ptr(shared_ptr &dyingObj) 51 | // { 52 | // this->ptr = dyingObj.ptr; 53 | // this->refCount = dyingObj.refCount; 54 | 55 | // dyingObj.ptr = nullptr; 56 | // dyingObj.refCount = nullptr; 57 | // } 58 | 59 | shared_ptr &operator=(shared_ptr &dyingObj) 60 | { 61 | __cleanup__(); 62 | 63 | this->ptr = dyingObj.ptr; 64 | this->refCount = dyingObj.refCount; 65 | 66 | dyingObj.ptr = dyingObj.refCount = nullptr; 67 | } 68 | 69 | type &operator[](size_t pos) 70 | { 71 | return *(this->ptr + pos); 72 | } 73 | 74 | uint32_t get_count() const 75 | { 76 | return *refCount; 77 | } 78 | 79 | type *get() const 80 | { 81 | return this->ptr; 82 | } 83 | 84 | type *operator->() const 85 | { 86 | return this->ptr; 87 | } 88 | 89 | type &operator*() const 90 | { 91 | return this->ptr; 92 | } 93 | 94 | ~shared_ptr() 95 | { 96 | __cleanup__(); 97 | } 98 | }; 99 | 100 | namespace std 101 | { 102 | template 103 | using shared_ptr = ::shared_ptr; 104 | } -------------------------------------------------------------------------------- /source/lib/slab.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2021-2022 ilobilo 2 | 3 | #pragma once 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | struct slab_t 10 | { 11 | lock_t lock; 12 | uint64_t firstfree; 13 | uint64_t size; 14 | 15 | void init(uint64_t size); 16 | void *alloc(); 17 | void free(void *ptr); 18 | }; 19 | 20 | struct slabHdr 21 | { 22 | slab_t *slab; 23 | }; 24 | 25 | class SlabAlloc 26 | { 27 | private: 28 | lock_t lock; 29 | 30 | struct bigallocMeta 31 | { 32 | size_t pages; 33 | size_t size; 34 | }; 35 | 36 | slab_t *get_slab(size_t size); 37 | 38 | void *big_malloc(size_t size); 39 | void *big_realloc(void *oldptr, size_t size); 40 | void big_free(void *ptr); 41 | size_t big_allocsize(void *ptr); 42 | 43 | public: 44 | slab_t slabs[10]; 45 | 46 | SlabAlloc(); 47 | 48 | void *malloc(size_t size); 49 | void *calloc(size_t num, size_t size); 50 | void *realloc(void *oldptr, size_t size); 51 | void free(void *ptr); 52 | size_t allocsize(void *ptr); 53 | }; -------------------------------------------------------------------------------- /source/lib/timer.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2021-2022 ilobilo 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | using namespace kernel::system::sched; 10 | 11 | namespace timer 12 | { 13 | void sleep(uint64_t sec) 14 | { 15 | if (hpet::initialised) hpet::sleep(sec); 16 | else if (pit::initialised) pit::sleep(sec); 17 | else rtc::sleep(sec); 18 | } 19 | 20 | void msleep(uint64_t msec) 21 | { 22 | if (hpet::initialised) hpet::msleep(msec); 23 | else if (pit::initialised) pit::msleep(msec); 24 | else 25 | { 26 | warn("HPET or PIT has not been initialised!"); 27 | warn("Using RTC!"); 28 | rtc::sleep(msec / 100); 29 | } 30 | } 31 | 32 | void usleep(uint64_t us) 33 | { 34 | if (hpet::initialised) hpet::usleep(us); 35 | else if (pit::initialised) 36 | { 37 | warn("HPET has not been initialised!"); 38 | warn("Using PIT!"); 39 | pit::msleep(MICS2MS(us)); 40 | } 41 | else 42 | { 43 | warn("HPET or PIT has not been initialised!"); 44 | warn("Using RTC!"); 45 | rtc::sleep(MICS2SEC(us)); 46 | } 47 | } 48 | } -------------------------------------------------------------------------------- /source/lib/timer.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2021-2022 ilobilo 2 | 3 | #pragma once 4 | 5 | #include 6 | 7 | namespace timer 8 | { 9 | #define SEC2MICS(num) ((num) * 1000000) 10 | #define MS2MICS(num) ((num) * 1000) 11 | 12 | #define MICS2SEC(num) ((num) / 1000000) 13 | #define MICS2MS(num) ((num) / 1000) 14 | 15 | void sleep(uint64_t sec); 16 | void msleep(uint64_t msec); 17 | void usleep(uint64_t us); 18 | } -------------------------------------------------------------------------------- /source/linker.ld: -------------------------------------------------------------------------------- 1 | OUTPUT_FORMAT(elf64-x86-64) 2 | OUTPUT_ARCH(i386:x86-64) 3 | 4 | ENTRY(_start) 5 | 6 | PHDRS 7 | { 8 | null PT_NULL FLAGS(0); 9 | text PT_LOAD FLAGS((1 << 0) | (1 << 2)); 10 | rodata PT_LOAD FLAGS((1 << 2)); 11 | data PT_LOAD FLAGS((1 << 1) | (1 << 2)); 12 | } 13 | 14 | SECTIONS 15 | { 16 | . = 0xffffffff80000000; 17 | 18 | .text : { 19 | *(.text .text.*) 20 | } :text 21 | 22 | . += CONSTANT(MAXPAGESIZE); 23 | 24 | .init_array : { 25 | PROVIDE_HIDDEN (__init_array_start = .); 26 | KEEP (*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*))) 27 | KEEP (*(.init_array .ctors)) 28 | PROVIDE_HIDDEN (__init_array_end = .); 29 | } 30 | 31 | .rodata : { 32 | *(.rodata .rodata.*) 33 | } :rodata 34 | 35 | . += CONSTANT(MAXPAGESIZE); 36 | 37 | .data : { 38 | *(.data .data.*) 39 | } :data 40 | 41 | .bss : { 42 | *(COMMON) 43 | *(.bss .bss.*) 44 | } :data 45 | } -------------------------------------------------------------------------------- /source/misc/bg.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ilobilo/kernel/e85ed7ec06901c40b339769cfc7236b6b094a9f3/source/misc/bg.bmp -------------------------------------------------------------------------------- /source/misc/unifont.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ilobilo/kernel/e85ed7ec06901c40b339769cfc7236b6b094a9f3/source/misc/unifont.bin -------------------------------------------------------------------------------- /source/misc/unifont.sfn: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ilobilo/kernel/e85ed7ec06901c40b339769cfc7236b6b094a9f3/source/misc/unifont.sfn -------------------------------------------------------------------------------- /source/system/cpu/apic/apic.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2021-2022 ilobilo 2 | 3 | #pragma once 4 | 5 | #include 6 | #include 7 | 8 | namespace kernel::system::cpu::apic { 9 | 10 | enum events 11 | { 12 | ACPI_TIMER = 0x0001, 13 | ACPI_BUSMASTER = 0x0010, 14 | ACPI_GLOBAL = 0x0020, 15 | ACPI_POWER_BUTTON = 0x0100, 16 | ACPI_SLEEP_BUTTON = 0x0200, 17 | ACPI_RTC_ALARM = 0x0400, 18 | ACPI_PCIE_WAKE = 0x4000, 19 | ACPI_WAKE = 0x8000 20 | }; 21 | 22 | extern bool initialised; 23 | 24 | uint32_t lapic_read(uint32_t reg); 25 | void lapic_write(uint32_t reg, uint32_t value); 26 | 27 | uint32_t ioapic_read(uintptr_t ioapic_address, size_t reg); 28 | void ioapic_write(uintptr_t ioapic_address, size_t reg, uint32_t data); 29 | 30 | void ioapic_redirect_gsi(uint32_t gsi, uint8_t vec, uint16_t flags); 31 | void ioapic_redirect_irq(uint32_t irq, uint8_t vect); 32 | void apic_send_ipi(uint32_t lapic_id, uint32_t flags); 33 | void eoi(); 34 | 35 | void lapic_oneshot(uint8_t vector, uint64_t ms = 1); 36 | void lapic_periodic(uint8_t vector, uint64_t ms = 1); 37 | 38 | void lapic_init(uint8_t processor_id); 39 | void init(); 40 | } -------------------------------------------------------------------------------- /source/system/cpu/gdt/gdt.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2021-2022 ilobilo 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | namespace kernel::system::cpu::gdt { 12 | 13 | [[gnu::aligned(0x1000)]] GDT DefaultGDT 14 | { 15 | {0x0000, 0, 0, 0x00, 0x00, 0}, // NULL 16 | {0xFFFF, 0, 0, 0x9A, 0x00, 0}, // 16 Bit code 17 | {0xFFFF, 0, 0, 0x92, 0x00, 0}, // 16 Bit data 18 | {0xFFFF, 0, 0, 0x9A, 0xCF, 0}, // 32 Bit code 19 | {0xFFFF, 0, 0, 0x92, 0xCF, 0}, // 32 Bit data 20 | {0x0000, 0, 0, 0x9A, 0x20, 0}, // 64 Bit code 21 | {0x0000, 0, 0, 0x92, 0x00, 0}, // 64 Bit data 22 | {0x0000, 0, 0, 0xFA, 0x20, 0}, // User code 23 | {0x0000, 0, 0, 0xF2, 0x00, 0}, // User data 24 | {0x0000, 0, 0, 0x89, 0x00, 0, 0, 0} // TSS 25 | }; 26 | 27 | new_lock(gdt_lock); 28 | bool initialised = false; 29 | GDTDescriptor gdtDescriptor; 30 | TSS *tss = new TSS[smp_request.response->cpu_count](); 31 | 32 | void reloadgdt() 33 | { 34 | asm volatile ("lgdt %0" : : "m"(gdtDescriptor) : "memory"); 35 | } 36 | 37 | void reloadtss() 38 | { 39 | asm volatile ("ltr %0" : : "r"(static_cast(GDT_TSS))); 40 | } 41 | 42 | void reloadall(size_t cpu) 43 | { 44 | lockit(gdt_lock); 45 | 46 | uintptr_t base = reinterpret_cast(&tss[cpu]); 47 | uintptr_t limit = base + sizeof(tss[cpu]); 48 | 49 | DefaultGDT.Tss.Length = limit; 50 | 51 | DefaultGDT.Tss.Base0 = base; 52 | DefaultGDT.Tss.Base1 = base >> 16; 53 | DefaultGDT.Tss.Flags1 = 0x89; 54 | DefaultGDT.Tss.Flags2 = 0x00; 55 | DefaultGDT.Tss.Base2 = base >> 24; 56 | DefaultGDT.Tss.Base3 = base >> 32; 57 | DefaultGDT.Tss.Reserved = 0x00; 58 | 59 | reloadgdt(); 60 | reloadtss(); 61 | } 62 | 63 | void init() 64 | { 65 | log("Initialising GDT"); 66 | 67 | if (initialised) 68 | { 69 | warn("GDT has already been initialised!\n"); 70 | return; 71 | } 72 | 73 | gdtDescriptor.Size = sizeof(GDT) - 1; 74 | gdtDescriptor.Offset = reinterpret_cast(&DefaultGDT); 75 | 76 | reloadall(0); 77 | tss[0].RSP[0] = reinterpret_cast(kernel_stack + STACK_SIZE); 78 | 79 | serial::newline(); 80 | initialised = true; 81 | } 82 | } -------------------------------------------------------------------------------- /source/system/cpu/gdt/gdt.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2021-2022 ilobilo 2 | 3 | #pragma once 4 | 5 | #include 6 | #include 7 | 8 | namespace kernel::system::cpu::gdt { 9 | 10 | static constexpr uint8_t GDT_NULL = 0x00; 11 | static constexpr uint8_t GDT_CODE_16 = 0x08; 12 | static constexpr uint8_t GDT_DATA_16 = 0x10; 13 | static constexpr uint8_t GDT_CODE_32 = 0x18; 14 | static constexpr uint8_t GDT_DATA_32 = 0x20; 15 | static constexpr uint8_t GDT_CODE_64 = 0x28; 16 | static constexpr uint8_t GDT_DATA_64 = 0x30; 17 | static constexpr uint8_t GDT_USER_CODE_64 = 0x38; 18 | static constexpr uint8_t GDT_USER_DATA_64 = 0x40; 19 | static constexpr uint8_t GDT_TSS = 0x48; 20 | 21 | struct [[gnu::packed]] GDTDescriptor 22 | { 23 | uint16_t Size; 24 | uint64_t Offset; 25 | }; 26 | 27 | struct [[gnu::packed]] GDTEntry 28 | { 29 | uint16_t Limit0; 30 | uint16_t Base0; 31 | uint8_t Base1; 32 | uint8_t Access; 33 | uint8_t Granularity; 34 | uint8_t Base2; 35 | }; 36 | 37 | struct [[gnu::packed]] TSSEntry 38 | { 39 | uint16_t Length; 40 | uint16_t Base0; 41 | uint8_t Base1; 42 | uint8_t Flags1; 43 | uint8_t Flags2; 44 | uint8_t Base2; 45 | uint32_t Base3; 46 | uint32_t Reserved; 47 | }; 48 | 49 | struct [[gnu::packed, gnu::aligned(0x1000)]] GDT 50 | { 51 | GDTEntry Null; 52 | GDTEntry _16BitCode; 53 | GDTEntry _16BitData; 54 | GDTEntry _32BitCode; 55 | GDTEntry _32BitData; 56 | GDTEntry _64BitCode; 57 | GDTEntry _64BitData; 58 | GDTEntry UserCode; 59 | GDTEntry UserData; 60 | TSSEntry Tss; 61 | }; 62 | 63 | struct [[gnu::packed]] TSS 64 | { 65 | uint32_t Reserved0; 66 | uint64_t RSP[3]; 67 | uint64_t Reserved1; 68 | uint64_t IST[7]; 69 | uint64_t Reserved2; 70 | uint16_t Reserved3; 71 | uint16_t IOPBOffset; 72 | }; 73 | 74 | extern GDT DefaultGDT; 75 | extern bool initialised; 76 | extern TSS *tss; 77 | 78 | extern "C" void LoadGDT(GDTDescriptor *gdtDescriptor); 79 | extern "C" void LoadTSS(); 80 | 81 | void reloadall(size_t cpu); 82 | void reloadgdt(); 83 | void reloadtss(); 84 | void init(); 85 | } -------------------------------------------------------------------------------- /source/system/cpu/idt/idt.asm: -------------------------------------------------------------------------------- 1 | ; Copyright (C) 2021-2022 ilobilo 2 | 3 | %include "lib/cpu.inc" 4 | 5 | [EXTERN int_handler] 6 | int_common_stub: 7 | test qword [rsp + 24], 0x03 8 | jz .next0 9 | swapgs 10 | .next0: 11 | 12 | pushall 13 | mov rdi, rsp 14 | call int_handler 15 | popall 16 | add rsp, 16 17 | 18 | test qword [rsp + 8], 0x03 19 | jz .next1 20 | swapgs 21 | .next1: 22 | 23 | iretq 24 | 25 | %macro isr 1 26 | isr_%1: 27 | %if !(%1 == 8 || (%1 >= 10 && %1 <= 14) || %1 == 17 || %1 == 21 || %1 == 29 || %1 == 30) 28 | push 0 29 | %endif 30 | push %1 31 | jmp int_common_stub 32 | %endmacro 33 | 34 | %assign i 0 35 | %rep 256 36 | isr i 37 | %assign i i+1 38 | %endrep 39 | 40 | section .data 41 | int_table: 42 | %assign i 0 43 | %rep 256 44 | dq isr_%+i 45 | %assign i i+1 46 | %endrep 47 | [GLOBAL int_table] -------------------------------------------------------------------------------- /source/system/cpu/idt/idt.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2021-2022 ilobilo 2 | 3 | #pragma once 4 | 5 | #include 6 | #include 7 | 8 | namespace kernel::system::cpu::idt { 9 | 10 | static constexpr uint8_t SYSCALL = 0x69; 11 | 12 | enum IRQS 13 | { 14 | IRQ0 = 32, 15 | IRQ1 = 33, 16 | IRQ2 = 34, 17 | IRQ3 = 35, 18 | IRQ4 = 36, 19 | IRQ5 = 37, 20 | IRQ6 = 38, 21 | IRQ7 = 39, 22 | IRQ8 = 40, 23 | IRQ9 = 41, 24 | IRQ10 = 42, 25 | IRQ11 = 43, 26 | IRQ12 = 44, 27 | IRQ13 = 45, 28 | IRQ14 = 46, 29 | IRQ15 = 47, 30 | }; 31 | 32 | struct [[gnu::packed]] IDTEntry 33 | { 34 | uint16_t Offset1; 35 | uint16_t Selector; 36 | uint8_t IST; 37 | uint8_t TypeAttr; 38 | uint16_t Offset2; 39 | uint32_t Offset3; 40 | uint32_t Zero; 41 | }; 42 | 43 | struct [[gnu::packed]] IDTPtr 44 | { 45 | uint16_t Limit; 46 | uint64_t Base; 47 | }; 48 | 49 | using int_handler_func = void (*)(registers_t *); 50 | using int_handler_func_arg = void (*)(registers_t *, uint64_t); 51 | 52 | struct int_handler_t 53 | { 54 | uintptr_t handler; 55 | uint64_t args; 56 | bool arg = false; 57 | }; 58 | 59 | extern int_handler_t interrupt_handlers[]; 60 | 61 | #define SET_HANDLER_ARG(x, y, z) { \ 62 | interrupt_handlers[x].handler = reinterpret_cast(y); \ 63 | interrupt_handlers[x].arg = true; \ 64 | interrupt_handlers[x].args = (z); \ 65 | } 66 | 67 | #define SET_HANDLER(x, y) { \ 68 | interrupt_handlers[x].handler = reinterpret_cast(y); \ 69 | interrupt_handlers[x].arg = false; \ 70 | } 71 | 72 | #define GET_HANDLER(x, y) { \ 73 | if (interrupt_handlers[x].handler) \ 74 | { \ 75 | if (interrupt_handlers[x].arg) \ 76 | { \ 77 | reinterpret_cast(interrupt_handlers[x].handler)(y, interrupt_handlers[x].args); \ 78 | } \ 79 | else reinterpret_cast(interrupt_handlers[x].handler)(y); \ 80 | } \ 81 | } 82 | 83 | extern IDTEntry idt[]; 84 | extern IDTPtr idtr; 85 | 86 | extern bool initialised; 87 | 88 | void idt_set_descriptor(uint8_t vector, void *isr, uint8_t typeattr = 0x8E, uint8_t ist = 0); 89 | void reload(); 90 | 91 | extern "C" void *int_table[]; 92 | void init(); 93 | 94 | uint8_t alloc_vector(); 95 | 96 | void register_interrupt_handler(uint8_t vector, int_handler_func handler, bool ioapic = true); 97 | void register_interrupt_handler(uint8_t vector, int_handler_func_arg handler, uint64_t args, bool ioapic = true); 98 | } -------------------------------------------------------------------------------- /source/system/cpu/pic/pic.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2021-2022 ilobilo 2 | 3 | #include 4 | #include 5 | 6 | namespace kernel::system::cpu::pic { 7 | 8 | void eoi(uint64_t int_no) 9 | { 10 | if (int_no >= 40) outb(pic::PIC2_COMMAND, pic::PIC_EOI); 11 | outb(pic::PIC1_COMMAND, pic::PIC_EOI); 12 | } 13 | 14 | void disable() 15 | { 16 | outb(0xA1, 0xFF); 17 | outb(0x21, 0xFF); 18 | } 19 | 20 | void init() 21 | { 22 | outb(0x20, 0x11); 23 | outb(0xA0, 0x11); 24 | outb(0x21, 0x20); 25 | outb(0xA1, 0x28); 26 | outb(0x21, 0x04); 27 | outb(0xA1, 0x02); 28 | outb(0x21, 0x01); 29 | outb(0xA1, 0x01); 30 | outb(0x21, 0x00); 31 | outb(0xA1, 0x00); 32 | } 33 | } -------------------------------------------------------------------------------- /source/system/cpu/pic/pic.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2021-2022 ilobilo 2 | 3 | #pragma once 4 | 5 | #include 6 | 7 | namespace kernel::system::cpu::pic { 8 | 9 | enum PIC 10 | { 11 | PIC1 = 0x20, 12 | PIC2 = 0xA0, 13 | PIC1_COMMAND = PIC1, 14 | PIC1_DATA = (PIC1+1), 15 | PIC2_COMMAND = PIC2, 16 | PIC2_DATA = (PIC2+1), 17 | PIC_EOI = 0x20 18 | }; 19 | 20 | void eoi(uint64_t int_no); 21 | void disable(); 22 | void init(); 23 | } -------------------------------------------------------------------------------- /source/system/cpu/smp/smp.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2021-2022 ilobilo 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | using namespace kernel::system::mm; 19 | 20 | namespace kernel::system::cpu::smp { 21 | 22 | bool initialised = false; 23 | 24 | new_lock(cpu_lock); 25 | cpu_t *cpus = new cpu_t[smp_request.response->cpu_count](); 26 | 27 | static void cpu_init(limine_smp_info *cpu) 28 | { 29 | if (cpu->lapic_id != smp_request.response->bsp_lapic_id) 30 | { 31 | asm volatile ("mov %%rsp, %0" : "=r"(gdt::tss[reinterpret_cast(cpu->extra_argument)->id].RSP[0]) : : "memory"); 32 | } 33 | 34 | cpu_lock.lock(); 35 | set_kernel_gs(cpu->extra_argument); 36 | set_gs(cpu->extra_argument); 37 | 38 | gdt::reloadall(this_cpu->id); 39 | idt::reload(); 40 | 41 | vmm::kernel_pagemap->switchTo(); 42 | 43 | this_cpu->lapic_id = cpu->lapic_id; 44 | this_cpu->tss = &gdt::tss[this_cpu->id]; 45 | 46 | enableSSE(); 47 | enableSMEP(); 48 | enableSMAP(); 49 | enableUMIP(); 50 | enablePAT(); 51 | 52 | uint32_t a = 0, b = 0, c = 0, d = 0; 53 | __get_cpuid(1, &a, &b, &c, &d); 54 | if (c & bit_XSAVE) 55 | { 56 | write_cr(4, read_cr(4) | (1 << 18)); 57 | 58 | // uint64_t xcr0 = (0 | (1 << 0)) | (1 << 1); 59 | // if (c & bit_AVX) xcr0 |= (1 << 2); 60 | 61 | // if (__get_cpuid(7, &a, &b, &c, &d)) 62 | // { 63 | // if (b & bit_AVX512F) 64 | // { 65 | // xcr0 |= (1 << 5); 66 | // xcr0 |= (1 << 6); 67 | // xcr0 |= (1 << 7); 68 | // } 69 | // } 70 | // wrxcr(0, xcr0); 71 | 72 | assert(__get_cpuid_count(0x0D, 0, &a, &b, &c, &d), "CPUID failure"); 73 | this_cpu->fpu_storage_size = c; 74 | this_cpu->fpu_restore = xrstor; 75 | 76 | assert(__get_cpuid_count(0x0D, 1, &a, &b, &c, &d), "CPUID failure"); 77 | if (a & bit_XSAVEOPT) this_cpu->fpu_save = xsaveopt; 78 | else this_cpu->fpu_save = xsave; 79 | } 80 | else if (d & bit_FXSAVE) 81 | { 82 | write_cr(4, read_cr(4) | (1 << 9)); 83 | 84 | this_cpu->fpu_storage_size = 512; 85 | this_cpu->fpu_save = fxsave; 86 | this_cpu->fpu_restore = fxrstor; 87 | } 88 | else panic("No known SIMD save mechanism"); 89 | 90 | wrmsr(0xC0000080, rdmsr(0xC0000080) | (1 << 0)); 91 | wrmsr(0xC0000081, 0x33002800000000); 92 | wrmsr(0xC0000082, reinterpret_cast(syscall::syscall_entry)); 93 | wrmsr(0xC0000084, ~static_cast(0x02)); 94 | 95 | log("CPU %ld is up", this_cpu->id); 96 | this_cpu->is_up = true; 97 | 98 | cpu_lock.unlock(); 99 | if (cpu->lapic_id != smp_request.response->bsp_lapic_id) 100 | { 101 | if (apic::initialised) apic::lapic_init(this_cpu->lapic_id); 102 | scheduler::init(); 103 | while (true) asm volatile ("hlt"); 104 | } 105 | } 106 | 107 | void init() 108 | { 109 | log("Initialising SMP"); 110 | 111 | if (initialised) 112 | { 113 | warn("CPUs are already up!\n"); 114 | return; 115 | } 116 | 117 | for (size_t i = 0; i < smp_request.response->cpu_count; i++) 118 | { 119 | limine_smp_info *smp_info = smp_request.response->cpus[i]; 120 | smp_info->extra_argument = reinterpret_cast(&cpus[i]); 121 | cpus[i].id = i; 122 | 123 | uint64_t sched_stack = malloc(STACK_SIZE); 124 | gdt::tss[i].IST[0] = sched_stack + STACK_SIZE + hhdm_offset; 125 | 126 | if (smp_request.response->bsp_lapic_id != smp_info->lapic_id) 127 | { 128 | smp_request.response->cpus[i]->goto_address = cpu_init; 129 | while (cpus[i].is_up == false); 130 | } 131 | else cpu_init(smp_info); 132 | } 133 | 134 | log("All CPUs are up\n"); 135 | initialised = true; 136 | } 137 | } -------------------------------------------------------------------------------- /source/system/cpu/smp/smp.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2021-2022 ilobilo 2 | 3 | #pragma once 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | using namespace kernel::system::sched; 11 | 12 | namespace kernel::system::cpu::smp { 13 | 14 | struct cpu_t 15 | { 16 | uint64_t id; 17 | uint32_t lapic_id; 18 | gdt::TSS *tss; 19 | 20 | size_t fpu_storage_size; 21 | void (*fpu_save)(uint8_t*); 22 | void (*fpu_restore)(uint8_t*); 23 | 24 | scheduler::thread_t *current_thread; 25 | scheduler::process_t *current_proc; 26 | scheduler::process_t *idle_proc; 27 | 28 | errno_t err; 29 | 30 | volatile bool is_up; 31 | }; 32 | 33 | extern bool initialised; 34 | extern cpu_t *cpus; 35 | 36 | #define this_cpu ({ &kernel::system::cpu::smp::cpus[read_gs(0)]; }) 37 | 38 | void init(); 39 | } -------------------------------------------------------------------------------- /source/system/cpu/syscall/syscall.asm: -------------------------------------------------------------------------------- 1 | %include "lib/cpu.inc" 2 | 3 | EXTERN syscall_table 4 | 5 | syscall_entry: 6 | swapgs 7 | mov gs:[8], rsp 8 | mov rsp, gs:[16] 9 | sti 10 | 11 | push qword 0x43 12 | push qword gs:[8] 13 | push r11 14 | push qword 0x3B 15 | push rcx 16 | push 0 17 | push 0 18 | pushall 19 | 20 | mov rdi, rsp 21 | lea rbx, [rel syscall_table] 22 | call [rbx + rax * 8] 23 | 24 | popall 25 | add rsp, 56 26 | 27 | cli 28 | swapgs 29 | o64 sysret 30 | GLOBAL syscall_entry -------------------------------------------------------------------------------- /source/system/cpu/syscall/syscall.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2021-2022 ilobilo 2 | 3 | #pragma once 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | namespace kernel::system::cpu::syscall { 10 | 11 | struct syscall_ret 12 | { 13 | uint64_t retval; 14 | uint64_t err; 15 | }; 16 | 17 | #define RDX_ERRNO regs->rdx 18 | #define RAX_RET regs->rax 19 | #define RDI_ARG0 regs->rdi 20 | #define RSI_ARG1 regs->rsi 21 | #define RDX_ARG2 regs->rdx 22 | #define R10_ARG3 regs->r10 23 | #define R8_ARG4 regs->r8 24 | #define R9_ARG5 regs->r9 25 | 26 | enum syscalls 27 | { 28 | SYSCALL_READ = 0, 29 | SYSCALL_WRITE = 1, 30 | SYSCALL_OPEN = 2, 31 | SYSCALL_CLOSE = 3, 32 | SYSCALL_IOCTL = 16, 33 | SYSCALL_ACCESS = 21, 34 | SYSCALL_GETPID = 39, 35 | SYSCALL_FORK = 57, 36 | SYSCALL_EXIT = 60, 37 | SYSCALL_UNAME = 63, 38 | SYSCALL_GETCWD = 79, 39 | SYSCALL_CHDIR = 80, 40 | SYSCALL_MKDIR = 83, 41 | SYSCALL_RMDIR = 84, 42 | SYSCALL_LINK = 86, 43 | SYSCALL_CHMOD = 90, 44 | SYSCALL_FCHMOD = 91, 45 | SYSCALL_CHOWN = 92, 46 | SYSCALL_FCHOWN = 93, 47 | SYSCALL_LCHOWN = 94, 48 | SYSCALL_SYSINFO = 99, 49 | SYSCALL_GETPPID = 110, 50 | SYSCALL_MOUNT = 165, 51 | SYSCALL_REBOOT = 169, 52 | SYSCALL_TIME = 201, 53 | SYSCALL_OPENAT = 257, 54 | SYSCALL_MKDIRAT = 258, 55 | SYSCALL_UNLINKAT = 263, 56 | SYSCALL_LINKAT = 265, 57 | SYSCALL_READLINKAT = 267, 58 | SYSCALL_FACCESAT = 269 59 | }; 60 | 61 | using syscall_t = void (*)(registers_t *); 62 | 63 | extern bool initialised; 64 | 65 | [[gnu::naked]] static inline syscall_ret syscall_i(size_t number, ...) 66 | { 67 | asm volatile ( 68 | "push %rbp \n\t" 69 | "mov %rsp, %rbp \n\t" 70 | "mov %rdi, %rax \n\t" 71 | "mov %rsi, %rdi \n\t" 72 | "mov %rdx, %rsi \n\t" 73 | "mov %rcx, %rdx \n\t" 74 | "mov %r8, %r10 \n\t" 75 | "mov %r9, %r8 \n\t" 76 | "mov 8(%rsp), %r9 \n\t" 77 | "int $0x69 \n\t" 78 | "mov %rbp, %rsp \n\t" 79 | "pop %rbp \n\t" 80 | "ret" 81 | ); 82 | } 83 | 84 | [[gnu::naked]] static inline syscall_ret syscall_s(size_t number, ...) 85 | { 86 | asm volatile ( 87 | "push %rbp \n\t" 88 | "mov %rsp, %rbp \n\t" 89 | "mov %rdi, %rax \n\t" 90 | "mov %rsi, %rdi \n\t" 91 | "mov %rdx, %rsi \n\t" 92 | "mov %rcx, %rdx \n\t" 93 | "mov %r8, %r10 \n\t" 94 | "mov %r9, %r8 \n\t" 95 | "mov 8(%rsp), %r9 \n\t" 96 | "syscall \n\t" 97 | "mov %rbp, %rsp \n\t" 98 | "pop %rbp \n\t" 99 | "ret" 100 | ); 101 | } 102 | 103 | extern "C" syscall_t syscall_table[]; 104 | extern "C" void syscall_entry(); 105 | 106 | void reboot(std::string message); 107 | void init(); 108 | } -------------------------------------------------------------------------------- /source/system/mm/pmm/pmm.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2021-2022 ilobilo 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | namespace kernel::system::mm::pmm { 12 | 13 | Bitmap bitmap; 14 | bool initialised = false; 15 | static uintptr_t highest_addr = 0; 16 | static size_t lastI = 0; 17 | static size_t usedRam = 0; 18 | static size_t freeRam = 0; 19 | 20 | new_lock(pmm_lock); 21 | 22 | static void *inner_alloc(size_t count, size_t limit) 23 | { 24 | size_t p = 0; 25 | 26 | while (lastI < limit) 27 | { 28 | if (!bitmap[lastI++]) 29 | { 30 | if (++p == count) 31 | { 32 | size_t page = lastI - count; 33 | for (size_t i = page; i < lastI; i++) bitmap.Set(i, true); 34 | return reinterpret_cast(page * 0x1000); 35 | } 36 | } 37 | else p = 0; 38 | } 39 | return nullptr; 40 | } 41 | 42 | void *alloc(size_t count) 43 | { 44 | lockit(pmm_lock); 45 | 46 | size_t i = lastI; 47 | void *ret = inner_alloc(count, highest_addr / 0x1000); 48 | if (ret == nullptr) 49 | { 50 | lastI = 0; 51 | ret = inner_alloc(count, i); 52 | if (ret == nullptr) panic("Out of memory!"); 53 | } 54 | memset(reinterpret_cast(reinterpret_cast(ret) + hhdm_offset), 0, count * 0x1000); 55 | 56 | usedRam += count * 0x1000; 57 | freeRam -= count * 0x1000; 58 | 59 | return ret; 60 | } 61 | 62 | void free(void *ptr, size_t count) 63 | { 64 | if (ptr == nullptr) return; 65 | lockit(pmm_lock); 66 | 67 | size_t page = reinterpret_cast(ptr) / 0x1000; 68 | for (size_t i = page; i < page + count; i++) bitmap.Set(i, false); 69 | if (lastI > page) lastI = page; 70 | 71 | usedRam -= count * 0x1000; 72 | freeRam += count * 0x1000; 73 | } 74 | 75 | void *realloc(void *ptr, size_t oldcount, size_t newcount) 76 | { 77 | if (ptr == nullptr) return alloc(newcount); 78 | 79 | if (!newcount) 80 | { 81 | free(ptr, oldcount); 82 | return nullptr; 83 | } 84 | 85 | if (newcount < oldcount) oldcount = newcount; 86 | 87 | void *newptr = alloc(newcount); 88 | memcpy(newptr, ptr, oldcount); 89 | free(ptr); 90 | return newptr; 91 | } 92 | 93 | size_t freemem() 94 | { 95 | return freeRam; 96 | } 97 | 98 | size_t usedmem() 99 | { 100 | return usedRam; 101 | } 102 | 103 | void init() 104 | { 105 | log("Initialising PMM"); 106 | 107 | if (initialised) 108 | { 109 | warn("PMM has already been initialised!\n"); 110 | return; 111 | } 112 | 113 | limine_memmap_entry **memmaps = memmap_request.response->entries; 114 | uint64_t memmap_count = memmap_request.response->entry_count; 115 | 116 | for (size_t i = 0; i < memmap_count; i++) 117 | { 118 | if (memmaps[i]->type != LIMINE_MEMMAP_USABLE) continue; 119 | 120 | uintptr_t top = memmaps[i]->base + memmaps[i]->length; 121 | freeRam += memmaps[i]->length; 122 | 123 | if (top > highest_addr) highest_addr = top; 124 | } 125 | 126 | size_t bitmapSize = ALIGN_UP((highest_addr / 0x1000) / 8, 0x1000); 127 | 128 | for (size_t i = 0; i < memmap_count; i++) 129 | { 130 | if (memmaps[i]->type != LIMINE_MEMMAP_USABLE) continue; 131 | 132 | if (memmaps[i]->length >= bitmapSize) 133 | { 134 | bitmap.buffer = reinterpret_cast(memmaps[i]->base); 135 | memset(bitmap.buffer, 0xFF, bitmapSize); 136 | 137 | memmaps[i]->length -= bitmapSize; 138 | memmaps[i]->base += bitmapSize; 139 | freeRam -= bitmapSize; 140 | break; 141 | } 142 | } 143 | 144 | for (size_t i = 0; i < memmap_count; i++) 145 | { 146 | if (memmaps[i]->type != LIMINE_MEMMAP_USABLE) continue; 147 | 148 | for (uintptr_t t = 0; t < memmaps[i]->length; t += 0x1000) 149 | { 150 | bitmap.Set((memmaps[i]->base + t) / 0x1000, false); 151 | } 152 | } 153 | 154 | serial::newline(); 155 | initialised = true; 156 | } 157 | } -------------------------------------------------------------------------------- /source/system/mm/pmm/pmm.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2021-2022 ilobilo 2 | 3 | #pragma once 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | namespace kernel::system::mm::pmm { 10 | 11 | extern Bitmap bitmap; 12 | extern bool initialised; 13 | 14 | void *alloc(size_t count = 1); 15 | 16 | template 17 | type alloc(size_t count = 1) 18 | { 19 | return reinterpret_cast(alloc(count)); 20 | } 21 | 22 | void *realloc(void *ptr, size_t oldcount = 1, size_t newcount = 1); 23 | void free(void *ptr, size_t count = 1); 24 | 25 | size_t freemem(); 26 | size_t usedmem(); 27 | 28 | void init(); 29 | } -------------------------------------------------------------------------------- /source/system/mm/vmm/vmm.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2021-2022 ilobilo 2 | 3 | #pragma once 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | namespace kernel::system::mm::vmm { 11 | 12 | static constexpr uint64_t large_page_size = 0x200000; 13 | static constexpr uint64_t page_size = 0x1000; 14 | 15 | enum PT_Flag 16 | { 17 | Present = (1 << 0), 18 | ReadWrite = (1 << 1), 19 | UserSuper = (1 << 2), 20 | WriteThrough = (1 << 3), 21 | CacheDisable = (1 << 4), 22 | Accessed = (1 << 5), 23 | LargerPages = (1 << 7), 24 | PAT = (1 << 7), 25 | Custom0 = (1 << 9), 26 | Custom1 = (1 << 10), 27 | Custom2 = (1 << 11), 28 | NX = (1UL << 63) 29 | }; 30 | 31 | enum mmap_flags 32 | { 33 | ProtNone = 0x00, 34 | ProtRead = 0x01, 35 | ProtWrite = 0x02, 36 | ProtExec = 0x04, 37 | 38 | MapPrivate = 0x01, 39 | MapShared = 0x02, 40 | MapFixed = 0x04, 41 | MapAnon = 0x08 42 | }; 43 | 44 | struct PDEntry 45 | { 46 | uint64_t value = 0; 47 | 48 | void setflag(PT_Flag flag, bool enabled) 49 | { 50 | uint64_t bitSel = static_cast(flag); 51 | this->value &= ~bitSel; 52 | if (enabled) this->value |= bitSel; 53 | } 54 | void setflags(uint64_t flags, bool enabled) 55 | { 56 | uint64_t bitSel = flags; 57 | this->value &= ~bitSel; 58 | if (enabled) this->value |= bitSel; 59 | } 60 | 61 | bool getflag(PT_Flag flag) 62 | { 63 | uint64_t bitSel = static_cast(flag); 64 | return (this->value & bitSel) ? true : false; 65 | } 66 | bool getflags(uint64_t flags) 67 | { 68 | return (this->value & flags) ? true : false; 69 | } 70 | 71 | uint64_t getAddr() 72 | { 73 | return (this->value & 0x000FFFFFFFFFF000) >> 12; 74 | } 75 | void setAddr(uint64_t address) 76 | { 77 | address &= 0x000000FFFFFFFFFF; 78 | this->value &= 0xFFF0000000000FFF; 79 | this->value |= (address << 12); 80 | } 81 | }; 82 | 83 | struct [[gnu::aligned(0x1000)]] PTable 84 | { 85 | PDEntry entries[512]; 86 | }; 87 | 88 | struct Pagemap; 89 | struct mmap_range_global; 90 | struct mmap_range_local 91 | { 92 | Pagemap *pagemap; 93 | mmap_range_global *global; 94 | uint64_t base; 95 | uint64_t length; 96 | int64_t offset; 97 | int prot; 98 | int flags; 99 | }; 100 | 101 | struct Pagemap 102 | { 103 | lock_t lock; 104 | PTable *TOPLVL = nullptr; 105 | vector ranges; 106 | 107 | PDEntry *virt2pte(uint64_t vaddr, bool allocate = true, bool hugepages = false); 108 | uint64_t virt2phys(uint64_t vaddr, bool hugepages = false) 109 | { 110 | PDEntry *pml_entry = this->virt2pte(vaddr, false, hugepages); 111 | if (pml_entry == nullptr || !pml_entry->getflag(Present)) return 0; 112 | 113 | return pml_entry->getAddr() << 12; 114 | } 115 | 116 | void mapMem(uint64_t vaddr, uint64_t paddr, uint64_t flags = (Present | ReadWrite), bool hugepages = false); 117 | void mapMemRange(uint64_t vaddr, uint64_t paddr, uint64_t size, uint64_t flags = (Present | ReadWrite), bool hugepages = false); 118 | 119 | bool remapMem(uint64_t vaddr_old, uint64_t vaddr_new, uint64_t flags = (Present | ReadWrite)); 120 | 121 | bool unmapMem(uint64_t vaddr, bool hugepages = false); 122 | void unmapMemRange(uint64_t vaddr, uint64_t pagecount, bool hugepages = false); 123 | 124 | auto addr2range(uint64_t addr) 125 | { 126 | struct ret { mmap_range_local *local; uint64_t mem_page; uint64_t file_page; }; 127 | 128 | for (auto range : this->ranges) 129 | { 130 | if (addr >= range->base && addr < range->base + range->length) 131 | { 132 | uint64_t mem_page = addr / page_size; 133 | uint64_t file_page = range->offset / page_size + (mem_page - range->base / page_size); 134 | return ret { range, mem_page, file_page }; 135 | } 136 | } 137 | 138 | return ret { nullptr, 0, 0 }; 139 | } 140 | 141 | void mapRange(uint64_t vaddr, uint64_t paddr, uint64_t length, int prot, int flags); 142 | void *mmap(void *addr, uint64_t length, int prot, int flags, vfs::resource_t *res, int64_t offset); 143 | bool munmap(void *addr, uint64_t length); 144 | 145 | Pagemap *fork(); 146 | void deleteThis(); 147 | void switchTo(); 148 | void save(); 149 | }; 150 | 151 | struct mmap_range_global 152 | { 153 | Pagemap shadow_pagemap; 154 | vector locals; 155 | vfs::resource_t *res; 156 | uint64_t base; 157 | uint64_t length; 158 | int64_t offset; 159 | 160 | void map_in_range(uint64_t vaddr, uint64_t paddr, int prot); 161 | }; 162 | 163 | extern bool initialised; 164 | extern bool lvl5; 165 | extern Pagemap *kernel_pagemap; 166 | 167 | Pagemap *newPagemap(); 168 | PTable *getPagemap(); 169 | 170 | void init(); 171 | } -------------------------------------------------------------------------------- /source/system/net/arp/arp.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2021-2022 ilobilo 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | namespace kernel::system::net::arp { 10 | 11 | vector table; 12 | bool debug = NET_DEBUG; 13 | 14 | tableEntry *table_add(macaddr mac, ipv4addr ip) 15 | { 16 | tableEntry *entry = new tableEntry; 17 | entry->mac = mac; 18 | entry->ip = ip; 19 | table.push_back(entry); 20 | return entry; 21 | } 22 | 23 | tableEntry *table_search(ipv4addr ip) 24 | { 25 | for (size_t i = 0; i < table.size(); i++) 26 | { 27 | if (table[i]->ip == ip) return table[i]; 28 | } 29 | return nullptr; 30 | } 31 | 32 | tableEntry *table_update(macaddr mac, ipv4addr ip) 33 | { 34 | tableEntry *oldentry = table_search(ip); 35 | if (oldentry == nullptr) return table_add(mac, ip); 36 | oldentry->mac = mac; 37 | return oldentry; 38 | } 39 | 40 | void send(nicmgr::NIC *nic, macaddr dmac, ipv4addr dip) 41 | { 42 | std::shared_ptr packet(new arpHdr); 43 | 44 | packet->hwtype = HWTYPE_ETHERNET; 45 | packet->protype = ethernet::TYPE_IPv4; 46 | 47 | packet->hwsize = 6; 48 | packet->prosize = 4; 49 | 50 | packet->opcode = ARP_REQUEST; 51 | 52 | packet->smac = nic->MAC; 53 | packet->sip = nic->IPv4; 54 | 55 | packet->dmac = dmac; 56 | packet->dip = dip; 57 | 58 | ethernet::send(nic, dmac, reinterpret_cast(packet.get()), sizeof(arpHdr), ethernet::TYPE_ARP); 59 | 60 | if (debug) log("ARP: Packet sent!"); 61 | } 62 | 63 | void reply(nicmgr::NIC *nic, arpHdr *packet) 64 | { 65 | packet->dmac = packet->smac; 66 | packet->dip = packet->sip; 67 | 68 | packet->smac = nic->MAC; 69 | packet->sip = nic->IPv4; 70 | 71 | packet->opcode = ARP_REPLY; 72 | 73 | ethernet::send(nic, packet->dmac, reinterpret_cast(packet), sizeof(arpHdr), ethernet::TYPE_ARP); 74 | } 75 | 76 | void receive(nicmgr::NIC *nic, arpHdr *packet) 77 | { 78 | if (bigendian(packet->hwtype) != HWTYPE_ETHERNET) 79 | { 80 | if (debug) error("ARP: Unsupported hardware type!"); 81 | return; 82 | } 83 | if (bigendian(packet->protype) != ethernet::TYPE_IPv4) 84 | { 85 | if (debug) error("ARP: Unsupported protocol type!"); 86 | return; 87 | } 88 | 89 | tableEntry *entry = table_search(packet->sip); 90 | if (entry == nullptr) entry = table_add(packet->smac, packet->sip); 91 | else entry->mac = packet->smac; 92 | 93 | switch (bigendian(packet->opcode)) 94 | { 95 | case ARP_REQUEST: 96 | if (debug) log("ARP: Request!"); 97 | reply(nic, packet); 98 | break; 99 | case ARP_REPLY: 100 | if (debug) 101 | { 102 | log("ARP: Reply!"); 103 | error("Not supported!"); 104 | } 105 | break; 106 | default: 107 | if (debug) error("ARP: Opcode not supported!"); 108 | break; 109 | } 110 | } 111 | } -------------------------------------------------------------------------------- /source/system/net/arp/arp.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2021-2022 ilobilo 2 | 3 | #pragma once 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | using namespace kernel::drivers::net; 10 | 11 | namespace kernel::system::net::arp { 12 | 13 | enum opcodes 14 | { 15 | ARP_REQUEST = 0x01, 16 | ARP_REPLY = 0x02, 17 | }; 18 | 19 | enum hwtypes 20 | { 21 | HWTYPE_ETHERNET = 0x01 22 | }; 23 | 24 | struct [[gnu::packed]] arpHdr 25 | { 26 | bigendian hwtype; 27 | bigendian protype; 28 | uint8_t hwsize; 29 | uint8_t prosize; 30 | bigendian opcode; 31 | macaddr smac; 32 | ipv4addr sip; 33 | macaddr dmac; 34 | ipv4addr dip; 35 | }; 36 | 37 | struct tableEntry 38 | { 39 | macaddr mac; 40 | ipv4addr ip; 41 | }; 42 | 43 | extern vector table; 44 | extern bool debug; 45 | 46 | tableEntry *table_add(macaddr mac, ipv4addr ip); 47 | tableEntry *table_search(ipv4addr ip); 48 | tableEntry *table_update(macaddr mac, ipv4addr ip); 49 | 50 | void send(nicmgr::NIC *nic, macaddr dmac, ipv4addr dip); 51 | void receive(nicmgr::NIC *nic, arpHdr *packet); 52 | } -------------------------------------------------------------------------------- /source/system/net/ethernet/ethernet.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2021-2022 ilobilo 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | namespace kernel::system::net::ethernet { 11 | 12 | bool debug = NET_DEBUG; 13 | 14 | void send(nicmgr::NIC *nic, macaddr dmac, void *data, size_t length, uint16_t protocol) 15 | { 16 | ethHdr *frame = malloc(sizeof(ethHdr) + length); 17 | 18 | frame->smac = nic->MAC; 19 | frame->dmac = dmac; 20 | frame->type = protocol; 21 | 22 | memcpy(frame->data, data, length); 23 | 24 | nic->send(reinterpret_cast(frame), sizeof(ethHdr) + length); 25 | free(frame); 26 | if (debug) log("Ethernet: Packet sent!"); 27 | } 28 | 29 | void receive(nicmgr::NIC *nic, ethHdr *packet) 30 | { 31 | if (packet->dmac != nic->MAC && packet->dmac != macaddr(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF)) return; 32 | 33 | switch (packet->type) 34 | { 35 | case TYPE_ARP: 36 | if (debug) log("Ethernet: Received ARP packet!"); 37 | arp::receive(nic, reinterpret_cast(packet->data)); 38 | break; 39 | case TYPE_IPv4: 40 | if (debug) log("Ethernet: Received IPv4 packet!"); 41 | ipv4::receive(nic, reinterpret_cast(packet->data), packet->smac); 42 | break; 43 | } 44 | } 45 | } -------------------------------------------------------------------------------- /source/system/net/ethernet/ethernet.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2021-2022 ilobilo 2 | 3 | #pragma once 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | using namespace kernel::drivers::net; 10 | 11 | namespace kernel::system::net::ethernet { 12 | 13 | enum protocol_t 14 | { 15 | TYPE_ARP = 0x0806, 16 | TYPE_IPv4 = 0x0800 17 | }; 18 | 19 | struct [[gnu::packed]] ethHdr 20 | { 21 | macaddr dmac; 22 | macaddr smac; 23 | bigendian type; 24 | uint8_t data[]; 25 | }; 26 | 27 | extern bool debug; 28 | 29 | void send(nicmgr::NIC *nic, macaddr dmac, void *data, size_t length, uint16_t protocol); 30 | void receive(nicmgr::NIC *nic, ethHdr *packet); 31 | } -------------------------------------------------------------------------------- /source/system/net/icmpv4/icmpv4.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2021-2022 ilobilo 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | namespace kernel::system::net::icmpv4 { 11 | 12 | bool debug = NET_DEBUG; 13 | 14 | static void reply(nicmgr::NIC *nic, ipv4addr dip, icmpv4Hdr *oldpacket, size_t length) 15 | { 16 | icmpv4Hdr *newpacket = malloc(length); 17 | 18 | newpacket->type = TYPE_ECHO_REPLY; 19 | newpacket->code = 0; 20 | newpacket->csum = 0; 21 | 22 | icmpv4Echo *oldecho = reinterpret_cast(oldpacket->data); 23 | icmpv4Echo *newecho = reinterpret_cast(newpacket->data); 24 | 25 | newecho->id = oldecho->id; 26 | newecho->seq = oldecho->seq; 27 | memcpy(newecho->data, oldecho->data, length - sizeof(icmpv4Hdr) - sizeof(icmpv4Echo)); 28 | 29 | newpacket->csum = checksum(newpacket, length); 30 | 31 | ipv4::send(nic, dip, newpacket, length, ipv4::IPv4_PROT_ICMPv4); 32 | free(newpacket); 33 | } 34 | 35 | void receive(nicmgr::NIC *nic, icmpv4Hdr *packet, ipv4::ipv4Hdr *iphdr) 36 | { 37 | switch (packet->type) 38 | { 39 | case TYPE_ECHO_REPLY: 40 | if (debug) log("ICMPv4: Echo reply!"); 41 | break; 42 | case TYPE_ECHO_REQST: 43 | if (debug) log("ICMPv4: Echo request!"); 44 | reply(nic, iphdr->sip, packet, iphdr->len - iphdr->ihl * 4); 45 | break; 46 | case TYPE_DEST_UNRCH: 47 | if (debug) error("ICMPv4: Destination unreachable!"); 48 | break; 49 | default: 50 | if (debug) error("ICMPv4: Unsupported type %d!", packet->type); 51 | break; 52 | } 53 | } 54 | } -------------------------------------------------------------------------------- /source/system/net/icmpv4/icmpv4.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2021-2022 ilobilo 2 | 3 | #pragma once 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | using namespace kernel::drivers::net; 10 | 11 | namespace kernel::system::net::icmpv4 { 12 | 13 | // TODO: Add more types 14 | enum icmpv4Type 15 | { 16 | TYPE_ECHO_REPLY = 0, 17 | TYPE_DEST_UNRCH = 3, 18 | TYPE_ECHO_REQST = 8, 19 | }; 20 | 21 | struct [[gnu::packed]] icmpv4Hdr 22 | { 23 | uint8_t type; 24 | uint8_t code; 25 | bigendian csum; 26 | uint8_t data[]; 27 | }; 28 | 29 | struct [[gnu::packed]] icmpv4Echo 30 | { 31 | uint16_t id; 32 | uint16_t seq; 33 | uint8_t data[]; 34 | }; 35 | 36 | struct [[gnu::packed]] icmpv4DstUnreach 37 | { 38 | uint8_t unused; 39 | uint8_t len; 40 | uint16_t var; 41 | uint8_t data[]; 42 | }; 43 | 44 | extern bool debug; 45 | 46 | void receive(nicmgr::NIC *nic, icmpv4Hdr *packet, ipv4::ipv4Hdr *iphdr); 47 | } -------------------------------------------------------------------------------- /source/system/net/ipv4/ipv4.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2021-2022 ilobilo 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | namespace kernel::system::net::ipv4 { 11 | 12 | bool debug = NET_DEBUG; 13 | 14 | void send(nicmgr::NIC *nic, ipv4addr dip, void *data, size_t length, ipv4Prot protocol) 15 | { 16 | ipv4Hdr *packet = malloc(length + sizeof(ipv4Hdr)); 17 | 18 | packet->version = VER_IPv4; 19 | packet->ihl = 5; 20 | packet->len = sizeof(ipv4Hdr) + length; 21 | packet->flags = 0; 22 | packet->ttl = IP_TTL; 23 | packet->proto = protocol; 24 | packet->csum = 0; 25 | packet->sip = nic->IPv4; 26 | packet->dip = dip; 27 | 28 | packet->csum = checksum(packet, packet->ihl * 4); 29 | 30 | memcpy(packet->data, data, length); 31 | 32 | macaddr dmac; 33 | arp::tableEntry *entry = arp::table_search(dip); 34 | 35 | for (size_t i = IP_TRIES; i > 0 && entry == nullptr; i--) 36 | { 37 | arp::send(nic, macaddr(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), dip); 38 | entry = arp::table_search(dip); 39 | } 40 | if (entry != nullptr) dmac = entry->mac; 41 | else 42 | { 43 | error("IPv4: Could not find destination MAC address!"); 44 | return; 45 | } 46 | 47 | ethernet::send(nic, dmac, reinterpret_cast(packet), length + sizeof(ipv4Hdr), ethernet::TYPE_IPv4); 48 | free(packet); 49 | 50 | if (debug) log("IPv4: Packet sent!"); 51 | } 52 | 53 | void receive(nicmgr::NIC *nic, ipv4Hdr *packet, macaddr smac) 54 | { 55 | arp::table_update(smac, packet->sip); 56 | // if (!arraycmp(nic->IPv4, packet->dip, 4)) 57 | // { 58 | // if (debug) error("IPv4: Packet is not for us!"); 59 | // return; 60 | // } 61 | 62 | if (packet->ihl < 5) 63 | { 64 | if (debug) error("IPv4: Packet IHL must be at least 5!"); 65 | return; 66 | } 67 | if (packet->ttl == 0) 68 | { 69 | if (debug) error("IPv4: TTL has reached 0!"); 70 | return; 71 | } 72 | 73 | bigendian csum = packet->csum; 74 | packet->csum = 0; 75 | if (csum.value != checksum(packet, sizeof(ipv4Hdr)).value) 76 | { 77 | if (debug) error("IPv4: Invalid checksum!"); 78 | return; 79 | } 80 | 81 | switch (packet->version) 82 | { 83 | case VER_IPv4: 84 | if (debug) log("IPv4: Version 4"); 85 | switch (packet->proto) 86 | { 87 | case IPv4_PROT_ICMPv4: 88 | if (debug) log("IPv4: Detected ICMP packet!"); 89 | icmpv4::receive(nic, reinterpret_cast(packet->data), packet); 90 | break; 91 | case IPv4_PROT_TCP: 92 | if (debug) log("IPv4: Detected TCP packet!"); 93 | break; 94 | case IPv4_PROT_UDP: 95 | if (debug) log("IPv4: Detected UDP packet!"); 96 | break; 97 | default: 98 | if (debug) error("IPv4: Invalid protocol %d!", packet->proto); 99 | break; 100 | } 101 | break; 102 | default: 103 | if (debug) error("IPv4: Unsupported version %d!", packet->version); 104 | break; 105 | } 106 | } 107 | } -------------------------------------------------------------------------------- /source/system/net/ipv4/ipv4.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2021-2022 ilobilo 2 | 3 | #pragma once 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | using namespace kernel::drivers::net; 10 | 11 | namespace kernel::system::net::ipv4 { 12 | 13 | static constexpr uint8_t IP_TTL = 64; 14 | static constexpr uint64_t IP_TRIES = 3; 15 | 16 | enum version 17 | { 18 | VER_IPv4 = 4, 19 | VER_IPv6 = 6, 20 | }; 21 | 22 | enum ipv4Prot 23 | { 24 | IPv4_PROT_ICMPv4 = 1, 25 | IPv4_PROT_TCP = 6, 26 | IPv4_PROT_UDP = 17, 27 | }; 28 | 29 | struct [[gnu::packed]] ipv4Hdr 30 | { 31 | uint8_t ihl : 4; 32 | uint8_t version : 4; 33 | uint8_t ecn : 2; 34 | uint8_t dscp : 6; 35 | bigendian len; 36 | bigendian id; 37 | uint16_t frag_offset : 13; 38 | uint8_t flags : 3; 39 | uint8_t ttl; 40 | uint8_t proto; 41 | bigendian csum; 42 | ipv4addr sip; 43 | ipv4addr dip; 44 | uint8_t data[]; 45 | }; 46 | 47 | extern bool debug; 48 | 49 | void send(nicmgr::NIC *nic, ipv4addr dip, void *data, size_t length, ipv4Prot protocol); 50 | void receive(nicmgr::NIC *nic, ipv4Hdr *packet, macaddr smac); 51 | } -------------------------------------------------------------------------------- /source/system/pci/pcidesc.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2021-2022 ilobilo 2 | 3 | #pragma once 4 | 5 | #include 6 | #include 7 | 8 | namespace kernel::system::pci { 9 | 10 | extern const char *device_classes[20]; 11 | 12 | std::string getvendorname(uint16_t vendorid); 13 | std::string getdevicename(uint16_t vendorid, uint16_t deviceid); 14 | std::string getsubclassname(uint8_t classcode, uint8_t subclasscode); 15 | std::string getprogifname(uint8_t classcode, uint8_t subclasscode, uint8_t progif); 16 | } -------------------------------------------------------------------------------- /source/system/sched/hpet/hpet.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2021-2022 ilobilo 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | namespace kernel::system::sched::hpet { 10 | 11 | bool initialised = false; 12 | static uint32_t clk = 0; 13 | HPET *hpet; 14 | 15 | uint64_t counter() 16 | { 17 | return mminq(&hpet->main_counter_value); 18 | } 19 | 20 | void usleep(uint64_t us) 21 | { 22 | uint64_t target = counter() + (us * 1000000000) / clk; 23 | while (counter() < target); 24 | } 25 | 26 | void msleep(uint64_t msec) 27 | { 28 | usleep(MS2MICS(msec)); 29 | } 30 | 31 | void sleep(uint64_t sec) 32 | { 33 | usleep(SEC2MICS(sec)); 34 | } 35 | 36 | void init() 37 | { 38 | log("Initialising HPET"); 39 | 40 | if (initialised) 41 | { 42 | warn("HPET has already been initialised!\n"); 43 | return; 44 | } 45 | if (!acpi::hpethdr) 46 | { 47 | error("HPET table not found!\n"); 48 | return; 49 | } 50 | 51 | hpet = reinterpret_cast(acpi::hpethdr->address.Address); 52 | clk = hpet->general_capabilities >> 32; 53 | 54 | mmoutq(&hpet->general_configuration, 0); 55 | mmoutq(&hpet->main_counter_value, 0); 56 | mmoutq(&hpet->general_configuration, 1); 57 | 58 | serial::newline(); 59 | initialised = true; 60 | } 61 | } -------------------------------------------------------------------------------- /source/system/sched/hpet/hpet.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2021-2022 ilobilo 2 | 3 | #pragma once 4 | 5 | #include 6 | 7 | namespace kernel::system::sched::hpet { 8 | 9 | struct HPET 10 | { 11 | uint64_t general_capabilities; 12 | uint64_t reserved; 13 | uint64_t general_configuration; 14 | uint64_t reserved2; 15 | uint64_t general_int_status; 16 | uint64_t reserved3; 17 | uint64_t reserved4[24]; 18 | uint64_t main_counter_value; 19 | uint64_t reserved5; 20 | }; 21 | 22 | extern bool initialised; 23 | extern HPET *hpet; 24 | 25 | uint64_t counter(); 26 | 27 | void usleep(uint64_t us); 28 | void msleep(uint64_t msec); 29 | void sleep(uint64_t sec); 30 | 31 | void init(); 32 | } -------------------------------------------------------------------------------- /source/system/sched/pit/pit.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2021-2022 ilobilo 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | using namespace kernel::system::cpu; 11 | 12 | namespace kernel::system::sched::pit { 13 | 14 | bool initialised = false; 15 | bool schedule = false; 16 | uint64_t tick = 0; 17 | uint64_t frequency = PIT_DEF_FREQ; 18 | new_lock(pit_lock); 19 | 20 | void sleep(uint64_t sec) 21 | { 22 | uint64_t start = tick; 23 | while (tick < start + sec * frequency); 24 | } 25 | 26 | void msleep(uint64_t msec) 27 | { 28 | uint64_t start = tick; 29 | while (tick < start + msec * (frequency / 100)); 30 | } 31 | 32 | uint64_t get_tick() 33 | { 34 | return tick; 35 | } 36 | 37 | static void PIT_Handler(registers_t *regs) 38 | { 39 | tick++; 40 | if (schedule) scheduler::schedule(regs); 41 | } 42 | 43 | void setfreq(uint64_t freq) 44 | { 45 | lockit(pit_lock); 46 | 47 | if (freq < 19) freq = 19; 48 | frequency = freq; 49 | uint64_t divisor = 1193180 / frequency; 50 | 51 | outb(0x43, 0x36); 52 | 53 | uint8_t l = static_cast(divisor); 54 | uint8_t h = static_cast(divisor >> 8); 55 | 56 | outb(0x40, l); 57 | outb(0x40, h); 58 | } 59 | 60 | uint64_t getfreq() 61 | { 62 | lockit(pit_lock); 63 | 64 | uint64_t freq = 0; 65 | outb(0x43, 0b0000000); 66 | freq = inb(0x40); 67 | freq |= inb(0x40) << 8; 68 | freq = 1193180 / freq; 69 | 70 | return freq; 71 | } 72 | 73 | void resetfreq() 74 | { 75 | setfreq(PIT_DEF_FREQ); 76 | } 77 | 78 | void init(uint64_t freq) 79 | { 80 | log("Initialising PIT"); 81 | 82 | if (initialised) 83 | { 84 | warn("PIT has already been initialised!\n"); 85 | return; 86 | } 87 | 88 | setfreq(freq); 89 | idt::register_interrupt_handler(idt::IRQ0, PIT_Handler, true); 90 | 91 | serial::newline(); 92 | initialised = true; 93 | } 94 | } -------------------------------------------------------------------------------- /source/system/sched/pit/pit.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2021-2022 ilobilo 2 | 3 | #pragma once 4 | 5 | #include 6 | 7 | namespace kernel::system::sched::pit { 8 | 9 | #define PIT_DEF_FREQ 100 10 | 11 | #define MS2PIT(ms) (100 / (ms)) 12 | #define PIT2MS(freq) (100 / (freq)) 13 | 14 | extern bool initialised; 15 | extern bool schedule; 16 | extern uint64_t frequency; 17 | 18 | void sleep(uint64_t sec); 19 | void msleep(uint64_t msec); 20 | uint64_t get_tick(); 21 | 22 | void setfreq(uint64_t freq = PIT_DEF_FREQ); 23 | uint64_t getfreq(); 24 | void resetfreq(); 25 | 26 | void init(uint64_t freq = PIT_DEF_FREQ); 27 | } -------------------------------------------------------------------------------- /source/system/sched/rtc/rtc.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2021-2022 ilobilo 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | namespace kernel::system::sched::rtc { 10 | 11 | int bcdtobin(int value) 12 | { 13 | return (value >> 4) * 10 + (value & 15); 14 | } 15 | 16 | uint64_t century() 17 | { 18 | if (acpi::fadthdr && acpi::fadthdr->Century == 0) return 20; 19 | outb(0x70, 0x32); 20 | return bcdtobin(inb(0x71)); 21 | } 22 | 23 | uint64_t year() 24 | { 25 | outb(0x70, 0x09); 26 | return bcdtobin(inb(0x71)); 27 | } 28 | 29 | uint64_t month() 30 | { 31 | outb(0x70, 0x08); 32 | return bcdtobin(inb(0x71)); 33 | } 34 | 35 | uint64_t day() 36 | { 37 | outb(0x70, 0x07); 38 | return bcdtobin(inb(0x71)); 39 | } 40 | 41 | uint64_t hour() 42 | { 43 | outb(0x70, 0x04); 44 | return bcdtobin(inb(0x71)); 45 | } 46 | 47 | uint64_t minute() 48 | { 49 | outb(0x70, 0x02); 50 | return bcdtobin(inb(0x71)); 51 | } 52 | 53 | uint64_t second() 54 | { 55 | outb(0x70, 0x00); 56 | return bcdtobin(inb(0x71)); 57 | } 58 | 59 | uint64_t time() 60 | { 61 | return hour() * 3600 + minute() * 60 + second(); 62 | } 63 | 64 | uint64_t epoch() 65 | { 66 | uint64_t seconds = second(), minutes = minute(), hours = hour(), days = day(), months = month(), years = year(), centuries = century(); 67 | 68 | uint64_t jdn_current = jdn(days, months, centuries * 100 + years); 69 | uint64_t jdn_1970 = jdn(1, 1, 1970); 70 | uint64_t diff = jdn_current - jdn_1970; 71 | 72 | return (diff * (60 * 60 * 24)) + hours * 3600 + minutes * 60 + seconds; 73 | } 74 | 75 | uint64_t seconds_since_boot() 76 | { 77 | return epoch() - boot_time_request.response->boot_time; 78 | } 79 | 80 | void sleep(uint64_t sec) 81 | { 82 | uint64_t lastsec = time() + sec; 83 | while (lastsec != time()); 84 | } 85 | 86 | char timestr[30]; 87 | char *getTime() 88 | { 89 | sprintf(timestr, "%.4ld/%.2ld/%.2ld %.2ld:%.2ld:%.2ld", century() * 100 + year(), month(), 90 | day(), hour(), 91 | minute(), second()); 92 | return timestr; 93 | } 94 | } -------------------------------------------------------------------------------- /source/system/sched/rtc/rtc.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2021-2022 ilobilo 2 | 3 | #pragma once 4 | 5 | #include 6 | 7 | namespace kernel::system::sched::rtc { 8 | 9 | uint64_t century(), year(), month(), day(), hour(), minute(), second(); 10 | 11 | uint64_t time(); 12 | uint64_t epoch(); 13 | uint64_t seconds_since_boot(); 14 | 15 | void sleep(uint64_t sec); 16 | 17 | char *getTime(); 18 | } -------------------------------------------------------------------------------- /source/system/sched/scheduler/scheduler.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2021-2022 ilobilo 2 | 3 | #pragma once 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | using namespace kernel::system::mm; 13 | 14 | namespace kernel::system::sched::scheduler { 15 | 16 | static constexpr uint64_t max_procs = 65536; 17 | static constexpr uint64_t max_fds = 256; 18 | static constexpr uint64_t MMAP_ANON_BASE = 0x80000000000; 19 | static constexpr uint64_t THREAD_STACK_TOP = 0x70000000000; 20 | 21 | enum state_t 22 | { 23 | INITIAL, 24 | READY, 25 | RUNNING, 26 | BLOCKED, 27 | SLEEPING, 28 | KILLED 29 | }; 30 | 31 | enum priority_t 32 | { 33 | LOW = 3, 34 | MID = 5, 35 | HIGH = 7, 36 | }; 37 | 38 | struct process_t; 39 | struct thread_t 40 | { 41 | uint64_t cpu; 42 | uint8_t *stack; 43 | uint8_t *kstack; 44 | 45 | int tid = 1; 46 | errno_t err; 47 | state_t state; 48 | uint8_t *stack_phys; 49 | uint8_t *kstack_phys; 50 | uint8_t *fpu_storage; 51 | size_t fpu_storage_size; 52 | uint64_t gsbase; 53 | uint64_t fsbase; 54 | registers_t regs; 55 | process_t *parent; 56 | priority_t priority; 57 | 58 | bool user; 59 | 60 | thread_t(process_t *parent, priority_t priority, Auxval auxval, vector argv, vector envp); 61 | thread_t(uint64_t addr, uint64_t args, process_t *parent, priority_t priority); 62 | 63 | thread_t(auto addr, uint64_t args, process_t *parent, priority_t priority) : thread_t(reinterpret_cast(addr), args, parent, priority) { }; 64 | 65 | thread_t() { }; 66 | 67 | bool map_user(); 68 | 69 | thread_t *fork(registers_t *regs); 70 | 71 | void block(); 72 | void unblock(); 73 | void exit(bool halt = true); 74 | }; 75 | 76 | struct process_t 77 | { 78 | std::string name; 79 | int pid = 0; 80 | int next_tid = 1; 81 | state_t state; 82 | vmm::Pagemap *pagemap; 83 | uint64_t mmap_anon_base = MMAP_ANON_BASE; 84 | lock_t fd_lock; 85 | vfs::fs_node_t *current_dir; 86 | void *fds[max_fds]; 87 | vector threads; 88 | vector children; 89 | process_t *parent; 90 | uint64_t thread_stack_top = THREAD_STACK_TOP; 91 | 92 | bool in_table = false; 93 | 94 | thread_t *add_user_thread(uint64_t addr, uint64_t args, priority_t priority, Auxval auxval, vector argv, vector envp); 95 | thread_t *add_thread(uint64_t addr, uint64_t args, priority_t priority = MID); 96 | 97 | thread_t *add_user_thread(auto addr, uint64_t args, priority_t priority, Auxval auxval, vector argv, vector envp) 98 | { 99 | this->add_user_thread(reinterpret_cast(addr), args, priority, auxval, argv, envp); 100 | } 101 | thread_t *add_thread(auto addr, uint64_t args, priority_t priority = MID) 102 | { 103 | return this->add_thread(reinterpret_cast(addr), args, priority); 104 | } 105 | thread_t *add_thread(thread_t *thread); 106 | 107 | bool enqueue(); 108 | 109 | process_t(std::string name, uint64_t addr, uint64_t args, priority_t priority = MID); 110 | process_t(std::string name, auto addr, uint64_t args, priority_t priority = MID) : process_t(name, reinterpret_cast(addr), args, priority) { }; 111 | 112 | process_t(std::string name); 113 | process_t() { }; 114 | 115 | void block(); 116 | void unblock(); 117 | void exit(bool halt = true); 118 | 119 | private: 120 | }; 121 | 122 | extern bool debug; 123 | extern process_t *initproc; 124 | 125 | extern vector proc_table; 126 | 127 | extern size_t proc_count; 128 | extern size_t thread_count; 129 | 130 | int alloc_pid(); 131 | process_t *start_program(vfs::fs_node_t *dir, std::string path, vector argv, vector envp, std::string stdin, std::string stdout, std::string stderr, std::string procname = ""); 132 | 133 | void yield(uint64_t ms = 1); 134 | void schedule(registers_t *regs); 135 | 136 | void kill(); 137 | void init(bool last = false); 138 | } 139 | 140 | scheduler::thread_t *this_thread(); 141 | scheduler::process_t *this_proc(); 142 | 143 | static inline int getpid() 144 | { 145 | if (this_proc() == nullptr) return -1; 146 | return this_proc()->pid; 147 | } 148 | 149 | static inline int getppid() 150 | { 151 | if (this_proc() == nullptr) return -1; 152 | if (this_proc()->parent == nullptr) return -1; 153 | return this_proc()->parent->pid; 154 | } 155 | 156 | static inline int gettid() 157 | { 158 | if (this_thread() == nullptr) return -1; 159 | return this_thread()->tid; 160 | } -------------------------------------------------------------------------------- /source/system/trace/trace.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2021-2022 ilobilo 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | using namespace kernel::drivers::display; 10 | 11 | namespace kernel::system::trace { 12 | 13 | symtable_t *symbol_table; 14 | static size_t entries = 1; 15 | 16 | symtable_t lookup(uint64_t addr) 17 | { 18 | symtable_t result { 0, "" }; 19 | for (size_t i = 0; i < entries; i++) 20 | { 21 | symtable_t entry = symbol_table[i]; 22 | if (entry.addr <= addr && entry.addr > result.addr) result = entry; 23 | } 24 | return result; 25 | } 26 | 27 | bool backtrace(uint64_t addr, size_t &i, bool terminal) 28 | { 29 | symtable_t symtable = lookup(addr); 30 | while (symtable.name == "int_handler" || symtable.name == "int_common_stub" || symtable.name == "int_common_stub.next0") 31 | { 32 | i--; 33 | return true; 34 | } 35 | 36 | if (symtable.name == "" || symtable.addr == 0) return false; 37 | error("#%zu 0x%lX \t%s", i, symtable.addr, symtable.name.c_str()); 38 | if (terminal) printf("\n[\033[31mPANIC\033[0m] #%zu 0x%lX \t%s", i, symtable.addr, symtable.name.c_str()); 39 | 40 | return true; 41 | } 42 | 43 | void trace(bool terminal) 44 | { 45 | static stackframe_t *sf = nullptr; 46 | sf = reinterpret_cast(__builtin_frame_address(0)); 47 | 48 | error("Stack trace:"); 49 | if (terminal) printf("\n[\033[31mPANIC\033[0m] Stack trace:"); 50 | 51 | for (size_t i = 0; i < 15 && sf; i++) 52 | { 53 | if (!backtrace(sf->rip, i, terminal)) break; 54 | sf = sf->frame; 55 | } 56 | } 57 | 58 | void init() 59 | { 60 | uint64_t kfile = reinterpret_cast(kernel_file_request.response->kernel_file->address); 61 | Elf64_Ehdr *header = reinterpret_cast(kfile); 62 | Elf64_Shdr *sections = reinterpret_cast(kfile + header->e_shoff); 63 | Elf64_Sym *symtab; 64 | char *strtab; 65 | 66 | for (size_t i = 0; i < header->e_shnum; i++) 67 | { 68 | switch (sections[i].sh_type) 69 | { 70 | case SHT_SYMTAB: 71 | symtab = reinterpret_cast(kfile + sections[i].sh_offset); 72 | entries = sections[i].sh_size / sections[i].sh_entsize; 73 | break; 74 | case SHT_STRTAB: 75 | strtab = reinterpret_cast(kfile + sections[i].sh_offset); 76 | break; 77 | } 78 | } 79 | 80 | size_t j, min_idx; 81 | for (size_t i = 0; i < entries - 1; i++) 82 | { 83 | min_idx = i; 84 | for (j = i + 1; j < entries; j++) if (symtab[j].st_value < symtab[min_idx].st_value) min_idx = j; 85 | 86 | Elf64_Sym temp = symtab[min_idx]; 87 | symtab[min_idx] = symtab[i]; 88 | symtab[i] = temp; 89 | } 90 | 91 | while (symtab[0].st_value == 0) 92 | { 93 | symtab++; 94 | entries--; 95 | } 96 | 97 | symbol_table = new symtable_t[entries]; 98 | 99 | for (size_t i = 0, entriesbck = entries; i < entriesbck; i++) 100 | { 101 | symtable_t sym 102 | { 103 | symtab[i].st_value, 104 | std::string(&strtab[symtab[i].st_name]) 105 | }; 106 | symbol_table[i] = sym; 107 | } 108 | } 109 | } -------------------------------------------------------------------------------- /source/system/trace/trace.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2021-2022 ilobilo 2 | 3 | #pragma once 4 | 5 | #include 6 | #include 7 | 8 | namespace kernel::system::trace { 9 | 10 | struct stackframe_t 11 | { 12 | stackframe_t *frame; 13 | uint64_t rip; 14 | }; 15 | 16 | struct symtable_t 17 | { 18 | uint64_t addr; 19 | std::string name; 20 | }; 21 | 22 | void trace(bool terminal); 23 | void init(); 24 | } -------------------------------------------------------------------------------- /source/system/ubsan/ubsan.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2021-2022 ilobilo 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | static void print(const char *message, source_location loc) 8 | { 9 | if (strstr(loc.file, "acpi.cpp") && ((loc.line == 101 && loc.column == 55) || (loc.line == 100 && loc.column == 64))) return; 10 | warn("Ubsan: %s at file %s, line %d, column %d", message, loc.file, loc.line, loc.column); 11 | while (true) asm volatile ("cli; hlt"); 12 | } 13 | 14 | extern "C" void __ubsan_handle_add_overflow(overflow_data *data) 15 | { 16 | print("addition overflow", data->location); 17 | } 18 | 19 | extern "C" void __ubsan_handle_sub_overflow(overflow_data *data) 20 | { 21 | print("subtraction overflow", data->location); 22 | } 23 | 24 | extern "C" void __ubsan_handle_mul_overflow(overflow_data *data) 25 | { 26 | print("multiplication overflow", data->location); 27 | } 28 | 29 | extern "C" void __ubsan_handle_divrem_overflow(overflow_data *data) 30 | { 31 | print("division overflow", data->location); 32 | } 33 | 34 | extern "C" void __ubsan_handle_negate_overflow(overflow_data *data) 35 | { 36 | print("negation overflow", data->location); 37 | } 38 | 39 | extern "C" void __ubsan_handle_pointer_overflow(overflow_data *data) 40 | { 41 | print("pointer overflow", data->location); 42 | } 43 | 44 | extern "C" void __ubsan_handle_shift_out_of_bounds(shift_out_of_bounds_data *data) 45 | { 46 | print("shift out of bounds", data->location); 47 | } 48 | 49 | extern "C" void __ubsan_handle_load_invalid_value(invalid_value_data *data) 50 | { 51 | print("invalid load value", data->location); 52 | } 53 | 54 | extern "C" void __ubsan_handle_out_of_bounds(array_out_of_bounds_data *data) 55 | { 56 | print("array out of bounds", data->location); 57 | } 58 | 59 | extern "C" void __ubsan_handle_type_mismatch_v1(type_mismatch_v1_data *data, uintptr_t ptr) 60 | { 61 | if (ptr == 0) print("use of NULL pointer", data->location); 62 | 63 | else if (ptr & ((1 << data->log_alignment) - 1)) 64 | { 65 | print("use of misaligned pointer", data->location); 66 | } 67 | else print("no space for object", data->location); 68 | } 69 | 70 | extern "C" void __ubsan_handle_vla_bound_not_positive(negative_vla_data *data) 71 | { 72 | print("variable-length argument is negative", data->location); 73 | } 74 | 75 | extern "C" void __ubsan_handle_nonnull_return(nonnull_return_data *data) 76 | { 77 | print("non-null return is null", data->location); 78 | } 79 | 80 | extern "C" void __ubsan_handle_nonnull_return_v1(nonnull_return_data *data) 81 | { 82 | print("non-null return is null", data->location); 83 | } 84 | 85 | extern "C" void __ubsan_handle_nonnull_arg(nonnull_arg_data *data) 86 | { 87 | print("non-null argument is null", data->location); 88 | } 89 | 90 | extern "C" void __ubsan_handle_builtin_unreachable(unreachable_data *data) 91 | { 92 | print("unreachable code reached", data->location); 93 | } 94 | 95 | extern "C" void __ubsan_handle_invalid_builtin(invalid_builtin_data *data) 96 | { 97 | print("invalid builtin", data->location); 98 | } 99 | 100 | extern "C" void __ubsan_handle_float_cast_overflow(float_cast_overflow_data *data) 101 | { 102 | print("float cast overflow", data->location); 103 | } 104 | 105 | extern "C" void __ubsan_handle_missing_return(missing_return_data *data) 106 | { 107 | print("missing return", data->location); 108 | } 109 | 110 | extern "C" void __ubsan_handle_alignment_assumption(alignment_assumption_data *data) 111 | { 112 | print("alignment assumption", data->location); 113 | } -------------------------------------------------------------------------------- /source/system/ubsan/ubsan.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2021-2022 ilobilo 2 | 3 | #pragma once 4 | 5 | #include 6 | 7 | struct source_location 8 | { 9 | const char *file; 10 | uint32_t line; 11 | uint32_t column; 12 | }; 13 | 14 | struct type_descriptor 15 | { 16 | uint16_t kind; 17 | uint16_t info; 18 | char name[]; 19 | }; 20 | 21 | struct overflow_data 22 | { 23 | source_location location; 24 | type_descriptor *type; 25 | }; 26 | 27 | struct shift_out_of_bounds_data 28 | { 29 | source_location location; 30 | type_descriptor *left_type; 31 | type_descriptor *right_type; 32 | }; 33 | 34 | struct invalid_value_data 35 | { 36 | source_location location; 37 | type_descriptor *type; 38 | }; 39 | 40 | struct array_out_of_bounds_data 41 | { 42 | source_location location; 43 | type_descriptor *array_type; 44 | type_descriptor *index_type; 45 | }; 46 | 47 | struct type_mismatch_v1_data 48 | { 49 | source_location location; 50 | type_descriptor *type; 51 | uint8_t log_alignment; 52 | uint8_t type_check_kind; 53 | }; 54 | 55 | struct negative_vla_data 56 | { 57 | source_location location; 58 | type_descriptor *type; 59 | }; 60 | 61 | struct nonnull_return_data 62 | { 63 | source_location location; 64 | }; 65 | 66 | struct nonnull_arg_data 67 | { 68 | source_location location; 69 | }; 70 | 71 | struct unreachable_data 72 | { 73 | source_location location; 74 | }; 75 | 76 | struct invalid_builtin_data 77 | { 78 | source_location location; 79 | uint8_t kind; 80 | }; 81 | 82 | struct float_cast_overflow_data 83 | { 84 | source_location location; 85 | }; 86 | 87 | struct missing_return_data 88 | { 89 | source_location location; 90 | }; 91 | 92 | struct alignment_assumption_data 93 | { 94 | source_location location; 95 | source_location assumption_location; 96 | type_descriptor *type; 97 | }; -------------------------------------------------------------------------------- /source/wrappers/assert.h: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2021-2022 ilobilo 2 | 3 | #pragma once 4 | 5 | #ifdef __cplusplus 6 | extern "C" { 7 | #endif 8 | 9 | __attribute__((noreturn)) void panic(const char *message, const char *file, const char *func, int line); 10 | 11 | #ifdef __cplusplus 12 | } 13 | #endif 14 | 15 | #define assert(x) (!(x) ? panic("Assertion failed: " #x, __FILE__, __PRETTY_FUNCTION__, __LINE__) : (void)(x)) -------------------------------------------------------------------------------- /source/wrappers/climits: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2021-2022 ilobilo 2 | 3 | #pragma once 4 | 5 | #include -------------------------------------------------------------------------------- /source/wrappers/cstdarg: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2021-2022 ilobilo 2 | 3 | #pragma once 4 | 5 | #include 6 | 7 | namespace std 8 | { 9 | using ::va_list; 10 | } -------------------------------------------------------------------------------- /source/wrappers/cstring: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2021-2022 ilobilo 2 | 3 | #pragma once 4 | 5 | #include 6 | #include -------------------------------------------------------------------------------- /source/wrappers/ctype.h: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2021-2022 ilobilo 2 | 3 | #pragma once 4 | 5 | #ifdef __cplusplus 6 | extern "C" { 7 | #endif 8 | 9 | int isspace(char c); 10 | 11 | int isdigit(int c); 12 | int isalpha(int c); 13 | int islower(int c); 14 | 15 | char tolower(char c); 16 | char toupper(char c); 17 | 18 | #ifdef __cplusplus 19 | } 20 | #endif -------------------------------------------------------------------------------- /source/wrappers/functional: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2021-2022 ilobilo 2 | 3 | #pragma once 4 | 5 | #include -------------------------------------------------------------------------------- /source/wrappers/math.h: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2021-2022 ilobilo 2 | 3 | #pragma once 4 | 5 | #ifdef __cplusplus 6 | extern "C" { 7 | #endif 8 | 9 | int pow(int base, int exponent); 10 | 11 | #ifdef __cplusplus 12 | } 13 | #endif -------------------------------------------------------------------------------- /source/wrappers/stdio.h: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2021-2022 ilobilo 2 | 3 | #pragma once 4 | 5 | #ifdef __cplusplus 6 | extern "C" { 7 | #endif 8 | 9 | #ifdef __cplusplus 10 | } 11 | #endif -------------------------------------------------------------------------------- /source/wrappers/stdlib.h: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2021-2022 ilobilo 2 | 3 | #pragma once 4 | 5 | #include 6 | #include 7 | 8 | #ifdef __cplusplus 9 | extern "C" { 10 | #endif 11 | 12 | int abs(int num); 13 | int sign(int num); 14 | 15 | uint64_t rand(); 16 | void srand(uint64_t seed); 17 | 18 | long strtol(const char *nPtr, char **endPtr, int base); 19 | long long int strtoll(const char *nPtr, char **endPtr, int base); 20 | unsigned long strtoul(const char *nPtr, char **endPtr, int base); 21 | unsigned long long int strtoull(const char *nPtr, char **endPtr, int base); 22 | 23 | int itoa(int num, unsigned char *str, int len, int base); 24 | int atoi(const char *str); 25 | 26 | void *malloc(size_t size); 27 | void *calloc(size_t num, size_t size); 28 | void *realloc(void *ptr, size_t size); 29 | void free(void *ptr); 30 | 31 | #ifdef __cplusplus 32 | } 33 | #endif -------------------------------------------------------------------------------- /source/wrappers/string: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2021-2022 ilobilo 2 | 3 | #pragma once 4 | 5 | #include -------------------------------------------------------------------------------- /source/wrappers/string.h: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2021-2022 ilobilo 2 | 3 | #pragma once 4 | 5 | #include 6 | 7 | #ifdef __cplusplus 8 | extern "C" { 9 | #endif 10 | 11 | size_t strlen(const char *str); 12 | 13 | char *strcpy(char *destination, const char *source); 14 | char *strncpy(char *destination, const char *source, size_t n); 15 | 16 | char *strcat(char *destination, const char *source); 17 | char *strchr(const char *str, char ch); 18 | 19 | int strcmp(const char *a, const char *b); 20 | int strncmp(const char *a, const char *b, size_t n); 21 | 22 | char *strdup(const char *src); 23 | void strrev(unsigned char *str); 24 | char *strstr(const char *str, const char *substr); 25 | 26 | void *memcpy(void *dest, const void *src, size_t len); 27 | int memcmp(const void *ptr1, const void *ptr2, size_t len); 28 | void *memset(void *dest, int ch, size_t n); 29 | void *memmove(void *dest, const void *src, size_t len); 30 | 31 | #ifdef __cplusplus 32 | } 33 | #endif --------------------------------------------------------------------------------