├── .github └── workflows │ └── c-cpp.yml ├── .gitignore ├── LICENSE ├── Makefile ├── README.md ├── ata_ext2_grub2_sector ├── ata_grub2_sector ├── bochsdbg.rc ├── bochsrc_ata.bxrc ├── bochsrc_floppy.bxrc ├── bochsrc_iso.bxrc ├── bootloader ├── Makefile ├── ata_biosparams.inc ├── ata_ext2_biosparams.inc ├── ata_ext2_partitions.inc ├── ata_loadkernel.inc ├── ata_partitions.inc ├── biosparams.asm ├── biosparams.lds ├── bootloader.asm ├── bootloader.lds ├── floppy_biosparams.inc ├── floppy_loadkernel.inc └── floppy_partitions.inc ├── floppy_grub2_sector ├── fstab.example ├── grub.cfg.example ├── grub_ata.cfg ├── grub_floppy.cfg ├── kernel ├── .gitignore ├── CMakeLists.txt ├── Makefile ├── bits.c ├── bits.h ├── cpu │ ├── acpi.c │ ├── acpi.h │ ├── cpuid.asm │ ├── cpuid.c │ ├── cpuid.h │ ├── fpu.asm │ ├── fpu.c │ ├── fpu.h │ ├── gdt.asm │ ├── gdt.c │ ├── gdt.h │ ├── idt.asm │ ├── idt.c │ ├── idt.h │ ├── interrupts.c │ ├── interrupts.h │ ├── irq.asm │ ├── irq.c │ ├── irq.h │ ├── isr.asm │ ├── isr.c │ ├── isr.h │ ├── mmu.asm │ ├── mmu.c │ ├── mmu.h │ ├── panic.c │ ├── panic.h │ ├── pic.c │ ├── pic.h │ ├── power.c │ ├── power.h │ ├── syscall.asm │ ├── syscall.c │ ├── syscall.h │ ├── system.h │ ├── tss.asm │ ├── tss.c │ └── tss.h ├── debug.c ├── debug.h ├── drivers │ ├── eth │ │ ├── e1000.c │ │ ├── e1000.h │ │ ├── ne2k.c │ │ └── ne2k.h │ ├── ethernet.c │ ├── ethernet.h │ ├── filesystem.h │ ├── fs │ │ ├── ext2.c │ │ ├── ext2.h │ │ ├── fat.c │ │ ├── fat.h │ │ ├── iso9660.c │ │ └── iso9660.h │ ├── io │ │ ├── ahci.c │ │ ├── ahci.h │ │ ├── ata.c │ │ ├── ata.h │ │ ├── floppy.c │ │ ├── floppy.h │ │ ├── ide.c │ │ ├── ide.h │ │ ├── scsi.c │ │ └── scsi.h │ ├── iodriver.h │ ├── keyboard.c │ ├── keyboard.h │ ├── mbr.c │ ├── mbr.h │ ├── pci.c │ ├── pci.h │ ├── screen.c │ ├── screen.h │ ├── serial.c │ ├── serial.h │ ├── usb.c │ ├── usb.h │ └── video │ │ ├── framebuffer.c │ │ └── framebuffer.h ├── kernel.asm ├── kernel.c ├── kernel.h ├── kernel.lds ├── kstring.c ├── kstring.h ├── libc │ ├── arpa │ │ └── inet.c │ ├── ctype.c │ ├── errno.c │ ├── include │ │ ├── arpa │ │ │ └── inet.h │ │ ├── ctype.h │ │ ├── dirent.h │ │ ├── errno.h │ │ ├── fcntl.h │ │ ├── math.h │ │ ├── stdarg.h │ │ ├── stdbool.h │ │ ├── stddef.h │ │ ├── stdint.h │ │ ├── stdio.h │ │ ├── stdlib.h │ │ ├── string.h │ │ ├── sys │ │ │ ├── stat.h │ │ │ └── types.h │ │ └── time.h │ ├── math.c │ ├── stdio.c │ ├── stdlib.c │ ├── string.c │ └── time.c ├── modules │ ├── acpica.c │ ├── acpica.h │ ├── bitmap.c │ ├── bitmap.h │ ├── cmos.c │ ├── cmos.h │ ├── elf.c │ ├── elf.h │ ├── fd.c │ ├── fd.h │ ├── fonts │ │ └── rasterized.h │ ├── heap.c │ ├── heap.h │ ├── kblayout │ │ ├── kb.c │ │ ├── kb.h │ │ └── us.h │ ├── multiboot2.h │ ├── net │ │ ├── arp.c │ │ ├── arp.h │ │ ├── dhcp.c │ │ ├── dhcp.h │ │ ├── dns.c │ │ ├── dns.h │ │ ├── http.c │ │ ├── http.h │ │ ├── icmp.c │ │ ├── icmp.h │ │ ├── ip.c │ │ ├── ip.h │ │ ├── tcp.c │ │ ├── tcp.h │ │ ├── udp.c │ │ └── udp.h │ ├── process.c │ ├── process.h │ ├── spinlock.asm │ ├── spinlock.c │ ├── spinlock.h │ ├── timer.c │ ├── timer.h │ ├── uuid.c │ ├── uuid.h │ ├── vfs.c │ ├── vfs.h │ ├── vt.c │ └── vt.h ├── multiboot2.inc ├── ring3.c ├── ring3.h ├── rootfs.c └── rootfs.h ├── lba2chs.py ├── mtoolsrc ├── rootfs ├── boot │ └── grub │ │ └── grub.cfg └── etc │ └── fstab ├── slirp.conf ├── system ├── CMakeLists.txt ├── Makefile ├── bin │ ├── Makefile │ ├── init │ │ ├── Makefile │ │ ├── init.c │ │ └── init.h │ └── sh │ │ ├── Makefile │ │ ├── sh.c │ │ └── sh.h └── libc │ ├── Makefile │ ├── ctype.c │ ├── dirent.c │ ├── errno.c │ ├── fcntl.c │ ├── include │ ├── ctype.h │ ├── dirent.h │ ├── errno.h │ ├── fcntl.h │ ├── math.h │ ├── stdarg.h │ ├── stdbool.h │ ├── stddef.h │ ├── stdint.h │ ├── stdio.h │ ├── stdlib.h │ ├── string.h │ ├── sys │ │ ├── stat.h │ │ └── types.h │ └── unistd.h │ ├── math.c │ ├── stdio.c │ ├── stdlib.c │ ├── string.c │ ├── sys │ └── stat.c │ └── unistd.c └── virt2phys.py /.github/workflows/c-cpp.yml: -------------------------------------------------------------------------------- 1 | name: C/C++ CI 2 | 3 | on: 4 | push: 5 | branches: [ "master" ] 6 | pull_request: 7 | branches: [ "master" ] 8 | 9 | jobs: 10 | build: 11 | 12 | runs-on: ubuntu-latest 13 | 14 | steps: 15 | - uses: ilammy/setup-nasm@v1 16 | - uses: actions/checkout@v4 17 | - name: make 18 | run: make 19 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | #build dir 2 | build/ 3 | grub2.img 4 | rootfs/init.elf 5 | rootfs/kernel.elf 6 | 7 | floppy_disk.img 8 | ata_disk.img 9 | ata_disk_ext2.img 10 | cdrom.iso 11 | ata_disk.vdi 12 | ata_disk.vmdk 13 | serial.txt 14 | slirp-pktlog.txt 15 | qemu-pktlog.pcap 16 | vbox-pktlog.pcap 17 | 18 | .idea/ 19 | .vscode/ 20 | 21 | # Prerequisites 22 | *.d 23 | 24 | # Object files 25 | *.o 26 | *.ko 27 | *.obj 28 | *.elf 29 | 30 | # Linker output 31 | *.ilk 32 | *.map 33 | *.exp 34 | 35 | # Precompiled Headers 36 | *.gch 37 | *.pch 38 | 39 | # Libraries 40 | *.lib 41 | *.a 42 | *.la 43 | *.lo 44 | 45 | # Shared objects (inc. Windows DLLs) 46 | *.dll 47 | *.so 48 | *.so.* 49 | *.dylib 50 | 51 | # Executables 52 | *.exe 53 | *.out 54 | *.app 55 | *.i*86 56 | *.x86_64 57 | *.hex 58 | 59 | # Debug files 60 | *.dSYM/ 61 | *.su 62 | *.idb 63 | *.pdb 64 | 65 | # Kernel Module Compile Results 66 | *.mod* 67 | *.cmd 68 | .tmp_versions/ 69 | modules.order 70 | Module.symvers 71 | Mkfile.old 72 | dkms.conf 73 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # DOS 2 | A Simple x86 Operating System written in C. 3 | 4 | ## What's working 5 | ### Grub2 6 | The Kernel is loaded by Grub2. The boot configuration is located in `rootfs/boot/grub/grub.cfg`. 7 | 8 | ### Multiboot 2 9 | The Kernel is loaded by Grub2 using the Multiboot 2 protocol. The Kernel is loaded at `0x100000` and is loaded in 32-bit mode. 10 | 11 | ### MBR Parsing 12 | The Kernel parses the MBR and finds its own partition. It does not support extended partitions. Then it setups the filesystem and mounts it. 13 | 14 | ### FAT12/16 15 | The Kernel supports FAT12 and FAT16. It can read files and directories. The Kernel cannot write to FAT12/16. 16 | 17 | ### Ext2 18 | The Kernel supports Ext2. It can read files and directories. The Kernel cannot write to Ext2. 19 | 20 | ### Syscalls 21 | The Kernel supports syscalls via the `int 0x80` instruction. Currently the following syscalls are supported: 22 | - `sys_write` 23 | - `sys_read` 24 | - `sys_open` 25 | - `sys_close` 26 | - `sys_stat` 27 | - `sys_getpid` 28 | - `sys_fork` 29 | - `sys_execve` 30 | - `sys_exit` 31 | 32 | ### ELF parsing 33 | The Kernel can parse ELF files and execute them. It can also load debug symbols from itself. 34 | 35 | ### Kernel Modules 36 | Currently the Kernel is built as a single binary. In the future it will be split into modules. The Kernel will load the modules from the filesystem. 37 | 38 | ### Networking 39 | The Kernel supports the Intel 82540EM series of network cards. It can send and receive packets. The following protocols are supported: 40 | - ARP 41 | - IPv4 42 | - UDP 43 | - TCP 44 | - DHCP 45 | - DNS 46 | 47 | ### Libc 48 | The Kernel is built on top of a primitive libc. It is located in `kernel/libc`. There's also a `system/libc` which is used by the userspace programs and in the future will generate a shared library. 49 | 50 | ## Goals 51 | - [x] Grub2 52 | - [x] Multiboot 2 53 | - [x] MBR Parsing 54 | - [x] FAT12/16 55 | - [x] Ext2 56 | - [x] ISO9660 57 | - [ ] x86_64 58 | - [x] Syscalls 59 | - [x] Multitasking 60 | - [x] Virtual Memory 61 | - [x] ELF parsing 62 | - [] Dynamic Linking 63 | - [x] Kernel Modules 64 | - [x] ACPI 65 | - [ ] ACPICA 66 | - [x] PCI 67 | - [x] ATA 68 | - [x] ATAPI 69 | - [x] Networking 70 | - [ ] Virtual File System 71 | - [ ] Init System 72 | - [ ] Shell 73 | - [x] Libc 74 | -------------------------------------------------------------------------------- /ata_ext2_grub2_sector: -------------------------------------------------------------------------------- 1 |  -------------------------------------------------------------------------------- /ata_grub2_sector: -------------------------------------------------------------------------------- 1 |  -------------------------------------------------------------------------------- /bochsdbg.rc: -------------------------------------------------------------------------------- 1 | c 2 | -------------------------------------------------------------------------------- /bochsrc_ata.bxrc: -------------------------------------------------------------------------------- 1 | # configuration file generated by Bochs 2 | plugin_ctrl: voodoo=true, unmapped=true, biosdev=true, speaker=true, extfpuirq=true, parallel=true, serial=true, busmouse=false, e1000=true, es1370=false, gameport=true, ne2k=true, sb16=true, usb_uhci=true, usb_ohci=false, usb_ehci=false, usb_xhci=false 3 | config_interface: win32config 4 | display_library: win32 5 | memory: host=32, guest=32 6 | romimage: file="C:\Program Files\Bochs-2.7/BIOS-bochs-latest", address=0x00000000, options=none 7 | vgaromimage: file="C:\Program Files\Bochs-2.7/VGABIOS-lgpl-latest" 8 | boot: disk 9 | floppy_bootsig_check: disabled=0 10 | floppya: type=none 11 | # no floppyb 12 | ata0: enabled=true, ioaddr1=0x1f0, ioaddr2=0x3f0, irq=14 13 | ata0-master: type=disk, path="./ata_disk.img", mode=flat, cylinders=256, heads=4, spt=32, sect_size=512, model="ATAMVLIRA", biosdetect=auto, translation=auto 14 | ata0-slave: type=none 15 | ata1: enabled=true, ioaddr1=0x170, ioaddr2=0x370, irq=15 16 | ata1-master: type=none 17 | ata1-slave: type=none 18 | ata2: enabled=false 19 | ata3: enabled=false 20 | optromimage1: file=none 21 | optromimage2: file=none 22 | optromimage3: file=none 23 | optromimage4: file=none 24 | optramimage1: file=none 25 | optramimage2: file=none 26 | optramimage3: file=none 27 | optramimage4: file=none 28 | pci: enabled=1, chipset=i440bx, slot1=voodoo, slot2=e1000, slot3=none, slot4=none, slot5=none 29 | vga: extension=vbe, update_freq=60, realtime=1, ddc=builtin 30 | cpu: count=1, ips=4000000, model=corei7_sandy_bridge_2600k, reset_on_triple_fault=1, cpuid_limit_winnt=0, ignore_bad_msrs=1, mwait_is_nop=0 31 | print_timestamps: enabled=0 32 | port_e9_hack: enabled=0 33 | private_colormap: enabled=0 34 | clock: sync=realtime, time0=local, rtc_sync=1 35 | # no cmosimage 36 | log: - 37 | logprefix: %t%e%d 38 | debug: action=ignore 39 | info: action=report 40 | error: action=report 41 | panic: action=ask 42 | keyboard: type=at, serial_delay=250, paste_delay=100000, user_shortcut=none 43 | mouse: type=ps2, enabled=false, toggle=ctrl+mbutton 44 | sound: waveoutdrv=win, waveout=none, waveindrv=win, wavein=none, midioutdrv=win, midiout=none 45 | speaker: enabled=true, mode=sound, volume=15 46 | parport1: enabled=true, file=none 47 | parport2: enabled=false 48 | com1: enabled=true, mode=file, dev="./serial.txt" 49 | com2: enabled=false 50 | com3: enabled=false 51 | com4: enabled=false 52 | voodoo: enabled=true, model=voodoo1 53 | e1000: card=0, enabled=true, mac=08:00:27:70:fd:03, ethmod=slirp, ethdev="xl0", script="./slirp.conf", bootrom=none 54 | e1000: card=1, enabled=false 55 | e1000: card=2, enabled=false 56 | e1000: card=3, enabled=false 57 | ne2k: card=0, enabled=true, mac=08:00:27:70:fd:03, ethmod=slirp, ethdev="xl0", script="./slirp.conf", irq=10, bootrom=none 58 | ne2k: card=1, enabled=false 59 | ne2k: card=2, enabled=false 60 | ne2k: card=3, enabled=false 61 | sb16: enabled=true, midimode=0, wavemode=0, loglevel=0, dmatimer=1000000 62 | usb_uhci: enabled=1, port1=none, options1=none, port2=none, options2=none 63 | -------------------------------------------------------------------------------- /bochsrc_floppy.bxrc: -------------------------------------------------------------------------------- 1 | # configuration file generated by Bochs 2 | plugin_ctrl: voodoo=true, unmapped=true, biosdev=true, speaker=true, extfpuirq=true, parallel=true, serial=true, busmouse=false, e1000=true, es1370=false, gameport=true, ne2k=true, sb16=true, usb_uhci=true, usb_ohci=false, usb_ehci=false, usb_xhci=false 3 | config_interface: win32config 4 | display_library: win32 5 | memory: host=32, guest=32 6 | romimage: file="C:\Program Files\Bochs-2.7/BIOS-bochs-latest", address=0x00000000, options=none 7 | vgaromimage: file="C:\Program Files\Bochs-2.7/VGABIOS-lgpl-latest" 8 | boot: floppy 9 | floppy_bootsig_check: disabled=0 10 | floppya: type=1_44, 1_44=./floppy_disk.img, status=inserted, write_protected=0 11 | # no floppyb 12 | ata0: enabled=true, ioaddr1=0x1f0, ioaddr2=0x3f0, irq=14 13 | ata0-master: type=none 14 | ata0-slave: type=none 15 | ata1: enabled=true, ioaddr1=0x170, ioaddr2=0x370, irq=15 16 | ata1-master: type=none 17 | ata1-slave: type=none 18 | ata2: enabled=false 19 | ata3: enabled=false 20 | optromimage1: file=none 21 | optromimage2: file=none 22 | optromimage3: file=none 23 | optromimage4: file=none 24 | optramimage1: file=none 25 | optramimage2: file=none 26 | optramimage3: file=none 27 | optramimage4: file=none 28 | pci: enabled=1, chipset=i440bx, slot1=voodoo, slot2=e1000, slot3=none, slot4=none, slot5=none 29 | vga: extension=vbe, update_freq=60, realtime=1, ddc=builtin 30 | cpu: count=1, ips=4000000, model=corei7_sandy_bridge_2600k, reset_on_triple_fault=1, cpuid_limit_winnt=0, ignore_bad_msrs=1, mwait_is_nop=0 31 | print_timestamps: enabled=0 32 | port_e9_hack: enabled=0 33 | private_colormap: enabled=0 34 | clock: sync=realtime, time0=local, rtc_sync=1 35 | # no cmosimage 36 | log: - 37 | logprefix: %t%e%d 38 | debug: action=ignore 39 | info: action=report 40 | error: action=report 41 | panic: action=ask 42 | keyboard: type=at, serial_delay=250, paste_delay=100000, user_shortcut=none 43 | mouse: type=ps2, enabled=false, toggle=ctrl+mbutton 44 | sound: waveoutdrv=win, waveout=none, waveindrv=win, wavein=none, midioutdrv=win, midiout=none 45 | speaker: enabled=true, mode=sound, volume=15 46 | parport1: enabled=true, file=none 47 | parport2: enabled=false 48 | com1: enabled=true, mode=file, dev="./serial.txt" 49 | com2: enabled=false 50 | com3: enabled=false 51 | com4: enabled=false 52 | voodoo: enabled=true, model=voodoo1 53 | e1000: card=0, enabled=true, mac=08:00:27:70:fd:03, ethmod=slirp, ethdev="xl0", script="./slirp.conf", bootrom=none 54 | e1000: card=1, enabled=false 55 | e1000: card=2, enabled=false 56 | e1000: card=3, enabled=false 57 | ne2k: card=0, enabled=true, mac=08:00:27:70:fd:03, ethmod=slirp, ethdev="xl0", script="./slirp.conf", irq=10, bootrom=none 58 | ne2k: card=1, enabled=false 59 | ne2k: card=2, enabled=false 60 | ne2k: card=3, enabled=false 61 | sb16: enabled=true, midimode=0, wavemode=0, loglevel=0, dmatimer=1000000 62 | usb_uhci: enabled=1, port1=none, options1=none, port2=none, options2=none 63 | -------------------------------------------------------------------------------- /bochsrc_iso.bxrc: -------------------------------------------------------------------------------- 1 | # configuration file generated by Bochs 2 | plugin_ctrl: voodoo=true, unmapped=true, biosdev=true, speaker=true, extfpuirq=true, parallel=true, serial=true, busmouse=false, e1000=true, es1370=false, gameport=true, ne2k=false, sb16=false, usb_uhci=true, usb_ohci=false, usb_ehci=false, usb_xhci=false 3 | config_interface: win32config 4 | display_library: win32 5 | memory: host=32, guest=32 6 | romimage: file="C:\Program Files\Bochs-2.7/BIOS-bochs-latest", address=0x00000000, options=none 7 | vgaromimage: file="C:\Program Files\Bochs-2.7/VGABIOS-lgpl-latest" 8 | boot: cdrom 9 | floppy_bootsig_check: disabled=0 10 | # no floppya 11 | # no floppyb 12 | ata0: enabled=true, ioaddr1=0x1f0, ioaddr2=0x3f0, irq=14 13 | ata0-master: type=cdrom, path="./cdrom.iso", status=inserted, model="ISOMVLIRA", biosdetect=auto 14 | ata0-slave: type=none 15 | ata1: enabled=false 16 | ata2: enabled=false 17 | ata3: enabled=false 18 | optromimage1: file=none 19 | optromimage2: file=none 20 | optromimage3: file=none 21 | optromimage4: file=none 22 | optramimage1: file=none 23 | optramimage2: file=none 24 | optramimage3: file=none 25 | optramimage4: file=none 26 | pci: enabled=1, chipset=i440bx, slot1=voodoo, slot2=e1000, slot3=none, slot4=none, slot5=none 27 | vga: extension=vbe, update_freq=60, realtime=1, ddc=builtin 28 | cpu: count=1, ips=4000000, model=corei7_sandy_bridge_2600k, reset_on_triple_fault=1, cpuid_limit_winnt=0, ignore_bad_msrs=1, mwait_is_nop=0 29 | print_timestamps: enabled=0 30 | port_e9_hack: enabled=0 31 | private_colormap: enabled=0 32 | clock: sync=realtime, time0=local, rtc_sync=1 33 | # no cmosimage 34 | log: - 35 | logprefix: %t%e%d 36 | debug: action=ignore 37 | info: action=report 38 | error: action=report 39 | panic: action=ask 40 | keyboard: type=at, serial_delay=250, paste_delay=100000, user_shortcut=none 41 | mouse: type=ps2, enabled=false, toggle=ctrl+mbutton 42 | sound: waveoutdrv=win, waveout=none, waveindrv=win, wavein=none, midioutdrv=win, midiout=none 43 | speaker: enabled=true, mode=sound, volume=15 44 | parport1: enabled=true, file=none 45 | parport2: enabled=false 46 | com1: enabled=true, mode=file, dev="./serial.txt" 47 | com2: enabled=false 48 | com3: enabled=false 49 | com4: enabled=false 50 | voodoo: enabled=true, model=voodoo1 51 | e1000: card=0, enabled=true, mac=08:00:27:70:fd:03, ethmod=slirp, ethdev="xl0", script="./slirp.conf", bootrom=none 52 | e1000: card=1, enabled=false 53 | e1000: card=2, enabled=false 54 | e1000: card=3, enabled=false 55 | ne2k: card=0, enabled=true, mac=08:00:27:70:fd:03, ethmod=slirp, ethdev="xl0", script="./slirp.conf", irq=10, bootrom=none 56 | ne2k: card=1, enabled=false 57 | ne2k: card=2, enabled=false 58 | ne2k: card=3, enabled=false 59 | sb16: enabled=true, midimode=0, wavemode=0, loglevel=0, dmatimer=1000000 60 | usb_uhci: enabled=1, port1=none, options1=none, port2=none, options2=none 61 | -------------------------------------------------------------------------------- /bootloader/Makefile: -------------------------------------------------------------------------------- 1 | BUILD_DIR=../build/bootloader 2 | 3 | BOOTLOADER_SRCS := $(wildcard bootloader*.asm) 4 | BOOTLOADER_OBJS := $(patsubst %.asm, $(BUILD_DIR)/%.o, $(BOOTLOADER_SRCS)) 5 | 6 | BIOSPARAMS_SRCS := $(wildcard biosparams*.asm) 7 | BIOSPARAMS_OBJS := $(patsubst %.asm, $(BUILD_DIR)/%.o, $(BIOSPARAMS_SRCS)) 8 | 9 | all: dir $(BUILD_DIR)/bootloader $(BUILD_DIR)/biosparams 10 | 11 | dir: 12 | mkdir -p $(BUILD_DIR) 13 | 14 | $(BUILD_DIR)/%.o: %.asm 15 | nasm -f elf -F dwarf -g $< -o $@ $(ARG1) 16 | 17 | $(BUILD_DIR)/bootloader: $(BOOTLOADER_OBJS) 18 | ld -m elf_i386 -nmagic -T bootloader.lds $< -o $@.elf 19 | objcopy -O binary -j .text $@.elf $@ 20 | 21 | $(BUILD_DIR)/biosparams: $(BIOSPARAMS_OBJS) 22 | ld -m elf_i386 -nmagic -T biosparams.lds $< -o $@.elf 23 | objcopy -O binary -j .text $@.elf $@ 24 | 25 | clean: 26 | rm -f $(BUILD_DIR)/* 27 | -------------------------------------------------------------------------------- /bootloader/ata_biosparams.inc: -------------------------------------------------------------------------------- 1 | %ifndef ATA_ASM 2 | %define ATA_ASM 3 | 4 | bios_param: 5 | param_bytes_per_sector dw 0x0200; Bytes per Sector 6 | param_sectors_per_cluster db 0x01; Sectors per Cluster 7 | param_reserved_sectors dw 0x0001; Reserved Sectors 8 | param_number_of_fat db 0x02; Number of file allocation tables 9 | param_rootdir_entries dw 0x0200; Root Directory Entries 10 | param_small_sectors dw 0x7FFF; Small Sectors 11 | param_media_type db 0xF8; Media Type 12 | param_sectors_per_fat dw 0x0020; Sectors per file allocation table 13 | param_sectors_per_track dw 0x0020; Sectors per Track 14 | param_number_of_heads dw 0x0004; Number of Heads 15 | param_hidden_sectors dd 0x00000001; Hidden Sectors 16 | param_large_sectors dd 0x00000000; Large Sectors 17 | 18 | ext_bios_param: 19 | param_disk_number db 0x80; Physical Disk Number 20 | param_checkdisk db 0x00; Check Disk 21 | param_signature db 0x29; Signature 22 | param_serial_number dd 0x00000000; Volume Serial Number 23 | param_volume_label db "MARCOSLIRA", 0x20; Volume Label 24 | param_filesystem db "FAT16", 0x20, 0x20, 0x20; System ID 25 | 26 | %macro GRUB_BOOT_SECTOR 0 27 | db 0x02 28 | %endmacro 29 | 30 | %endif 31 | -------------------------------------------------------------------------------- /bootloader/ata_ext2_biosparams.inc: -------------------------------------------------------------------------------- 1 | %ifndef ATA_ASM 2 | %define ATA_ASM 3 | 4 | bios_param: 5 | param_bytes_per_sector dw 0x0200; Bytes per Sector 6 | param_sectors_per_cluster db 0x01; Sectors per Cluster 7 | param_reserved_sectors dw 0x0001; Reserved Sectors 8 | param_number_of_fat db 0x00; Number of file allocation tables 9 | param_rootdir_entries dw 0x0000; Root Directory Entries 10 | param_small_sectors dw 0x7FF8; Small Sectors 11 | param_media_type db 0xF8; Media Type 12 | param_sectors_per_fat dw 0x0000; Sectors per file allocation table 13 | param_sectors_per_track dw 0x0020; Sectors per Track 14 | param_number_of_heads dw 0x0004; Number of Heads 15 | param_hidden_sectors dd 0x00000001; Hidden Sectors 16 | param_large_sectors dd 0x00000000; Large Sectors 17 | 18 | ext_bios_param: 19 | param_disk_number db 0x80; Physical Disk Number 20 | param_checkdisk db 0x00; Check Disk 21 | param_signature db 0x29; Signature 22 | param_serial_number dd 0x00000000; Volume Serial Number 23 | param_volume_label db "MARCOSLIRA", 0x20; Volume Label 24 | param_filesystem db "EXT2", 0x20, 0x20, 0x20, 0x20; System ID 25 | 26 | %macro GRUB_BOOT_SECTOR 0 27 | db 0x02 28 | %endmacro 29 | 30 | %endif 31 | -------------------------------------------------------------------------------- /bootloader/ata_ext2_partitions.inc: -------------------------------------------------------------------------------- 1 | %ifndef ATA_PART_ASM 2 | %define ATA_PART_ASM 3 | 4 | %macro PARTITION1 0 5 | db 0x80 ; Bootable 6 | 7 | ; CHS start 8 | db 0x00 9 | db 0x02 10 | db 0x00 11 | 12 | db 0x7F ; Partittion type 13 | 14 | ; CHS end 15 | db 0x02 16 | db 0x09 17 | db 0x01 18 | 19 | dd 0x00000001 ; LBA start 20 | dd 0x00000200 ; Number of sectors 21 | %endmacro 22 | 23 | %macro PARTITION2 0 24 | db 0x00 ; Bootable 25 | 26 | ; CHS start 27 | db 0x02 28 | db 0x0A 29 | db 0x01 30 | 31 | db 0x83 ; Partittion type 32 | 33 | ; CHS end 34 | db 0x0A 35 | db 0x08 36 | db 0x02 37 | 38 | dd 0x00000201 ; LBA start 39 | dd 0x00007DFF ; Number of sectors 40 | %endmacro 41 | 42 | %macro PARTITION3 0 43 | db 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00 44 | %endmacro 45 | 46 | %macro PARTITION4 0 47 | db 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00 48 | %endmacro 49 | 50 | %endif 51 | -------------------------------------------------------------------------------- /bootloader/ata_loadkernel.inc: -------------------------------------------------------------------------------- 1 | [bits 16] 2 | load_kernel: 3 | ; We will assume that the Kernel is the first file in the disk 4 | 5 | mov ah, 8 6 | mov dl, [boot_drive] 7 | int 0x13 8 | 9 | mov bx, KERNEL_SEG 10 | mov es, bx 11 | mov bx, KERNEL_OFF 12 | mov NUM_OF_SECTORS, 127 13 | mov CYLINDER_NUM, 0 ; Sector (1+20*2+56)=97 14 | mov HEAD_NUM, 3 15 | mov SECTOR_NUM, 2 16 | call disk_load 17 | 18 | ret 19 | -------------------------------------------------------------------------------- /bootloader/ata_partitions.inc: -------------------------------------------------------------------------------- 1 | %ifndef ATA_PART_ASM 2 | %define ATA_PART_ASM 3 | 4 | %macro PARTITION1 0 5 | db 0x80 ; Bootable 6 | 7 | ; CHS start 8 | db 0x00 9 | db 0x02 10 | db 0x00 11 | 12 | db 0x7F ; Partittion type 13 | 14 | ; CHS end 15 | db 0x02 16 | db 0x09 17 | db 0x01 18 | 19 | dd 0x00000001 ; LBA start 20 | dd 0x00000200 ; Number of sectors 21 | %endmacro 22 | 23 | %macro PARTITION2 0 24 | db 0x00 ; Bootable 25 | 26 | ; CHS start 27 | db 0x02 28 | db 0x0A 29 | db 0x01 30 | 31 | db 0x04 ; Partittion type 32 | 33 | ; CHS end 34 | db 0x0A 35 | db 0x08 36 | db 0x02 37 | 38 | dd 0x00000201 ; LBA start 39 | dd 0x00007DFF ; Number of sectors 40 | %endmacro 41 | 42 | %macro PARTITION3 0 43 | db 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00 44 | %endmacro 45 | 46 | %macro PARTITION4 0 47 | db 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00 48 | %endmacro 49 | 50 | %endif 51 | -------------------------------------------------------------------------------- /bootloader/biosparams.asm: -------------------------------------------------------------------------------- 1 | [bits 16] 2 | 3 | os_name db "MVLIRA05"; OS Name 4 | 5 | %ifdef FLOPPY 6 | %include "floppy_biosparams.inc" 7 | %elifdef ATA 8 | %include "ata_biosparams.inc" 9 | %elifdef ATAEXT2 10 | %include "ata_ext2_biosparams.inc" 11 | %endif 12 | 13 | times 28 db 0x0 14 | 15 | dw 0x8000 ; Address 16 | GRUB_BOOT_SECTOR ; LBA 17 | db 0x00 18 | db 0x00 19 | db 0x00 20 | db 0x00 21 | -------------------------------------------------------------------------------- /bootloader/biosparams.lds: -------------------------------------------------------------------------------- 1 | OUTPUT(biosparams); 2 | 3 | SECTIONS 4 | { 5 | .text 0x0: 6 | { 7 | /*. = 0x0;*/ 8 | *(.text) 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /bootloader/bootloader.asm: -------------------------------------------------------------------------------- 1 | [bits 16] 2 | 3 | %define DRIVE_NUM dl 4 | %define HEAD_NUM dh 5 | %define CYLINDER_NUM ch 6 | %define SECTOR_NUM cl 7 | %define NUM_OF_SECTORS al 8 | 9 | section .text 10 | global boot 11 | 12 | start: 13 | jmp boot 14 | nop 15 | 16 | %ifdef FLOPPY 17 | %include "floppy_partitions.inc" 18 | %elifdef ATA 19 | %include "ata_partitions.inc" 20 | %elifdef ATAEXT2 21 | %include "ata_ext2_partitions.inc" 22 | %endif 23 | 24 | boot: 25 | cli 26 | cld 27 | 28 | xor ax, ax ; mov ax, 0 29 | mov ds, ax 30 | mov es, ax 31 | mov ss, ax 32 | mov sp, ax 33 | 34 | .copy_lower: 35 | mov cx, 0x1000 36 | mov si, 0x7C00 37 | mov di, 0x0600 38 | rep movsb 39 | 40 | jmp 0:low_start 41 | 42 | low_start: 43 | sti 44 | 45 | mov [boot_drive], DRIVE_NUM 46 | 47 | mov bh, 0 48 | 49 | mov ah, 0 50 | mov DRIVE_NUM, [boot_drive] 51 | int 0x13 52 | jc reset_fail 53 | 54 | mov bp, 0x9000 55 | mov sp, bp 56 | 57 | call find_bootable_partition 58 | 59 | mov si, no_bootable_partition 60 | call puts 61 | cli 62 | hlt 63 | 64 | reset_fail: 65 | mov si, reset_failed 66 | call puts 67 | cli 68 | hlt 69 | 70 | putchar: 71 | mov ah, 0x0E 72 | int 0x10 73 | 74 | ret 75 | 76 | puts: 77 | .loop: 78 | lodsb 79 | or al, al 80 | jz .done 81 | 82 | mov cx, 1 83 | call putchar 84 | jmp .loop 85 | 86 | .done: 87 | ret 88 | 89 | disk_reset: 90 | mov ah, 0x00 91 | int 0x13 92 | ret 93 | 94 | disk_load: 95 | push ax 96 | 97 | mov DRIVE_NUM, [boot_drive] 98 | call disk_reset 99 | 100 | mov ah, 0x02 101 | mov DRIVE_NUM, [boot_drive] 102 | int 0x13 103 | jc disk_error 104 | 105 | mov dh, al 106 | pop ax 107 | cmp dh, al 108 | jne disk_error_sectors 109 | 110 | ret 111 | 112 | disk_error: 113 | mov si, disk_error_msg 114 | call puts 115 | cli 116 | hlt 117 | 118 | disk_error_sectors: 119 | mov si, disk_error_sectors_msg 120 | call puts 121 | cli 122 | hlt 123 | 124 | find_bootable_partition: 125 | mov bx, 0x01AE ; 0x01AE + 0x10 on first interaction = 0x01BE 126 | add bx, 0x0600 127 | .read_mbr: 128 | .no_bootable: 129 | add bx, 0x0010 130 | cmp bx, 0x07FE 131 | je .no_bootable_partition_found 132 | 133 | cmp byte [bx], 0x80 134 | jne .no_bootable 135 | 136 | mov si, loading_msg 137 | call puts 138 | 139 | ; Bootable partition found 140 | ; Read first sector of partition 141 | mov [_bx], bx 142 | mov HEAD_NUM, [bx + 0x1] 143 | mov SECTOR_NUM, [bx + 0x2] 144 | mov CYLINDER_NUM, [bx + 0x3] 145 | mov NUM_OF_SECTORS, 1 146 | xor bx, bx 147 | mov es, bx 148 | mov bx, 0x7C00 149 | call disk_load 150 | 151 | cmp word [0x7C00 + 0x1FE], 0xAA55 152 | jne .invalid_mbr 153 | 154 | jmp 0x0:0x7C00 155 | 156 | .invalid_mbr: 157 | mov bx, [_bx] 158 | mov si, invalid_mbr_msg 159 | call puts 160 | jmp .no_bootable 161 | 162 | .no_bootable_partition_found: 163 | 164 | ret 165 | 166 | loading_msg db "Loading...", 0xD, 0xA, 0x00 167 | disk_error_msg db "Disk read error", 0xD, 0xA, 0x0 168 | disk_error_sectors_msg db "Disk read error: Sectors read not equal to sectors requested", 0xD, 0xA, 0x0 169 | no_bootable_partition db "No bootable partition found", 0xD, 0xA, 0x0 170 | invalid_mbr_msg db "Invalid MBR", 0xD, 0xA, 0x0 171 | reset_failed db "Reset failed", 0xD, 0xA, 0x0 172 | user_data dw 0 173 | boot_drive db 0 174 | curr_y db 0 175 | curr_x db 0 176 | _bx dw 0 177 | 178 | times 440 - ($-$$) db 0 179 | dd 0x01020304 180 | dw 0x0000 181 | 182 | PARTITION1 183 | PARTITION2 184 | PARTITION3 185 | PARTITION4 186 | 187 | dw 0xAA55 188 | -------------------------------------------------------------------------------- /bootloader/bootloader.lds: -------------------------------------------------------------------------------- 1 | OUTPUT(bootloader); 2 | 3 | SECTIONS 4 | { 5 | .text 0x0600: 6 | { 7 | /*. = 0x0;*/ 8 | *(.text) 9 | } 10 | 11 | .data : 12 | { 13 | *(.data) 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /bootloader/floppy_biosparams.inc: -------------------------------------------------------------------------------- 1 | %ifndef FLOPPY_ASM 2 | %define FLOPPY_ASM 3 | 4 | bios_param: 5 | param_bytes_per_sector dw 0x0200; Bytes per Sector 6 | param_sectors_per_cluster db 0x01; Sectors per Cluster 7 | param_reserved_sectors dw 0x0001; Reserved Sectors 8 | param_number_of_fat db 0x02; Number of file allocation tables 9 | param_rootdir_entries dw 0x00E0; Root Directory Entries 10 | param_small_sectors dw 0x0B3F; Small Sectors 11 | param_media_type db 0xF0; Media Type 12 | param_sectors_per_fat dw 0x0009; Sectors per file allocation table 13 | param_sectors_per_track dw 0x0012; Sectors per Track 14 | param_number_of_heads dw 0x0002; Number of Heads 15 | param_hidden_sectors dd 0x00000001; Hidden Sectors 16 | param_large_sectors dd 0x00000000; Large Sectors 17 | 18 | ext_bios_param: 19 | param_disk_number db 0x00; Physical Disk Number 20 | param_checkdisk db 0x00; Check Disk 21 | param_signature db 0x29; Signature 22 | param_serial_number dd 0x00000000; Volume Serial Number 23 | param_volume_label db "MARCOSLIRA", 0x20; Volume Label 24 | param_filesystem db "FAT12", 0x20, 0x20, 0x20; System ID 25 | 26 | %macro GRUB_BOOT_SECTOR 0 27 | db 0x02 28 | %endmacro 29 | 30 | %endif 31 | -------------------------------------------------------------------------------- /bootloader/floppy_loadkernel.inc: -------------------------------------------------------------------------------- 1 | [bits 16] 2 | load_kernel: 3 | ; We will assume that the Kernel is the first file in the disk 4 | 5 | mov bx, KERNEL_SEG 6 | mov es, bx 7 | mov bx, KERNEL_OFF 8 | mov NUM_OF_SECTORS, 63 9 | mov CYLINDER_NUM, 0 ; Sector (1 + 9 * 2 + 14)=33 10 | mov HEAD_NUM, 1 11 | mov SECTOR_NUM, 16 12 | call disk_load 13 | 14 | mov bx, KERNEL_SEG_2 15 | mov es, bx 16 | mov bx, KERNEL_OFF_2 17 | mov NUM_OF_SECTORS, 63 18 | mov CYLINDER_NUM, 2 ; Sector 33 + 63 (previously loaded) 19 | mov HEAD_NUM, 1 20 | mov SECTOR_NUM, 7 21 | call disk_load 22 | 23 | ret 24 | -------------------------------------------------------------------------------- /bootloader/floppy_partitions.inc: -------------------------------------------------------------------------------- 1 | %ifndef FLOPPY_PART_ASM 2 | %define FLOPPY_PART_ASM 3 | 4 | %macro PARTITION1 0 5 | db 0x80 ; Bootable 6 | 7 | ; CHS start 8 | db 0x00 9 | db 0x02 10 | db 0x00 11 | 12 | db 0x7F ; Partition type 13 | 14 | ; CHS end 15 | db 0x01 16 | db 0x03 17 | db 0x05 18 | 19 | dd 0x00000001 ; LBA start 20 | dd 0x00000200 ; Number of sectors 21 | %endmacro 22 | 23 | %macro PARTITION2 0 24 | db 0x00 ; Bootable 25 | 26 | ; CHS start 27 | db 0x01 28 | db 0x04 29 | db 0x05 30 | 31 | db 0x01 ; Partition type 32 | 33 | ; CHS end 34 | db 0x2D 35 | db 0x2D 36 | db 0x00 37 | 38 | dd 0x00000201 ; LBA start 39 | dd 0x0000093F ; Number of sectors 40 | %endmacro 41 | 42 | %macro PARTITION3 0 43 | db 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00 44 | %endmacro 45 | 46 | %macro PARTITION4 0 47 | db 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00 48 | %endmacro 49 | 50 | %endif 51 | -------------------------------------------------------------------------------- /floppy_grub2_sector: -------------------------------------------------------------------------------- 1 |  -------------------------------------------------------------------------------- /fstab.example: -------------------------------------------------------------------------------- 1 | # /etc/fstab: static file system information. 2 | # 3 | # Use 'blkid' to print the universally unique identifier for a 4 | # device; this may be used with UUID= as a more robust way to name devices 5 | # that works even if disks are added and removed. See fstab(5). 6 | # 7 | # 8 | /dev/ / auto defaults 0 1 9 | /swapfile swap swap defaults 0 0 10 | -------------------------------------------------------------------------------- /grub.cfg.example: -------------------------------------------------------------------------------- 1 | set timeout=0 2 | 3 | menuentry "MVLIRA" { 4 | multiboot2 /kernel.elf root= 5 | boot 6 | } 7 | -------------------------------------------------------------------------------- /grub_ata.cfg: -------------------------------------------------------------------------------- 1 | set root=(hd0,msdos2) 2 | configfile /boot/grub/grub.cfg 3 | -------------------------------------------------------------------------------- /grub_floppy.cfg: -------------------------------------------------------------------------------- 1 | set root=(fd0,msdos2) 2 | configfile /boot/grub/grub.cfg 3 | -------------------------------------------------------------------------------- /kernel/.gitignore: -------------------------------------------------------------------------------- 1 | cmake-build-debug/* 2 | -------------------------------------------------------------------------------- /kernel/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.16) 2 | project(kernel) 3 | 4 | set(CMAKE_C_STANDARD 99) 5 | 6 | include_directories(SYSTEM ./libc/include) 7 | 8 | set(SOURCE_FILES 9 | kernel.c kernel.h 10 | bits.c bits.h 11 | cpu/idt.c cpu/idt.h 12 | cpu/irq.c cpu/irq.h 13 | cpu/gdt.c cpu/gdt.h 14 | cpu/isr.c cpu/isr.h 15 | cpu/pic.c cpu/pic.h 16 | cpu/syscall.c cpu/syscall.h 17 | cpu/system.h 18 | modules/timer.c modules/timer.h 19 | modules/kblayout/us.h 20 | libc/stdio.c libc/include/stdio.h 21 | libc/string.c libc/include/string.h 22 | libc/stdlib.c libc/include/stdlib.h 23 | libc/ctype.c libc/include/ctype.h 24 | libc/include/stddef.h 25 | libc/include/stdint.h 26 | libc/include/stdarg.h 27 | libc/math.c libc/include/math.h 28 | drivers/fat.c drivers/fat.h 29 | drivers/screen.c drivers/screen.h 30 | drivers/keyboard.c drivers/keyboard.h 31 | drivers/floppy.c drivers/floppy.h) 32 | 33 | add_executable(kernel ${SOURCE_FILES}) 34 | -------------------------------------------------------------------------------- /kernel/Makefile: -------------------------------------------------------------------------------- 1 | BUILD_DIR=../build/kernel 2 | BIN=$(BUILD_DIR)/kernel.elf 3 | 4 | CC=gcc 5 | CFLAGS=-ffreestanding -O0 -g -m32 -I libc/include -fno-pic -fno-omit-frame-pointer -nostdlib -nolibc -nodefaultlibs -Wl,--stack,0x8000 -Wno-packed-bitfield-compat -march=pentium3 -fno-common 6 | LDFLAGS=-g -m elf_i386 -T kernel.lds 7 | 8 | ASM_SRCS = $(wildcard *.asm cpu/*.asm modules/*.asm) 9 | ASM_OBJS = $(patsubst %.asm, $(BUILD_DIR)/%.obj, $(ASM_SRCS)) 10 | SRCS := $(wildcard *.c libc/*.c libc/arpa/*.c libc/sys/*.c drivers/*.c drivers/eth/*.c drivers/fs/*.c drivers/io/*.c drivers/video/*.c cpu/*.c modules/*.c modules/kblayout/*.c modules/net/*.c) 11 | HDRS := $(wildcard *.h libc/include/*.h lib/include/arpa/*.h lib/include/sys/*.h drivers/*.h drivers/eth/*.c drivers/fs/*.h drivers/io/*.h drivers/video/*.h cpu/*.h modules/*.h modules/kblayout/*.h modules/net/*.h) 12 | OBJS := $(patsubst %.c, $(BUILD_DIR)/%.o, $(SRCS)) 13 | 14 | all: dir $(BIN) 15 | 16 | dir: 17 | mkdir -p $(BUILD_DIR) 18 | mkdir -p $(BUILD_DIR)/drivers 19 | mkdir -p $(BUILD_DIR)/drivers/eth 20 | mkdir -p $(BUILD_DIR)/drivers/fs 21 | mkdir -p $(BUILD_DIR)/drivers/io 22 | mkdir -p $(BUILD_DIR)/drivers/video 23 | mkdir -p $(BUILD_DIR)/libc 24 | mkdir -p $(BUILD_DIR)/libc/arpa 25 | mkdir -p $(BUILD_DIR)/cpu 26 | mkdir -p $(BUILD_DIR)/modules 27 | mkdir -p $(BUILD_DIR)/modules/net 28 | mkdir -p $(BUILD_DIR)/modules/kblayout 29 | 30 | $(BUILD_DIR)/%.obj: %.asm 31 | nasm -f elf32 $< -o $@ 32 | 33 | $(BUILD_DIR)/%.o: %.c $(HDRS) 34 | $(CC) $(CFLAGS) -c $< -o $@ 35 | 36 | $(BIN): $(ASM_OBJS) $(OBJS) 37 | ld $^ $(LDFLAGS) -o $@ 38 | 39 | clean: 40 | rm -f $(OBJS) $(ASM_OBJS) 41 | -------------------------------------------------------------------------------- /kernel/bits.h: -------------------------------------------------------------------------------- 1 | #ifndef BITS_H 2 | #define BITS_H 3 | 4 | #include 5 | #include 6 | 7 | void outb(uint16_t addr, uint8_t val); 8 | 9 | uint8_t inb(uint16_t addr); 10 | 11 | void outw(uint16_t addr, uint16_t val); 12 | 13 | uint16_t inw(uint16_t addr); 14 | 15 | void outl(uint16_t addr, uint32_t val); 16 | 17 | uint32_t inl(uint16_t addr); 18 | 19 | void insl(uint16_t addr, uint32_t *buffer, size_t quads); 20 | 21 | void outsb(uint16_t addr, uint8_t *buffer, uint32_t size); 22 | 23 | void insb(uint16_t addr, uint8_t *buffer, uint32_t size); 24 | 25 | void outsw(uint16_t addr, uint16_t *buffer, uint32_t size); 26 | 27 | void insw(uint16_t addr, uint16_t *buffer, uint32_t size); 28 | 29 | void io_wait(void); 30 | 31 | uint16_t switch_endian_16(uint16_t val); 32 | 33 | uint32_t switch_endian_32(uint32_t val); 34 | 35 | uint64_t switch_endian_64(uint64_t val); 36 | 37 | uint16_t popcnt16(uint16_t val); 38 | 39 | uint32_t popcnt32(uint32_t val); 40 | 41 | uint64_t popcnt64(uint64_t val); 42 | 43 | #define GET_BIT(reg, bit) (((reg) >> (bit)) & 1) 44 | #define SET_BIT(reg, bit) ((reg) | (1 << bit)) 45 | 46 | #define DISABLE_BIT(reg, bit) ((reg) & ~(1 << bit)) 47 | #define ENABLE_BIT(reg, bit) ((reg) | (1 << bit)) 48 | #define TOGGLE_BIT(reg, bit) ((reg) ^ (1 << bit)) 49 | #define ISSET_BIT(reg, bit) (((reg) & (1 << bit)) != 0) 50 | 51 | #define DISABLE_BIT_INT(reg, bit) ((reg) & ~(bit)) 52 | #define ENABLE_BIT_INT(reg, bit) ((reg) | (bit)) 53 | #define TOGGLE_BIT_INT(reg, bit) ((reg) ^ (bit)) 54 | #define ISSET_BIT_INT(reg, bit) (((reg) & (bit)) != 0) 55 | 56 | #endif // BITS_H 57 | -------------------------------------------------------------------------------- /kernel/cpu/acpi.h: -------------------------------------------------------------------------------- 1 | #ifndef KERNEL_ACPI_H 2 | #define KERNEL_ACPI_H 3 | 4 | #include 5 | 6 | // Root System Description Pointer 7 | #pragma pack(push, 1) 8 | typedef struct acpi_rsdp { 9 | char signature[8]; 10 | uint8_t checksum; 11 | char oem_id[6]; 12 | uint8_t revision; 13 | uint32_t rsdt_address; 14 | } acpi_rsdp; 15 | #pragma pack(pop) 16 | 17 | // Root System Description Table 18 | #pragma pack(push, 1) 19 | typedef struct acpi_rsdt { 20 | char signature[4]; 21 | uint32_t length; 22 | uint8_t revision; 23 | uint8_t checksum; 24 | char oem_id[6]; 25 | char oem_table_id[8]; 26 | uint32_t oem_revision; 27 | uint32_t creator_id; 28 | uint32_t creator_revision; 29 | //uint32_t *entries; 30 | } acpi_rsdt; 31 | #pragma pack(pop) 32 | 33 | // Generic Address Structure 34 | #pragma pack(push, 1) 35 | typedef struct acpi_generic_address_structure { 36 | uint8_t address_space_id; 37 | uint8_t register_bit_width; 38 | uint8_t register_bit_offset; 39 | uint8_t reserved; 40 | uint64_t address; 41 | } acpi_generic_address_structure; 42 | #pragma pack(pop) 43 | 44 | enum ACPIAddressSpaceID { 45 | ACPI_ADDRESS_SPACE_SYSTEM_MEMORY = 0, 46 | ACPI_ADDRESS_SPACE_SYSTEM_IO, 47 | ACPI_ADDRESS_SPACE_PCI_CONFIGURATION_SPACE, 48 | ACPI_ADDRESS_SPACE_EMBEDDED_CONTROLLER, 49 | ACPI_ADDRESS_SPACE_SMBUS, 50 | ACPI_ADDRESS_SPACE_CMOS, 51 | ACPI_ADDRESS_SPACE_PCI_BAR_TARGET, 52 | ACPI_ADDRESS_SPACE_IPMI, 53 | ACPI_ADDRESS_SPACE_GPIO, 54 | ACPI_ADDRESS_SPACE_GENERIC_SERIAL_BUS, 55 | ACPI_ADDRESS_SPACE_PLATFORM_COMMUNICATION_CHANNEL 56 | }; 57 | 58 | // Fixed ACPI Description Table 59 | #pragma pack(push, 1) 60 | typedef struct acpi_fadt { 61 | acpi_rsdt header; 62 | uint32_t firmware_ctrl; 63 | uint32_t dsdt; 64 | 65 | uint8_t reserved; 66 | 67 | uint8_t preferred_pm_profile; 68 | uint16_t sci_int; 69 | uint32_t smi_cmd; 70 | uint8_t acpi_enable; 71 | uint8_t acpi_disable; 72 | uint8_t s4bios_req; 73 | uint8_t pstate_cnt; 74 | uint32_t pm1a_event_block; 75 | uint32_t pm1b_event_block; 76 | uint32_t pm1a_control_block; 77 | uint32_t pm1b_control_block; 78 | uint32_t pm2_control_block; 79 | uint32_t pm_timer_block; 80 | uint32_t gpe0_block; 81 | uint32_t gpe1_block; 82 | uint8_t pm1_event_length; 83 | uint8_t pm1_control_length; 84 | uint8_t pm2_control_length; 85 | uint8_t pm_timer_length; 86 | uint8_t gpe0_length; 87 | uint8_t gpe1_length; 88 | uint8_t gpe1_base; 89 | uint8_t cstate_control; 90 | uint16_t worst_c2_latency; 91 | uint16_t worst_c3_latency; 92 | uint16_t flush_size; 93 | uint16_t flush_stride; 94 | uint8_t duty_offset; 95 | uint8_t duty_width; 96 | uint8_t day_alarm; 97 | uint8_t month_alarm; 98 | uint8_t century; 99 | 100 | uint16_t boot_architecture_flags; 101 | 102 | uint8_t reserved2; 103 | uint32_t flags; 104 | 105 | acpi_generic_address_structure reset_reg; 106 | 107 | uint8_t reset_value; 108 | uint8_t reserved3[3]; 109 | } acpi_fadt; 110 | #pragma pack(pop) 111 | 112 | // Differentiated System Description Table 113 | #pragma pack(push, 1) 114 | typedef struct acpi_dsdt { 115 | acpi_rsdt header; 116 | uint8_t definition_block[0]; 117 | } acpi_dsdt; 118 | #pragma pack(pop) 119 | 120 | enum ACPIPM1AControlRegisters { 121 | ACPI_PM1A_CONTROL_SCI_EN = 1 << 0, 122 | ACPI_PM1A_CONTROL_BM_RLD = 1 << 1, 123 | ACPI_PM1A_CONTROL_GBL_RLS = 1 << 2, 124 | ACPI_PM1A_CONTROL_SLP_EN = 1 << 13 125 | }; 126 | 127 | void acpi_init(acpi_rsdp *rsdp); 128 | 129 | void acpi_shutdown(void); 130 | 131 | void acpi_reboot(void); 132 | 133 | #endif // KERNEL_ACPI_H 134 | -------------------------------------------------------------------------------- /kernel/cpu/cpuid.asm: -------------------------------------------------------------------------------- 1 | global cpuid_available 2 | 3 | section .text 4 | cpuid_available: 5 | pushfd ; Save EFLAGS 6 | pushfd ; Store EFLAGS 7 | xor dword [esp], 0x00200000 ; Invert the ID bit in stored EFLAGS 8 | popfd ; Load stored EFLAGS (with ID bit inverted) 9 | pushfd ; Store EFLAGS again (ID bit may or may not be inverted) 10 | pop eax ; eax = modified EFLAGS (ID bit may or may not be inverted) 11 | xor eax, [esp] ; eax = whichever bits were changed 12 | popfd ; Restore original EFLAGS 13 | and eax, 0x00200000 ; eax = zero if ID bit can't be changed, else non-zero 14 | shr eax, 21 ; get bit 21 15 | ret 16 | -------------------------------------------------------------------------------- /kernel/cpu/cpuid.c: -------------------------------------------------------------------------------- 1 | #include "cpuid.h" 2 | 3 | #define DEBUG 1 4 | 5 | #include 6 | #include "../debug.h" 7 | 8 | cpu_info cpuinfo; 9 | 10 | bool get_cpuid_info(void) { 11 | memset(&cpuinfo, 0, sizeof(cpu_info)); 12 | if (cpuid_available()) { 13 | // Get Vendor ID 14 | uint32_t eax, ebx, ecx, edx; 15 | asm volatile("cpuid" 16 | : "=a"(eax), "=b"(ebx), "=c"(ecx), "=d"(edx) 17 | : "a"(0)); 18 | 19 | // copy to cpu_info->vendor_id 20 | memcpy(&cpuinfo.vendor_id[0], &ebx, 4); 21 | memcpy(&cpuinfo.vendor_id[4], &edx, 4); 22 | memcpy(&cpuinfo.vendor_id[8], &ecx, 4); 23 | 24 | // Get Processor Info 25 | asm volatile("cpuid" 26 | : "=a"(eax), "=b"(ebx), "=c"(ecx), "=d"(edx) 27 | : "a"(1)); 28 | 29 | dbgprint("CPUID: eax: %x, ebx: %x, ecx: %x, edx: %x\n", eax, ebx, ecx, edx); 30 | 31 | // copy to cpu_info->ecx 32 | cpuinfo.ecx = ecx; 33 | 34 | // copy to cpu_info->edx 35 | cpuinfo.edx = edx; 36 | 37 | return true; 38 | } 39 | 40 | return false; 41 | } 42 | -------------------------------------------------------------------------------- /kernel/cpu/cpuid.h: -------------------------------------------------------------------------------- 1 | #ifndef KERNEL_CPUID_H 2 | #define KERNEL_CPUID_H 3 | 4 | #include 5 | #include 6 | 7 | typedef struct cpu_info { 8 | char vendor_id[12]; 9 | 10 | // ecx features 11 | uint32_t ecx; 12 | 13 | // edx features 14 | uint32_t edx; 15 | } cpu_info; 16 | 17 | extern cpu_info cpuinfo; 18 | 19 | enum CPUIDFeatureECX { 20 | CPUID_FEAT_ECX_SSE3 = 1UL << 0UL, 21 | CPUID_FEAT_ECX_PCLMUL = 1UL << 1UL, 22 | CPUID_FEAT_ECX_DTES64 = 1UL << 2UL, 23 | CPUID_FEAT_ECX_MONITOR = 1UL << 3UL, 24 | CPUID_FEAT_ECX_DS_CPL = 1UL << 4UL, 25 | CPUID_FEAT_ECX_VMX = 1UL << 5UL, 26 | CPUID_FEAT_ECX_SMX = 1UL << 6UL, 27 | CPUID_FEAT_ECX_EST = 1UL << 7UL, 28 | CPUID_FEAT_ECX_TM2 = 1UL << 8UL, 29 | CPUID_FEAT_ECX_SSSE3 = 1UL << 9UL, 30 | CPUID_FEAT_ECX_CID = 1UL << 10UL, 31 | CPUID_FEAT_ECX_SDBG = 1UL << 11UL, 32 | CPUID_FEAT_ECX_FMA = 1UL << 12UL, 33 | CPUID_FEAT_ECX_CX16 = 1UL << 13UL, 34 | CPUID_FEAT_ECX_XTPR = 1UL << 14UL, 35 | CPUID_FEAT_ECX_PDCM = 1UL << 15UL, 36 | 37 | CPUID_FEAT_ECX_PCID = 1UL << 17UL, 38 | CPUID_FEAT_ECX_DCA = 1UL << 18UL, 39 | CPUID_FEAT_ECX_SSE4_1 = 1UL << 19UL, 40 | CPUID_FEAT_ECX_SSE4_2 = 1UL << 20UL, 41 | CPUID_FEAT_ECX_X2APIC = 1UL << 21UL, 42 | CPUID_FEAT_ECX_MOVBE = 1UL << 22UL, 43 | CPUID_FEAT_ECX_POPCNT = 1UL << 23UL, 44 | CPUID_FEAT_ECX_TSC = 1UL << 24UL, 45 | CPUID_FEAT_ECX_AES = 1UL << 25UL, 46 | CPUID_FEAT_ECX_XSAVE = 1UL << 26UL, 47 | CPUID_FEAT_ECX_OSXSAVE = 1UL << 27UL, 48 | CPUID_FEAT_ECX_AVX = 1UL << 28UL, 49 | CPUID_FEAT_ECX_F16C = 1UL << 29UL, 50 | CPUID_FEAT_ECX_RDRAND = 1UL << 30UL, 51 | CPUID_FEAT_ECX_HYPERVISOR = 1UL << 31UL, 52 | }; 53 | 54 | enum CPUIDFeatureEDX { 55 | CPUID_FEAT_EDX_FPU = 1UL << 0UL, 56 | CPUID_FEAT_EDX_VME = 1UL << 1UL, 57 | CPUID_FEAT_EDX_DE = 1UL << 2UL, 58 | CPUID_FEAT_EDX_PSE = 1UL << 3UL, 59 | CPUID_FEAT_EDX_TSC = 1UL << 4UL, 60 | CPUID_FEAT_EDX_MSR = 1UL << 5UL, 61 | CPUID_FEAT_EDX_PAE = 1UL << 6UL, 62 | CPUID_FEAT_EDX_MCE = 1UL << 7UL, 63 | CPUID_FEAT_EDX_CX8 = 1UL << 8UL, 64 | CPUID_FEAT_EDX_APIC = 1UL << 9UL, 65 | 66 | CPUID_FEAT_EDX_SEP = 1UL << 11UL, 67 | CPUID_FEAT_EDX_MTRR = 1UL << 12UL, 68 | CPUID_FEAT_EDX_PGE = 1UL << 13UL, 69 | CPUID_FEAT_EDX_MCA = 1UL << 14UL, 70 | CPUID_FEAT_EDX_CMOV = 1UL << 15UL, 71 | CPUID_FEAT_EDX_PAT = 1UL << 16UL, 72 | CPUID_FEAT_EDX_PSE36 = 1UL << 17UL, 73 | CPUID_FEAT_EDX_PSN = 1UL << 18UL, 74 | CPUID_FEAT_EDX_CLFLUSH = 1UL << 19UL, 75 | 76 | CPUID_FEAT_EDX_DTS = 1UL << 21UL, 77 | CPUID_FEAT_EDX_ACPI = 1UL << 22UL, 78 | CPUID_FEAT_EDX_MMX = 1UL << 23UL, 79 | CPUID_FEAT_EDX_FXSR = 1UL << 24UL, 80 | CPUID_FEAT_EDX_SSE = 1UL << 25UL, 81 | CPUID_FEAT_EDX_SSE2 = 1UL << 26UL, 82 | CPUID_FEAT_EDX_SS = 1UL << 27UL, 83 | CPUID_FEAT_EDX_HTT = 1UL << 28UL, 84 | CPUID_FEAT_EDX_TM = 1UL << 29UL, 85 | CPUID_FEAT_EDX_IA64 = 1UL << 30UL, 86 | CPUID_FEAT_EDX_PBE = 1UL << 31UL, 87 | }; 88 | 89 | extern bool cpuid_available(void); 90 | 91 | bool get_cpuid_info(void); 92 | 93 | #endif // KERNEL_CPUID_H 94 | -------------------------------------------------------------------------------- /kernel/cpu/fpu.asm: -------------------------------------------------------------------------------- 1 | global fpu_available 2 | 3 | section .text 4 | fpu_available: 5 | fninit 6 | fnstsw [.testword] 7 | cmp word [.testword], 0 8 | jne .nofpu 9 | fnstcw [.testword] 10 | mov ax, [.testword] 11 | and ax, 0x103F 12 | cmp ax, 0x003f 13 | jne .nofpu 14 | 15 | mov eax, 1 16 | ret 17 | 18 | .nofpu: 19 | mov eax, 0 20 | ret 21 | 22 | .testword dw 0x55AA 23 | -------------------------------------------------------------------------------- /kernel/cpu/fpu.c: -------------------------------------------------------------------------------- 1 | #include "fpu.h" 2 | 3 | #define DEBUG_SERIAL 0 4 | #define DEBUG 1 5 | 6 | #include 7 | #include 8 | #include 9 | #include "../bits.h" 10 | #include "../debug.h" 11 | 12 | void fpu_load_control_word(const uint16_t control) { 13 | asm volatile("fldcw %0;" 14 | : 15 | : "m"(control)); 16 | } 17 | 18 | void fpu_init(void) { 19 | uint32_t cr0; 20 | asm volatile("mov %%cr0, %0;" 21 | : "=r"(cr0)); 22 | if (fpu_available()) { 23 | dbgprint("FPU available\n"); 24 | cr0 = DISABLE_BIT_INT(cr0, CR0_EM); 25 | cr0 = DISABLE_BIT_INT(cr0, CR0_TS); 26 | 27 | asm volatile("mov %0, %%cr0;" 28 | : 29 | : "r"(cr0)); 30 | 31 | fpu_load_control_word(FPU_CTRL_NO_EXCEPTIONS); 32 | 33 | sse_init(); 34 | } else { 35 | dbgprint("FPU not available\n"); 36 | cr0 = ENABLE_BIT_INT(cr0, CR0_EM); 37 | 38 | asm volatile("mov %0, %%cr0;" 39 | : 40 | : "r"(cr0)); 41 | } 42 | } 43 | 44 | void sse_init(void) { 45 | uint32_t cr0; 46 | uint32_t cr4; 47 | asm volatile("mov %%cr0, %0;" 48 | : "=r"(cr0)); 49 | asm volatile("mov %%cr4, %0;" 50 | : "=r"(cr4)); 51 | 52 | if (ISSET_BIT_INT(cpuinfo.edx, CPUID_FEAT_EDX_SSE)) { 53 | dbgprint("SSE available\n"); 54 | cr0 = DISABLE_BIT_INT(cr0, CR0_EM); 55 | cr0 = ENABLE_BIT_INT(cr0, CR0_MP); 56 | cr4 = ENABLE_BIT_INT(cr4, CR4_OSFXSR); 57 | cr4 = ENABLE_BIT_INT(cr4, CR4_OSXMMEXCPT); 58 | asm volatile("mov %0, %%cr0;" 59 | : 60 | : "r"(cr0)); 61 | asm volatile("mov %0, %%cr4;" 62 | : 63 | : "r"(cr4)); 64 | 65 | double a = 1.0; 66 | double b = 2.0; 67 | dbgprint("Testing SSE: %lf\n", a - b); 68 | } else { 69 | dbgprint("SSE not available\n"); 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /kernel/cpu/fpu.h: -------------------------------------------------------------------------------- 1 | #ifndef KERNEL_FPU_H 2 | #define KERNEL_FPU_H 3 | 4 | #include 5 | #include 6 | #include "cpuid.h" 7 | 8 | enum FPUControlWord { 9 | FPU_CTRL_NO_EXCEPTIONS = 0x37F, 10 | FPU_CTRL_INVALID_OP = 0x37E, 11 | FPU_CTRL_DIV_ZERO = 0x37A, 12 | }; 13 | 14 | enum CR0 { 15 | CR0_MP = 1UL << 1UL, 16 | CR0_EM = 1UL << 2UL, 17 | CR0_TS = 1UL << 3UL, 18 | CR0_ET = 1UL << 4UL, 19 | CR0_NE = 1UL << 5UL, 20 | CR0_WP = 1UL << 16UL, 21 | CR0_AM = 1UL << 18UL, 22 | CR0_NW = 1UL << 29UL, 23 | CR0_CD = 1UL << 30UL, 24 | CR0_PG = 1UL << 31UL 25 | }; 26 | 27 | enum CR4 { 28 | CR4_VME = 1UL << 0UL, 29 | CR4_PVI = 1UL << 1UL, 30 | CR4_TSD = 1UL << 2UL, 31 | CR4_DE = 1UL << 3UL, 32 | CR4_PSE = 1UL << 4UL, 33 | CR4_PAE = 1UL << 5UL, 34 | CR4_MCE = 1UL << 6UL, 35 | CR4_PGE = 1UL << 7UL, 36 | CR4_PCE = 1UL << 8UL, 37 | CR4_OSFXSR = 1UL << 9UL, 38 | CR4_OSXMMEXCPT = 1UL << 10UL, 39 | CR4_UMIP = 1UL << 11UL, 40 | CR4_VMXE = 1UL << 13UL, 41 | CR4_SMXE = 1UL << 14UL, 42 | CR4_FSGSBASE = 1UL << 16UL, 43 | CR4_PCIDE = 1UL << 17UL, 44 | CR4_OSXSAVE = 1UL << 18UL, 45 | CR4_SMEP = 1UL << 20UL, 46 | CR4_SMAP = 1UL << 21UL 47 | }; 48 | 49 | extern bool fpu_available(void); 50 | 51 | void fpu_load_control_word(const uint16_t control); 52 | 53 | void fpu_init(void); 54 | 55 | void sse_init(void); 56 | 57 | #endif // KERNEL_FPU_H 58 | -------------------------------------------------------------------------------- /kernel/cpu/gdt.asm: -------------------------------------------------------------------------------- 1 | global gdt_flush 2 | 3 | section .text 4 | gdt_flush: 5 | mov eax, [esp + 4] 6 | lgdt [eax] 7 | 8 | mov ax, 0x10 9 | mov ds, ax 10 | mov es, ax 11 | mov fs, ax 12 | mov gs, ax 13 | mov ss, ax 14 | jmp 0x08:flush2 15 | 16 | flush2: 17 | ret 18 | -------------------------------------------------------------------------------- /kernel/cpu/gdt.c: -------------------------------------------------------------------------------- 1 | #include "gdt.h" 2 | 3 | #include 4 | #include "tss.h" 5 | 6 | static gdt_entry gdt[6]; 7 | 8 | void gdt_set_gate(int num, uint32_t base, uint32_t limit, uint8_t access, uint8_t gran) { 9 | gdt[num].entry.base_low = (base & 0xFFFF); 10 | gdt[num].entry.base_middle = (base >> 16) & 0xFF; 11 | gdt[num].entry.base_high = (base >> 24) & 0xFF; 12 | 13 | gdt[num].entry.limit_low = (limit & 0xFFFF); 14 | gdt[num].entry.granularity = ((limit >> 16) & 0x0F); 15 | 16 | gdt[num].entry.granularity |= (gran & 0xF0); 17 | gdt[num].entry.access = access; 18 | } 19 | 20 | void gdt_init(void) { 21 | gdt_ptr gp; 22 | gp.base = (uint32_t)gdt; 23 | gp.limit = sizeof(gdt) - 1; 24 | 25 | // NS 26 | gdt_set_gate(0, 0, 0, 0, 0); 27 | // CS 28 | gdt_set_gate(1, 0, 0xFFFFFFFF, GDT_ACCESS_PRESENT | GDT_ACCESS_RING0 | GDT_ACCESS_SEGMENT | GDT_ACCESS_EXECUTABLE | GDT_ACCESS_READ_WRITE, 0xCF); 29 | // DS 30 | gdt_set_gate(2, 0, 0xFFFFFFFF, GDT_ACCESS_PRESENT | GDT_ACCESS_RING0 | GDT_ACCESS_SEGMENT | GDT_ACCESS_DATA | GDT_ACCESS_READ_WRITE, 0xCF); 31 | // Ring3 CS 32 | gdt_set_gate(3, 0, 0xFFFFFFFF, GDT_ACCESS_PRESENT | GDT_ACCESS_RING3 | GDT_ACCESS_SEGMENT | GDT_ACCESS_EXECUTABLE | GDT_ACCESS_READ_WRITE, 0xCF); 33 | // Ring3 DS 34 | gdt_set_gate(4, 0, 0xFFFFFFFF, GDT_ACCESS_PRESENT | GDT_ACCESS_RING3 | GDT_ACCESS_SEGMENT | GDT_ACCESS_DATA | GDT_ACCESS_READ_WRITE, 0xCF); 35 | 36 | install_tss(5, 0x10, 0x0); 37 | 38 | //gdt_set_gate(6, 0, 0xFFFFFFFF, 0x92, 0x0); 39 | //gdt_set_gate(7, 0, 0xFFFFFFFF, 0x9A, 0x0); 40 | 41 | gdt_flush(&gp); 42 | tss_flush(); 43 | } 44 | -------------------------------------------------------------------------------- /kernel/cpu/gdt.h: -------------------------------------------------------------------------------- 1 | #ifndef KERNEL_GDT_H 2 | #define KERNEL_GDT_H 3 | 4 | #include 5 | 6 | typedef union gdt_entry { 7 | #pragma pack(push, 1) 8 | struct { 9 | uint16_t limit_low; 10 | uint16_t base_low; 11 | uint8_t base_middle; 12 | uint8_t access; 13 | uint8_t granularity; 14 | uint8_t base_high; 15 | } entry; 16 | #pragma pack(pop) 17 | 18 | #pragma pack(push, 1) 19 | struct { 20 | uint32_t limit_low : 16; 21 | uint32_t base_low : 24; 22 | uint8_t accessed : 1; 23 | uint8_t read_write : 1; // readable for code, writable for data 24 | uint8_t conforming_expand_down : 1; // conforming for code, expand down for data 25 | uint8_t code : 1; // 1 for code, 0 for data 26 | uint8_t code_data_segment : 1; // should be 1 for everything but TSS and LDT 27 | uint8_t DPL : 2; // privilege level 28 | uint8_t present : 1; 29 | uint8_t limit_high : 4; 30 | uint8_t available : 1; // only used in software; has no effect on hardware 31 | uint8_t long_mode : 1; 32 | uint8_t big : 1; // 32-bit opcodes for code, uint32_t stack for data 33 | uint8_t granularity : 1; // 1 to use 4k page addressing, 0 for byte addressing 34 | uint8_t base_high : 8; 35 | } bits; 36 | #pragma pack(pop) 37 | } gdt_entry; 38 | 39 | #pragma pack(push, 1) 40 | typedef struct gdt_ptr { 41 | uint16_t limit; 42 | uint32_t base; 43 | } gdt_ptr; 44 | #pragma pack(pop) 45 | 46 | enum GDTAccess { 47 | GDT_ACCESS_PRESENT = 0x80, 48 | GDT_ACCESS_RING0 = 0x00, 49 | GDT_ACCESS_RING1 = 0x20, 50 | GDT_ACCESS_RING2 = 0x40, 51 | GDT_ACCESS_RING3 = 0x60, 52 | GDT_ACCESS_SEGMENT = 0x10, 53 | GDT_ACCESS_TSS = 0x00, 54 | GDT_ACCESS_EXECUTABLE = 0x08, 55 | GDT_ACCESS_DATA = 0x00, 56 | GDT_ACCESS_DIRECTION_CONFORMING = 0x04, 57 | GDT_ACCESS_READ_WRITE = 0x02, 58 | GDT_ACCESS_READ_ONLY = 0x00, 59 | GDT_ACCESS_ACCESSED = 0x01 60 | }; 61 | 62 | extern void gdt_flush(gdt_ptr *ptr); 63 | 64 | void gdt_set_gate(int num, uint32_t base, uint32_t limit, uint8_t access, uint8_t gran); 65 | 66 | void gdt_init(void); 67 | 68 | #endif //KERNEL_GDT_H 69 | -------------------------------------------------------------------------------- /kernel/cpu/idt.asm: -------------------------------------------------------------------------------- 1 | global load_idt 2 | 3 | section .text 4 | load_idt: 5 | mov eax, [esp + 4] 6 | lidt [eax] 7 | ret 8 | -------------------------------------------------------------------------------- /kernel/cpu/idt.c: -------------------------------------------------------------------------------- 1 | #include "idt.h" 2 | 3 | #include "../bits.h" 4 | #include 5 | 6 | idt_entry idt[256]; 7 | 8 | void idt_set_gate(int num, uint32_t base, uint16_t sel, uint8_t flags) { 9 | idt[num].base_low = base & 0xFFFF; 10 | idt[num].base_high = (base >> 16) & 0xFFFF; 11 | idt[num].selector = sel; 12 | idt[num].zero = 0; 13 | idt[num].flags = flags | 0x60; 14 | } 15 | 16 | void idt_init(void) { 17 | idt_ptr ip; 18 | ip.base = (uint32_t)idt; 19 | ip.limit = sizeof(idt) - 1; 20 | 21 | memset(idt, 0, sizeof(idt)); 22 | 23 | load_idt(&ip); 24 | } 25 | -------------------------------------------------------------------------------- /kernel/cpu/idt.h: -------------------------------------------------------------------------------- 1 | #ifndef KERNEL_IDT_H 2 | #define KERNEL_IDT_H 3 | 4 | #include 5 | 6 | #pragma pack(push, 1) 7 | typedef struct idt_entry { 8 | uint16_t base_low; 9 | uint16_t selector; 10 | uint8_t zero; 11 | uint8_t flags; 12 | uint16_t base_high; 13 | } idt_entry; 14 | #pragma pack(pop) 15 | 16 | #pragma pack(push, 1) 17 | typedef struct idt_ptr { 18 | uint16_t limit; 19 | uint32_t base; 20 | } idt_ptr; 21 | #pragma pack(pop) 22 | 23 | extern void load_idt(idt_ptr *ptr); 24 | 25 | void idt_set_gate(int num, uint32_t base, uint16_t sel, uint8_t flags); 26 | 27 | void idt_init(void); 28 | 29 | #endif //KERNEL_IDT_H 30 | -------------------------------------------------------------------------------- /kernel/cpu/interrupts.c: -------------------------------------------------------------------------------- 1 | #include "interrupts.h" 2 | 3 | static bool was_interrupts_enabled = false; 4 | 5 | bool interrupts_was_enabled(void) { 6 | return was_interrupts_enabled; 7 | } 8 | 9 | void interrupts_enable(void) { 10 | asm volatile("sti"); 11 | was_interrupts_enabled = true; 12 | } 13 | 14 | void interrupts_reenable(void) { 15 | if (was_interrupts_enabled) { 16 | asm volatile("sti"); 17 | } 18 | } 19 | 20 | void interrupts_disable(void) { 21 | asm volatile("cli"); 22 | } 23 | -------------------------------------------------------------------------------- /kernel/cpu/interrupts.h: -------------------------------------------------------------------------------- 1 | #ifndef INTERRUPT_H 2 | #define INTERRUPT_H 3 | 4 | #include 5 | 6 | bool interrupts_was_enabled(void); 7 | 8 | void interrupts_enable(void); 9 | 10 | void interrupts_reenable(void); 11 | 12 | void interrupts_disable(void); 13 | 14 | #endif // INTERRUPT_H 15 | -------------------------------------------------------------------------------- /kernel/cpu/irq.asm: -------------------------------------------------------------------------------- 1 | global irq0 2 | global irq1 3 | global irq2 4 | global irq3 5 | global irq4 6 | global irq5 7 | global irq6 8 | global irq7 9 | global irq8 10 | global irq9 11 | global irq10 12 | global irq11 13 | global irq12 14 | global irq13 15 | global irq14 16 | global irq15 17 | 18 | section .text 19 | 20 | irq0: 21 | cli 22 | push byte 0 23 | push byte 32 24 | jmp irq_common_stub 25 | 26 | irq1: 27 | cli 28 | push byte 0 29 | push byte 33 30 | jmp irq_common_stub 31 | 32 | irq2: 33 | cli 34 | push byte 0 35 | push byte 34 36 | jmp irq_common_stub 37 | 38 | irq3: 39 | cli 40 | push byte 0 41 | push byte 35 42 | jmp irq_common_stub 43 | 44 | irq4: 45 | cli 46 | push byte 0 47 | push byte 36 48 | jmp irq_common_stub 49 | 50 | irq5: 51 | cli 52 | push byte 0 53 | push byte 37 54 | jmp irq_common_stub 55 | 56 | irq6: 57 | cli 58 | push byte 0 59 | push byte 38 60 | jmp irq_common_stub 61 | 62 | irq7: 63 | cli 64 | push byte 0 65 | push byte 39 66 | jmp irq_common_stub 67 | 68 | irq8: 69 | cli 70 | push byte 0 71 | push byte 40 72 | jmp irq_common_stub 73 | 74 | irq9: 75 | cli 76 | push byte 0 77 | push byte 41 78 | jmp irq_common_stub 79 | 80 | irq10: 81 | cli 82 | push byte 0 83 | push byte 42 84 | jmp irq_common_stub 85 | 86 | irq11: 87 | cli 88 | push byte 0 89 | push byte 43 90 | jmp irq_common_stub 91 | 92 | irq12: 93 | cli 94 | push byte 0 95 | push byte 44 96 | jmp irq_common_stub 97 | 98 | irq13: 99 | cli 100 | push byte 0 101 | push byte 45 102 | jmp irq_common_stub 103 | 104 | irq14: 105 | cli 106 | push byte 0 107 | push byte 46 108 | jmp irq_common_stub 109 | 110 | irq15: 111 | cli 112 | push byte 0 113 | push byte 47 114 | jmp irq_common_stub 115 | 116 | irq_common_stub: 117 | extern irq_handler 118 | extern mmu_load_kernel_pdt 119 | extern process_unload 120 | extern process_reload 121 | extern process_switch 122 | 123 | pushad 124 | push ds 125 | push es 126 | push fs 127 | push gs 128 | 129 | mov eax, cr0 130 | push eax 131 | mov eax, cr2 132 | push eax 133 | mov eax, cr3 134 | push eax 135 | mov eax, cr4 136 | push eax 137 | 138 | mov ax, 0x10 139 | mov ds, ax 140 | mov es, ax 141 | mov fs, ax 142 | mov gs, ax 143 | 144 | push esp 145 | ;call mmu_load_kernel_pdt 146 | call process_unload; save current process state 147 | call irq_handler 148 | 149 | call process_reload; reload current process state 150 | 151 | ;push 0; PID 152 | ;call process_switch 153 | ;add esp, 4 154 | 155 | add esp, 4 156 | 157 | add esp, 16 158 | 159 | pop gs 160 | pop fs 161 | pop es 162 | pop ds 163 | popad 164 | add esp, 8 165 | 166 | iret 167 | -------------------------------------------------------------------------------- /kernel/cpu/irq.c: -------------------------------------------------------------------------------- 1 | #include "irq.h" 2 | 3 | #include "gdt.h" 4 | #include "idt.h" 5 | #include "pic.h" 6 | #include "../bits.h" 7 | 8 | void (*irq_routines[16])(registers *, uint32_t) = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; 9 | 10 | void irq_install_handler(int irq, void (*handler)(registers *, uint32_t)) { 11 | irq_routines[irq] = handler; 12 | } 13 | 14 | void irq_uninstall_handler(int irq) { 15 | irq_routines[irq] = 0; 16 | } 17 | 18 | void irq_init(void) { 19 | idt_set_gate(32, (uint32_t)irq0, 0x08, 0x8E); 20 | idt_set_gate(33, (uint32_t)irq1, 0x08, 0x8E); 21 | idt_set_gate(34, (uint32_t)irq2, 0x08, 0x8E); 22 | idt_set_gate(35, (uint32_t)irq3, 0x08, 0x8E); 23 | idt_set_gate(36, (uint32_t)irq4, 0x08, 0x8E); 24 | idt_set_gate(37, (uint32_t)irq5, 0x08, 0x8E); 25 | idt_set_gate(38, (uint32_t)irq6, 0x08, 0x8E); 26 | idt_set_gate(39, (uint32_t)irq7, 0x08, 0x8E); 27 | idt_set_gate(40, (uint32_t)irq8, 0x08, 0x8E); 28 | idt_set_gate(41, (uint32_t)irq9, 0x08, 0x8E); 29 | idt_set_gate(42, (uint32_t)irq10, 0x08, 0x8E); 30 | idt_set_gate(43, (uint32_t)irq11, 0x08, 0x8E); 31 | idt_set_gate(44, (uint32_t)irq12, 0x08, 0x8E); 32 | idt_set_gate(45, (uint32_t)irq13, 0x08, 0x8E); 33 | idt_set_gate(46, (uint32_t)irq14, 0x08, 0x8E); 34 | idt_set_gate(47, (uint32_t)irq15, 0x08, 0x8E); 35 | } 36 | 37 | void irq_handler(registers *r) { 38 | if (irq_routines[r->int_no - 32]) { 39 | irq_routines[r->int_no - 32](r, r->int_no - 32); 40 | } 41 | 42 | pic_send_eoi(r->int_no - 32); 43 | } 44 | 45 | void irq_mask(uint8_t irq) { 46 | uint16_t port; 47 | uint8_t value; 48 | 49 | if (irq < 8) { 50 | port = PIC1; 51 | } else { 52 | port = PIC2; 53 | irq -= 8; 54 | } 55 | 56 | value = inb(port) | (1 << irq); 57 | outb(port, value); 58 | } 59 | 60 | void irq_unmask(uint8_t irq) { 61 | uint16_t port; 62 | uint8_t value; 63 | 64 | if (irq < 8) { 65 | port = PIC1; 66 | } else { 67 | port = PIC2; 68 | irq -= 8; 69 | } 70 | 71 | value = inb(port) & ~(1 << irq); 72 | outb(port, value); 73 | } 74 | -------------------------------------------------------------------------------- /kernel/cpu/irq.h: -------------------------------------------------------------------------------- 1 | #ifndef KERNEL_IRQ_H 2 | #define KERNEL_IRQ_H 3 | 4 | #include 5 | #include "system.h" 6 | 7 | enum IRQ { 8 | IRQ_PIT = 0, 9 | IRQ_KEYBOARD, 10 | IRQ_CASCADE, 11 | IRQ_COM2, 12 | IRQ_COM1, 13 | IRQ_LPT2, 14 | IRQ_FLOPPY, 15 | IRQ_LPT1, 16 | IRQ_CMOS, 17 | IRQ_FREE_0, 18 | IRQ_FREE_1, 19 | IRQ_FREE_2, 20 | IRQ_PS2_MOUSE, 21 | IRQ_FPU, 22 | IRQ_ATA_PRIMARY, 23 | IRQ_ATA_SECONDARY 24 | }; 25 | 26 | extern void irq0(void); 27 | 28 | extern void irq1(void); 29 | 30 | extern void irq2(void); 31 | 32 | extern void irq3(void); 33 | 34 | extern void irq4(void); 35 | 36 | extern void irq5(void); 37 | 38 | extern void irq6(void); 39 | 40 | extern void irq7(void); 41 | 42 | extern void irq8(void); 43 | 44 | extern void irq9(void); 45 | 46 | extern void irq10(void); 47 | 48 | extern void irq11(void); 49 | 50 | extern void irq12(void); 51 | 52 | extern void irq13(void); 53 | 54 | extern void irq14(void); 55 | 56 | extern void irq15(void); 57 | 58 | void irq_install_handler(int irq, void (*handler)(registers *, uint32_t)); 59 | 60 | void irq_uninstall_handler(int irq); 61 | 62 | void irq_init(void); 63 | 64 | void irq_handler(registers *r); 65 | 66 | void irq_mask(uint8_t irq); 67 | 68 | void irq_unmask(uint8_t irq); 69 | 70 | #endif //KERNEL_IRQ_H 71 | -------------------------------------------------------------------------------- /kernel/cpu/isr.h: -------------------------------------------------------------------------------- 1 | #ifndef KERNEL_ISR_H 2 | #define KERNEL_ISR_H 3 | 4 | #include "system.h" 5 | 6 | extern void isr0(void); 7 | 8 | extern void isr1(void); 9 | 10 | extern void isr2(void); 11 | 12 | extern void isr3(void); 13 | 14 | extern void isr4(void); 15 | 16 | extern void isr5(void); 17 | 18 | extern void isr6(void); 19 | 20 | extern void isr7(void); 21 | 22 | extern void isr8(void); 23 | 24 | extern void isr9(void); 25 | 26 | extern void isr10(void); 27 | 28 | extern void isr11(void); 29 | 30 | extern void isr12(void); 31 | 32 | extern void isr13(void); 33 | 34 | extern void isr14(void); 35 | 36 | extern void isr15(void); 37 | 38 | extern void isr16(void); 39 | 40 | extern void isr17(void); 41 | 42 | extern void isr18(void); 43 | 44 | extern void isr19(void); 45 | 46 | extern void isr20(void); 47 | 48 | extern void isr21(void); 49 | 50 | extern void isr22(void); 51 | 52 | extern void isr23(void); 53 | 54 | extern void isr24(void); 55 | 56 | extern void isr25(void); 57 | 58 | extern void isr26(void); 59 | 60 | extern void isr27(void); 61 | 62 | extern void isr28(void); 63 | 64 | extern void isr29(void); 65 | 66 | extern void isr30(void); 67 | 68 | extern void isr31(void); 69 | 70 | extern void isr127(void); 71 | 72 | void isr_install_handler(int isr, void (*handler)(registers *, uint32_t)); 73 | 74 | void isr_uninstall_handler(int isr); 75 | 76 | void isr_init(void); 77 | 78 | void isr_fault_handler(registers *r); 79 | 80 | #endif //KERNEL_ISR_H 81 | -------------------------------------------------------------------------------- /kernel/cpu/mmu.asm: -------------------------------------------------------------------------------- 1 | global mmu_enable_paging 2 | 3 | section .text 4 | mmu_enable_paging: 5 | mov eax, [esp + 4] 6 | mov cr3, eax 7 | 8 | mov eax, cr0 9 | or eax, 0x80000000 10 | mov cr0, eax 11 | ret 12 | -------------------------------------------------------------------------------- /kernel/cpu/mmu.h: -------------------------------------------------------------------------------- 1 | #ifndef KERNEL_MMU_H 2 | #define KERNEL_MMU_H 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #define MMU_MAX_PAGES 1024 * 1024 9 | 10 | #pragma pack(push, 1) 11 | typedef struct page_directory { 12 | bool present: 1; 13 | bool rw: 1; 14 | bool user: 1; 15 | bool write_through: 1; 16 | bool cache_disabled: 1; 17 | bool accessed: 1; 18 | bool dirty: 1; 19 | bool page_size: 1; 20 | uint8_t available: 4; 21 | uint32_t address: 20; // -> page_table 22 | } page_directory; 23 | #pragma pack(pop) 24 | 25 | #pragma pack(push, 1) 26 | typedef struct page { 27 | bool present: 1; 28 | bool rw: 1; 29 | bool user: 1; 30 | bool write_through: 1; 31 | bool cache_disabled: 1; 32 | bool accessed: 1; 33 | bool dirty: 1; 34 | bool pat: 1; 35 | bool global: 1; 36 | uint8_t available: 3; 37 | uint32_t address: 20; // -> physical address 38 | } page; 39 | #pragma pack(pop) 40 | 41 | #pragma pack(push, 1) 42 | typedef struct page_directory_table { 43 | page_directory entries[1024]; 44 | } page_directory_table; 45 | #pragma pack(pop) 46 | 47 | #pragma pack(push, 1) 48 | typedef struct page_table { 49 | page entries[1024]; 50 | } page_table; 51 | #pragma pack(pop) 52 | 53 | extern page_directory_table *current_pdt; 54 | 55 | extern void mmu_enable_paging(page_directory_table *pdt); 56 | 57 | void mmu_load_pdt(page_directory_table *pdt); 58 | 59 | uintptr_t mmu_get_physical_address(uintptr_t virtual_addr); 60 | 61 | uintptr_t mmu_get_physical_address_pdt(uintptr_t virtual_addr, page_directory_table *pdt); 62 | 63 | page_directory_table *mmu_new_page_directory(void); 64 | 65 | void mmu_init(uintptr_t kernel_start_real_addr, uintptr_t kernel_end_real_addr, uintptr_t kernel_start_addr, uintptr_t kernel_end_addr); 66 | 67 | bool mmu_is_mapped(page_directory_table *pdt, uintptr_t virt_addr); 68 | 69 | void mmu_map_pages(page_directory_table *pdt, uintptr_t real_addr, uintptr_t virt_addr, size_t len, bool rw, bool user, bool executable); 70 | 71 | void mmu_unmap_pages(page_directory_table *pdt, uintptr_t virt_addr, size_t len); 72 | 73 | void *mmu_alloc_pages(size_t pages); 74 | 75 | void mmu_free_pages(page_directory_table *pdt, void *addr, size_t pages); 76 | 77 | void mmu_copy_kernel_pages(page_directory_table *pdt); 78 | 79 | page_directory_table *mmu_clone_pdt(page_directory_table *pdt); 80 | 81 | void mmu_load_kernel_pdt(void); 82 | 83 | #endif // KERNEL_MMU_H 84 | -------------------------------------------------------------------------------- /kernel/cpu/panic.h: -------------------------------------------------------------------------------- 1 | #ifndef KERNEL_PANIC_H 2 | #define KERNEL_PANIC_H 3 | 4 | #include 5 | #include "system.h" 6 | 7 | #define panic(msg, ...) _panic(__FILE__, __LINE__, msg, ##__VA_ARGS__) 8 | 9 | void _panic(const char *file, const int line, const char *msg, ...); 10 | 11 | void panic_handler(registers *r, const char *msg, ...); 12 | 13 | #endif // KERNEL_PANIC_H 14 | -------------------------------------------------------------------------------- /kernel/cpu/pic.c: -------------------------------------------------------------------------------- 1 | #include "pic.h" 2 | 3 | #define DEBUG 1 4 | 5 | #include "../bits.h" 6 | #include "../debug.h" 7 | 8 | static inline uint8_t pic_read(enum PIC pic, enum PICRegister reg) { 9 | return inb(pic + reg); 10 | } 11 | 12 | static inline void pic_write(enum PIC pic, enum PICRegister reg, uint8_t data) { 13 | outb(pic + reg, data); 14 | } 15 | 16 | void pic_send_eoi(unsigned char irq) { 17 | if (irq >= 8) { 18 | pic_write(PIC2, PIC_COMMAND, 0x20); 19 | } 20 | 21 | pic_write(PIC1, PIC_COMMAND, 0x20); 22 | } 23 | 24 | void pic_remap(uint8_t offset1, uint8_t offset2) { 25 | //uint8_t a1 = pic_read(PIC1, PIC_DATA); 26 | //uint8_t a2 = pic_read(PIC2, PIC_DATA); 27 | uint8_t a1 = 0; 28 | uint8_t a2 = 0; 29 | 30 | pic_write(PIC1, PIC_COMMAND, ICW1_INIT | ICW1_ICW4); 31 | io_wait(); 32 | pic_write(PIC2, PIC_COMMAND, ICW1_INIT | ICW1_ICW4); 33 | io_wait(); 34 | pic_write(PIC1, PIC_DATA, offset1); 35 | io_wait(); 36 | pic_write(PIC2, PIC_DATA, offset2); 37 | io_wait(); 38 | pic_write(PIC1, PIC_DATA, 4); 39 | io_wait(); 40 | pic_write(PIC2, PIC_DATA, 2); 41 | io_wait(); 42 | 43 | pic_write(PIC1, PIC_DATA, ICW4_8086); 44 | io_wait(); 45 | pic_write(PIC2, PIC_DATA, ICW4_8086); 46 | io_wait(); 47 | 48 | pic_write(PIC1, PIC_DATA, a1); 49 | pic_write(PIC2, PIC_DATA, a2); 50 | } 51 | -------------------------------------------------------------------------------- /kernel/cpu/pic.h: -------------------------------------------------------------------------------- 1 | #ifndef KERNEL_PIC_H 2 | #define KERNEL_PIC_H 3 | 4 | #include 5 | 6 | enum PIC { 7 | PIC1 = 0x20, 8 | PIC2 = 0xA0, 9 | }; 10 | 11 | enum PICRegister { 12 | PIC_COMMAND = 0x00, 13 | PIC_DATA = 0x01, 14 | }; 15 | 16 | enum ICW1 { 17 | ICW1_ICW4 = 0x01, 18 | ICW1_SINGLE = 0x02, 19 | ICW1_INTERVAL4 = 0x04, 20 | ICW1_LEVEL = 0x08, 21 | ICW1_INIT = 0x10, 22 | }; 23 | 24 | enum ICW4 { 25 | ICW4_8086 = 0x01, 26 | ICW4_AUTO = 0x02, 27 | ICW4_BUF_SLAVE = 0x08, 28 | ICW4_BUF_MASTER = 0x0C, 29 | ICW4_SFNM = 0x10, 30 | }; 31 | 32 | void pic_send_eoi(unsigned char irq); 33 | 34 | void pic_remap(uint8_t offset1, uint8_t offset2); 35 | 36 | #endif //KERNEL_PIC_H 37 | -------------------------------------------------------------------------------- /kernel/cpu/power.c: -------------------------------------------------------------------------------- 1 | #include "power.h" 2 | 3 | #define DEBUG 1 4 | #define DEBUG_SERIAL 1 5 | 6 | #include "acpi.h" 7 | #include "interrupts.h" 8 | #include "../bits.h" 9 | #include "../debug.h" 10 | #include "../rootfs.h" 11 | #include "../drivers/keyboard.h" 12 | #include "../drivers/screen.h" 13 | 14 | static void before_shutdown(void) { 15 | keyboard_clear_buffer(); 16 | 17 | screen_setcolor(COLOR_BLACK << 4 | COLOR_GRAY); 18 | screen_clear(); 19 | 20 | if (rootfs_io.device != -2) { 21 | rootfs_io.stop(&rootfs_io); 22 | } 23 | } 24 | 25 | void power_shutdown(void) { 26 | before_shutdown(); 27 | 28 | acpi_shutdown(); 29 | dbgprint("ACPI shutdown failed!\n"); 30 | 31 | interrupts_disable(); 32 | 33 | outw(0x604, 0x2000); // QEMU 34 | outw(0xB004, 0x0 | 0x2000); // Bochs 35 | outw(0x4004, 0x3400); // VirtualBox 36 | outw(0x600, 0x34); // VMware 37 | 38 | while (true) { 39 | asm volatile("hlt"); 40 | } 41 | } 42 | 43 | void power_reboot(void) { 44 | before_shutdown(); 45 | 46 | acpi_reboot(); 47 | dbgprint("ACPI reboot failed!\n"); 48 | 49 | interrupts_disable(); 50 | 51 | keyboard_clear_buffer(); 52 | outb(KB_CTRL_REGISTER, KB_RESET); 53 | 54 | while (true) { 55 | asm volatile("hlt"); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /kernel/cpu/power.h: -------------------------------------------------------------------------------- 1 | #ifndef POWER_H 2 | #define POWER_H 3 | 4 | void power_shutdown(void); 5 | 6 | void power_reboot(void); 7 | 8 | #endif // POWER_H 9 | -------------------------------------------------------------------------------- /kernel/cpu/syscall.asm: -------------------------------------------------------------------------------- 1 | global syscall_handler 2 | 3 | section .text 4 | syscall_handler: 5 | extern run_syscall 6 | extern __syscall_ret 7 | extern mmu_load_kernel_pdt 8 | extern process_unload 9 | extern process_reload 10 | extern process_switch 11 | 12 | cli 13 | push byte 1 14 | push byte 0 15 | 16 | pushad 17 | push ds 18 | push es 19 | push fs 20 | push gs 21 | 22 | mov eax, cr0 23 | push eax 24 | mov eax, cr2 25 | push eax 26 | mov eax, cr3 27 | push eax 28 | mov eax, cr4 29 | push eax 30 | 31 | mov ax, 0x10 32 | mov ds, ax 33 | mov es, ax 34 | mov fs, ax 35 | mov gs, ax 36 | 37 | push esp 38 | ;call mmu_load_kernel_pdt 39 | call process_unload; save current process state 40 | call run_syscall 41 | 42 | mov [__syscall_ret], eax 43 | 44 | call process_reload; reload new process state 45 | 46 | ;push 0; PID 47 | ;call process_switch 48 | ;add esp, 4 49 | 50 | add esp, 4 51 | 52 | add esp, 16 53 | 54 | pop gs 55 | pop fs 56 | pop es 57 | pop ds 58 | popad 59 | 60 | add esp, 8 61 | 62 | mov eax, [__syscall_ret] 63 | 64 | iret 65 | -------------------------------------------------------------------------------- /kernel/cpu/syscall.h: -------------------------------------------------------------------------------- 1 | #ifndef KERNEL_SYSCALL_H 2 | #define KERNEL_SYSCALL_H 3 | 4 | extern void syscall_handler(void); 5 | 6 | void syscall_init(void); 7 | 8 | #endif //KERNEL_SYSCALL_H 9 | -------------------------------------------------------------------------------- /kernel/cpu/system.h: -------------------------------------------------------------------------------- 1 | #ifndef KERNEL_SYSTEM_H 2 | #define KERNEL_SYSTEM_H 3 | 4 | #include 5 | #include 6 | 7 | #pragma pack(push, 1) 8 | typedef struct eflags { 9 | bool carry: 1; 10 | uint8_t reserved0: 1; 11 | bool parity: 1; 12 | uint8_t reserved1: 1; 13 | bool adjust: 1; 14 | uint8_t reserved2: 1; 15 | bool zero: 1; 16 | bool sign: 1; 17 | bool trap: 1; 18 | bool interrupt: 1; 19 | bool direction: 1; 20 | bool overflow: 1; 21 | uint8_t iopl : 2; 22 | bool nt: 1; 23 | uint8_t reserved3: 1; 24 | bool resume: 1; 25 | bool virtual_86: 1; 26 | bool alignment: 1; 27 | bool virtual_interrupt: 1; 28 | bool virtual_interrupt_pending: 1; 29 | bool id: 1; 30 | uint16_t reserved4: 10; 31 | } eflags; 32 | #pragma pack(pop) 33 | 34 | /** 35 | * All registers should be 32 bit, since asm "push" moves the stack 32 bit for any value 36 | */ 37 | typedef struct registers { 38 | uint32_t cr4; 39 | uint32_t cr3; 40 | uint32_t cr2; 41 | uint32_t cr0; 42 | 43 | uint32_t gs; 44 | uint32_t fs; 45 | uint32_t es; 46 | uint32_t ds; 47 | 48 | uint32_t edi; 49 | uint32_t esi; 50 | uint32_t ebp; 51 | uint32_t esp; 52 | uint32_t ebx; 53 | uint32_t edx; 54 | uint32_t ecx; 55 | uint32_t eax; 56 | 57 | uint32_t int_no; 58 | uint32_t err_code; 59 | 60 | uint32_t eip; 61 | uint32_t cs; 62 | 63 | eflags eflags; 64 | 65 | uint32_t useresp; 66 | uint32_t ss; 67 | } registers; 68 | 69 | #endif //KERNEL_SYSTEM_H 70 | -------------------------------------------------------------------------------- /kernel/cpu/tss.asm: -------------------------------------------------------------------------------- 1 | global tss_flush 2 | 3 | section .text 4 | tss_flush: 5 | mov ax, (5 * 8) | 3 6 | ltr ax 7 | ret 8 | -------------------------------------------------------------------------------- /kernel/cpu/tss.c: -------------------------------------------------------------------------------- 1 | #include "tss.h" 2 | 3 | #include 4 | #include "gdt.h" 5 | 6 | tss_entry tss; 7 | 8 | void install_tss(int num, uint16_t ss0, uint32_t esp0) { 9 | uint32_t base = (uint32_t)&tss; 10 | uint32_t limit = base + sizeof(tss); 11 | 12 | gdt_set_gate(num, base, limit, 0xE9, 0x00); 13 | 14 | memset(&tss, 0x0, sizeof(tss)); 15 | 16 | tss.ss0 = ss0; 17 | tss.esp0 = esp0; 18 | tss.cs = 0x0b; 19 | tss.ss = 0x13; 20 | tss.ds = 0x13; 21 | tss.es = 0x13; 22 | tss.fs = 0x13; 23 | tss.gs = 0x13; 24 | 25 | tss.iomap_base = sizeof(tss); 26 | } 27 | 28 | void set_kernel_stack(uint32_t stack) { 29 | tss.esp0 = stack; 30 | } 31 | -------------------------------------------------------------------------------- /kernel/cpu/tss.h: -------------------------------------------------------------------------------- 1 | #ifndef KERNEL_TSS_H 2 | #define KERNEL_TSS_H 3 | 4 | #include 5 | 6 | #pragma pack(push, 1) 7 | typedef struct tss_entry { 8 | uint32_t prev_tss; 9 | uint32_t esp0; 10 | uint32_t ss0; 11 | uint32_t esp1; 12 | uint32_t ss1; 13 | uint32_t esp2; 14 | uint32_t ss2; 15 | uint32_t cr3; 16 | uint32_t eip; 17 | uint32_t eflags; 18 | uint32_t eax; 19 | uint32_t ecx; 20 | uint32_t edx; 21 | uint32_t ebx; 22 | uint32_t esp; 23 | uint32_t ebp; 24 | uint32_t esi; 25 | uint32_t edi; 26 | uint32_t es; 27 | uint32_t cs; 28 | uint32_t ss; 29 | uint32_t ds; 30 | uint32_t fs; 31 | uint32_t gs; 32 | uint32_t ldt; 33 | uint16_t trap; 34 | uint16_t iomap_base; 35 | } tss_entry; 36 | #pragma pack(pop) 37 | 38 | extern void tss_flush(void); 39 | 40 | void install_tss(int num, uint16_t ss0, uint32_t esp0); 41 | 42 | void set_kernel_stack(uint32_t stack); 43 | 44 | #endif // KERNEL_TSS_H 45 | -------------------------------------------------------------------------------- /kernel/debug.h: -------------------------------------------------------------------------------- 1 | #define FORCE_DEBUG_OFF 0 2 | 3 | #ifndef DEBUG 4 | #define DEBUG 0 5 | #endif 6 | 7 | #ifndef DEBUG_SERIAL 8 | #define DEBUG_SERIAL 0 9 | #endif 10 | 11 | #if DEBUG && !FORCE_DEBUG_OFF 12 | 13 | #if DEBUG_SERIAL 14 | #define _dbgprint _serial_dbgprint 15 | #else 16 | #define _dbgprint _screen_dbgprint 17 | #endif 18 | 19 | #define dbgprint(...) _dbgprint(__FILE__, __LINE__, __VA_ARGS__) 20 | #define dbgwait() _dbgwait() 21 | #else 22 | #define dbgprint(...) 23 | #define dbgwait() 24 | #endif 25 | 26 | #ifndef DEBUG_H 27 | #define DEBUG_H 28 | 29 | #include 30 | #include 31 | #include 32 | #include "modules/process.h" 33 | 34 | void _screen_dbgprint(const char *filename, int line, const char *msg, ...); 35 | void _serial_dbgprint(const char *filename, int line, const char *msg, ...); 36 | 37 | void _dbgwait(void); 38 | 39 | void hexdump(int(*write)(const char *format, ...), void *ptr, size_t n); 40 | 41 | void callstack(uint32_t ebp, process *p); 42 | 43 | #endif // DEBUG_H 44 | -------------------------------------------------------------------------------- /kernel/drivers/eth/ne2k.h: -------------------------------------------------------------------------------- 1 | #ifndef NE2K_H 2 | #define NE2K_H 3 | 4 | #include "../pci.h" 5 | #include "../ethernet.h" 6 | 7 | enum NE2KRegisters { 8 | NE2K_REG_COMMAND = 0x00, 9 | NE2K_REG_CLDA0 = 0x01, 10 | NE2K_REG_CLDA1 = 0x02, 11 | NE2K_REG_BNRY = 0x03, 12 | NE2K_REG_TSR = 0x04, 13 | NE2K_REG_NCR = 0x05, 14 | NE2K_REG_FIFO = 0x06, 15 | NE2K_REG_ISR = 0x07, 16 | NE2K_REG_CRDA0 = 0x08, 17 | NE2K_REG_CRDA1 = 0x09, 18 | NE2K_REG_RSR = 0x0C, 19 | 20 | 21 | NE2K_REG_PSTART = 0x01, 22 | NE2K_REG_PSTOP = 0x02, 23 | NE2K_REG_TPSR = 0x04, 24 | NE2K_REG_TBCR0 = 0x05, 25 | NE2K_REG_TBCR1 = 0x06, 26 | 27 | NE2K_REG_RSAR0 = 0x08, 28 | NE2K_REG_RSAR1 = 0x09, 29 | NE2K_REG_RBCR0 = 0x0A, 30 | NE2K_REG_RBCR1 = 0x0B, 31 | NE2K_REG_RCR = 0x0C, 32 | NE2K_REG_TCR = 0x0D, 33 | NE2K_REG_DCR = 0x0E, 34 | NE2K_REG_IMR = 0x0F, 35 | 36 | NE2K_REG_DATA = 0x10, 37 | }; 38 | 39 | enum NE2KCommands { 40 | NE2K_CMD_STOP = 0x01, 41 | NE2K_CMD_START = 0x02, 42 | NE2K_CMD_TRANSMIT = 0x04, 43 | NE2K_CMD_RD0 = 0x08, 44 | NE2K_CMD_RD1 = 0x10, 45 | NE2K_CMD_RD2 = 0x20, 46 | NE2K_CMD_PS0 = 0x40, 47 | NE2K_CMD_PS1 = 0x80, 48 | 49 | NE2K_CMD_PAGE0 = 0x00, 50 | NE2K_CMD_PAGE1 = 0x40, 51 | NE2K_CMD_PAGE2 = 0x80, 52 | }; 53 | 54 | enum NE2KInterruptStatus { 55 | NE2K_ISR_PRX = 0x01, 56 | NE2K_ISR_PTX = 0x02, 57 | NE2K_ISR_RXE = 0x04, 58 | NE2K_ISR_TXE = 0x08, 59 | NE2K_ISR_OVW = 0x10, 60 | NE2K_ISR_CNT = 0x20, 61 | NE2K_ISR_RDC = 0x40, 62 | NE2K_ISR_RST = 0x80, 63 | }; 64 | 65 | enum NE2KInterruptMask { 66 | NE2K_IMR_PRXE = 0x01, 67 | NE2K_IMR_PTXE = 0x02, 68 | NE2K_IMR_RXEE = 0x04, 69 | NE2K_IMR_TXEE = 0x08, 70 | NE2K_IMR_OVWE = 0x10, 71 | NE2K_IMR_CNTE = 0x20, 72 | NE2K_IMR_RDCE = 0x40, 73 | }; 74 | 75 | enum NE2KDataConfiguration { 76 | NE2K_DCR_WTS = 0x01, 77 | NE2K_DCR_BOS = 0x02, 78 | NE2K_DCR_LAS = 0x04, 79 | NE2K_DCR_LS = 0x08, 80 | NE2K_DCR_AR = 0x10, 81 | NE2K_DCR_FT0 = 0x20, 82 | NE2K_DCR_FT1 = 0x40, 83 | }; 84 | 85 | enum NE2KTransmitConfiguration { 86 | NE2K_TCR_CRC = 0x01, 87 | NE2K_TCR_LB0 = 0x02, 88 | NE2K_TCR_LB1 = 0x04, 89 | NE2K_TCR_ATD = 0x08, 90 | NE2K_TCR_OFST = 0x10, 91 | }; 92 | 93 | enum NE2KTransmitStatus { 94 | NE2K_TSR_PTX = 0x01, 95 | NE2K_TSR_COL = 0x04, 96 | NE2K_TSR_ABT = 0x08, 97 | NE2K_TSR_CRS = 0x10, 98 | NE2K_TSR_FU = 0x20, 99 | NE2K_TSR_CDH = 0x40, 100 | NE2K_TSR_OWC = 0x80, 101 | }; 102 | 103 | enum NE2KReceiveConfiguration { 104 | NE2K_RCR_SEP = 0x01, 105 | NE2K_RCR_AR = 0x02, 106 | NE2K_RCR_AB = 0x04, 107 | NE2K_RCR_AM = 0x08, 108 | NE2K_RCR_PRO = 0x10, 109 | NE2K_RCR_MON = 0x20, 110 | }; 111 | 112 | enum NE2KReceiveStatus { 113 | NE2K_RSR_PRX = 0x01, 114 | NE2K_RSR_CRC = 0x02, 115 | NE2K_RSR_FAE = 0x04, 116 | NE2K_RSR_FO = 0x08, 117 | NE2K_RSR_MPA = 0x10, 118 | NE2K_RSR_PHY = 0x20, 119 | NE2K_RSR_DIS = 0x40, 120 | NE2K_RSR_DFR = 0x80, 121 | }; 122 | 123 | typedef struct ne2k_receive_buffer { 124 | uint8_t status; 125 | uint8_t next_packet; 126 | uint16_t count; 127 | } ne2k_receive_buffer; 128 | 129 | ethernet_driver *ne2k_init(pci_device *device, uint8_t bus, uint8_t slot, uint8_t func); 130 | 131 | unsigned int ne2k_send_packet(ethernet_driver *driver, ethernet_packet *packet, size_t packet_length); 132 | 133 | void ne2k_receive_packet(ethernet_driver *driver, ethernet_packet *packet, size_t packet_length); 134 | 135 | #endif // NE2K_H 136 | -------------------------------------------------------------------------------- /kernel/drivers/ethernet.c: -------------------------------------------------------------------------------- 1 | #include "ethernet.h" 2 | 3 | #define DEBUG 1 4 | #define DEBUG_SERIAL 1 5 | 6 | #include 7 | #include 8 | #include 9 | #include "eth/e1000.h" 10 | #include "eth/ne2k.h" 11 | #include "../bits.h" 12 | #include "../debug.h" 13 | #include "../cpu/irq.h" 14 | #include "../modules/net/arp.h" 15 | #include "../modules/net/dhcp.h" 16 | #include "../modules/net/ip.h" 17 | 18 | ethernet_driver *eth[2]; 19 | 20 | static void ethernet_handler(registers *r, uint32_t int_no) { 21 | dbgprint("ethernet_handler: %d\n", int_no); 22 | for (int i = 0; i < 2; i++) { 23 | if (!eth[i]) { 24 | continue; 25 | } 26 | 27 | if (eth[i]->int_no == int_no && eth[i]->int_handler) { 28 | eth[i]->int_handler(eth[i]); 29 | } 30 | } 31 | } 32 | 33 | static bool ethernet_assign_driver(ethernet_driver *driver) { 34 | for (int i = 0; i < 2; i++) { 35 | if (!eth[i]) { 36 | eth[i] = driver; 37 | dbgprint("Assigned ethernet driver to interface %d\n", i); 38 | return true; 39 | } 40 | } 41 | 42 | return false; 43 | } 44 | 45 | void ethernet_init(pci_device *device, pci_header *header, uint8_t bus, uint8_t slot, uint8_t func) { 46 | ethernet_driver *driver = NULL; 47 | switch (header->vendor) { 48 | case 0x8086: // Intel 49 | switch (header->device) { 50 | case 0x100E: // e1000 51 | driver = e1000_init(device, bus, slot, func); 52 | break; 53 | } 54 | break; 55 | 56 | case 0x10EC: // Realtek 57 | switch (header->device) { 58 | case 0x8029: // ne2k 59 | driver = ne2k_init(device, bus, slot, func); 60 | break; 61 | } 62 | } 63 | 64 | if (!driver) { 65 | dbgprint("Unknown ethernet device!\n"); 66 | return; 67 | } 68 | 69 | if (!driver->mac[0] && !driver->mac[1] && !driver->mac[2] && !driver->mac[3] && !driver->mac[4] && !driver->mac[5]) { 70 | return; 71 | } 72 | 73 | driver->int_no = device->interrupt_line; 74 | 75 | if (!ethernet_assign_driver(driver)) { 76 | dbgprint("Too many ethernet devices!\n"); 77 | return; 78 | } 79 | 80 | dbgprint("Interrupt line: %d\n", device->interrupt_line); 81 | dbgprint("MAC: %02x:%02x:%02x:%02x:%02x:%02x\n", driver->mac[0], driver->mac[1], driver->mac[2], driver->mac[3], driver->mac[4], driver->mac[5]); 82 | dbgprint("Sending DHCP request...\n"); 83 | 84 | irq_install_handler(device->interrupt_line, ethernet_handler); 85 | if (driver->int_enable) { 86 | driver->int_enable(driver); 87 | } 88 | 89 | dhcp_init(driver); 90 | } 91 | 92 | void ethernet_send_packet(ethernet_driver *driver, uint8_t destination_mac[6], enum EtherType ethertype, void *data, size_t data_size) { 93 | ethernet_packet eth_packet; 94 | memcpy(eth_packet.header.source_mac, driver->mac, 6); 95 | memcpy(eth_packet.header.destination_mac, destination_mac, 6); 96 | eth_packet.header.ethertype = htons(ethertype); 97 | eth_packet.data = data; 98 | 99 | driver->write(driver, ð_packet, data_size); 100 | } 101 | 102 | void ethernet_process_packet(ethernet_driver *driver, ethernet_packet *packet, size_t data_size) { 103 | dbgprint("ethernet_process_packet: %dB, %x\n", data_size, ntohs(packet->header.ethertype)); 104 | switch (ntohs(packet->header.ethertype)) { 105 | case ETHERTYPE_ARP: 106 | arp_receive_packet(driver, (arp_packet *) packet->data); 107 | break; 108 | 109 | case ETHERTYPE_IPV4: 110 | ipv4_receive_packet(driver, (ipv4_packet *) packet->data, packet->data + sizeof(ipv4_packet), data_size - sizeof(ethernet_header)); 111 | break; 112 | } 113 | } 114 | -------------------------------------------------------------------------------- /kernel/drivers/filesystem.h: -------------------------------------------------------------------------------- 1 | #ifndef FILESYSTEM_H 2 | #define FILESYSTEM_H 3 | 4 | #include 5 | #include 6 | #include "iodriver.h" 7 | 8 | enum FileSystemType { 9 | FS_EMPTY = 0, 10 | FS_FAT12, 11 | FS_FAT16, 12 | FS_EXT2, 13 | FS_ISO9660, 14 | 15 | FS_TMPFS, 16 | FS_DEVFS, 17 | FS_PROCFS, 18 | FS_SYSFS, 19 | FS_PTYFS, 20 | }; 21 | 22 | typedef struct filesystem { 23 | enum FileSystemType type; 24 | uint32_t start_lba; 25 | void *params; 26 | void (*init)(iodriver *driver, struct filesystem *fs); 27 | int (*stat)(iodriver *driver, struct filesystem *fs, const char *path, struct stat *st); 28 | void *(*load_file)(iodriver *driver, struct filesystem *fs, const struct stat *st); 29 | int (*read)(iodriver *driver, struct filesystem *fs, const struct stat *st, void *buf, size_t count, size_t offset); 30 | int (*write)(iodriver *driver, struct filesystem *fs, const struct stat *st, void *buf, size_t count, size_t offset); 31 | int (*readdir)(iodriver *driver, struct filesystem *fs, const struct stat *st, size_t index, char *name, struct stat *out_st); 32 | } filesystem; 33 | 34 | #endif // FILESYSTEM_H 35 | -------------------------------------------------------------------------------- /kernel/drivers/fs/fat.h: -------------------------------------------------------------------------------- 1 | #ifndef FAT_H 2 | #define FAT_H 3 | 4 | #include 5 | #include 6 | #include "../iodriver.h" 7 | #include "../filesystem.h" 8 | 9 | /* 10 | * 0x00: Unused 11 | * 0xFF0-0xFF6: Reserved cluster 12 | * 0xFF7: Bad cluster 13 | * 0xFF8-0xFFF: Last cluster in a file 14 | * (anything else): Number of the next cluster in the file 15 | * 16 | * (physical sector number) = 33 + (FAT entry number) - 2 17 | */ 18 | 19 | #pragma pack(push, 1) 20 | typedef struct bios_params { 21 | uint16_t bytes_per_sector; 22 | uint8_t sectors_per_cluster; 23 | uint16_t reserved_sectors; 24 | uint8_t number_of_fat; 25 | uint16_t rootdir_entries; 26 | uint16_t small_sectors; 27 | uint8_t media_type; 28 | uint16_t sectors_per_fat; 29 | uint16_t sectors_per_track; 30 | uint16_t num_of_heads; 31 | uint32_t hidden_sectors; 32 | uint32_t large_sectors; 33 | 34 | uint8_t disk_number; 35 | uint8_t checkdisk; 36 | uint8_t signature; 37 | uint32_t serial_number; 38 | char volume_label[11]; 39 | char filesystem[8]; 40 | } bios_params; 41 | #pragma pack(pop) 42 | 43 | #pragma pack(push, 1) 44 | typedef struct fat_entry_attributes { 45 | bool read_only : 1; 46 | bool hidden : 1; 47 | bool system : 1; 48 | bool volume : 1; 49 | bool directory : 1; 50 | bool archive : 1; 51 | bool device : 1; 52 | bool lfn : 1; 53 | } fat_entry_attributes; 54 | #pragma pack(pop) 55 | 56 | #pragma pack(push, 1) 57 | typedef struct fat_entry_date { 58 | uint8_t day: 5; 59 | uint8_t month: 4; 60 | uint8_t year: 7; 61 | } fat_entry_date; 62 | #pragma pack(pop) 63 | 64 | #pragma pack(push, 1) 65 | typedef struct fat_entry_time { 66 | uint8_t second: 5; 67 | uint8_t minute: 6; 68 | uint8_t hour: 5; 69 | } fat_entry_time; 70 | #pragma pack(pop) 71 | 72 | #pragma pack(push, 1) 73 | typedef struct fat_entry { 74 | char name[8]; 75 | char ext[3]; 76 | fat_entry_attributes attributes; 77 | uint8_t winnt; 78 | uint8_t creation_msstamp; 79 | fat_entry_time created_time; 80 | fat_entry_date created_date; 81 | fat_entry_date last_access_date; 82 | uint16_t cluster_fat32; 83 | fat_entry_time last_write_time; 84 | fat_entry_date last_write_date; 85 | uint16_t cluster; 86 | uint32_t size; 87 | } fat_entry; 88 | #pragma pack(pop) 89 | 90 | /* 91 | * 0x00 Entry never used 92 | * 0xe5 File is deleted 93 | * 0x2e (A ".") Directory 94 | * 0x05 In a FAT32 entry, 0x05 as the lead character is translated to 0xe5, a Kanji character, so that Japanese language versions work. 95 | */ 96 | 97 | void fat_init(iodriver *driver, filesystem *fs); 98 | 99 | int fat_stat(iodriver *driver, filesystem *fs, const char *path, struct stat *st); 100 | 101 | void *fat_load_file(iodriver *driver, filesystem *fs, const struct stat *st); 102 | 103 | int fat_read(iodriver *driver, filesystem *fs, const struct stat *st, void *buf, size_t count, size_t offset); 104 | 105 | int fat_write(iodriver *driver, filesystem *fs, const struct stat *st, void *buf, size_t count, size_t offset); 106 | 107 | int fat_readdir(iodriver *driver, filesystem *fs, const struct stat *st, size_t index, char *name, struct stat *out_st); 108 | 109 | void fat_list_files(iodriver *driver, filesystem *fs); 110 | 111 | #endif //FAT_H 112 | -------------------------------------------------------------------------------- /kernel/drivers/io/ahci.c: -------------------------------------------------------------------------------- 1 | #include "ahci.h" 2 | 3 | #define DEBUG 1 4 | #define DEBUG_SERIAL 1 5 | 6 | #include "../../debug.h" 7 | -------------------------------------------------------------------------------- /kernel/drivers/io/ahci.h: -------------------------------------------------------------------------------- 1 | #ifndef AHCI_H 2 | #define AHCI_H 3 | 4 | #endif // AHCI_H 5 | -------------------------------------------------------------------------------- /kernel/drivers/io/ata.c: -------------------------------------------------------------------------------- 1 | #include "ata.h" 2 | 3 | #define DEBUG 1 4 | #define DEBUG_SERIAL 1 5 | 6 | #include 7 | #include "ide.h" 8 | #include "../../bits.h" 9 | #include "../../debug.h" 10 | #include "../../cpu/irq.h" 11 | 12 | iodriver ata_io; 13 | 14 | static const uint8_t atapi_packet[12] = {0xA8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; 15 | 16 | volatile static int irq_primary_c; 17 | volatile static int irq_secondary_c; 18 | 19 | static void ata_primary_handler(registers *r, uint32_t int_no) { 20 | //dbgprint("irq14"); 21 | irq_primary_c++; 22 | } 23 | 24 | static void ata_secondary_handler(registers *r, uint32_t int_no) { 25 | //dbgprint("irq15"); 26 | irq_secondary_c++; 27 | } 28 | 29 | iodriver *ata_init(pci_device *device, uint8_t bus, uint8_t slot, uint8_t func) { 30 | irq_primary_c = 0; 31 | irq_secondary_c = 0; 32 | 33 | uint32_t irq_primary = IRQ_ATA_PRIMARY; 34 | uint32_t irq_secondary = IRQ_ATA_SECONDARY; 35 | 36 | if (ISSET_BIT(device->header.prog_if, 0)) { // PCI native mode, controller 0 37 | irq_primary = device->interrupt_line; 38 | } else { 39 | device->base_address[0] = 0x1F0; 40 | device->base_address[1] = 0x3F6; 41 | } 42 | 43 | if (ISSET_BIT(device->header.prog_if, 2)) { // PCI native mode, controller 1 44 | irq_secondary = device->interrupt_line; 45 | } else { 46 | device->base_address[2] = 0x170; 47 | device->base_address[3] = 0x376; 48 | } 49 | 50 | if (ISSET_BIT(device->header.prog_if, 7)) { // DMA 51 | device->header.command.bus_master = 1; 52 | device->header.command.memory_space = 1; 53 | pci_write_word(bus, slot, func, 0x04, *(uint16_t *)&device->header.command); 54 | } else { 55 | device->base_address[4] = 0x000; 56 | } 57 | 58 | ata_io = *ide_init(device); 59 | irq_install_handler(irq_primary, ata_primary_handler); 60 | irq_install_handler(irq_secondary, ata_secondary_handler); 61 | return &ata_io; 62 | } 63 | 64 | void ata_400ns_delay(unsigned char channel) { 65 | for (int i = 0; i < 4; i++) { 66 | ide_read(channel, ATA_REG_ALTSTATUS); 67 | } 68 | } 69 | 70 | void ata_wait_irq_primary(void) { 71 | while (irq_primary_c <= 0) { asm volatile("hlt"); } 72 | irq_primary_c--; 73 | } 74 | 75 | void ata_wait_irq_secondary(void) { 76 | while (irq_secondary_c <= 0) { asm volatile("hlt"); } 77 | irq_secondary_c--; 78 | } 79 | 80 | int ata_search_for_drive(int boot_drive) { 81 | // Assume IDE 82 | 83 | return ide_search_for_drive(boot_drive); 84 | } 85 | -------------------------------------------------------------------------------- /kernel/drivers/io/ata.h: -------------------------------------------------------------------------------- 1 | #ifndef ATA_H 2 | #define ATA_H 3 | 4 | #include "../iodriver.h" 5 | #include "../pci.h" 6 | 7 | enum ATAIORegisters { 8 | ATA_REG_DATA = 0x000, 9 | ATA_REG_ERROR = 0x001, 10 | ATA_REG_FEATURES = 0x001, 11 | ATA_REG_SECCOUNT0 = 0x002, 12 | ATA_REG_LBA0 = 0x003, 13 | ATA_REG_LBA1 = 0x004, 14 | ATA_REG_LBA2 = 0x005, 15 | ATA_REG_HDDEVSEL = 0x006, 16 | ATA_REG_COMMAND = 0x007, 17 | ATA_REG_STATUS = 0x007, 18 | ATA_REG_SECCOUNT1 = 0x008, 19 | ATA_REG_LBA3 = 0x009, 20 | ATA_REG_LBA4 = 0x00A, 21 | ATA_REG_LBA5 = 0x00B, 22 | ATA_REG_CONTROL = 0x00C, 23 | ATA_REG_ALTSTATUS = 0x00C, 24 | ATA_REG_DEVADDRESS = 0x00D 25 | }; 26 | 27 | enum ATACRRegisters { 28 | ATA_CR_ALTERNATE = 0x000, 29 | ATA_CR_DEVICE = 0x000, 30 | ATA_CR_HEAD = 0x001, 31 | }; 32 | 33 | enum ATAErrorRegisters { 34 | ATA_ERR_AMNT = 0x00, 35 | ATA_ERR_TKZNF = 0x01, 36 | ATA_ERR_ABRT = 0x04, 37 | ATA_ERR_MCR = 0x08, 38 | ATA_ERR_IDNF = 0x10, 39 | ATA_ERR_MC = 0x20, 40 | ATA_ERR_UNC = 0x40, 41 | ATA_ERR_BBK = 0x80 42 | }; 43 | 44 | enum ATAStatusRegisters { 45 | ATA_SR_BSY = 0x80, 46 | ATA_SR_DRDY = 0x40, 47 | ATA_SR_DF = 0x20, 48 | ATA_SR_DSC = 0x10, 49 | ATA_SR_DRQ = 0x08, 50 | ATA_SR_CORR = 0x04, 51 | ATA_SR_IDX = 0x02, 52 | ATA_SR_ERR = 0x01 53 | }; 54 | 55 | enum ATACommands { 56 | ATA_CMD_READ_PIO = 0x20, 57 | ATA_CMD_READ_PIO_EXT = 0x24, 58 | ATA_CMD_READ_DMA = 0xC8, 59 | ATA_CMD_READ_DMA_EXT = 0x25, 60 | ATA_CMD_WRITE_PIO = 0x30, 61 | ATA_CMD_WRITE_PIO_EXT = 0x34, 62 | ATA_CMD_WRITE_DMA = 0xCA, 63 | ATA_CMD_WRITE_DMA_EXT = 0x35, 64 | ATA_CMD_CACHE_FLUSH = 0xE7, 65 | ATA_CMD_CACHE_FLUSH_EXT = 0xEA, 66 | ATA_CMD_PACKET = 0xA0, 67 | ATA_CMD_IDENTIFY_PACKET = 0xA1, 68 | ATA_CMD_IDENTIFY = 0xEC 69 | }; 70 | 71 | enum ATAIdentify { 72 | ATA_ID_DEVICETYPE = 0, 73 | ATA_ID_CYLINDERS = 2, 74 | ATA_ID_HEADS = 6, 75 | ATA_ID_SECTORS = 12, 76 | ATA_ID_SERIAL = 20, 77 | ATA_ID_MODEL = 54, 78 | ATA_ID_CAPABILITIES = 98, 79 | ATA_ID_FIELDVALID = 106, 80 | ATA_ID_MAX_LBA = 120, 81 | ATA_ID_COMMANDSETS = 164, 82 | ATA_ID_MAX_LBA_EXT = 200 83 | }; 84 | 85 | enum ATABusMasterRegisters { 86 | ATA_BMR_COMMAND = 0x000, 87 | ATA_BMR_STATUS = 0x002, 88 | ATA_BMR_PRDT = 0x004, 89 | }; 90 | 91 | #define ATA_MASTER 0x00 92 | #define ATA_SLAVE 0x01 93 | 94 | #define ATA_PRIMARY 0x00 95 | #define ATA_SECONDARY 0x01 96 | 97 | #define ATA_READ 0x00 98 | #define ATA_WRITE 0x01 99 | 100 | extern iodriver ata_io; 101 | 102 | iodriver *ata_init(pci_device *device, uint8_t bus, uint8_t slot, uint8_t func); 103 | 104 | void ata_400ns_delay(unsigned char channel); 105 | 106 | void ata_wait_irq_primary(void); 107 | 108 | void ata_wait_irq_secondary(void); 109 | 110 | int ata_search_for_drive(int boot_drive); 111 | 112 | #endif // ATA_H 113 | -------------------------------------------------------------------------------- /kernel/drivers/io/ide.h: -------------------------------------------------------------------------------- 1 | #ifndef IDE_H 2 | #define IDE_H 3 | 4 | #include "ata.h" 5 | 6 | #include "../iodriver.h" 7 | #include "../pci.h" 8 | 9 | #define IDE_ATA 0x00 10 | #define IDE_ATAPI 0x01 11 | 12 | typedef struct ide_channel_registers { 13 | uint16_t base; 14 | uint16_t ctrl; 15 | uint16_t bmide; 16 | uint8_t n_ien; 17 | } ide_channel_registers; 18 | 19 | typedef struct ide_device { 20 | uint8_t reserved; 21 | uint8_t channel; 22 | uint8_t drive; 23 | uint16_t type; 24 | uint16_t signature; 25 | uint16_t capabilities; 26 | uint32_t command_sets; 27 | uint32_t size; 28 | uint32_t sector_size; 29 | uint8_t model[41]; 30 | } ide_device; 31 | 32 | #pragma pack(push, 1) 33 | typedef struct prd_table { 34 | uint32_t addr; 35 | uint16_t size; 36 | uint16_t reserved: 15; 37 | bool last: 1; 38 | } prd_table; 39 | #pragma pack(pop) 40 | 41 | iodriver *ide_init(pci_device *device); 42 | 43 | int ide_reset(iodriver *driver); 44 | 45 | uint8_t ide_read(uint8_t channel, uint8_t reg); 46 | 47 | void ide_write(uint8_t channel, uint8_t reg, uint8_t data); 48 | 49 | void ide_read_buffer(uint8_t channel, uint8_t reg, uint16_t *buffer, uint16_t quads); 50 | 51 | int ide_send_atapi_command(uint8_t device, uint16_t length, uint8_t command[12]); 52 | 53 | uint8_t ide_polling(uint8_t channel, uint16_t advanced_check); 54 | 55 | uint8_t ide_print_error(iodriver *driver, uint8_t err); 56 | 57 | void ide_motor_on(iodriver *driver); 58 | 59 | void ide_motor_off(iodriver *driver); 60 | 61 | int ide_do_sector(IOOperation direction, iodriver *driver, uint32_t lba, uint16_t number_of_sectors, uint8_t *buffer, bool keepOn); 62 | 63 | int ide_sector_read(iodriver *driver, uint32_t lba, uint8_t *buffer, bool keepOn); 64 | 65 | int ide_sector_write(iodriver *driver, uint32_t lba, uint8_t *buffer, bool keepOn); 66 | 67 | int ide_search_for_drive(int boot_drive); 68 | 69 | #endif // IDE_H 70 | -------------------------------------------------------------------------------- /kernel/drivers/io/scsi.c: -------------------------------------------------------------------------------- 1 | #include "scsi.h" 2 | -------------------------------------------------------------------------------- /kernel/drivers/io/scsi.h: -------------------------------------------------------------------------------- 1 | #ifndef SCSI_H 2 | #define SCSI_H 3 | 4 | enum SCSICommands { 5 | SCSI_TEST_UNIT_READY = 0x00, 6 | SCSI_REQUEST_SENSE = 0x03, 7 | SCSI_FORMAT_UNIT = 0x04, 8 | SCSI_INQUIRY = 0x12, 9 | SCSI_START_STOP_UNIT = 0x1B, 10 | SCSI_PREVENT_ALLOW_MEDIUM_REMOVAL = 0x1E, 11 | SCSI_READ_FORMAT_CAPACITIES = 0x23, 12 | SCSI_READ_CAPACITY = 0x25, 13 | SCSI_READ_10 = 0x28, 14 | SCSI_WRITE_10 = 0x2A, 15 | SCSI_SEEK_10 = 0x2B, 16 | SCSI_WRITE_AND_VERIFY_10 = 0x2E, 17 | SCSI_VERIFY_10 = 0x2F, 18 | SCSI_SYNCHRONIZE_CACHE = 0x35, 19 | SCSI_WRITE_BUFFER = 0x3B, 20 | SCSI_READ_BUFFER = 0x3C, 21 | SCSI_READ_TOC_PMA_ATIP = 0x43, 22 | SCSI_GET_CONFIGURATION = 0x46, 23 | SCSI_GET_EVENT_STATUS_NOTIFICATION = 0x4A, 24 | SCSI_READ_DISC_INFORMATION = 0x51, 25 | SCSI_READ_TRACK_INFORMATION = 0x52, 26 | SCSI_RESERVE_TRACK = 0x53, 27 | SCSI_SEND_OPC_INFORMATION = 0x54, 28 | SCSI_MODE_SELECT_10 = 0x55, 29 | SCSI_REPAIR_TRACK = 0x58, 30 | SCSI_MODE_SENSE_10 = 0x5A, 31 | SCSI_CLOSE_TRACK_SESSION = 0x5B, 32 | SCSI_READ_BUFFER_CAPACITY = 0x5C, 33 | SCSI_SEND_CUE_SHEET = 0x5D, 34 | SCSI_REPORT_LUNS = 0xA0, 35 | SCSI_BLANK = 0xA1, 36 | SCSI_SECURITY_PROTOCOL_IN = 0xA2, 37 | SCSI_SEND_KEY = 0xA3, 38 | SCSI_REPORT_KEY = 0xA4, 39 | SCSI_LOAD_UNLOAD_MEDIUM = 0xA6, 40 | SCSI_SET_READ_AHEAD = 0xA7, 41 | SCSI_READ_12 = 0xA8, 42 | SCSI_WRITE_12 = 0xAA, 43 | SCSI_READ_MEDIA_SERIAL_NUMBER_SERVICE_ACTION_IN_12 = 0xAB, 44 | SCSI_GET_PERFORMANCE = 0xAC, 45 | SCSI_READ_DISC_STRUCTURE = 0xAD, 46 | SCSI_SECURITY_PROTOCOL_OUT = 0xB5, 47 | SCSI_SET_STREAMING = 0xB6, 48 | SCSI_READ_CD_MSF = 0xB9, 49 | SCSI_SET_CD_SPEED = 0xBB, 50 | SCSI_MECHANISM_STATUS = 0xBD, 51 | SCSI_READ_CD = 0xBE, 52 | SCSI_SEND_DISC_STRUCTURE = 0xBF, 53 | }; 54 | 55 | #endif // SCSI_H 56 | -------------------------------------------------------------------------------- /kernel/drivers/iodriver.h: -------------------------------------------------------------------------------- 1 | #ifndef IODRIVER_H 2 | #define IODRIVER_H 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | typedef struct iodriver { 9 | int16_t device; 10 | uint8_t *io_buffer; 11 | uint16_t sector_size; 12 | size_t size; 13 | void *partitions; 14 | int (*reset)(struct iodriver *driver); 15 | void (*start)(struct iodriver *driver); 16 | void (*stop)(struct iodriver *driver); 17 | int (*read_sector)(struct iodriver *driver, uint32_t lba, uint8_t *data, bool keepOn); 18 | int (*write_sector)(struct iodriver *driver, uint32_t lba, uint8_t *data, bool keepOn); 19 | } iodriver; 20 | 21 | typedef enum IOOperation { 22 | IO_READ = 0, 23 | IO_WRITE = 1 24 | } IOOperation; 25 | 26 | #endif // IODRIVER_H 27 | -------------------------------------------------------------------------------- /kernel/drivers/keyboard.c: -------------------------------------------------------------------------------- 1 | #include "keyboard.h" 2 | 3 | #define DEBUG 1 4 | #define DEBUG_SERIAL 1 5 | 6 | #include 7 | #include "../bits.h" 8 | #include "../debug.h" 9 | #include "../cpu/irq.h" 10 | #include "../cpu/panic.h" 11 | #include "../cpu/pic.h" 12 | #include "../modules/kblayout/kb.h" 13 | 14 | static unsigned char scancode; 15 | static int irq_c = 0; 16 | static bool pressed[256]; 17 | 18 | static void _keyboard_reset(void) { 19 | char tmp = inb(KB_RESET_REGISTER); 20 | outb(KB_RESET_REGISTER, tmp | 0x80); 21 | outb(KB_RESET_REGISTER, tmp & 0x7F); 22 | inb(KB_DATA_REGISTER); 23 | } 24 | 25 | void keyboard_handler(registers *r, uint32_t int_no) { 26 | while (ISSET_BIT_INT(inb(KB_STATUS_REGISTER), 2)) {} 27 | irq_c++; 28 | scancode = inb(KB_DATA_REGISTER); 29 | 30 | if (!ISSET_BIT_INT(scancode, 0x80)) { 31 | pressed[scancode] = true; 32 | } else { 33 | pressed[DISABLE_BIT_INT(scancode, 0x80)] = false; 34 | } 35 | 36 | // Check for CTRL + ALT + DEL 37 | if (pressed[0x1d] && pressed[0x38] && pressed[0x53]) { 38 | panic("CTRL + ALT + DEL"); 39 | } 40 | } 41 | 42 | void keyboard_init(void) { 43 | irq_c = 0; 44 | irq_install_handler(IRQ_KEYBOARD, keyboard_handler); 45 | _keyboard_reset(); 46 | kblayout = kblayout_us; 47 | memset(pressed, 0, sizeof(pressed)); 48 | } 49 | 50 | void keyboard_wait_irq(void) { 51 | while (irq_c <= 0) { asm volatile("hlt"); } 52 | irq_c--; 53 | } 54 | 55 | char keyboard_read(void) { 56 | keyboard_wait_irq(); 57 | return scancode; 58 | } 59 | 60 | void keyboard_clear_buffer(void) { 61 | char temp; 62 | do { 63 | temp = inb(KB_STATUS_REGISTER); 64 | if (ISSET_BIT(temp, 0)) { 65 | inb(KB_DATA_REGISTER); 66 | } 67 | } while (ISSET_BIT(temp, 1)); 68 | } 69 | -------------------------------------------------------------------------------- /kernel/drivers/keyboard.h: -------------------------------------------------------------------------------- 1 | #ifndef KEYBOARD_H 2 | #define KEYBOARD_H 3 | 4 | #include "../cpu/system.h" 5 | 6 | enum KeyboardRegisters { 7 | KB_DATA_REGISTER = 0x60, 8 | KB_RESET_REGISTER = 0x61, 9 | KB_STATUS_REGISTER = 0x64, 10 | KB_CTRL_REGISTER = 0x64 11 | }; 12 | 13 | #define KB_RESET 0xFE 14 | 15 | void keyboard_init(void); 16 | 17 | void keyboard_wait_irq(void); 18 | 19 | char keyboard_read(void); 20 | 21 | void keyboard_clear_buffer(void); 22 | 23 | #endif //KEYBOARD_H 24 | -------------------------------------------------------------------------------- /kernel/drivers/mbr.c: -------------------------------------------------------------------------------- 1 | #include "mbr.h" 2 | 3 | #define DEBUG 1 4 | #define DEBUG_SERIAL 1 5 | 6 | #include 7 | #include 8 | #include "../debug.h" 9 | #include "../bits.h" 10 | #include "fs/fat.h" 11 | #include "fs/ext2.h" 12 | #include "fs/iso9660.h" 13 | 14 | filesystem *mbr_init(iodriver *driver, unsigned int partition) { 15 | dbgprint("Reading MBR %p\n", driver->read_sector); 16 | driver->read_sector(driver, 0, driver->io_buffer, true); 17 | 18 | if (driver->io_buffer[510] != 0x55 || driver->io_buffer[511] != 0xAA) { 19 | dbgprint("MBR signature not found: expected 0x55 0xAA, got 0x%x 0x%x\n", driver->io_buffer[510], driver->io_buffer[511]); 20 | return NULL; 21 | } 22 | 23 | mbr_partition *partitions = calloc(4, sizeof(mbr_partition)); 24 | driver->partitions = partitions; 25 | memcpy(driver->partitions, &driver->io_buffer[446], 4 * sizeof(mbr_partition)); 26 | 27 | for (int i = 0; i < 4; i++) { 28 | if (partitions[i].start_lba == 0) { 29 | dbgprint("\n", i); 30 | continue; 31 | } 32 | 33 | dbgprint("Partition %d\n", i); 34 | 35 | dbgprint("\tStart: %d (%d %d %d)\n", partitions[i].start_lba, partitions[i].start_cylinder, partitions[i].start_head, partitions[i].start_sector); 36 | dbgprint("\tEnd: %d (%d %d %d)\n", partitions[i].start_lba + partitions[i].size, partitions[i].end_cylinder, partitions[i].end_head, partitions[i].end_sector); 37 | dbgprint("\tType: %d\n", partitions[i].type); 38 | dbgprint("\tBootable: %d\n", ISSET_BIT_INT(partitions[i].bootable, 0x80)); 39 | } 40 | 41 | return mbr_get_fs(driver, partition); 42 | } 43 | 44 | filesystem *mbr_get_fs(iodriver *driver, int partition) { 45 | mbr_partition *partitions = driver->partitions; 46 | filesystem *fs = malloc(sizeof(filesystem)); 47 | switch (partitions[partition].type) { 48 | case 0x00: 49 | free(fs); 50 | return NULL; 51 | case 0x01: { 52 | fs->type = FS_FAT12; 53 | fs->start_lba = partitions[partition].start_lba; 54 | fs->init = &fat_init; 55 | fs->stat = &fat_stat; 56 | fs->load_file = &fat_load_file; 57 | fs->read = &fat_read; 58 | fs->write = &fat_write; 59 | fs->readdir = &fat_readdir; 60 | return fs; 61 | } 62 | case 0x04: 63 | case 0x06: { 64 | fs->type = FS_FAT16; 65 | fs->start_lba = partitions[partition].start_lba; 66 | fs->init = &fat_init; 67 | fs->stat = &fat_stat; 68 | fs->load_file = &fat_load_file; 69 | fs->read = &fat_read; 70 | fs->write = &fat_write; 71 | fs->readdir = &fat_readdir; 72 | return fs; 73 | } 74 | case 0x83: { 75 | fs->type = FS_EXT2; 76 | fs->start_lba = partitions[partition].start_lba; 77 | fs->init = &ext2_init; 78 | fs->stat = &ext2_stat; 79 | fs->load_file = &ext2_load_file; 80 | fs->read = &ext2_read; 81 | fs->write = &ext2_write; 82 | fs->readdir = &ext2_readdir; 83 | return fs; 84 | } 85 | case 0x96: 86 | case 0xCD: 87 | fs->type = FS_ISO9660; 88 | fs->start_lba = partitions[partition].start_lba; 89 | fs->init = &iso9660_init; 90 | fs->stat = &iso9660_stat; 91 | fs->load_file = &iso9660_load_file; 92 | fs->read = &iso9660_read; 93 | fs->write = &iso9660_write; 94 | fs->readdir = &iso9660_readdir; 95 | return fs; 96 | default: 97 | free(fs); 98 | return NULL; 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /kernel/drivers/mbr.h: -------------------------------------------------------------------------------- 1 | #ifndef MBR_H 2 | #define MBR_H 3 | 4 | #include 5 | #include "iodriver.h" 6 | #include "filesystem.h" 7 | 8 | #pragma pack(push, 1) 9 | typedef struct mbr_partition { 10 | uint8_t bootable; 11 | uint8_t start_head; 12 | uint8_t start_sector; 13 | uint8_t start_cylinder; 14 | uint8_t type; 15 | uint8_t end_head; 16 | uint8_t end_sector; 17 | uint8_t end_cylinder; 18 | uint32_t start_lba; 19 | uint32_t size; 20 | } mbr_partition; 21 | #pragma pack(pop) 22 | 23 | filesystem *mbr_init(iodriver *driver, unsigned int partition); 24 | 25 | filesystem *mbr_get_fs(iodriver *driver, int partition); 26 | 27 | #endif // MBR_H 28 | -------------------------------------------------------------------------------- /kernel/drivers/screen.c: -------------------------------------------------------------------------------- 1 | #include "screen.h" 2 | 3 | #include "video/framebuffer.h" 4 | 5 | enum ScreenMode screen_mode = SCREEN_MODE_FRAMEBUFFER; 6 | 7 | void screen_init(enum ScreenMode mode) { 8 | screen_mode = mode; 9 | } 10 | 11 | void screen_caret(void) { 12 | switch (screen_mode) { 13 | case SCREEN_MODE_FRAMEBUFFER: 14 | framebuffer_caret(); 15 | } 16 | } 17 | 18 | unsigned char screen_getcolor(void) { 19 | switch (screen_mode) { 20 | case SCREEN_MODE_FRAMEBUFFER: 21 | return framebuffer_getcolor(); 22 | } 23 | } 24 | 25 | void screen_setcolor(unsigned char c) { 26 | switch (screen_mode) { 27 | case SCREEN_MODE_FRAMEBUFFER: 28 | framebuffer_setcolor(c); 29 | } 30 | } 31 | 32 | void screen_clear(void) { 33 | switch (screen_mode) { 34 | case SCREEN_MODE_FRAMEBUFFER: 35 | framebuffer_clear(); 36 | } 37 | } 38 | 39 | void screen_getxy(int *x, int *y) { 40 | switch (screen_mode) { 41 | case SCREEN_MODE_FRAMEBUFFER: 42 | framebuffer_getxy(x, y); 43 | } 44 | } 45 | 46 | void screen_gotoxy(int x, int y) { 47 | switch (screen_mode) { 48 | case SCREEN_MODE_FRAMEBUFFER: 49 | framebuffer_gotoxy(x, y); 50 | } 51 | } 52 | 53 | int screen_write(const char c) { 54 | switch (screen_mode) { 55 | case SCREEN_MODE_FRAMEBUFFER: 56 | return framebuffer_write(c); 57 | } 58 | 59 | return -1; 60 | } 61 | 62 | int screen_write_str(const char *str) { 63 | switch (screen_mode) { 64 | case SCREEN_MODE_FRAMEBUFFER: 65 | return framebuffer_write_str(str); 66 | } 67 | 68 | return -1; 69 | } 70 | -------------------------------------------------------------------------------- /kernel/drivers/screen.h: -------------------------------------------------------------------------------- 1 | #ifndef KERNEL_SCREEN_H 2 | #define KERNEL_SCREEN_H 3 | 4 | enum ScreenColors { 5 | COLOR_BLACK = 0, 6 | COLOR_BLUE, 7 | COLOR_GREEN, 8 | COLOR_CYAN, 9 | COLOR_RED, 10 | COLOR_PURPLE, 11 | COLOR_BROWN, 12 | COLOR_GRAY, 13 | COLOR_DARKGRAY, 14 | COLOR_LIGHTBLUE, 15 | COLOR_LIGHTGREEN, 16 | COLOR_LIGHTCYAN, 17 | COLOR_LIGHTRED, 18 | COLOR_LIGHTPURPLE, 19 | COLOR_YELLOW, 20 | COLOR_WHITE 21 | }; 22 | 23 | enum ScreenMode { 24 | SCREEN_MODE_FRAMEBUFFER, 25 | }; 26 | 27 | void screen_init(enum ScreenMode mode); 28 | 29 | void screen_caret(void); 30 | 31 | unsigned char screen_getcolor(void); 32 | 33 | void screen_setcolor(unsigned char c); 34 | 35 | void screen_clear(void); 36 | 37 | void screen_getxy(int *x, int *y); 38 | 39 | void screen_gotoxy(int x, int y); 40 | 41 | int screen_write(const char c); 42 | 43 | int screen_write_str(const char *str); 44 | 45 | #endif // KERNEL_SCREEN_H 46 | -------------------------------------------------------------------------------- /kernel/drivers/serial.c: -------------------------------------------------------------------------------- 1 | #include "serial.h" 2 | 3 | #define DEBUG 0 4 | 5 | #include 6 | #include 7 | #include 8 | #include "../debug.h" 9 | #include "../bits.h" 10 | 11 | static bool ports_enabled[8] = {false}; 12 | 13 | static uint8_t get_port_id(enum SerialPorts port) { 14 | switch (port) { 15 | case SERIAL_COM1: 16 | return 0; 17 | case SERIAL_COM2: 18 | return 1; 19 | case SERIAL_COM3: 20 | return 2; 21 | case SERIAL_COM4: 22 | return 3; 23 | case SERIAL_COM5: 24 | return 4; 25 | case SERIAL_COM6: 26 | return 5; 27 | case SERIAL_COM7: 28 | return 6; 29 | case SERIAL_COM8: 30 | return 7; 31 | } 32 | } 33 | 34 | bool is_serial_enabled(enum SerialPorts port) { 35 | return ports_enabled[get_port_id(port)]; 36 | } 37 | 38 | bool serial_init(enum SerialPorts port, uint16_t baud_divisor) { 39 | if (port == 0) { 40 | return false; 41 | } 42 | 43 | if (is_serial_enabled(port)) { 44 | return false; 45 | } 46 | 47 | outb(port + SERIAL_REG_INTERRUPT_ENABLE, 0x00); 48 | outb(port + SERIAL_REG_LINE_CONTROL, 0x80); 49 | outb(port + SERIAL_REG_BAUD_LOW, (uint8_t)(baud_divisor & 0xFF)); 50 | outb(port + SERIAL_REG_BAUD_HIGH, (uint8_t)((baud_divisor >> 8) & 0xFF)); 51 | outb(port + SERIAL_REG_LINE_CONTROL, 0x03); 52 | outb(port + SERIAL_REG_FIFO_CONTROL, 0xC7); 53 | outb(port + SERIAL_REG_MODEM_CONTROL, 0x0B); 54 | outb(port + SERIAL_REG_MODEM_CONTROL, 0x1E); 55 | outb(port + SERIAL_REG_DATA, 0xAE); 56 | 57 | while ((inb(port + SERIAL_REG_LINE_STATUS) & 0x20) == 0) {} 58 | 59 | // Check if serial is faulty (i.e: not same byte as sent) 60 | if (inb(port + SERIAL_REG_DATA) != 0xAE) { 61 | return false; 62 | } 63 | 64 | // If serial is not faulty set it in normal operation mode 65 | // (not-loopback with IRQs enabled and OUT#1 and OUT#2 bits enabled) 66 | outb(port + SERIAL_REG_MODEM_CONTROL, 0x0F); 67 | 68 | ports_enabled[get_port_id(port)] = true; 69 | 70 | return true; 71 | } 72 | 73 | bool serial_read(enum SerialPorts port, char *c) { 74 | if (port == 0) { 75 | return false; 76 | } 77 | 78 | if (!is_serial_enabled(port)) { 79 | return false; 80 | } 81 | 82 | while ((inb(port + SERIAL_REG_LINE_STATUS) & 0x01) == 0) { } 83 | 84 | *c = inb(port); 85 | 86 | return true; 87 | } 88 | 89 | bool serial_write(enum SerialPorts port, char c) { 90 | if (port == 0) { 91 | return false; 92 | } 93 | 94 | if (!is_serial_enabled(port)) { 95 | return false; 96 | } 97 | 98 | while ((inb(port + SERIAL_REG_LINE_STATUS) & 0x20) == 0) {} 99 | 100 | outb(port, c); 101 | 102 | return true; 103 | } 104 | 105 | bool serial_write_str(enum SerialPorts port, const char *str, ...) { 106 | va_list args; 107 | 108 | va_start(args, str); 109 | bool ret = serial_write_str_varargs(port, str, args); 110 | va_end(args); 111 | return ret; 112 | } 113 | 114 | bool serial_write_str_varargs(enum SerialPorts port, const char *str, va_list args) { 115 | if (port == 0) { 116 | return false; 117 | } 118 | 119 | if (!is_serial_enabled(port)) { 120 | return false; 121 | } 122 | 123 | char buffer[2048] = ""; 124 | vsprintf(buffer, str, args); 125 | 126 | dbgprint("serial_write_str: %s\n", buffer); 127 | 128 | for (int i = 0; buffer[i]; i++) { 129 | serial_write(port, buffer[i]); 130 | } 131 | 132 | return true; 133 | } 134 | -------------------------------------------------------------------------------- /kernel/drivers/serial.h: -------------------------------------------------------------------------------- 1 | #ifndef SERIAL_H 2 | #define SERIAL_H 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | enum SerialPorts { 9 | SERIAL_COM1 = 0x3F8, 10 | SERIAL_COM2 = 0x2F8, 11 | SERIAL_COM3 = 0x3E8, 12 | SERIAL_COM4 = 0x2E8, 13 | SERIAL_COM5 = 0x5F8, 14 | SERIAL_COM6 = 0x4F8, 15 | SERIAL_COM7 = 0x5E8, 16 | SERIAL_COM8 = 0x4E8, 17 | }; 18 | 19 | enum SerialRegisters { 20 | SERIAL_REG_DATA = 0, 21 | SERIAL_REG_INTERRUPT_ENABLE = 1, 22 | SERIAL_REG_BAUD_LOW = 0, 23 | SERIAL_REG_BAUD_HIGH = 1, 24 | SERIAL_REG_FIFO_CONTROL = 2, 25 | SERIAL_REG_LINE_CONTROL = 3, 26 | SERIAL_REG_MODEM_CONTROL = 4, 27 | SERIAL_REG_LINE_STATUS = 5, 28 | SERIAL_REG_MODEM_STATUS = 6, 29 | SERIAL_REG_SCRATCH = 7, 30 | }; 31 | 32 | bool is_serial_enabled(enum SerialPorts port); 33 | 34 | bool serial_init(enum SerialPorts port, uint16_t baud_divisor); 35 | 36 | bool serial_read(enum SerialPorts port, char *c); 37 | 38 | bool serial_write(enum SerialPorts port, char c); 39 | 40 | bool serial_write_str(enum SerialPorts port, const char *str, ...); 41 | 42 | bool serial_write_str_varargs(enum SerialPorts port, const char *str, va_list args); 43 | 44 | #endif // SERIAL_H 45 | -------------------------------------------------------------------------------- /kernel/drivers/usb.c: -------------------------------------------------------------------------------- 1 | #include "usb.h" 2 | 3 | #include "../bits.h" 4 | #include "../debug.h" 5 | 6 | void usb_init(pci_device *device, pci_header *header, uint8_t bus, uint8_t slot, uint8_t func) { 7 | dbgprint("Initializing USB controller\n"); 8 | 9 | switch (header->prog_if) { 10 | case 0x00: 11 | // USB 1.0 (Intel) 12 | dbgprint("\tUHCI Controller\n"); 13 | break; 14 | 15 | case 0x10: 16 | // USB 1.0 (Microsoft) 17 | dbgprint("\tOHCI Controller\n"); 18 | break; 19 | 20 | case 0x20: 21 | // USB 2.0 22 | dbgprint("\tEHCI Controller\n"); 23 | break; 24 | 25 | case 0x30: 26 | // USB 3.0 27 | dbgprint("\tXHCI Controller\n"); 28 | break; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /kernel/drivers/usb.h: -------------------------------------------------------------------------------- 1 | #ifndef USB_H 2 | #define USB_H 3 | 4 | #include "pci.h" 5 | 6 | enum UHCIRegisters { 7 | UHCI_REG_USBCMD = 0x00, 8 | UHCI_REG_USBSTS = 0x02, 9 | UHCI_REG_USBINTR = 0x04, 10 | UHCI_REG_FRNUM = 0x06, 11 | UHCI_REG_FRBASEADD = 0x08, 12 | UHCI_REG_SOFMOD = 0x0C, 13 | UHCI_REG_PORTSC1 = 0x10, 14 | UHCI_REG_PORTSC2 = 0x12, 15 | }; 16 | 17 | enum UHCICommandRegister { 18 | UHCI_CMD_RUN = 1 << 0x00, 19 | UHCI_CMD_HCRESET = 1 << 0x01, 20 | UHCI_CMD_GRESET = 1 << 0x02, 21 | UHCI_CMD_GSUSPEND = 1 << 0x03, 22 | UHCI_CMD_GRESUME = 1 << 0x04, 23 | UHCI_CMD_SWDBG = 1 << 0x5, 24 | UHCI_CMD_CF = 1 << 0x6, 25 | UHCI_CMD_MAXP = 1 << 0x7, 26 | }; 27 | 28 | enum UHCIStatusRegister { 29 | UHCI_STS_INT = 1 << 0x00, 30 | UHCI_STS_ERRINT = 1 << 0x01, 31 | UHCI_STS_RD = 1 << 0x02, 32 | UHCI_STS_SE = 1 << 0x03, 33 | UHCI_STS_PE = 1 << 0x04, 34 | UHCI_STS_HLT = 1 << 0x05, 35 | }; 36 | 37 | enum UHCIInterruptEnableRegister { 38 | UHCI_INT_TOCRC = 1 << 0x00, 39 | UHCI_INT_RE = 1 << 0x01, 40 | UHCI_INT_CE = 1 << 0x02, 41 | UHCI_INT_SP = 1 << 0x03, 42 | }; 43 | 44 | void usb_init(pci_device *device, pci_header *header, uint8_t bus, uint8_t slot, uint8_t func); 45 | 46 | #endif // USB_H 47 | -------------------------------------------------------------------------------- /kernel/drivers/video/framebuffer.h: -------------------------------------------------------------------------------- 1 | #ifndef KERNEL_FRAMEBUFFER_H 2 | #define KERNEL_FRAMEBUFFER_H 3 | 4 | #include 5 | 6 | typedef struct framebuffer_config { 7 | uint64_t addr; 8 | uint32_t pitch; 9 | uint32_t width; 10 | uint32_t height; 11 | uint8_t bpp; 12 | uint8_t type; 13 | } framebuffer_config; 14 | 15 | enum ScreenRegisters { 16 | SCREEN_CONTROL = 0x3D4, 17 | SCREEN_DATA = 0x3D5 18 | }; 19 | 20 | enum FramebufferType { 21 | FRAMEBUFFER_TYPE_INDEXED = 0, 22 | FRAMEBUFFER_TYPE_RGB = 1, 23 | FRAMEBUFFER_TYPE_TEXT = 2, 24 | }; 25 | 26 | void framebuffer_setup(framebuffer_config *config); 27 | 28 | void framebuffer_init(void); 29 | 30 | void framebuffer_caret(void); 31 | 32 | unsigned char framebuffer_getcolor(void); 33 | 34 | void framebuffer_setcolor(unsigned char c); 35 | 36 | void framebuffer_clear(void); 37 | 38 | void framebuffer_getxy(int *x, int *y); 39 | 40 | void framebuffer_gotoxy(int x, int y); 41 | 42 | int framebuffer_write(const char c); 43 | 44 | int framebuffer_write_str(const char *str); 45 | 46 | #endif // KERNEL_FRAMEBUFFER_H 47 | -------------------------------------------------------------------------------- /kernel/kernel.asm: -------------------------------------------------------------------------------- 1 | [bits 32] 2 | 3 | global _start 4 | global kernel_start 5 | global switch_ring3 6 | 7 | global sys_stack 8 | 9 | %include "multiboot2.inc" 10 | 11 | section .multiboot2_header 12 | 13 | multiboot_header: 14 | align 8 15 | 16 | dd MULTIBOOT2_HEADER_MAGIC 17 | dd GRUB_MULTIBOOT_ARCHITECTURE_I386 18 | dd multiboot_header_end - multiboot_header 19 | dd -(MULTIBOOT2_HEADER_MAGIC + GRUB_MULTIBOOT_ARCHITECTURE_I386 + (multiboot_header_end - multiboot_header)) 20 | framebuffer_tag_start: 21 | align 8 22 | 23 | ;dw MULTIBOOT_HEADER_TAG_FRAMEBUFFER 24 | ;dw MULTIBOOT_HEADER_TAG_OPTIONAL 25 | ;dd framebuffer_tag_end - framebuffer_tag_start 26 | ;dd 800 27 | ;dd 600 28 | ;dd 32 29 | framebuffer_tag_end: 30 | align 8 31 | 32 | dw MULTIBOOT_HEADER_TAG_END 33 | dw 0 34 | dd 8 35 | multiboot_header_end: 36 | 37 | section .text.setup 38 | 39 | _start: 40 | mov esp, proto_stack 41 | push ebx 42 | push eax 43 | 44 | mov eax, 0x0 ; Counter 45 | mov ebx, 0x0 ; Real address 46 | .fill_id_table: 47 | mov ecx, ebx 48 | or ecx, 3 49 | mov [table_0 + eax * 4], ecx 50 | invlpg [table_0 + eax * 4] 51 | add ebx, 4096 52 | inc eax 53 | cmp eax, 1024 54 | jne .fill_id_table 55 | 56 | mov eax, 0x0 ; Counter 57 | mov ebx, 0x000000 ; Real address 58 | .fill_kernel_table: 59 | mov ecx, ebx 60 | or ecx, 3 61 | mov [table_768 + eax * 4], ecx 62 | invlpg [table_768 + eax * 4] 63 | add ebx, 4096 64 | inc eax 65 | cmp eax, 1024 66 | jne .fill_kernel_table 67 | 68 | enable_paging: 69 | mov ebx, table_0 70 | or ebx, 3 71 | mov [page_directory + 0], ebx 72 | 73 | mov ebx, table_768 74 | or ebx, 3 75 | mov [page_directory + 768 * 4], ebx 76 | 77 | mov eax, page_directory 78 | mov cr3, eax 79 | mov eax, cr0 80 | or eax, 0x80000000 81 | mov cr0, eax 82 | 83 | pop eax 84 | pop ebx 85 | 86 | jmp stublet 87 | 88 | section .text 89 | 90 | stublet: 91 | extern kernel_main 92 | extern _esp 93 | 94 | mov esp, sys_stack 95 | mov ebp, esp 96 | mov [_esp], esp 97 | 98 | push 0 99 | popf 100 | 101 | push ebx 102 | push eax 103 | mov ebp, 0 104 | call kernel_main 105 | cli 106 | hlt 107 | jmp $ 108 | 109 | switch_ring3: 110 | extern __ring3_addr 111 | extern set_kernel_stack 112 | extern process_set_by_pid 113 | extern process_enable_round_robin 114 | 115 | cli 116 | 117 | push esp 118 | call set_kernel_stack 119 | add esp, 4 120 | 121 | mov esi, [esp + 4] ; pdt 122 | mov eax, [esp + 8] ; addr 123 | mov esp, [esp + 12]; stack 124 | mov [__ring3_addr], eax 125 | 126 | mov cr3, esi 127 | xor esi, esi 128 | 129 | push 0 130 | push 0 131 | 132 | mov ax, (4 * 8) | 3 ; ring 3 data with bottom 2 bits set for ring 3 133 | mov ds, ax 134 | mov es, ax 135 | mov fs, ax 136 | mov gs, ax ; SS is handled by iret 137 | 138 | ; set up the stack frame iret expects 139 | mov eax, esp 140 | push (4 * 8) | 3 ; data selector 141 | push eax ; current esp 142 | sti 143 | pushf ; eflags 144 | cli 145 | push (3 * 8) | 3 ; code selector (ring 3 code with bottom 2 bits set for ring 3) 146 | 147 | mov eax, [__ring3_addr] 148 | push eax 149 | 150 | push 1 151 | call process_set_by_pid 152 | add esp, 4 153 | call process_enable_round_robin 154 | 155 | iret 156 | ret 157 | 158 | section .bss 159 | 160 | sys_stack_bottom: 161 | resb 0x8000 162 | sys_stack: 163 | 164 | section .bss.setup 165 | 166 | page_directory: 167 | resd 1024 168 | table_0: 169 | resd 1024 170 | table_768: 171 | resd 1024 172 | proto_stack_bottom: 173 | resb 0x100 174 | proto_stack: 175 | -------------------------------------------------------------------------------- /kernel/kernel.h: -------------------------------------------------------------------------------- 1 | #ifndef KERNEL_H 2 | #define KERNEL_H 3 | 4 | #include 5 | 6 | #define KERNEL_ADDR 0x100000 7 | 8 | extern char kernel_start_real_addr[]; 9 | extern char kernel_start_addr[]; 10 | extern char kernel_end_addr[]; 11 | extern char kernel_end_real_addr[]; 12 | 13 | extern void restore_segment_selector(void); 14 | 15 | void kernel_int_wait(void); 16 | 17 | void kernel_main(uint32_t magic, uint32_t addr); 18 | 19 | #endif //KERNEL_H 20 | -------------------------------------------------------------------------------- /kernel/kernel.lds: -------------------------------------------------------------------------------- 1 | /* OUTPUT_FORMAT(elf32-i386); */ 2 | /* OUTPUT_ARCH(i386); */ 3 | 4 | ENTRY(_start); 5 | 6 | SECTIONS 7 | { 8 | . = 0x100000; 9 | 10 | PROVIDE(kernel_start_real_addr = .); 11 | 12 | .boot ALIGN(8) : 13 | { 14 | *(.multiboot2_header) 15 | } 16 | 17 | .text.setup ALIGN(0x1000) : 18 | { 19 | *(.text.setup) 20 | } 21 | 22 | .bss.setup ALIGN(0x1000) : 23 | { 24 | *(.bss.setup) 25 | } 26 | 27 | . += 0xC0000000; 28 | 29 | PROVIDE(kernel_start_addr = .); 30 | 31 | .text ALIGN(0x1000) : AT(ADDR(.text) - 0xC0000000) 32 | { 33 | *(.text) 34 | } 35 | 36 | .rodata ALIGN(0x1000) : AT(ADDR(.rodata) - 0xC0000000) 37 | { 38 | *(.rodata) 39 | } 40 | 41 | .data ALIGN(0x1000) : AT(ADDR(.data) - 0xC0000000) 42 | { 43 | *(.data) 44 | } 45 | 46 | .debug_line ALIGN(0x1000) : AT(ADDR(.debug_line) - 0xC0000000) 47 | { 48 | *(.debug_line) 49 | } 50 | 51 | .bss ALIGN(0x1000) : AT(ADDR(.bss) - 0xC0000000) 52 | { 53 | *(.bss) 54 | } 55 | 56 | PROVIDE(kernel_end_addr = .); 57 | 58 | . -= 0xC0000000; 59 | 60 | PROVIDE(kernel_end_real_addr = .); 61 | } 62 | -------------------------------------------------------------------------------- /kernel/kstring.c: -------------------------------------------------------------------------------- 1 | #include "kstring.h" 2 | -------------------------------------------------------------------------------- /kernel/kstring.h: -------------------------------------------------------------------------------- 1 | #ifndef KSTRING_H 2 | #define KSTRING_H 3 | 4 | typedef struct string_t { 5 | char *str; 6 | unsigned int len; 7 | } string_t; 8 | 9 | #endif 10 | -------------------------------------------------------------------------------- /kernel/libc/arpa/inet.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "../../bits.h" 4 | 5 | inline uint64_t htonll(uint64_t hostlonglong) { 6 | #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ 7 | return switch_endian_64(hostlonglong); 8 | #else 9 | return hostlonglong; 10 | #endif 11 | } 12 | 13 | inline uint32_t htonl(uint32_t hostlong) { 14 | #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ 15 | return switch_endian_32(hostlong); 16 | #else 17 | return hostlong; 18 | #endif 19 | } 20 | 21 | inline uint16_t htons(uint16_t hostshort) { 22 | #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ 23 | return switch_endian_16(hostshort); 24 | #else 25 | return hostshort; 26 | #endif 27 | } 28 | 29 | inline uint64_t ntohll(uint64_t netlonglong) { 30 | #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ 31 | return switch_endian_64(netlonglong); 32 | #else 33 | return netlonglong; 34 | #endif 35 | } 36 | 37 | inline uint32_t ntohl(uint32_t netlong) { 38 | #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ 39 | return switch_endian_32(netlong); 40 | #else 41 | return netlong; 42 | #endif 43 | } 44 | 45 | inline uint16_t ntohs(uint16_t netshort) { 46 | #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ 47 | return switch_endian_16(netshort); 48 | #else 49 | return netshort; 50 | #endif 51 | } 52 | -------------------------------------------------------------------------------- /kernel/libc/ctype.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int isalnum(int c) { 4 | return isalpha(c) || isdigit(c); 5 | } 6 | 7 | int isalpha(int c) { 8 | return islower(c) || isupper(c); 9 | } 10 | 11 | int isblank(int c) { 12 | return c == ' ' || c == '\t'; 13 | } 14 | 15 | int iscntrl(int c) { 16 | return (c >= 0 && c <= 31) || c == 127; 17 | } 18 | 19 | int isdigit(int c) { 20 | return c >= '0' && c <= '9'; 21 | } 22 | 23 | int isgraph(int c) { 24 | return c >= 33 && c <= 126; 25 | } 26 | 27 | int islower(int c) { 28 | return c >= 'a' && c <= 'z'; 29 | } 30 | 31 | int isprint(int c) { 32 | return isgraph(c) || c == ' '; 33 | } 34 | 35 | int ispunct(int c) { 36 | return isgraph(c) && !isalnum(c); 37 | } 38 | 39 | int isspace(int c) { 40 | return isblank(c) || c >= 9 && c <= 13; 41 | } 42 | 43 | int isupper(int c) { 44 | return c >= 'A' && c <= 'Z'; 45 | } 46 | 47 | int isxdigit(int c) { 48 | return isdigit(c) || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F'); 49 | } 50 | 51 | int toupper(int c) { 52 | if (c >= 'a' && c <= 'z') { 53 | return 'A' + c - 'a'; 54 | } 55 | 56 | return c; 57 | } 58 | 59 | int tolower(int c) { 60 | if (c >= 'A' && c <= 'Z') { 61 | return 'a' + c - 'A'; 62 | } 63 | 64 | return c; 65 | } 66 | -------------------------------------------------------------------------------- /kernel/libc/errno.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int errno; 4 | -------------------------------------------------------------------------------- /kernel/libc/include/arpa/inet.h: -------------------------------------------------------------------------------- 1 | #ifndef ARPA_INET_H 2 | #define ARPA_INET_H 3 | 4 | #include 5 | 6 | uint64_t htonll(uint64_t hostlonglong); 7 | uint32_t htonl(uint32_t hostlong); 8 | uint16_t htons(uint16_t hostshort); 9 | uint64_t ntohll(uint64_t netlonglong); 10 | uint32_t ntohl(uint32_t netlong); 11 | uint16_t ntohs(uint16_t netshort); 12 | 13 | #endif // ARPA_INET_H 14 | -------------------------------------------------------------------------------- /kernel/libc/include/ctype.h: -------------------------------------------------------------------------------- 1 | #ifndef CTYPE_H 2 | #define CTYPE_H 3 | 4 | int isalnum(int c); 5 | 6 | int isalpha(int c); 7 | 8 | int isblank(int c); 9 | 10 | int iscntrl(int c); 11 | 12 | int isdigit(int c); 13 | 14 | int isgraph(int c); 15 | 16 | int islower(int c); 17 | 18 | int isprint(int c); 19 | 20 | int ispunct(int c); 21 | 22 | int isspace(int c); 23 | 24 | int isupper(int c); 25 | 26 | int isxdigit(int c); 27 | 28 | int toupper(int c); 29 | 30 | int tolower(int c); 31 | 32 | #endif //CTYPE_H 33 | -------------------------------------------------------------------------------- /kernel/libc/include/dirent.h: -------------------------------------------------------------------------------- 1 | #ifndef DIRENT_H 2 | #define DIRENT_H 3 | 4 | #include 5 | 6 | #define NAME_MAX 256 7 | 8 | typedef struct DIR DIR; 9 | 10 | struct dirent { 11 | ino_t d_ino; /* Inode number */ 12 | off_t d_off; /* Not an offset; see below */ 13 | unsigned short d_reclen; /* Length of this record */ 14 | unsigned char d_type; /* Type of file; not supported by all filesystem types */ 15 | char d_name[NAME_MAX]; /* Null-terminated filename */ 16 | }; 17 | 18 | #endif // DIRENT_H 19 | -------------------------------------------------------------------------------- /kernel/libc/include/fcntl.h: -------------------------------------------------------------------------------- 1 | #ifndef FCNTL_H 2 | #define FCNTL_H 3 | 4 | enum OpenFlags { 5 | O_RDONLY = 0, 6 | O_WRONLY = 1, 7 | O_RDWR = 2, 8 | 9 | O_APPEND = 1024, 10 | O_ASYNC = 8192, 11 | O_CLOEXEC = 524288, 12 | O_CREAT = 64, 13 | O_DIRECT = 16384, 14 | O_DIRECTORY = 65536, 15 | O_DSYNC = 4096, 16 | O_EXCL = 128, 17 | O_LARGEFILE = 0, 18 | O_NOATIME = 262144, 19 | O_NOCTTY = 256, 20 | O_NOFOLLOW = 131072, 21 | O_NONBLOCK = 2048, 22 | O_NDELAY = 2048, 23 | O_PATH = 2097152, 24 | O_SYNC = 1052672, 25 | O_TMPFILE = 4194304, 26 | O_TRUNC = 512 27 | }; 28 | 29 | #endif // FCNTL_H 30 | -------------------------------------------------------------------------------- /kernel/libc/include/math.h: -------------------------------------------------------------------------------- 1 | #ifndef MATH_H 2 | #define MATH_H 3 | 4 | #define M_PI 3.14159265358979323846 5 | #define M_E 2.71828182845904523536 6 | 7 | #define NAN (0.0 / 0.0) 8 | #define INFINITY (1e300 * 1e300) 9 | 10 | float fabs(float x); 11 | 12 | double fabsl(double x); 13 | 14 | float powf(float base, float power); 15 | 16 | double powl(double base, double power); 17 | 18 | float exp(float x); 19 | 20 | double expl(double x); 21 | 22 | float log(float x); 23 | 24 | double logl(double x); 25 | 26 | int isnanf(float x); 27 | 28 | int isnanl(double x); 29 | 30 | int isinff(float x); 31 | 32 | int isinfl(double x); 33 | 34 | #endif //MATH_H 35 | -------------------------------------------------------------------------------- /kernel/libc/include/stdarg.h: -------------------------------------------------------------------------------- 1 | #ifndef STDARG_H 2 | #define STDARG_H 3 | 4 | #define va_start(va_list, last_arg) __builtin_va_start(va_list, last_arg) 5 | #define va_end(va_list) __builtin_va_end(va_list) 6 | #define va_arg(va_list, last_arg) __builtin_va_arg(va_list, last_arg) 7 | 8 | typedef __builtin_va_list va_list; 9 | 10 | #endif //STDARG_H 11 | -------------------------------------------------------------------------------- /kernel/libc/include/stdbool.h: -------------------------------------------------------------------------------- 1 | #ifndef STDBOOL_H 2 | #define STDBOOL_H 3 | 4 | typedef _Bool bool; 5 | 6 | #define true 1 7 | #define false 0 8 | 9 | #define __bool_true_false_are_defined 1 10 | 11 | #endif // STDBOOL_H 12 | -------------------------------------------------------------------------------- /kernel/libc/include/stddef.h: -------------------------------------------------------------------------------- 1 | #ifndef STDDEF_H 2 | #define STDDEF_H 3 | 4 | typedef unsigned int size_t; 5 | 6 | typedef int wchar_t; 7 | 8 | #ifndef NULL 9 | #define NULL (void *)0 10 | #endif 11 | 12 | #endif //STDDEF_H 13 | -------------------------------------------------------------------------------- /kernel/libc/include/stdint.h: -------------------------------------------------------------------------------- 1 | #ifndef STDINT_H 2 | #define STDINT_H 3 | 4 | typedef __INT8_TYPE__ int8_t; 5 | typedef __INT16_TYPE__ int16_t; 6 | typedef __INT32_TYPE__ int32_t; 7 | typedef __INT64_TYPE__ int64_t; 8 | typedef __UINT8_TYPE__ uint8_t; 9 | typedef __UINT16_TYPE__ uint16_t; 10 | typedef __UINT32_TYPE__ uint32_t; 11 | typedef __UINT64_TYPE__ uint64_t; 12 | 13 | typedef __INT_LEAST8_TYPE__ int_least8_t; 14 | typedef __INT_LEAST16_TYPE__ int_least16_t; 15 | typedef __INT_LEAST32_TYPE__ int_least32_t; 16 | typedef __INT_LEAST64_TYPE__ int_least64_t; 17 | typedef __UINT_LEAST8_TYPE__ uint_least8_t; 18 | typedef __UINT_LEAST16_TYPE__ uint_least16_t; 19 | typedef __UINT_LEAST32_TYPE__ uint_least32_t; 20 | typedef __UINT_LEAST64_TYPE__ uint_least64_t; 21 | 22 | typedef __INT_FAST8_TYPE__ int_fast8_t; 23 | typedef __INT_FAST16_TYPE__ int_fast16_t; 24 | typedef __INT_FAST32_TYPE__ int_fast32_t; 25 | typedef __INT_FAST64_TYPE__ int_fast64_t; 26 | typedef __UINT_FAST8_TYPE__ uint_fast8_t; 27 | typedef __UINT_FAST16_TYPE__ uint_fast16_t; 28 | typedef __UINT_FAST32_TYPE__ uint_fast32_t; 29 | typedef __UINT_FAST64_TYPE__ uint_fast64_t; 30 | 31 | typedef __INTPTR_TYPE__ intptr_t; 32 | typedef __UINTPTR_TYPE__ uintptr_t; 33 | 34 | typedef __INTMAX_TYPE__ intmax_t; 35 | typedef __UINTMAX_TYPE__ uintmax_t; 36 | 37 | #endif //STDINT_H 38 | -------------------------------------------------------------------------------- /kernel/libc/include/stdio.h: -------------------------------------------------------------------------------- 1 | #ifndef STDIO_H 2 | #define STDIO_H 3 | 4 | #include 5 | #include "../../modules/fd.h" 6 | 7 | #define EOF (-1) 8 | 9 | #ifndef NULL 10 | #define NULL (void *)0 11 | #endif 12 | 13 | typedef struct iobuf { 14 | char *ptr; 15 | int cnt; 16 | char *base; 17 | int flag; 18 | int file; 19 | int charbuf; 20 | int bufsiz; 21 | } FILE; 22 | 23 | extern FILE *stdin; 24 | extern FILE *stdout; 25 | extern FILE *stderr; 26 | 27 | #define STDIN_FILENO 0 28 | #define STDOUT_FILENO 1 29 | #define STDERR_FILENO 2 30 | 31 | int fclose(FILE *stream); 32 | 33 | int fflush(FILE *stream); 34 | 35 | FILE *fopen(const char *filename, const char *mode); 36 | 37 | FILE *freopen(const char *filename, const char *mode, FILE *stream); 38 | 39 | int getchar(void); 40 | 41 | int putchar(char c); 42 | 43 | int read(file_descriptor *fd, void *buf, int size); 44 | 45 | int write(file_descriptor *fd, const void *buf, int size); 46 | 47 | int puts(const char *str); 48 | 49 | int vprintf(const char *format, va_list args); 50 | 51 | int printf(const char *format, ...); 52 | 53 | int vsprintf(char *str, const char *format, va_list args); 54 | 55 | int sprintf(char *str, const char *format, ...); 56 | 57 | int scanf(const char *format, ...); 58 | 59 | #endif //STDIO_H 60 | -------------------------------------------------------------------------------- /kernel/libc/include/stdlib.h: -------------------------------------------------------------------------------- 1 | #ifndef STDLIB_H 2 | #define STDLIB_H 3 | 4 | #include 5 | 6 | enum ExitCodes { 7 | EXIT_SUCCESS = 0, 8 | EXIT_FAILURE = 1, 9 | }; 10 | 11 | #define MB_CUR_MAX 8 12 | #ifndef NULL 13 | #define NULL (void *)0 14 | #endif 15 | #define RAND_MAX 32767 16 | 17 | typedef struct div_t { 18 | int quot; 19 | int rem; 20 | } div_t; 21 | 22 | typedef struct ldiv_t { 23 | long int quot; 24 | long int rem; 25 | } ldiv_t; 26 | 27 | #define _MIN_MALLOC_SIZE 16 28 | 29 | float atof(const char *str); 30 | 31 | int atoi(const char *str); 32 | 33 | char *htoa(short int value, char *str, int base); 34 | 35 | char *itoa(int value, char *str, int base); 36 | 37 | char *ltoa(long int value, char *str, int base); 38 | 39 | char *hutoa(unsigned short int value, char *str, int base); 40 | 41 | char *utoa(unsigned int value, char *str, int base); 42 | 43 | char *lutoa(unsigned long int value, char *str, int base); 44 | 45 | char *ftoa(float value, char *str, int precision); 46 | 47 | char *lftoa(double value, char *str, int precision); 48 | 49 | long int atol(const char *str); 50 | 51 | double strtod(const char *str, char **endptr); 52 | 53 | long int strtol(const char *str, char **endptr, int base); 54 | 55 | unsigned long int strtoul(const char *str, char **endptr, int base); 56 | 57 | void kernel_malloc_init(void); 58 | 59 | void *calloc(size_t num, size_t size); 60 | 61 | void *calloc_align(size_t num, size_t size, size_t align); 62 | 63 | void free(void *ptr); 64 | 65 | void *malloc(size_t size); 66 | 67 | void *malloc_align(size_t size, size_t align); 68 | 69 | void *realloc(void *ptr, size_t size); 70 | 71 | void abort(void); 72 | 73 | int atexit(void (*func)(void)); 74 | 75 | void exit(int status); 76 | 77 | char *getenv(const char *name); 78 | 79 | int system(const char *command); 80 | 81 | void *bsearch(const void *key, const void *base, size_t num, size_t size, int (*compar)(const void *, const void *)); 82 | 83 | void qsort(void *base, size_t num, size_t size, int (*compar)(const void *, const void *)); 84 | 85 | div_t div(int numer, int denom); 86 | 87 | ldiv_t ldiv(long int numer, long int denom); 88 | 89 | int abs(int x); 90 | 91 | long int labs(long int x); 92 | 93 | int rand(void); 94 | 95 | void srand(unsigned int seed); 96 | 97 | int mblen(const char *pmb, size_t max); 98 | 99 | size_t mbstowcs(wchar_t *dest, const char *src, size_t max); 100 | 101 | int mbtowc(wchar_t *pwc, const char *pmb, size_t max); 102 | 103 | size_t wcstombs(char *dest, const wchar_t *src, size_t max); 104 | 105 | int wctomb(char *pmb, wchar_t wc); 106 | 107 | #endif //STDLIB_H 108 | -------------------------------------------------------------------------------- /kernel/libc/include/string.h: -------------------------------------------------------------------------------- 1 | #ifndef STRING_H 2 | #define STRING_H 3 | 4 | #include 5 | 6 | void *memcpy(void *destination, const void *source, size_t n); 7 | 8 | char *strcpy(char *destination, const char *source); 9 | 10 | char *strncpy(char *destination, const char *source, size_t n); 11 | 12 | void *memmove(void *dest, const void *source, size_t n); 13 | 14 | char *strcat(char *destination, const char *source); 15 | 16 | char *strncat(char *destination, const char *source, size_t n); 17 | 18 | char *strupr(char *str); 19 | 20 | char *strlwr(char *str); 21 | 22 | int memcmp(const void *ptr1, const void *ptr2, size_t num); 23 | 24 | int strcmp(const char *str1, const char *str2); 25 | 26 | int strncmp(const char *str1, const char *str2, size_t num); 27 | 28 | const void *memchr(const void *ptr, int value, size_t num); 29 | 30 | const char *strchr(const char *str, int character); 31 | 32 | size_t strcspn(const char *str1, const char *str2); 33 | 34 | char *strpbrk(const char *str1, const char *str2); 35 | 36 | char *strrchr(const char *str, int character); 37 | 38 | size_t strspn(const char *str1, const char *str2); 39 | 40 | char *strstr(const char *str1, const char *str2); 41 | 42 | char *strtok(char *str, const char *delimiters); 43 | 44 | size_t strlen(const char *str); 45 | 46 | void *memset(void *ptr, int value, size_t num); 47 | 48 | #endif //STRING_H 49 | -------------------------------------------------------------------------------- /kernel/libc/include/sys/stat.h: -------------------------------------------------------------------------------- 1 | #ifndef STAT_H 2 | #define STAT_H 3 | 4 | #include 5 | 6 | struct stat { 7 | dev_t st_dev; /* ID of device containing file */ 8 | ino_t st_ino; /* inode number */ 9 | mode_t st_mode; /* protection */ 10 | nlink_t st_nlink; /* number of hard links */ 11 | uid_t st_uid; /* user ID of owner */ 12 | gid_t st_gid; /* group ID of owner */ 13 | dev_t st_rdev; /* device ID (if special file) */ 14 | off_t st_size; /* total size, in bytes */ 15 | blksize_t st_blksize; /* blocksize for file system I/O */ 16 | blkcnt_t st_blocks; /* number of 512B blocks allocated */ 17 | time_t st_atime; /* time of last access */ 18 | time_t st_mtime; /* time of last modification */ 19 | time_t st_ctime; /* time of last status change */ 20 | void *st_private; /* private data used by the implementation */ 21 | }; 22 | 23 | enum FileTypes { 24 | S_IFMT = 0xF000, /* Type of file descriptor */ 25 | S_IFBLK = 0x6000, /* block device */ 26 | S_IFCHR = 0x2000, /* character device */ 27 | S_IFIFO = 0x1000, /* FIFO (named pipe) */ 28 | S_IFREG = 0x8000, /* regular */ 29 | S_IFDIR = 0x4000, /* directory */ 30 | S_IFLNK = 0xA000, /* symbolic link */ 31 | S_IFSOCK = 0xC000, /* socket */ 32 | }; 33 | 34 | enum FileModes { 35 | S_IRWXU = 00700, /* Read, write, execute/search by owner */ 36 | S_IRUSR = 00400, /* Read permission, owner */ 37 | S_IWUSR = 00200, /* Write permission, owner */ 38 | S_IXUSR = 00100, /* Execute/search permission, owner */ 39 | S_IRWXG = 00070, /* Read, write, execute/search by group */ 40 | S_IRGRP = 00040, /* Read permission, group */ 41 | S_IWGRP = 00020, /* Write permission, group */ 42 | S_IXGRP = 00010, /* Execute/search permission, group */ 43 | S_IRWXO = 00007, /* Read, write, execute/search by others */ 44 | S_IROTH = 00004, /* Read permission, others */ 45 | S_IWOTH = 00002, /* Write permission, others */ 46 | S_IXOTH = 00001, /* Execute/search permission, others */ 47 | S_ISVTX = 01000, /* Sticky bit */ 48 | S_ISGID = 02000, /* Set-group-ID on execution */ 49 | S_ISUID = 04000, /* Set-user-ID on execution */ 50 | }; 51 | 52 | #endif // STAT_H 53 | -------------------------------------------------------------------------------- /kernel/libc/include/sys/types.h: -------------------------------------------------------------------------------- 1 | #ifndef SYS_TYPES_H 2 | #define SYS_TYPES_H 3 | 4 | #include 5 | 6 | typedef long blkcnt_t; 7 | typedef long blksize_t; 8 | typedef long clock_t; 9 | typedef long clockid_t; 10 | typedef long dev_t; 11 | typedef long fsblkcnt_t; 12 | typedef long fsfilcnt_t; 13 | typedef long gid_t; 14 | typedef long id_t; 15 | typedef long ino_t; 16 | typedef long key_t; 17 | typedef long mode_t; 18 | typedef long nlink_t; 19 | typedef long off_t; 20 | typedef long pid_t; 21 | typedef long pthread_attr_t; 22 | typedef long pthread_cond_t; 23 | typedef long pthread_condattr_t; 24 | typedef long pthread_key_t; 25 | typedef long pthread_mutex_t; 26 | typedef long pthread_mutexattr_t; 27 | typedef long pthread_once_t; 28 | typedef long pthread_rwlock_t; 29 | typedef long pthread_rwlockattr_t; 30 | typedef long pthread_t; 31 | typedef unsigned long ssize_t; 32 | typedef long suseconds_t; 33 | typedef long time_t; 34 | typedef long timer_t; 35 | typedef long uid_t; 36 | typedef long useconds_t; 37 | 38 | #endif // SYS_TYPES_H 39 | -------------------------------------------------------------------------------- /kernel/libc/include/time.h: -------------------------------------------------------------------------------- 1 | #ifndef TIME_H 2 | #define TIME_H 3 | 4 | #include 5 | 6 | extern int daylight; 7 | extern long int timezone; 8 | extern char *tzname[]; 9 | 10 | struct tm { 11 | int tm_sec; // seconds after the minute - [0, 60] including leap second 12 | int tm_min; // minutes after the hour - [0, 59] 13 | int tm_hour; // hours since midnight - [0, 23] 14 | int tm_mday; // day of the month - [1, 31] 15 | int tm_mon; // months since January - [0, 11] 16 | int tm_year; // years since 1900 17 | int tm_wday; // days since Sunday - [0, 6] 18 | int tm_yday; // days since January 1 - [0, 365] 19 | int tm_isdst; // daylight saving time flag 20 | }; 21 | 22 | #define CLOCKS_PER_SEC 1000 23 | #define CLK_TCK CLOCKS_PER_SEC 24 | 25 | struct timespec { 26 | time_t tv_sec; // seconds 27 | long tv_nsec; // nanoseconds 28 | }; 29 | 30 | #endif // TIME_H 31 | -------------------------------------------------------------------------------- /kernel/libc/math.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | 5 | float fabs(float x) { 6 | return fabsl((double)x); 7 | } 8 | 9 | double fabsl(double x) { 10 | return x < 0 ? -x : x; 11 | } 12 | 13 | float powf(float base, float power) { 14 | return (float)powl((double)base, (double)power); 15 | } 16 | 17 | double powl(double base, double power) { 18 | // a^b = exp(b * ln(a)) 19 | return expl(power * logl(base)); 20 | } 21 | 22 | float exp(float x) { 23 | return (float)expl((double)x); 24 | } 25 | 26 | double expl(double x) { 27 | // Use Taylor series to calculate e^x 28 | // e^x = 1 + x + x^2/2! + x^3/3! + ... 29 | 30 | double sum = 1.0; 31 | double term = 1.0; 32 | 33 | for (int n = 1; fabsl(term) > 0.00001; n++) { 34 | term *= x / n; 35 | sum += term; 36 | } 37 | 38 | return sum; 39 | } 40 | 41 | float log(float x) { 42 | return (float)logl((double)x); 43 | } 44 | 45 | double logl(double x) { 46 | // Use Halley-Newton method to calculate log(x) 47 | // y[n+1] = y[n] + 2 * (x - exp(y[n])) / (x + exp(y[n])) 48 | 49 | double yn = x - 1.0F; 50 | double yn1 = yn; 51 | 52 | do { 53 | yn = yn1; 54 | yn1 = yn + 2.0F * (x - exp(yn)) / (x + exp(yn)); 55 | } while (fabs(yn1 - yn) > 0.00001F); 56 | 57 | return yn1; 58 | } 59 | 60 | int isnanf(float x) { 61 | // NaN is not equal to itself 62 | return x != x; 63 | } 64 | 65 | int isnanl(double x) { 66 | // NaN is not equal to itself 67 | return x != x; 68 | } 69 | 70 | int isinff(float x) { 71 | // exponents are all 1s 72 | x = fabs(x); 73 | long int p = *(long int *)&x; 74 | return (p >> 23) == 0xFF; 75 | } 76 | 77 | int isinfl(double x) { 78 | // exponent are all 1 79 | x = fabsl(x); 80 | long long int p = *(long long int *)&x; 81 | return (p >> 52) == 0x7FF; 82 | } 83 | -------------------------------------------------------------------------------- /kernel/libc/time.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int daylight; 4 | long int timezone; 5 | char *tzname[]; 6 | -------------------------------------------------------------------------------- /kernel/modules/acpica.c: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/modscleo4/dos/0592124a91b4fca6e0bc0791f5c7077c9af7e29e/kernel/modules/acpica.c -------------------------------------------------------------------------------- /kernel/modules/acpica.h: -------------------------------------------------------------------------------- 1 | #ifndef ACPICA_H 2 | #define ACPICA_H 3 | 4 | 5 | 6 | #endif // ACPICA_H 7 | -------------------------------------------------------------------------------- /kernel/modules/bitmap.h: -------------------------------------------------------------------------------- 1 | #ifndef BITMAP_H 2 | #define BITMAP_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include "../cpu/mmu.h" 8 | 9 | #define BITMAP_MAX_MEM 0x100000000 // 4GB 10 | #define BITMAP_PAGE_SIZE 4096 11 | 12 | void bitmap_init(void *start_address, size_t max_memory); 13 | 14 | void bitmap_id_map(page_directory_table *pdt); 15 | 16 | void *bitmap_alloc_page(void); 17 | 18 | void *bitmap_alloc_contiguous_pages(size_t pages); 19 | 20 | void bitmap_free_pages(void *addr, size_t pages); 21 | 22 | size_t bitmap_allocated_pages(void); 23 | 24 | size_t bitmap_total_pages(void); 25 | 26 | #endif // BITMAP_H 27 | -------------------------------------------------------------------------------- /kernel/modules/cmos.c: -------------------------------------------------------------------------------- 1 | #include "cmos.h" 2 | 3 | #include "../bits.h" 4 | 5 | uint8_t read_cmos_register(uint8_t reg, uint8_t nmi) { 6 | outb(0x70, (nmi << 7) | reg); 7 | return inb(0x71); 8 | } 9 | 10 | int from_bcd(int val) { 11 | return ((val / 16) * 10) + (val % 16); 12 | } 13 | -------------------------------------------------------------------------------- /kernel/modules/cmos.h: -------------------------------------------------------------------------------- 1 | #ifndef CMOS_H 2 | #define CMOS_H 3 | 4 | #include 5 | 6 | uint8_t read_cmos_register(uint8_t reg, uint8_t nmi); 7 | 8 | int from_bcd(int val); 9 | 10 | #endif // CMOS_H 11 | -------------------------------------------------------------------------------- /kernel/modules/elf.c: -------------------------------------------------------------------------------- 1 | #include "elf.h" 2 | 3 | #define DEBUG 1 4 | #define DEBUG_SERIAL 1 5 | 6 | #include 7 | #include 8 | #include "../debug.h" 9 | 10 | elf32_section_header *elf32_find_section(elf32_header *header, const char *name) { 11 | dbgprint("section_header_offset = %d\n", header->section_header_offset); 12 | dbgprint("section_name_index = %d\n", header->section_name_index); 13 | dbgprint("section_header_size = %d\n", header->section_header_size); 14 | dbgprint("section_header_count = %d\n", header->section_header_count); 15 | 16 | elf32_section_header *section_header = (elf32_section_header *)(((void *)header) + header->section_header_offset); 17 | elf32_section_header *section_name_header = (elf32_section_header *)(((void *)section_header) + (header->section_name_index) * header->section_header_size); 18 | dbgprint("section_header_addr = %p\n", section_header); 19 | dbgprint("section_name_header_addr = %p\n", section_name_header); 20 | dbgprint("section_name_header_offset = %p\n", section_name_header->offset); 21 | 22 | for (int i = 1; i <= header->section_header_count; i++) { 23 | char *section_name = (char *) ((void *)header) + section_name_header->offset + section_header->name; 24 | dbgprint("section_name_addr = %p\n", section_name); 25 | 26 | if (strcmp(section_name, name) == 0) { 27 | dbgprint("Found section %s at %p\n", name, section_header); 28 | return section_header; 29 | } 30 | 31 | section_header++; 32 | } 33 | 34 | return NULL; 35 | } 36 | 37 | elf64_section_header *elf64_find_section(elf64_header *header, const char *name) { 38 | elf64_section_header *section_header = (elf64_section_header *)(((void *)header) + header->section_header_offset); 39 | elf64_section_header *section_name_header = (elf64_section_header *)(((void *)section_header) + (header->section_name_index) * header->section_header_size); 40 | dbgprint("section_header_addr = %p\n", section_header); 41 | dbgprint("section_name_header_addr = %p\n", section_name_header); 42 | 43 | for (int i = 1; i <= header->section_header_count; i++) { 44 | char *section_name = (char *) ((void *)header) + section_name_header->offset + section_header->name; 45 | 46 | if (strcmp(section_name, name) == 0) { 47 | dbgprint("Found section %s at %p\n", name, section_header); 48 | return section_header; 49 | } 50 | 51 | section_header++; 52 | } 53 | 54 | return NULL; 55 | } 56 | -------------------------------------------------------------------------------- /kernel/modules/fd.c: -------------------------------------------------------------------------------- 1 | #include "fd.h" 2 | -------------------------------------------------------------------------------- /kernel/modules/fd.h: -------------------------------------------------------------------------------- 1 | #ifndef FD_H 2 | #define FD_H 3 | 4 | #include "../drivers/filesystem.h" 5 | #include "../drivers/iodriver.h" 6 | 7 | typedef struct file_descriptor { 8 | bool used; 9 | enum FileTypes type; 10 | iodriver *io; 11 | filesystem *fs; 12 | struct stat st; 13 | char path[256]; 14 | uint32_t tty; 15 | bool tty_canon; 16 | uint32_t offset; 17 | uint32_t flags; 18 | struct { 19 | bool read; 20 | bool write; 21 | } access; 22 | } file_descriptor; 23 | 24 | #endif // FD_H 25 | -------------------------------------------------------------------------------- /kernel/modules/heap.h: -------------------------------------------------------------------------------- 1 | #ifndef HEAP_H 2 | #define HEAP_H 3 | 4 | /** 5 | * Bitmap Heap 6 | */ 7 | 8 | #include 9 | #include 10 | #include 11 | 12 | typedef struct heap_block { 13 | struct heap_block *next; 14 | size_t size; 15 | size_t used; 16 | size_t block_size; 17 | size_t lfb; 18 | } heap_block; 19 | 20 | typedef struct heap { 21 | heap_block *first_block; 22 | } heap; 23 | 24 | void heap_init(heap *this); 25 | 26 | int heap_add_block(heap *this, void *addr, size_t size, size_t block_size); 27 | 28 | void *heap_alloc(heap *this, size_t size); 29 | 30 | size_t heap_allocated_size(heap *this, void *addr); 31 | 32 | bool heap_free(heap *this, void *addr); 33 | 34 | #endif // HEAP_H 35 | -------------------------------------------------------------------------------- /kernel/modules/kblayout/kb.c: -------------------------------------------------------------------------------- 1 | #include "kb.h" 2 | 3 | unsigned char *kblayout; 4 | -------------------------------------------------------------------------------- /kernel/modules/kblayout/kb.h: -------------------------------------------------------------------------------- 1 | #ifndef KB_H 2 | #define KB_H 3 | 4 | #include "us.h" 5 | 6 | extern unsigned char *kblayout; 7 | 8 | #endif // KB_H 9 | -------------------------------------------------------------------------------- /kernel/modules/kblayout/us.h: -------------------------------------------------------------------------------- 1 | #ifndef KB_US_H 2 | #define KB_US_H 3 | 4 | static const unsigned char kblayout_us[128] = { 5 | 0, 27, '1', '2', '3', '4', '5', '6', '7', '8', /* 9 */ 6 | '9', '0', '-', '=', '\b', /* Backspace */ 7 | '\t', /* Tab */ 8 | 'q', 'w', 'e', 'r', /* 19 */ 9 | 't', 'y', 'u', 'i', 'o', 'p', '[', ']', '\n', /* Enter key */ 10 | 0, /* 29 - Control */ 11 | 'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', /* 39 */ 12 | '\'', '`', 0, /* Left shift */ 13 | '\\', 'z', 'x', 'c', 'v', 'b', 'n', /* 49 */ 14 | 'm', ',', '.', '/', 0, /* Right shift */ 15 | '*', 16 | 0, /* Alt */ 17 | ' ', /* Space bar */ 18 | 0, /* Caps lock */ 19 | 0, /* 59 - F1 key ... > */ 20 | 0, 0, 0, 0, 0, 0, 0, 0, 21 | 0, /* < ... F10 */ 22 | 0, /* 69 - Num lock*/ 23 | 0, /* Scroll Lock */ 24 | 0, /* Home key */ 25 | 0, /* Up Arrow */ 26 | 0, /* Page Up */ 27 | '-', 28 | 0, /* Left Arrow */ 29 | 0, 30 | 0, /* Right Arrow */ 31 | '+', 32 | 0, /* 79 - End key*/ 33 | 0, /* Down Arrow */ 34 | 0, /* Page Down */ 35 | 0, /* Insert Key */ 36 | 0, /* Delete Key */ 37 | 0, 0, 0, 38 | 0, /* F11 Key */ 39 | 0, /* F12 Key */ 40 | 0, /* All other keys are undefined */ 41 | }; 42 | 43 | #endif //KB_US_H 44 | -------------------------------------------------------------------------------- /kernel/modules/net/arp.h: -------------------------------------------------------------------------------- 1 | #ifndef ARP_H 2 | #define ARP_H 3 | 4 | #include 5 | #include 6 | #include "../../drivers/ethernet.h" 7 | 8 | #pragma pack(push, 1) 9 | typedef struct arp_packet { 10 | uint16_t hardware_type; 11 | uint16_t protocol_type; 12 | uint8_t hardware_size; 13 | uint8_t protocol_size; 14 | uint16_t opcode; 15 | uint8_t sender_mac[6]; 16 | uint8_t sender_ip[4]; 17 | uint8_t target_mac[6]; 18 | uint8_t target_ip[4]; 19 | } arp_packet; 20 | #pragma pack(pop) 21 | 22 | enum ARPHardwareType { 23 | ARP_HW_ETHERNET = 0x0001, 24 | }; 25 | 26 | enum ARPProtocolType { 27 | ARP_PROTO_IPV4 = 0x0800, 28 | }; 29 | 30 | enum ARPOperation { 31 | ARP_OP_REQUEST = 0x01, 32 | ARP_OP_REPLY = 0x02, 33 | }; 34 | 35 | bool arp_get_mac(ethernet_driver *driver, uint8_t ip[4], uint8_t out_mac[6], int timeout); 36 | 37 | void arp_send_request(ethernet_driver *driver, uint8_t ip[4]); 38 | 39 | void arp_send_reply(ethernet_driver *driver, uint8_t ip[4], uint8_t mac[6]); 40 | 41 | void arp_receive_packet(ethernet_driver *driver, arp_packet *packet); 42 | 43 | #endif // ARP_H 44 | -------------------------------------------------------------------------------- /kernel/modules/net/dhcp.h: -------------------------------------------------------------------------------- 1 | #ifndef DHCP_H 2 | #define DHCP_H 3 | 4 | #include 5 | #include "../../drivers/ethernet.h" 6 | 7 | #pragma pack(push, 1) 8 | typedef struct dhcp_packet { 9 | uint8_t op; 10 | uint8_t htype; 11 | uint8_t hlen; 12 | uint8_t hops; 13 | uint32_t xid; 14 | uint16_t secs; 15 | uint16_t flags; 16 | uint8_t ciaddr[4]; 17 | uint8_t yiaddr[4]; 18 | uint8_t siaddr[4]; 19 | uint8_t giaddr[4]; 20 | uint8_t chaddr[16]; 21 | uint8_t sname[64]; 22 | uint8_t file[128]; 23 | uint32_t magic_cookie; 24 | uint8_t options[312]; 25 | } dhcp_packet; 26 | #pragma pack(pop) 27 | 28 | enum DHCPBootOperation { 29 | DHCP_BOOT_OP_REQUEST = 0x01, 30 | DHCP_BOOT_OP_REPLY = 0x02, 31 | }; 32 | 33 | enum DHCPOperation { 34 | DHCP_OP_DISCOVER = 0x01, 35 | DHCP_OP_OFFER = 0x02, 36 | DHCP_OP_REQUEST = 0x03, 37 | DHCP_OP_DECLINE = 0x04, 38 | DHCP_OP_ACK = 0x05, 39 | DHCP_OP_NAK = 0x06, 40 | DHCP_OP_RELEASE = 0x07, 41 | DHCP_OP_INFORM = 0x08, 42 | }; 43 | 44 | enum DHCPHardwareType { 45 | DHCP_HTYPE_ETHERNET = 0x01, 46 | }; 47 | 48 | enum DHCPOption { 49 | DHCP_OPTION_SUBNET_MASK = 0x01, 50 | DHCP_OPTION_ROUTER = 0x03, 51 | DHCP_OPTION_DNS_SERVER = 0x06, 52 | DHCP_OPTION_HOST_NAME = 0x0c, 53 | DHCP_OPTION_DOMAIN_NAME = 0x0f, 54 | DHCP_OPTION_REQUESTED_IP = 0x32, 55 | DHCP_OPTION_LEASE_TIME = 0x33, 56 | DHCP_OPTION_MESSAGE_TYPE = 0x35, 57 | DHCP_OPTION_SERVER_IDENTIFIER = 0x36, 58 | DHCP_OPTION_PARAMETER_REQUEST_LIST = 0x37, 59 | DHCP_OPTION_END = 0xff, 60 | }; 61 | 62 | void dhcp_init(ethernet_driver *driver); 63 | 64 | void dhcp_send_discover(ethernet_driver *driver); 65 | 66 | void dhcp_send_request(ethernet_driver *driver, uint8_t server_ip[4], uint8_t requested_ip[4]); 67 | 68 | #endif // DHCP_H 69 | -------------------------------------------------------------------------------- /kernel/modules/net/dns.h: -------------------------------------------------------------------------------- 1 | #ifndef DNS_H 2 | #define DNS_H 3 | 4 | #include 5 | #include 6 | #include "../../drivers/ethernet.h" 7 | 8 | #pragma pack(push, 1) 9 | typedef struct dns_header { 10 | uint16_t id; 11 | union { 12 | #pragma pack(push, 1) 13 | struct { 14 | uint8_t rcode : 4; 15 | uint8_t z : 3; 16 | bool ra : 1; 17 | bool rd : 1; 18 | bool tc : 1; 19 | bool aa : 1; 20 | uint8_t opcode : 4; 21 | bool qr : 1; 22 | }; 23 | #pragma pack(pop) 24 | uint16_t raw; 25 | } flags; 26 | uint16_t questions; 27 | uint16_t answers; 28 | uint16_t authority; 29 | uint16_t additional; 30 | } dns_header; 31 | #pragma pack(pop) 32 | 33 | #pragma pack(push, 1) 34 | typedef struct dns_query { 35 | uint16_t type; 36 | uint16_t class; 37 | } dns_query; 38 | #pragma pack(pop) 39 | 40 | #pragma pack(push, 1) 41 | typedef struct dns_answer { 42 | uint16_t type; 43 | uint16_t class; 44 | uint32_t ttl; 45 | uint16_t data_length; 46 | } dns_answer; 47 | #pragma pack(pop) 48 | 49 | enum DNSMessage { 50 | DNS_MESSAGE_QUERY = 0, 51 | DNS_MESSAGE_RESPONSE = 1, 52 | }; 53 | 54 | enum DNSOpcode { 55 | DNS_OPCODE_QUERY = 0, 56 | DNS_OPCODE_IQUERY = 1, 57 | DNS_OPCODE_STATUS = 2, 58 | }; 59 | 60 | enum DNSRCode { 61 | DNS_RCODE_NO_ERROR = 0, 62 | DNS_RCODE_FORMAT_ERROR = 1, 63 | DNS_RCODE_SERVER_FAILURE = 2, 64 | DNS_RCODE_NAME_ERROR = 3, 65 | DNS_RCODE_NOT_IMPLEMENTED = 4, 66 | DNS_RCODE_REFUSED = 5, 67 | DNS_RCODE_YXDOMAIN = 6, 68 | DNS_RCODE_YXRRSET = 7, 69 | DNS_RCODE_NOTAUTH = 8, 70 | DNS_RCODE_NOTZONE = 9, 71 | }; 72 | 73 | enum DNSType { 74 | DNS_TYPE_A = 1, 75 | DNS_TYPE_NS = 2, 76 | DNS_TYPE_CNAME = 5, 77 | DNS_TYPE_SOA = 6, 78 | DNS_TYPE_PTR = 12, 79 | DNS_TYPE_MX = 15, 80 | DNS_TYPE_TXT = 16, 81 | DNS_TYPE_AAAA = 28, 82 | DNS_TYPE_SRV = 33, 83 | DNS_TYPE_OPT = 41, 84 | DNS_TYPE_ANY = 255, 85 | }; 86 | 87 | enum DNSClass { 88 | DNS_CLASS_IN = 1, 89 | DNS_CLASS_ANY = 255, 90 | }; 91 | 92 | void dns_init(void); 93 | 94 | bool dns_send_query(ethernet_driver *driver, uint8_t dns_server_ip[4], const char *domain, int type); 95 | 96 | bool dns_query_ipv4(ethernet_driver *driver, uint8_t dns_server_ip[4], const char *domain, uint8_t ip[4], int timeout); 97 | 98 | #endif // DNS_H 99 | -------------------------------------------------------------------------------- /kernel/modules/net/http.c: -------------------------------------------------------------------------------- 1 | #include "http.h" 2 | 3 | #define DEBUG 1 4 | 5 | #include 6 | #include 7 | #include 8 | #include "../../debug.h" 9 | #include "../../bits.h" 10 | 11 | void http_send_request(ethernet_driver *driver, uint8_t destination_ip[4], uint16_t destination_port, const char *method, const char *path, const char *host) { 12 | dbgprint("http_send_request\n"); 13 | char *request = calloc(1024, sizeof(char)); 14 | uint16_t source_port = 10101; 15 | sprintf(request, "%s %s HTTP/1.1\r\nHost: %s\r\nConnection: close\r\n\r\n", method, path, host); 16 | tcp_install_listener(source_port, http_receive_request); 17 | uint32_t ack; 18 | if (tcp_syn(driver, destination_ip, destination_port, source_port, 10000, &ack)) { 19 | tcp_send_packet(driver, driver->ipv4.ip, source_port, destination_ip, destination_port, 0, ack, false, true, false, true, request, strlen(request)); 20 | // tcp_close_connection(driver, destination_ip, destination_port, source_port); 21 | } 22 | 23 | free(request); 24 | } 25 | 26 | bool http_receive_request(ethernet_driver *driver, void *data, size_t data_size) { 27 | if (data_size == 0) { 28 | return true; 29 | } 30 | 31 | //dbgprint("http_receive_request\n"); 32 | //hexdump(data, data_size); 33 | char *request = malloc(data_size + 1); 34 | memcpy(request, data, data_size); 35 | 36 | dbgprint("%s\n", request); 37 | 38 | free(request); 39 | return true; 40 | } 41 | -------------------------------------------------------------------------------- /kernel/modules/net/http.h: -------------------------------------------------------------------------------- 1 | #ifndef HTTP_H 2 | #define HTTP_H 3 | 4 | #include 5 | #include 6 | #include "ip.h" 7 | #include "tcp.h" 8 | 9 | void http_send_request(ethernet_driver *driver, uint8_t destination_ip[4], uint16_t destination_port, const char *method, const char *path, const char *host); 10 | 11 | bool http_receive_request(ethernet_driver *driver, void *data, size_t data_size); 12 | 13 | #endif // HTTP_H 14 | -------------------------------------------------------------------------------- /kernel/modules/net/icmp.c: -------------------------------------------------------------------------------- 1 | #include "icmp.h" 2 | 3 | void icmp_receive_packet(ethernet_driver *driver, ipv4_packet *ipv4_packet, icmp_packet *packet, void *data) { 4 | 5 | } 6 | -------------------------------------------------------------------------------- /kernel/modules/net/icmp.h: -------------------------------------------------------------------------------- 1 | #ifndef ICMP_H 2 | #define ICMP_H 3 | 4 | #include 5 | #include 6 | #include "ip.h" 7 | 8 | #pragma pack(push, 1) 9 | typedef struct icmp_packet { 10 | uint8_t type; 11 | uint8_t code; 12 | uint16_t checksum; 13 | union { 14 | struct { 15 | uint16_t identifier; 16 | uint16_t sequence_number; 17 | } echo; 18 | 19 | struct { 20 | uint16_t unused; 21 | uint16_t mtu; 22 | } fragmentation; 23 | }; 24 | uint8_t data[]; 25 | } icmp_packet; 26 | #pragma pack(pop) 27 | 28 | void icmp_receive_packet(ethernet_driver *driver, ipv4_packet *ipv4_packet, icmp_packet *packet, void *data); 29 | 30 | #endif // ICMP_H 31 | -------------------------------------------------------------------------------- /kernel/modules/net/tcp.h: -------------------------------------------------------------------------------- 1 | #ifndef TCP_H 2 | #define TCP_H 3 | 4 | #include 5 | #include 6 | #include "ip.h" 7 | #include "../../drivers/ethernet.h" 8 | 9 | #pragma pack(push, 1) 10 | typedef struct tcp_packet { 11 | uint16_t source_port; 12 | uint16_t destination_port; 13 | uint32_t sequence_number; 14 | uint32_t acknowledgement_number; 15 | bool ns: 1; 16 | uint8_t reserved: 3; 17 | uint8_t data_offset: 4; 18 | struct { 19 | bool fin: 1; 20 | bool syn: 1; 21 | bool rst: 1; 22 | bool psh: 1; 23 | bool ack: 1; 24 | bool urg: 1; 25 | bool ece: 1; 26 | bool cwr: 1; 27 | } flags; 28 | uint16_t window_size; 29 | uint16_t checksum; 30 | uint16_t urgent_pointer; 31 | } tcp_packet; 32 | #pragma pack(pop) 33 | 34 | typedef bool (*tcp_listener)(ethernet_driver *, void *, size_t); 35 | 36 | void tcp_init(void); 37 | 38 | void tcp_send_packet(ethernet_driver *driver, uint8_t source_ip[4], uint16_t source_port, uint8_t destination_ip[4], uint16_t destination_port, uint32_t seq, uint32_t ack, bool is_syn, bool is_ack, bool is_fin, bool is_data, void *data, size_t data_size); 39 | 40 | bool tcp_syn(ethernet_driver *driver, uint8_t destination_ip[4], uint16_t destination_port, uint16_t source_port, int timeout, uint32_t *ack); 41 | 42 | void tcp_close_connection(ethernet_driver *driver, uint8_t destination_ip[4], uint16_t destination_port, uint16_t source_port); 43 | 44 | bool tcp_install_listener(uint16_t port, tcp_listener listener); 45 | 46 | void tcp_uninstall_listener(uint16_t port); 47 | 48 | void tcp_receive_packet(ethernet_driver *driver, ipv4_packet *ipv4_packet, tcp_packet *packet, void *data); 49 | 50 | #endif // TCP_H 51 | -------------------------------------------------------------------------------- /kernel/modules/net/udp.c: -------------------------------------------------------------------------------- 1 | #include "udp.h" 2 | 3 | #define DEBUG 1 4 | #define DEBUG_SERIAL 1 5 | 6 | #include 7 | #include 8 | #include 9 | #include "../../debug.h" 10 | #include "../../bits.h" 11 | 12 | static udp_listener *udp_listeners = NULL; 13 | 14 | void udp_init(void) { 15 | udp_listeners = calloc(65536, sizeof(udp_listener)); 16 | } 17 | 18 | uint16_t udp_calculate_checksum(udp_packet *packet, uint8_t source_ip[4], uint8_t destination_ip[4], void *data, size_t data_size) { 19 | ipv4_pseudo_header ipv4_header; 20 | udp_packet pseudo_header; 21 | memcpy(ipv4_header.source_ip, source_ip, 4); 22 | memcpy(ipv4_header.destination_ip, destination_ip, 4); 23 | ipv4_header.zero = 0; 24 | ipv4_header.protocol = IP_PROTOCOL_UDP; 25 | ipv4_header.length = packet->length; 26 | memcpy(&pseudo_header, packet, sizeof(udp_packet)); 27 | pseudo_header.checksum = 0; 28 | 29 | uint32_t checksum = 0; 30 | 31 | uint16_t *data16 = (uint16_t *)&ipv4_header; 32 | for (size_t i = 0; i < sizeof(ipv4_pseudo_header) / 2; i++) { 33 | checksum += data16[i]; 34 | } 35 | 36 | data16 = (uint16_t *)&pseudo_header; 37 | for (size_t i = 0; i < sizeof(udp_packet) / 2; i++) { 38 | checksum += data16[i]; 39 | } 40 | 41 | data16 = (uint16_t *)data; 42 | for (size_t i = 0; i < data_size / 2; i++) { 43 | checksum += data16[i]; 44 | } 45 | 46 | if (data_size % 2) { 47 | checksum += ((uint8_t *)data)[data_size - 1]; 48 | } 49 | 50 | while (checksum >> 16) { 51 | checksum = (checksum & 0xFFFF) + (checksum >> 16); 52 | } 53 | 54 | return ~checksum; 55 | } 56 | 57 | bool udp_send_packet(ethernet_driver *driver, uint8_t source_ip[4], uint16_t source_port, uint8_t destination_ip[4], uint16_t destination_port, void *data, size_t data_size) { 58 | dbgprint("udp_send_packet\n"); 59 | udp_packet packet; 60 | memset(&packet, 0, sizeof(udp_packet)); 61 | packet.source_port = htons(source_port); 62 | packet.destination_port = htons(destination_port); 63 | packet.length = htons(data_size + sizeof(udp_packet)); 64 | packet.checksum = udp_calculate_checksum(&packet, source_ip, destination_ip, data, data_size); 65 | 66 | return ipv4_send_packet(driver, source_ip, destination_ip, IP_PROTOCOL_UDP, &packet, sizeof(udp_packet), data, data_size); 67 | } 68 | 69 | bool udp_install_listener(uint16_t port, udp_listener listener) { 70 | if (udp_listeners[port]) { 71 | return false; 72 | } 73 | 74 | udp_listeners[port] = listener; 75 | return true; 76 | } 77 | 78 | void udp_uninstall_listener(uint16_t port) { 79 | udp_listeners[port] = NULL; 80 | } 81 | 82 | void udp_receive_packet(ethernet_driver *driver, ipv4_packet *ipv4_packet, udp_packet *packet, void *data) { 83 | if (!udp_listeners) { 84 | return; 85 | } 86 | 87 | dbgprint("udp_receive_packet\n"); 88 | uint16_t port = ntohs(packet->destination_port); 89 | uint16_t checksum = packet->checksum; 90 | 91 | packet->checksum = 0; 92 | if (checksum != udp_calculate_checksum(packet, ipv4_packet->source_ip, ipv4_packet->destination_ip, data, ntohs(packet->length) - sizeof(udp_packet))) { 93 | dbgprint("udp_receive_packet: checksum failed\n"); 94 | return; 95 | } 96 | packet->checksum = checksum; 97 | 98 | if (udp_listeners[port]) { 99 | udp_listener listener = udp_listeners[port]; 100 | listener(driver, data, ntohs(packet->length) - sizeof(udp_packet)); 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /kernel/modules/net/udp.h: -------------------------------------------------------------------------------- 1 | #ifndef UDP_H 2 | #define UDP_H 3 | 4 | #include 5 | #include 6 | #include "ip.h" 7 | #include "../../drivers/ethernet.h" 8 | 9 | #pragma pack(push, 1) 10 | typedef struct udp_packet { 11 | uint16_t source_port; 12 | uint16_t destination_port; 13 | uint16_t length; 14 | uint16_t checksum; 15 | } udp_packet; 16 | #pragma pack(pop) 17 | 18 | typedef void (*udp_listener)(ethernet_driver *, void *, size_t); 19 | 20 | void udp_init(void); 21 | 22 | bool udp_send_packet(ethernet_driver *driver, uint8_t source_ip[4], uint16_t source_port, uint8_t destination_ip[4], uint16_t destination_port, void *data, size_t data_size); 23 | 24 | bool udp_install_listener(uint16_t port, udp_listener listener); 25 | 26 | void udp_uninstall_listener(uint16_t port); 27 | 28 | void udp_receive_packet(ethernet_driver *driver, ipv4_packet *ipv4_packet, udp_packet *packet, void *data); 29 | 30 | 31 | #endif // UDP_H 32 | -------------------------------------------------------------------------------- /kernel/modules/process.h: -------------------------------------------------------------------------------- 1 | #ifndef PROCESS_H 2 | #define PROCESS_H 3 | 4 | #include 5 | #include 6 | #include "fd.h" 7 | #include "../cpu/mmu.h" 8 | #include "../cpu/system.h" 9 | 10 | typedef struct process { 11 | size_t pid; 12 | size_t ppid; 13 | size_t uid; 14 | size_t gid; 15 | size_t euid; 16 | size_t egid; 17 | uint8_t state; 18 | bool suspended; 19 | char cwd[256]; 20 | uint32_t capabilities; 21 | uintptr_t stack_pointer; 22 | uintptr_t stack_base; 23 | uintptr_t entry; 24 | page_directory_table *pdt; 25 | registers r; 26 | size_t fd_count; 27 | file_descriptor *fd; 28 | } process; 29 | 30 | enum ProcessState { 31 | PROCESS_RUNNING, 32 | PROCESS_WAITING, 33 | PROCESS_STOPPED, 34 | PROCESS_ZOMBIE 35 | }; 36 | 37 | enum ProcessCapability { 38 | PROCESS_CAP_READ = 1, 39 | PROCESS_CAP_WRITE = 2, 40 | PROCESS_CAP_EXEC = 4, 41 | PROCESS_CAP_CHOWN = 8, 42 | PROCESS_CAP_CHMOD = 16, 43 | PROCESS_CAP_KILL = 32, 44 | PROCESS_CAP_FORK = 64, 45 | PROCESS_CAP_EXECVE = 128, 46 | PROCESS_CAP_SETUID = 256, 47 | PROCESS_CAP_SETGID = 512, 48 | }; 49 | 50 | void process_init(void); 51 | 52 | void process_disable(void); 53 | 54 | process *process_create(uintptr_t entry, uintptr_t stack_base, page_directory_table *pdt, bool switch_to); 55 | 56 | void process_save_curr_state(process *p, uint32_t eip); 57 | 58 | void process_destroy(process *p); 59 | 60 | void process_unload(registers *r); 61 | 62 | void process_reload(registers *r); 63 | 64 | void process_switch(process *p, registers *r); 65 | 66 | void process_enable_round_robin(); 67 | 68 | void process_disable_round_robin(); 69 | 70 | void process_round_robin(registers *r); 71 | 72 | process *process_by_pid(size_t pid); 73 | 74 | process *process_current(void); 75 | 76 | process *process_kernel(void); 77 | 78 | process *process_fork(process *p); 79 | 80 | int process_execve(process *p, registers *r, const char *path, char *const argv[], char *const envp[]); 81 | 82 | int process_open_file(process *p, const char *path, int flags); 83 | 84 | int process_close_file(process *p, int fd); 85 | 86 | int process_stat_file(process *p, const char *path, struct stat *st); 87 | 88 | #endif // PROCESS_H 89 | -------------------------------------------------------------------------------- /kernel/modules/spinlock.asm: -------------------------------------------------------------------------------- 1 | global spinlock_test_and_set 2 | global spinlock_release 3 | 4 | section .text 5 | spinlock_test_and_set: 6 | mov ecx, [esp+8] 7 | mov edx, [esp+4] 8 | retry: 9 | xor eax, eax 10 | xacquire lock cmpxchg [edx], ecx 11 | je out 12 | pause: 13 | mov eax, [edx] 14 | test eax, eax 15 | jz retry 16 | rep nop 17 | jmp pause 18 | out: 19 | ret 20 | 21 | ;mov ecx, [esp+8] 22 | ;mov edx, [esp+4] 23 | ;mov eax, ecx 24 | ;xchg eax, [ecx] 25 | ;test eax, eax 26 | ;jnz spinlock_test_and_set 27 | ;ret 28 | 29 | spinlock_release: 30 | mov edx, [esp+4] 31 | xrelease mov word [edx], 0 32 | ret 33 | 34 | ;mov ecx, [esp+4] 35 | ;xor eax, eax 36 | ;xchg eax, [ecx] 37 | ;ret 38 | -------------------------------------------------------------------------------- /kernel/modules/spinlock.c: -------------------------------------------------------------------------------- 1 | #include "spinlock.h" 2 | 3 | #define DEBUG 1 4 | 5 | #include "../cpu/panic.h" 6 | #include "../debug.h" 7 | 8 | #define MAX_SPINLOCK 16 9 | 10 | static spinlock locks[MAX_SPINLOCK]; 11 | static volatile int lock_index = 0; 12 | 13 | spinlock *spinlock_init(void) { 14 | if (lock_index >= MAX_SPINLOCK) { 15 | panic("too many locks"); 16 | } 17 | 18 | spinlock *lock = &locks[lock_index++]; 19 | lock->locked = 0; 20 | return lock; 21 | } 22 | 23 | void spinlock_lock(spinlock *lock) { 24 | spinlock_test_and_set(&lock->locked, 1); 25 | } 26 | 27 | void spinlock_unlock(spinlock *lock) { 28 | spinlock_release(&lock->locked); 29 | } 30 | -------------------------------------------------------------------------------- /kernel/modules/spinlock.h: -------------------------------------------------------------------------------- 1 | #ifndef SPINLOCK_H 2 | #define SPINLOCK_H 3 | 4 | typedef struct spinlock { 5 | volatile int locked; 6 | } spinlock; 7 | 8 | extern int spinlock_test_and_set(volatile int *ptr, int val); 9 | 10 | extern void spinlock_release(volatile int *ptr); 11 | 12 | spinlock *spinlock_init(void); 13 | 14 | void spinlock_lock(spinlock *lock); 15 | 16 | void spinlock_unlock(spinlock *lock); 17 | 18 | #endif // SPINLOCK_H 19 | -------------------------------------------------------------------------------- /kernel/modules/timer.c: -------------------------------------------------------------------------------- 1 | #include "timer.h" 2 | 3 | #define DEBUG 1 4 | #define DEBUG_TIMER 1 5 | 6 | #include 7 | #include "bitmap.h" 8 | #include "cmos.h" 9 | #include "process.h" 10 | #include "../bits.h" 11 | #include "../debug.h" 12 | #include "../cpu/irq.h" 13 | #include "../cpu/pic.h" 14 | #include "../cpu/system.h" 15 | #include "../drivers/screen.h" 16 | 17 | static time t; 18 | static date d; 19 | static int timer_ticks = 0; 20 | 21 | static bool display_time = false; 22 | 23 | static void read_rtc(void) { 24 | t.second = from_bcd(read_cmos_register(0x00, 1)); 25 | t.minute = from_bcd(read_cmos_register(0x02, 1)); 26 | t.hour = from_bcd(read_cmos_register(0x04, 1)); 27 | 28 | d.day = from_bcd(read_cmos_register(0x07, 1)); 29 | d.month = from_bcd(read_cmos_register(0x08, 1)); 30 | d.year = from_bcd(read_cmos_register(0x09, 1)); 31 | 32 | int century = from_bcd(read_cmos_register(0x32, 1)); 33 | if (century == 0) { 34 | century = d.year >= 90 ? 19 : 20; 35 | } 36 | d.year += century * 100; 37 | } 38 | 39 | void rtc_init(void) { 40 | outb(0x70, 0x8A); 41 | outb(0x71, 0x20); 42 | 43 | read_rtc(); 44 | dbgprint("Time/date: %02d/%02d/%04d %02d:%02d:%02d\n", d.day, d.month, d.year, t.hour, t.minute, t.second); 45 | } 46 | 47 | void timer_phase(int hz) { 48 | int divisor = 1193180 / hz; 49 | outb(0x43, 0x36); 50 | outb(0x40, divisor & 0xFF); 51 | outb(0x40, (divisor >> 8) & 0xFF); 52 | } 53 | 54 | static void timer_irq_handler(registers *r, uint32_t int_no) { 55 | timer_ticks += 100; 56 | 57 | if (timer_ticks % 2000 == 0) { 58 | screen_caret(); 59 | } 60 | 61 | if (display_time && timer_ticks % 1000 == 0) { 62 | read_rtc(); 63 | char color; 64 | int x; 65 | int y; 66 | color = screen_getcolor(); 67 | screen_getxy(&x, &y); 68 | 69 | screen_gotoxy(0, 0); 70 | screen_setcolor(COLOR_GREEN << 4 | COLOR_WHITE); 71 | printf("Memory: %ld/%ld MiB", bitmap_allocated_pages() * BITMAP_PAGE_SIZE / 1024 / 1024, bitmap_total_pages() * BITMAP_PAGE_SIZE / 1024 / 1024); 72 | 73 | screen_setcolor(COLOR_GRAY << 4 | COLOR_BLACK); 74 | printf("Ring %d", r->cs & 0x3); 75 | 76 | screen_setcolor(COLOR_RED << 4 | COLOR_BLACK); 77 | printf("%p", r->eip); 78 | 79 | screen_setcolor(COLOR_BLUE << 4 | COLOR_GRAY); 80 | printf("PID: %ld", process_current()->pid); 81 | 82 | screen_gotoxy(-19, 0); 83 | screen_setcolor(COLOR_BLUE << 4 | COLOR_GRAY); 84 | printf("%02d/%02d/%04d %02d:%02d:%02d", d.day, d.month, d.year, t.hour, t.minute, t.second); 85 | 86 | screen_gotoxy(x, y); 87 | screen_setcolor(color); 88 | } 89 | 90 | if (timer_ticks % 1000 == 0) { 91 | process_round_robin(r); 92 | } 93 | } 94 | 95 | void timer_wait(int ms) { 96 | unsigned long elapsed_ticks = timer_ticks + ms; 97 | while (timer_ticks < elapsed_ticks) { asm volatile("hlt"); } 98 | } 99 | 100 | void timer_init(void) { 101 | rtc_init(); 102 | timer_phase(100); 103 | display_time = true; 104 | irq_install_handler(IRQ_PIT, timer_irq_handler); 105 | } 106 | 107 | void timer_enable_display(void) { 108 | display_time = true; 109 | } 110 | 111 | void timer_disable_display(void) { 112 | display_time = false; 113 | } 114 | -------------------------------------------------------------------------------- /kernel/modules/timer.h: -------------------------------------------------------------------------------- 1 | #ifndef TIMER_H 2 | #define TIMER_H 3 | 4 | typedef struct time { 5 | unsigned char hour; 6 | unsigned char minute; 7 | unsigned char second; 8 | } time; 9 | 10 | typedef struct date { 11 | unsigned int year; 12 | unsigned int month; 13 | unsigned int day; 14 | } date; 15 | 16 | void rtc_init(void); 17 | 18 | void timer_init(void); 19 | 20 | void timer_wait(int ms); 21 | 22 | void timer_enable_display(void); 23 | 24 | void timer_disable_display(void); 25 | 26 | #endif //TIMER_H 27 | -------------------------------------------------------------------------------- /kernel/modules/uuid.c: -------------------------------------------------------------------------------- 1 | #include "uuid.h" 2 | 3 | #include 4 | 5 | const char *printuuid(uuid id) { 6 | static char buf[37]; 7 | sprintf( 8 | buf, 9 | "%08x-%04x-%04x-%04x-%04x%08x", 10 | id.superlow, 11 | id.low >> 16, 12 | id.low & 0xffff, 13 | id.high >> 16, 14 | id.high & 0xffff, 15 | id.superhigh 16 | ); 17 | 18 | return buf; 19 | } 20 | -------------------------------------------------------------------------------- /kernel/modules/uuid.h: -------------------------------------------------------------------------------- 1 | #ifndef UUID_H 2 | #define UUID_H 3 | 4 | #include 5 | 6 | #pragma pack(push, 1) 7 | typedef struct uuid { 8 | uint32_t superlow; 9 | uint32_t low; 10 | uint32_t high; 11 | uint32_t superhigh; 12 | } uuid; 13 | #pragma pack(pop) 14 | 15 | const char *printuuid(uuid id); 16 | 17 | #endif // UUID_H 18 | -------------------------------------------------------------------------------- /kernel/modules/vfs.c: -------------------------------------------------------------------------------- 1 | #include "vfs.h" 2 | 3 | #define DEBUG 1 4 | #define DEBUG_SERIAL 1 5 | 6 | #include 7 | #include 8 | #include 9 | #include "../bits.h" 10 | #include "../debug.h" 11 | #include "../rootfs.h" 12 | #include "../cpu/panic.h" 13 | 14 | mount_t *vfs_root = NULL; 15 | 16 | static void vfs_describe_file(mount_t *mount, file_t *f, int level, bool recursive) { 17 | for (int i = 0; i < level; i++) { 18 | printf(" "); 19 | } 20 | 21 | if (ISSET_BIT_INT(f->st.st_mode, S_IFIFO)) { 22 | printf("p"); 23 | } else if (ISSET_BIT_INT(f->st.st_mode, S_IFCHR)) { 24 | printf("c"); 25 | } else if (ISSET_BIT_INT(f->st.st_mode, S_IFDIR)) { 26 | printf("d"); 27 | } else if (ISSET_BIT_INT(f->st.st_mode, S_IFBLK)) { 28 | printf("b"); 29 | } else if (ISSET_BIT_INT(f->st.st_mode, S_IFREG)) { 30 | printf("-"); 31 | } else if (ISSET_BIT_INT(f->st.st_mode, S_IFLNK)) { 32 | printf("l"); 33 | } else if (ISSET_BIT_INT(f->st.st_mode, S_IFSOCK)) { 34 | printf("s"); 35 | } else { 36 | printf("?"); 37 | } 38 | 39 | printf("%s", ISSET_BIT_INT(f->st.st_mode, S_IRUSR) ? "r" : "-"); 40 | printf("%s", ISSET_BIT_INT(f->st.st_mode, S_IWUSR) ? "w" : "-"); 41 | printf("%s", ISSET_BIT_INT(f->st.st_mode, S_IXUSR) ? "x" : "-"); 42 | 43 | printf("%s", ISSET_BIT_INT(f->st.st_mode, S_IRGRP) ? "r" : "-"); 44 | printf("%s", ISSET_BIT_INT(f->st.st_mode, S_IWGRP) ? "w" : "-"); 45 | printf("%s", ISSET_BIT_INT(f->st.st_mode, S_IXGRP) ? "x" : "-"); 46 | 47 | printf("%s", ISSET_BIT_INT(f->st.st_mode, S_IROTH) ? "r" : "-"); 48 | printf("%s", ISSET_BIT_INT(f->st.st_mode, S_IWOTH) ? "w" : "-"); 49 | printf("%s", ISSET_BIT_INT(f->st.st_mode, S_IXOTH) ? "x" : "-"); 50 | 51 | printf(" 1 %04ld\t%04ld", f->st.st_uid, f->st.st_gid); 52 | 53 | printf("\t%lu", f->st.st_size); 54 | 55 | printf("\t%lu", f->st.st_ctime); 56 | 57 | printf("\t%s", f->name); 58 | 59 | printf("\n"); 60 | 61 | if (recursive && ISSET_BIT_INT(f->st.st_mode, S_IFDIR)) { 62 | dbgprint("Reading directory %s\n", f->name); 63 | size_t count = f->st.st_size / sizeof(file_t); 64 | for (int i = 0; ; i++) { 65 | file_t *out_f = (file_t *)calloc(1, sizeof(file_t)); 66 | int readdir_ret = 0; 67 | if ((readdir_ret = mount->fs->readdir(mount->driver, mount->fs, &f->st, i, out_f->name, &out_f->st))) { 68 | dbgprint("Failed to readdir: %d\n", readdir_ret); 69 | break; 70 | } 71 | 72 | vfs_describe_file(mount, out_f, level + 1, (!strcmp(out_f->name, ".") || !strcmp(out_f->name, "..")) ? false : recursive); 73 | 74 | free(out_f->st.st_private); 75 | free(out_f); 76 | } 77 | } 78 | } 79 | 80 | void vfs_init(void) { 81 | dbgprint("Initializing VFS\n"); 82 | vfs_root = (mount_t *)calloc(1, sizeof(mount_t)); 83 | if (!vfs_root) { 84 | panic("Failed to allocate VFS root"); 85 | } 86 | 87 | vfs_root->driver = &rootfs_io; 88 | vfs_root->fs = &rootfs; 89 | vfs_root->root.name[0] = '/'; 90 | int stat_ret = 0; 91 | if ((stat_ret = rootfs.stat(&rootfs_io, &rootfs, "/", &vfs_root->root.st))) { 92 | free(vfs_root); 93 | vfs_root = NULL; 94 | panic("Failed to initialize VFS root: %d", stat_ret); 95 | } 96 | 97 | dbgprint("VFS root initialized\n"); 98 | dbgprint("Reading root directory\n"); 99 | vfs_describe_file(vfs_root, &vfs_root->root, 0, true); 100 | } 101 | 102 | bool vfs_mount(filesystem *fs, const char *path) { 103 | return false; 104 | } 105 | 106 | bool vfs_unmount(const char *path) { 107 | return false; 108 | } 109 | 110 | bool vfs_open(const char *path, file_t *file) { 111 | return false; 112 | } 113 | 114 | bool vfs_close(file_t *file) { 115 | return false; 116 | } 117 | -------------------------------------------------------------------------------- /kernel/modules/vfs.h: -------------------------------------------------------------------------------- 1 | #ifndef VFS_H 2 | #define VFS_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include "../drivers/filesystem.h" 8 | 9 | typedef struct file_t { 10 | char name[256]; 11 | struct stat st; 12 | } file_t; 13 | 14 | typedef struct mount_t { 15 | iodriver *driver; 16 | filesystem *fs; 17 | file_t root; 18 | } mount_t; 19 | 20 | extern mount_t *vfs_root; 21 | 22 | void vfs_init(void); 23 | 24 | bool vfs_mount(filesystem *fs, const char *path); 25 | 26 | bool vfs_unmount(const char *path); 27 | 28 | bool vfs_open(const char *path, file_t *file); 29 | 30 | bool vfs_close(file_t *file); 31 | 32 | #endif // VFS_H 33 | -------------------------------------------------------------------------------- /kernel/modules/vt.c: -------------------------------------------------------------------------------- 1 | #include "vt.h" 2 | -------------------------------------------------------------------------------- /kernel/modules/vt.h: -------------------------------------------------------------------------------- 1 | #ifndef VT_H 2 | #define VT_H 3 | 4 | #endif // VT_H 5 | -------------------------------------------------------------------------------- /kernel/multiboot2.inc: -------------------------------------------------------------------------------- 1 | %define GRUB_MULTIBOOT_ARCHITECTURE_I386 0x0 2 | 3 | ; How many bytes from the start of the file we search for the header. 4 | %define MULTIBOOT_SEARCH 32768 5 | %define MULTIBOOT_HEADER_ALIGN 8 6 | 7 | ; The magic field should contain this. 8 | %define MULTIBOOT2_HEADER_MAGIC 0xe85250d6 9 | 10 | ; This should be in %eax. 11 | %define MULTIBOOT2_BOOTLOADER_MAGIC 0x36d76289 12 | 13 | ; Alignment of multiboot modules. 14 | %define MULTIBOOT_MOD_ALIGN 0x00001000 15 | 16 | ; Alignment of the multiboot info structure. 17 | %define MULTIBOOT_INFO_ALIGN 0x00000008 18 | 19 | ; Flags set in the ’flags’ member of the multiboot header. 20 | 21 | %define MULTIBOOT_TAG_ALIGN 8 22 | %define MULTIBOOT_TAG_TYPE_END 0 23 | %define MULTIBOOT_TAG_TYPE_CMDLINE 1 24 | %define MULTIBOOT_TAG_TYPE_BOOT_LOADER_NAME 2 25 | %define MULTIBOOT_TAG_TYPE_MODULE 3 26 | %define MULTIBOOT_TAG_TYPE_BASIC_MEMINFO 4 27 | %define MULTIBOOT_TAG_TYPE_BOOTDEV 5 28 | %define MULTIBOOT_TAG_TYPE_MMAP 6 29 | %define MULTIBOOT_TAG_TYPE_VBE 7 30 | %define MULTIBOOT_TAG_TYPE_FRAMEBUFFER 8 31 | %define MULTIBOOT_TAG_TYPE_ELF_SECTIONS 9 32 | %define MULTIBOOT_TAG_TYPE_APM 10 33 | %define MULTIBOOT_TAG_TYPE_EFI32 11 34 | %define MULTIBOOT_TAG_TYPE_EFI64 12 35 | %define MULTIBOOT_TAG_TYPE_SMBIOS 13 36 | %define MULTIBOOT_TAG_TYPE_ACPI_OLD 14 37 | %define MULTIBOOT_TAG_TYPE_ACPI_NEW 15 38 | %define MULTIBOOT_TAG_TYPE_NETWORK 16 39 | %define MULTIBOOT_TAG_TYPE_EFI_MMAP 17 40 | %define MULTIBOOT_TAG_TYPE_EFI_BS 18 41 | %define MULTIBOOT_TAG_TYPE_EFI32_IH 19 42 | %define MULTIBOOT_TAG_TYPE_EFI64_IH 20 43 | %define MULTIBOOT_TAG_TYPE_LOAD_BASE_ADDR 21 44 | 45 | %define MULTIBOOT_HEADER_TAG_END 0 46 | %define MULTIBOOT_HEADER_TAG_INFORMATION_REQUEST 1 47 | %define MULTIBOOT_HEADER_TAG_ADDRESS 2 48 | %define MULTIBOOT_HEADER_TAG_ENTRY_ADDRESS 3 49 | %define MULTIBOOT_HEADER_TAG_CONSOLE_FLAGS 4 50 | %define MULTIBOOT_HEADER_TAG_FRAMEBUFFER 5 51 | %define MULTIBOOT_HEADER_TAG_MODULE_ALIGN 6 52 | %define MULTIBOOT_HEADER_TAG_EFI_BS 7 53 | %define MULTIBOOT_HEADER_TAG_ENTRY_ADDRESS_EFI32 8 54 | %define MULTIBOOT_HEADER_TAG_ENTRY_ADDRESS_EFI64 9 55 | %define MULTIBOOT_HEADER_TAG_RELOCATABLE 10 56 | 57 | %define MULTIBOOT_ARCHITECTURE_I386 0 58 | %define MULTIBOOT_ARCHITECTURE_MIPS32 4 59 | %define MULTIBOOT_HEADER_TAG_OPTIONAL 1 60 | 61 | %define MULTIBOOT_LOAD_PREFERENCE_NONE 0 62 | %define MULTIBOOT_LOAD_PREFERENCE_LOW 1 63 | %define MULTIBOOT_LOAD_PREFERENCE_HIGH 2 64 | 65 | %define MULTIBOOT_CONSOLE_FLAGS_CONSOLE_REQUIRED 1 66 | %define MULTIBOOT_CONSOLE_FLAGS_EGA_TEXT_SUPPORTED 2 67 | -------------------------------------------------------------------------------- /kernel/ring3.c: -------------------------------------------------------------------------------- 1 | #include "ring3.h" 2 | 3 | // This variable stores the address to the target Ring 3 4 | uint32_t __ring3_addr; 5 | -------------------------------------------------------------------------------- /kernel/ring3.h: -------------------------------------------------------------------------------- 1 | #ifndef RING3_H 2 | #define RING3_H 3 | 4 | #include 5 | #include "cpu/mmu.h" 6 | 7 | extern uint32_t _esp; 8 | 9 | extern void switch_ring3(page_directory_table *pdt, void *addr, uint32_t stack); 10 | 11 | #endif // RING3_H 12 | -------------------------------------------------------------------------------- /kernel/rootfs.c: -------------------------------------------------------------------------------- 1 | #include "rootfs.h" 2 | 3 | filesystem rootfs; 4 | iodriver rootfs_io; 5 | -------------------------------------------------------------------------------- /kernel/rootfs.h: -------------------------------------------------------------------------------- 1 | #ifndef ROOTFS_H 2 | #define ROOTFS_H 3 | 4 | #include "drivers/filesystem.h" 5 | #include "drivers/iodriver.h" 6 | 7 | extern filesystem rootfs; 8 | extern iodriver rootfs_io; 9 | 10 | #endif // ROOTFS_H 11 | -------------------------------------------------------------------------------- /lba2chs.py: -------------------------------------------------------------------------------- 1 | #!/bin/python3 2 | 3 | import sys 4 | from typing import List 5 | 6 | HEADS = 2 7 | CYLINDERS = 80 8 | SECTORS_PER_TRACK = 18 9 | SECTOR_SIZE = 512 10 | 11 | 12 | def lba2chs(lba: int) -> tuple[int, int, int]: 13 | cylinders = lba // (HEADS * SECTORS_PER_TRACK) 14 | head = (lba // SECTORS_PER_TRACK) % HEADS 15 | sector = (lba % SECTORS_PER_TRACK) + 1 16 | return (cylinders, head, sector) 17 | 18 | 19 | def chs2lba(cylinder: int, head: int, sector: int) -> int: 20 | return (cylinder * HEADS + head) * SECTORS_PER_TRACK + (sector - 1) 21 | 22 | 23 | def main(args: List[str]) -> int: 24 | if len(args) == 1: 25 | lba = int(args[0]) 26 | print(lba2chs(lba)) 27 | elif len(args) == 3: 28 | cylinder = int(args[0]) 29 | head = int(args[1]) 30 | sector = int(args[2]) 31 | lba = chs2lba(cylinder, head, sector) 32 | print(lba) 33 | else: 34 | print("Usage: lba2chs.py [lba] | lba2chs.py [cylinder] [head] [sector]") 35 | return 1 36 | 37 | return 0 38 | 39 | if __name__ == '__main__': 40 | sys.exit(main(sys.argv[1:])) 41 | -------------------------------------------------------------------------------- /mtoolsrc: -------------------------------------------------------------------------------- 1 | drive a: 2 | file="./floppy_disk.img" 3 | partition=2 1.44m filter 4 | 5 | drive c: 6 | file="./ata_disk.img" 7 | partition=2 fat_bits=16 cylinders=256 heads=4 sectors=32 filter 8 | mtools_skip_check=1 9 | -------------------------------------------------------------------------------- /rootfs/boot/grub/grub.cfg: -------------------------------------------------------------------------------- 1 | set timeout=0 2 | 3 | menuentry "MVLIRA" { 4 | multiboot2 /kernel.elf root=hd0p1 5 | boot 6 | } 7 | -------------------------------------------------------------------------------- /rootfs/etc/fstab: -------------------------------------------------------------------------------- 1 | # /etc/fstab: static file system information. 2 | # 3 | # Use 'blkid' to print the universally unique identifier for a 4 | # device; this may be used with UUID= as a more robust way to name devices 5 | # that works even if disks are added and removed. See fstab(5). 6 | # 7 | # 8 | /dev/hd0p1 / auto defaults 0 1 9 | /swapfile swap swap defaults 0 0 10 | -------------------------------------------------------------------------------- /slirp.conf: -------------------------------------------------------------------------------- 1 | # slirp config 2 | # The line above is mandatory 3 | 4 | # Supported options: 5 | # 6 | # RESTRICTED if set to 1, only built-in services are available 7 | # NET base IP address of the virtual network 8 | # MASK netmask of the virtual network 9 | # HOST IP address of the DHCP and TFTP server 10 | # HOSTNAME DHCP client hostname 11 | # DHCPSTART start address of DHCP pool 12 | # DNS IP address of the virtual DNS server 13 | # BOOTFILE boot filename returned by DHCP 14 | # DNSSEARCH comma-separated list of DNS suffixes to search (DHCP extension) 15 | # SMB_EXPORT absolute path to the shared folder (non-Windows SMB support) 16 | # SMB_SRV alternative IP address of the SMB server (default is 10.0.2.4) 17 | # HOSTFWD map guest port to host port for host-to-guest access 18 | # (format: protocol:hostaddr:hostport-guestaddr:guestport) 19 | 20 | # This is the default (classic slirp) setup 21 | restricted = 0 22 | net = 10.0.2.0 23 | mask = 255.255.255.0 24 | host = 10.0.2.2 25 | dhcpstart = 10.0.2.15 26 | dns = 10.0.2.3 27 | 28 | # This is the vnet setup 29 | # restricted = 1 30 | # net = 192.168.10.0 31 | # mask = 255.255.255.0 32 | # host = 192.168.10.1 33 | # dhcpstart = 192.168.10.15 34 | # dns = 192.168.10.2 35 | # bootfile = pxelinux.0 36 | 37 | # Host forwarding example (access guest SSH server from host port 12345) 38 | # hostfwd = tcp::12345-:22 39 | 40 | # Enable packet logging in text format (similar to vnet) 41 | pktlog = slirp-pktlog.txt 42 | -------------------------------------------------------------------------------- /system/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.16) 2 | project(system) 3 | 4 | set(CMAKE_CXX_STANDARD 99) 5 | 6 | set(SOURCE_FILES 7 | libc/stdio.c libc/include/stdio.h 8 | libc/string.c libc/include/string.h 9 | libc/stdlib.c libc/include/stdlib.h 10 | libc/ctype.c libc/include/ctype.h 11 | libc/include/stddef.h 12 | libc/include/stdint.h 13 | libc/include/stdarg.h 14 | libc/math.c libc/include/math.h 15 | libc/unistd.c libc/include/unistd.h 16 | shell/shell.c 17 | shell/shell.h) 18 | 19 | add_executable(system ${SOURCE_FILES}) 20 | -------------------------------------------------------------------------------- /system/Makefile: -------------------------------------------------------------------------------- 1 | BUILD_DIR=../build/system 2 | 3 | all: dir libc bin 4 | 5 | dir: 6 | mkdir -p $(BUILD_DIR) 7 | 8 | .PHONY: libc bin 9 | 10 | libc: 11 | make -C libc 12 | 13 | bin: 14 | make -C bin 15 | 16 | clean: 17 | make -C libc clean 18 | make -C bin clean 19 | -------------------------------------------------------------------------------- /system/bin/Makefile: -------------------------------------------------------------------------------- 1 | BUILD_DIR=../build/system/bin 2 | 3 | all: dir init sh 4 | 5 | dir: 6 | mkdir -p $(BUILD_DIR) 7 | 8 | .PHONY: init sh 9 | 10 | init: 11 | make -C init 12 | 13 | sh: 14 | make -C sh 15 | 16 | clean: 17 | make -C init clean 18 | make -C sh clean 19 | -------------------------------------------------------------------------------- /system/bin/init/Makefile: -------------------------------------------------------------------------------- 1 | BUILD_DIR=../../../build/system/bin/init 2 | BIN=$(BUILD_DIR)/init.elf 3 | 4 | CC=gcc 5 | CFLAGS=-ffreestanding -m32 -I ../../libc/include -nostdlib -nolibc -nodefaultlibs -Wl,--stack,0x4000 -Wno-packed-bitfield-compat -fno-common 6 | LDFLAGS=-m elf_i386 -Bstatic -L $(shell pwd)/../../../build/system/lib -lc 7 | 8 | ASM_SRCS = $(wildcard *.asm) 9 | ASM_OBJS = $(patsubst %.asm, $(BUILD_DIR)/%.obj, $(ASM_SRCS)) 10 | SRCS := $(wildcard *.c) 11 | HDRS := $(wildcard *.h ../../libc/include/*.h ../../libc/include/sys/*.h) 12 | OBJS := $(patsubst %.c, $(BUILD_DIR)/%.o, $(SRCS)) 13 | 14 | all: dir $(BIN) 15 | 16 | dir: 17 | mkdir -p $(BUILD_DIR) 18 | 19 | $(BUILD_DIR)/%.obj: %.asm 20 | nasm -f elf32 $< -o $@ 21 | 22 | $(BUILD_DIR)/%.o: %.c $(HDRS) 23 | $(CC) $(CFLAGS) -c $< -o $@ 24 | 25 | $(BIN): $(ASM_OBJS) $(OBJS) 26 | ld $^ $(LDFLAGS) -o $@ 27 | 28 | clean: 29 | rm -f $(OBJS) 30 | -------------------------------------------------------------------------------- /system/bin/init/init.c: -------------------------------------------------------------------------------- 1 | #include "init.h" 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | int main(int argc, char *argv[]) { 14 | open("/dev/tty1", O_RDONLY); // stdin 15 | open("/dev/tty1", O_WRONLY); // stdout 16 | open("/dev/tty1", O_WRONLY); // stderr 17 | 18 | int fstab_fd = open("/etc/fstab", O_RDONLY); 19 | if (fstab_fd < 0) { 20 | printf("failed to open /etc/fstab: %d\n", fstab_fd); 21 | return 1; 22 | } 23 | 24 | char buf[1024]; 25 | size_t to_read = 64; 26 | for (int i = 0; i < 1024; i += to_read) { 27 | ssize_t l = read(fstab_fd, buf + i, to_read); 28 | if (l < 0) { 29 | printf("failed to read /etc/fstab: %ld\n", l); 30 | return 1; 31 | } 32 | 33 | if (l < to_read) { 34 | buf[i + l] = '\0'; 35 | break; 36 | } 37 | } 38 | 39 | buf[1023] = '\0'; 40 | 41 | close(fstab_fd); 42 | 43 | printf("init started with %d arguments\n", argc); 44 | for (int i = 0; i < argc; i++) { 45 | printf("arg %d: %s\n", i, argv[i]); 46 | } 47 | 48 | printf("init reading /etc/fstab:\n%s\n", buf); 49 | 50 | pid_t pid = fork(); 51 | if (pid == 0) { 52 | pid = getpid(); 53 | printf("I am the child, my PID is %ld\n", pid); 54 | 55 | char *exe = "/bin/sh.elf"; 56 | char *argv[] = {"/bin/sh.elf", NULL}; 57 | char *envp[] = {NULL}; 58 | 59 | printf("executing %s\n", exe); 60 | 61 | int r; 62 | if ((r = execve(exe, argv, envp))) { 63 | printf("exec failed: %d\n", r); 64 | return 1; 65 | } 66 | } else { 67 | printf("I am the parent, child PID is %ld\n", pid); 68 | 69 | while (true) { 70 | // 71 | } 72 | } 73 | 74 | return 0; 75 | } 76 | -------------------------------------------------------------------------------- /system/bin/init/init.h: -------------------------------------------------------------------------------- 1 | #ifndef INIT_H 2 | #define INIT_H 3 | 4 | int main(int argc, char *argv[]); 5 | 6 | #endif //INIT_H 7 | -------------------------------------------------------------------------------- /system/bin/sh/Makefile: -------------------------------------------------------------------------------- 1 | BUILD_DIR=../../../build/system/bin/sh 2 | BIN=$(BUILD_DIR)/sh.elf 3 | 4 | CC=gcc 5 | CFLAGS=-ffreestanding -m32 -I ../../libc/include -nostdlib -nolibc -nodefaultlibs -Wl,--stack,0x4000 -Wno-packed-bitfield-compat -fno-common 6 | LDFLAGS=-m elf_i386 -Bstatic -L $(shell pwd)/../../../build/system/lib -lc 7 | 8 | ASM_SRCS = $(wildcard *.asm) 9 | ASM_OBJS = $(patsubst %.asm, $(BUILD_DIR)/%.obj, $(ASM_SRCS)) 10 | SRCS := $(wildcard *.c) 11 | HDRS := $(wildcard *.h ../../libc/include/*.h ../../libc/include/sys/*.h) 12 | OBJS := $(patsubst %.c, $(BUILD_DIR)/%.o, $(SRCS)) 13 | 14 | all: dir $(BIN) 15 | 16 | dir: 17 | mkdir -p $(BUILD_DIR) 18 | 19 | $(BUILD_DIR)/%.obj: %.asm 20 | nasm -f elf32 $< -o $@ 21 | 22 | $(BUILD_DIR)/%.o: %.c $(HDRS) 23 | $(CC) $(CFLAGS) -c $< -o $@ 24 | 25 | $(BIN): $(ASM_OBJS) $(OBJS) 26 | ld $^ $(LDFLAGS) -o $@ 27 | 28 | clean: 29 | rm -f $(OBJS) 30 | -------------------------------------------------------------------------------- /system/bin/sh/sh.h: -------------------------------------------------------------------------------- 1 | #ifndef SH_H 2 | #define SH_H 3 | 4 | int main(int argc, char *argv[]); 5 | 6 | #endif //SH_H 7 | -------------------------------------------------------------------------------- /system/libc/Makefile: -------------------------------------------------------------------------------- 1 | BUILD_DIR=../../build/system/libc 2 | LIB_DIR=../../build/system/lib 3 | STATIC_LIB=$(LIB_DIR)/libc.a 4 | DYNAMIC_LIB=$(LIB_DIR)/libc.so 5 | 6 | CC=gcc 7 | CFLAGS=-ffreestanding -m32 -I ./include -nostdlib -nolibc -nodefaultlibs -Wl,--stack,0x4000 -Wno-packed-bitfield-compat -fno-common -fpic 8 | LDFLAGS=-m elf_i386 -shared -fpic 9 | 10 | ASM_SRCS = $(wildcard *.asm) 11 | ASM_OBJS = $(patsubst %.asm, $(BUILD_DIR)/%.obj, $(ASM_SRCS)) 12 | SRCS := $(wildcard *.c sys/*.c) 13 | HDRS := $(wildcard include/*.h include/sys/*.h) 14 | OBJS := $(patsubst %.c, $(BUILD_DIR)/%.o, $(SRCS)) 15 | 16 | all: dir $(STATIC_LIB) $(DYNAMIC_LIB) 17 | 18 | dir: 19 | mkdir -p $(BUILD_DIR) 20 | mkdir -p $(BUILD_DIR)/sys 21 | mkdir -p $(LIB_DIR) 22 | 23 | $(BUILD_DIR)/%.obj: %.asm 24 | nasm -f elf32 $< -o $@ 25 | 26 | $(BUILD_DIR)/%.o: %.c $(HDRS) 27 | $(CC) $(CFLAGS) -c $< -o $@ 28 | 29 | $(STATIC_LIB): $(ASM_OBJS) $(OBJS) 30 | ar rcs $@ $^ 31 | 32 | $(DYNAMIC_LIB): $(ASM_OBJS) $(OBJS) 33 | ld $(LDFLAGS) $^ -o $@ 34 | 35 | clean: 36 | rm -f $(OBJS) $(ASM_OBJS) $(LIB) 37 | -------------------------------------------------------------------------------- /system/libc/ctype.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int toupper(int c) { 4 | if (c >= 'a' && c <= 'z') { 5 | return 'A' + c - 'a'; 6 | } 7 | 8 | return c; 9 | } 10 | 11 | int tolower(int c) { 12 | if (c >= 'A' && c <= 'Z') { 13 | return 'a' + c - 'A'; 14 | } 15 | 16 | return c; 17 | } 18 | -------------------------------------------------------------------------------- /system/libc/dirent.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | 5 | int closedir(DIR *dirp) { 6 | return 1; 7 | } 8 | 9 | DIR *opendir(const char *name) { 10 | return NULL; 11 | } 12 | 13 | struct dirent *readdir(DIR *dirp) { 14 | return NULL; 15 | } 16 | 17 | int readdir_r(DIR *dirp, struct dirent *entry, struct dirent **result) { 18 | return 1; 19 | } 20 | 21 | void rewinddir(DIR *dirp) { 22 | 23 | } 24 | 25 | void seekdir(DIR *dirp, long int loc) { 26 | 27 | } 28 | 29 | long telldir(DIR *dirp) { 30 | return 0; 31 | } 32 | -------------------------------------------------------------------------------- /system/libc/errno.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int errno; 4 | -------------------------------------------------------------------------------- /system/libc/fcntl.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | 5 | int open(const char *pathname, int flags) { 6 | return syscall(2, pathname, flags); 7 | } 8 | -------------------------------------------------------------------------------- /system/libc/include/ctype.h: -------------------------------------------------------------------------------- 1 | #ifndef CTYPE_H 2 | #define CTYPE_H 3 | 4 | int toupper(int); 5 | 6 | int tolower(int); 7 | 8 | #endif //CTYPE_H 9 | -------------------------------------------------------------------------------- /system/libc/include/dirent.h: -------------------------------------------------------------------------------- 1 | #ifndef DIRENT_H 2 | #define DIRENT_H 3 | 4 | #include 5 | 6 | typedef struct DIR DIR; 7 | 8 | #define NAME_MAX 256 9 | 10 | struct dirent { 11 | ino_t d_ino; /* Inode number */ 12 | off_t d_off; /* Not an offset; see below */ 13 | unsigned short d_reclen; /* Length of this record */ 14 | unsigned char d_type; /* Type of file; not supported by all filesystem types */ 15 | char d_name[NAME_MAX]; /* Null-terminated filename */ 16 | }; 17 | 18 | enum DirentType { 19 | DT_BLK = 0x6000, /* block device */ 20 | DT_CHR = 0x2000, /* character device */ 21 | DT_IFO = 0x1000, /* FIFO (named pipe) */ 22 | DT_REG = 0x8000, /* regular */ 23 | DT_DIR = 0x4000, /* directory */ 24 | DT_LNK = 0xA000, /* symbolic link */ 25 | DT_SOCK = 0xC000, /* socket */ 26 | DT_UNKNOWN = 0, 27 | }; 28 | 29 | int closedir(DIR *dirp); 30 | DIR *opendir(const char *name); 31 | struct dirent *readdir(DIR *dirp); 32 | int readdir_r(DIR *dirp, struct dirent *entry, struct dirent **result); 33 | void rewinddir(DIR *dirp); 34 | void seekdir(DIR *dirp, long int loc); 35 | long telldir(DIR *dirp); 36 | 37 | #endif // DIRENT_H 38 | -------------------------------------------------------------------------------- /system/libc/include/fcntl.h: -------------------------------------------------------------------------------- 1 | #ifndef FCNTL_H 2 | #define FCNTL_H 3 | 4 | enum OpenFlags { 5 | O_RDONLY = 0, 6 | O_WRONLY = 1, 7 | O_RDWR = 2, 8 | 9 | O_APPEND = 1024, 10 | O_ASYNC = 8192, 11 | O_CLOEXEC = 524288, 12 | O_CREAT = 64, 13 | O_DIRECT = 16384, 14 | O_DIRECTORY = 65536, 15 | O_DSYNC = 4096, 16 | O_EXCL = 128, 17 | O_LARGEFILE = 0, 18 | O_NOATIME = 262144, 19 | O_NOCTTY = 256, 20 | O_NOFOLLOW = 131072, 21 | O_NONBLOCK = 2048, 22 | O_NDELAY = 2048, 23 | O_PATH = 2097152, 24 | O_SYNC = 1052672, 25 | O_TMPFILE = 4194304, 26 | O_TRUNC = 512 27 | }; 28 | 29 | int open(const char *path, int flags); 30 | 31 | #endif // FCNTL_H 32 | -------------------------------------------------------------------------------- /system/libc/include/math.h: -------------------------------------------------------------------------------- 1 | #ifndef MATH_H 2 | #define MATH_H 3 | 4 | #define M_PI 3.14159265358979323846 5 | #define M_E 2.71828182845904523536 6 | 7 | #define NAN (0.0/0.0) 8 | #define INFINITY (1e300 * 1e300) 9 | 10 | float fabs(float); 11 | 12 | double fabsl(double); 13 | 14 | float powf(float, float); 15 | 16 | double powl(double, double); 17 | 18 | float exp(float); 19 | 20 | double expl(double); 21 | 22 | float log(float); 23 | 24 | double logl(double); 25 | 26 | int isnanf(float); 27 | 28 | int isnanl(double); 29 | 30 | int isinff(float); 31 | 32 | int isinfl(double); 33 | 34 | #endif //MATH_H 35 | -------------------------------------------------------------------------------- /system/libc/include/stdarg.h: -------------------------------------------------------------------------------- 1 | #ifndef STDARG_H 2 | #define STDARG_H 3 | 4 | #define va_start(v, l) __builtin_va_start(v, l) 5 | #define va_end(v) __builtin_va_end(v) 6 | #define va_arg(v, l) __builtin_va_arg(v, l) 7 | 8 | typedef __builtin_va_list va_list; 9 | 10 | #endif //STDARG_H 11 | -------------------------------------------------------------------------------- /system/libc/include/stdbool.h: -------------------------------------------------------------------------------- 1 | #ifndef STDBOOL_H 2 | #define STDBOOL_H 3 | 4 | typedef _Bool bool; 5 | 6 | #define true 1 7 | 8 | #define false 0 9 | 10 | #endif //STDBOOL_H 11 | -------------------------------------------------------------------------------- /system/libc/include/stddef.h: -------------------------------------------------------------------------------- 1 | #ifndef STDDEF_H 2 | #define STDDEF_H 3 | 4 | typedef unsigned int size_t; 5 | 6 | typedef int wchar_t; 7 | 8 | #ifndef NULL 9 | #define NULL (void *)0 10 | #endif 11 | 12 | #endif //STDDEF_H 13 | -------------------------------------------------------------------------------- /system/libc/include/stdint.h: -------------------------------------------------------------------------------- 1 | #ifndef STDINT_H 2 | #define STDINT_H 3 | 4 | typedef __INT8_TYPE__ int8_t; 5 | typedef __INT16_TYPE__ int16_t; 6 | typedef __INT32_TYPE__ int32_t; 7 | typedef __INT64_TYPE__ int64_t; 8 | typedef __UINT8_TYPE__ uint8_t; 9 | typedef __UINT16_TYPE__ uint16_t; 10 | typedef __UINT32_TYPE__ uint32_t; 11 | typedef __UINT64_TYPE__ uint64_t; 12 | 13 | typedef __INT_LEAST8_TYPE__ int_least8_t; 14 | typedef __INT_LEAST16_TYPE__ int_least16_t; 15 | typedef __INT_LEAST32_TYPE__ int_least32_t; 16 | typedef __INT_LEAST64_TYPE__ int_least64_t; 17 | typedef __UINT_LEAST8_TYPE__ uint_least8_t; 18 | typedef __UINT_LEAST16_TYPE__ uint_least16_t; 19 | typedef __UINT_LEAST32_TYPE__ uint_least32_t; 20 | typedef __UINT_LEAST64_TYPE__ uint_least64_t; 21 | 22 | typedef __INT_FAST8_TYPE__ int_fast8_t; 23 | typedef __INT_FAST16_TYPE__ int_fast16_t; 24 | typedef __INT_FAST32_TYPE__ int_fast32_t; 25 | typedef __INT_FAST64_TYPE__ int_fast64_t; 26 | typedef __UINT_FAST8_TYPE__ uint_fast8_t; 27 | typedef __UINT_FAST16_TYPE__ uint_fast16_t; 28 | typedef __UINT_FAST32_TYPE__ uint_fast32_t; 29 | typedef __UINT_FAST64_TYPE__ uint_fast64_t; 30 | 31 | typedef __INTPTR_TYPE__ intptr_t; 32 | typedef __UINTPTR_TYPE__ uintptr_t; 33 | 34 | typedef __INTMAX_TYPE__ intmax_t; 35 | typedef __UINTMAX_TYPE__ uintmax_t; 36 | 37 | #endif //STDINT_H 38 | -------------------------------------------------------------------------------- /system/libc/include/stdio.h: -------------------------------------------------------------------------------- 1 | #ifndef STDIO_H 2 | #define STDIO_H 3 | 4 | #include 5 | 6 | #define EOF (-1) 7 | 8 | #ifndef NULL 9 | #define NULL (void *)0 10 | #endif 11 | 12 | typedef struct iobuf { 13 | char *ptr; 14 | int cnt; 15 | char *base; 16 | int flag; 17 | int file; 18 | int charbuf; 19 | int bufsiz; 20 | } FILE; 21 | 22 | #define _IOREAD 1 23 | #define _IOWRT 2 24 | #define _IORW 0x0080 25 | 26 | extern FILE *stdin; 27 | extern FILE *stdout; 28 | extern FILE *stderr; 29 | 30 | int fclose(FILE *); 31 | 32 | int fflush(FILE *); 33 | 34 | FILE *fopen(const char *, const char *); 35 | 36 | FILE *freopen(const char *, const char *, FILE *); 37 | 38 | int getchar(void); 39 | 40 | int putchar(char); 41 | 42 | int puts(const char *); 43 | 44 | char *gets(char *); 45 | 46 | char *fgets(char *, int, FILE *); 47 | 48 | int vprintf(const char *, va_list); 49 | 50 | int printf(const char *, ...); 51 | 52 | int vsprintf(char *, const char *, va_list); 53 | 54 | int sprintf(char *, const char *, ...); 55 | 56 | int scanf(const char *, ...); 57 | 58 | #endif //STDIO_H 59 | -------------------------------------------------------------------------------- /system/libc/include/stdlib.h: -------------------------------------------------------------------------------- 1 | #ifndef STDLIB_H 2 | #define STDLIB_H 3 | 4 | #include 5 | 6 | #define EXIT_FAILURE 1 7 | #define EXIT_SUCCESS 0 8 | #define MB_CUR_MAX 8 9 | #ifndef NULL 10 | #define NULL (void *)0 11 | #endif 12 | #define RAND_MAX 32767 13 | 14 | typedef struct div_t { 15 | int quot; 16 | int rem; 17 | } div_t; 18 | 19 | typedef struct ldiv_t { 20 | long int quot; 21 | long int rem; 22 | } ldiv_t; 23 | 24 | float atof(const char *); 25 | 26 | int atoi(const char *); 27 | 28 | char *htoa(short int, char *, int); 29 | 30 | char *itoa(int, char *, int); 31 | 32 | char *ltoa(long int, char *, int); 33 | 34 | char *hutoa(unsigned short int, char *, int); 35 | 36 | char *utoa(unsigned int, char *, int); 37 | 38 | char *lutoa(unsigned long int, char *, int); 39 | 40 | char *ftoa(float, char *, int); 41 | 42 | char *lftoa(double, char *, int); 43 | 44 | long int atol(const char *); 45 | 46 | double strtod(const char *, char **); 47 | 48 | long int strtol(const char *, char **, int); 49 | 50 | unsigned long int strtoul(const char *, char **, int); 51 | 52 | void *calloc(size_t, size_t); 53 | 54 | void free(void *); 55 | 56 | void *malloc(size_t); 57 | 58 | void *realloc(void *, size_t); 59 | 60 | void abort(void); 61 | 62 | int atexit(void (*)(void)); 63 | 64 | void exit(int); 65 | 66 | char *getenv(const char *); 67 | 68 | int system(const char *); 69 | 70 | void *bsearch(const void *, const void *, size_t, size_t, int (*)(const void *, const void *)); 71 | 72 | void qsort(void *, size_t, size_t, int (*)(const void *, const void *)); 73 | 74 | int abs(int); 75 | 76 | div_t div(int, int); 77 | 78 | ldiv_t ldiv(long int, long int); 79 | 80 | long int labs(long int); 81 | 82 | int rand(void); 83 | 84 | void srand(unsigned int seed); 85 | 86 | int mblen(const char *, size_t); 87 | 88 | size_t mbstowcs(wchar_t *, const char *, size_t); 89 | 90 | int mbtowc(wchar_t *, const char *, size_t); 91 | 92 | size_t wcstombs(char *, const wchar_t *, size_t); 93 | 94 | int wctomb(char *, wchar_t); 95 | 96 | #endif //STDLIB_H 97 | -------------------------------------------------------------------------------- /system/libc/include/string.h: -------------------------------------------------------------------------------- 1 | #ifndef STRING_H 2 | #define STRING_H 3 | 4 | #include 5 | 6 | void *memcpy(void *destination, const void *source, size_t n); 7 | 8 | char *strcpy(char *destination, const char *source); 9 | 10 | char *strncpy(char *destination, const char *source, size_t n); 11 | 12 | void *memmove(void *dest, const void *source, size_t n); 13 | 14 | char *strcat(char *destination, const char *source); 15 | 16 | char *strncat(char *destination, const char *source, size_t n); 17 | 18 | char *strupr(char *str); 19 | 20 | char *strlwr(char *str); 21 | 22 | int memcmp(const void *ptr1, const void *ptr2, size_t num); 23 | 24 | int strcmp(const char *str1, const char *str2); 25 | 26 | int strncmp(const char *str1, const char *str2, size_t num); 27 | 28 | const void *memchr(const void *ptr, int value, size_t num); 29 | 30 | const char *strchr(const char *str, int character); 31 | 32 | size_t strcspn(const char *str1, const char *str2); 33 | 34 | char *strpbrk(const char *str1, const char *str2); 35 | 36 | char *strrchr(const char *str, int character); 37 | 38 | size_t strspn(const char *str1, const char *str2); 39 | 40 | char *strstr(const char *str1, const char *str2); 41 | 42 | char *strtok(char *str, const char *delimiters); 43 | 44 | size_t strlen(const char *str); 45 | 46 | void *memset(void *ptr, int value, size_t num); 47 | 48 | #endif // STRING_H 49 | -------------------------------------------------------------------------------- /system/libc/include/sys/stat.h: -------------------------------------------------------------------------------- 1 | #ifndef STAT_H 2 | #define STAT_H 3 | 4 | #include 5 | 6 | struct stat { 7 | dev_t st_dev; 8 | ino_t st_ino; 9 | mode_t st_mode; 10 | nlink_t st_nlink; 11 | uid_t st_uid; 12 | gid_t st_gid; 13 | dev_t st_rdev; 14 | off_t st_size; 15 | blksize_t st_blksize; 16 | blkcnt_t st_blocks; 17 | time_t st_atime; 18 | time_t st_mtime; 19 | time_t st_ctime; 20 | }; 21 | 22 | enum FileTypes { 23 | S_IFMT = 0xF000, 24 | S_IFBLK = 0x6000, 25 | S_IFCHR = 0x2000, 26 | S_IFIFO = 0x1000, 27 | S_IFREG = 0x8000, 28 | S_IFDIR = 0x4000, 29 | S_IFLNK = 0xA000, 30 | }; 31 | 32 | enum FileModes { 33 | S_IRWXU = 00700, 34 | S_IRUSR = 00400, 35 | S_IWUSR = 00200, 36 | S_IXUSR = 00100, 37 | S_IRWXG = 00070, 38 | S_IRGRP = 00040, 39 | S_IWGRP = 00020, 40 | S_IXGRP = 00010, 41 | S_IRWXO = 00007, 42 | S_IROTH = 00004, 43 | S_IWOTH = 00002, 44 | S_IXOTH = 00001, 45 | S_ISUID = 04000, 46 | S_ISGID = 02000, 47 | S_ISVTX = 01000, 48 | }; 49 | 50 | #define S_ISBLK(m) (((m) & S_IFMT) == S_IFBLK) 51 | #define S_ISCHR(m) (((m) & S_IFMT) == S_IFCHR) 52 | #define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR) 53 | #define S_ISFIFO(m) (((m) & S_IFMT) == S_IFIFO) 54 | #define S_ISREG(m) (((m) & S_IFMT) == S_IFREG) 55 | #define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK) 56 | 57 | int chmod(const char* pathname, mode_t mode); 58 | int fchmod(int fd, mode_t mode); 59 | int fstat(int fd, struct stat* buf); 60 | int lstat(const char* path, struct stat* buf); 61 | int mkdir(const char* pathname, mode_t mode); 62 | int mkfifo(const char* pathname, mode_t mode); 63 | int mknod(const char* pathname, mode_t mode, dev_t dev); 64 | int stat(const char* path, struct stat* buf); 65 | mode_t umask(mode_t mask); 66 | 67 | #endif // STAT_H 68 | -------------------------------------------------------------------------------- /system/libc/include/sys/types.h: -------------------------------------------------------------------------------- 1 | #ifndef SYS_TYPES_H 2 | #define SYS_TYPES_H 3 | 4 | #include 5 | 6 | typedef long blkcnt_t; 7 | typedef long blksize_t; 8 | typedef long clock_t; 9 | typedef long clockid_t; 10 | typedef long dev_t; 11 | typedef long fsblkcnt_t; 12 | typedef long fsfilcnt_t; 13 | typedef long gid_t; 14 | typedef long id_t; 15 | typedef long ino_t; 16 | typedef long key_t; 17 | typedef long mode_t; 18 | typedef long nlink_t; 19 | typedef long off_t; 20 | typedef long pid_t; 21 | typedef long pthread_attr_t; 22 | typedef long pthread_cond_t; 23 | typedef long pthread_condattr_t; 24 | typedef long pthread_key_t; 25 | typedef long pthread_mutex_t; 26 | typedef long pthread_mutexattr_t; 27 | typedef long pthread_once_t; 28 | typedef long pthread_rwlock_t; 29 | typedef long pthread_rwlockattr_t; 30 | typedef long pthread_t; 31 | typedef unsigned long ssize_t; 32 | typedef long suseconds_t; 33 | typedef long time_t; 34 | typedef long timer_t; 35 | typedef long uid_t; 36 | typedef long useconds_t; 37 | 38 | #endif // SYS_TYPES_H 39 | -------------------------------------------------------------------------------- /system/libc/include/unistd.h: -------------------------------------------------------------------------------- 1 | #ifndef UNISTDC_H 2 | #define UNISTDC_H 3 | 4 | #define STDIN_FILENO 0 5 | #define STDOUT_FILENO 1 6 | #define STDERR_FILENO 2 7 | 8 | #include 9 | #include 10 | 11 | int syscall(int, ...); 12 | 13 | ssize_t read(int fd, void *buf, size_t count); 14 | ssize_t write(int fd, void *buf, size_t count); 15 | int close(int fd); 16 | pid_t getpid(void); 17 | pid_t getppid(void); 18 | pid_t fork(void); 19 | int execve(const char *filename, char *const argv[], char *const envp[]); 20 | char *getcwd(char *buf, size_t size); 21 | int chdir(const char *path); 22 | int fchdir(int fd); 23 | uid_t getuid(void); 24 | gid_t getgid(void); 25 | int setuid(uid_t uid); 26 | int setgid(gid_t gid); 27 | uid_t geteuid(void); 28 | gid_t getegid(void); 29 | 30 | #endif //UNISTDC_H 31 | -------------------------------------------------------------------------------- /system/libc/math.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | 5 | float fabs(float x) { 6 | return fabsl((double)x); 7 | } 8 | 9 | double fabsl(double x) { 10 | return x < 0 ? -x : x; 11 | } 12 | 13 | float powf(float base, float power) { 14 | return (float)powl((double)base, (double)power); 15 | } 16 | 17 | double powl(double base, double power) { 18 | // a^b = exp(b * ln(a)) 19 | return expl(power * logl(base)); 20 | } 21 | 22 | float exp(float x) { 23 | return (float)expl((double)x); 24 | } 25 | 26 | double expl(double x) { 27 | // Use Taylor series to calculate e^x 28 | // e^x = 1 + x + x^2/2! + x^3/3! + ... 29 | 30 | double sum = 1.0; 31 | double term = 1.0; 32 | 33 | for (int n = 1; fabsl(term) > 0.00001; n++) { 34 | term *= x / n; 35 | sum += term; 36 | } 37 | 38 | return sum; 39 | } 40 | 41 | float log(float x) { 42 | return (float)logl((double)x); 43 | } 44 | 45 | double logl(double x) { 46 | // Use Halley-Newton method to calculate log(x) 47 | // y[n+1] = y[n] + 2 * (x - exp(y[n])) / (x + exp(y[n])) 48 | 49 | double yn = x - 1.0F; 50 | double yn1 = yn; 51 | 52 | do { 53 | yn = yn1; 54 | yn1 = yn + 2.0F * (x - exp(yn)) / (x + exp(yn)); 55 | } while (fabs(yn1 - yn) > 0.00001F); 56 | 57 | return yn1; 58 | } 59 | 60 | int isnanf(float x) { 61 | // NaN is not equal to itself 62 | return x != x; 63 | } 64 | 65 | int isnanl(double x) { 66 | // NaN is not equal to itself 67 | return x != x; 68 | } 69 | 70 | int isinff(float x) { 71 | // exponents are all 1s 72 | x = fabs(x); 73 | long int p = *(long int *)&x; 74 | return (p >> 23) == 0xFF; 75 | } 76 | 77 | int isinfl(double x) { 78 | // exponent are all 1 79 | x = fabsl(x); 80 | long long int p = *(long long int *)&x; 81 | return (p >> 52) == 0x7FF; 82 | } 83 | -------------------------------------------------------------------------------- /system/libc/sys/stat.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int chmod(const char *pathname, mode_t mode) { 5 | return syscall(90, pathname, mode); 6 | } 7 | 8 | int fchmod(int fd, mode_t mode) { 9 | return syscall(91, fd, mode); 10 | } 11 | 12 | int fstat(int fd, struct stat *buf) { 13 | return syscall(5, fd, buf); 14 | } 15 | 16 | int lstat(const char *path, struct stat *buf) { 17 | return syscall(6, path, buf); 18 | } 19 | 20 | int mkdir(const char *pathname, mode_t mode) { 21 | return syscall(83, pathname, mode); 22 | } 23 | 24 | int mkfifo(const char *pathname, mode_t mode) { 25 | return -1; 26 | } 27 | 28 | int mknod(const char *pathname, mode_t mode, dev_t dev) { 29 | return syscall(133, pathname, mode, dev); 30 | } 31 | 32 | int stat(const char *path, struct stat *buf) { 33 | return syscall(4, path, buf); 34 | } 35 | 36 | mode_t umask(mode_t mask) { 37 | return syscall(95, mask); 38 | } 39 | -------------------------------------------------------------------------------- /system/libc/unistd.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int syscall(int sysno, ...) { 5 | va_list args; 6 | 7 | long int arg0, arg1, arg2, arg3, arg4, arg5; 8 | 9 | va_start(args, sysno); 10 | arg0 = va_arg(args, long int); 11 | arg1 = va_arg(args, long int); 12 | arg2 = va_arg(args, long int); 13 | arg3 = va_arg(args, long int); 14 | arg4 = va_arg(args, long int); 15 | arg5 = va_arg(args, long int); 16 | va_end(args); 17 | 18 | int retval; 19 | 20 | asm volatile("push %%ebp;" 21 | "mov %1, %%ebp;" 22 | "int $0x80;" 23 | "pop %%ebp" 24 | : "=g"(retval) 25 | : "g"(arg5), "a"(sysno), "b"(arg0), "c"(arg1), "d"(arg2), "S"(arg3), "D"(arg4) 26 | : "memory"); 27 | 28 | return retval; 29 | } 30 | 31 | ssize_t read(int fd, void *buf, size_t count) { 32 | return syscall(0, fd, buf, count); 33 | } 34 | 35 | ssize_t write(int fd, void *buf, size_t count) { 36 | return syscall(1, fd, buf, count); 37 | } 38 | 39 | int close(int fd) { 40 | return syscall(3, fd); 41 | } 42 | 43 | pid_t getpid(void) { 44 | return syscall(39); 45 | } 46 | 47 | pid_t fork(void) { 48 | return syscall(57); 49 | } 50 | 51 | int execve(const char *filename, char *const argv[], char *const envp[]) { 52 | return syscall(59, filename, argv, envp); 53 | } 54 | 55 | char *getcwd(char *buf, size_t size) { 56 | return (char *)syscall(79, buf, size); 57 | } 58 | 59 | int chdir(const char *path) { 60 | return syscall(80, path); 61 | } 62 | 63 | int fchdir(int fd) { 64 | return syscall(81, fd); 65 | } 66 | 67 | uid_t getuid(void) { 68 | return syscall(102); 69 | } 70 | 71 | gid_t getgid(void) { 72 | return syscall(104); 73 | } 74 | 75 | int setuid(uid_t uid) { 76 | return syscall(105, uid); 77 | } 78 | 79 | int setgid(gid_t gid) { 80 | return syscall(106, gid); 81 | } 82 | 83 | uid_t geteuid(void) { 84 | return syscall(107); 85 | } 86 | 87 | gid_t getegid(void) { 88 | return syscall(108); 89 | } 90 | 91 | pid_t getppid(void) { 92 | return syscall(110); 93 | } 94 | -------------------------------------------------------------------------------- /virt2phys.py: -------------------------------------------------------------------------------- 1 | #!/bin/python3 2 | 3 | import sys 4 | 5 | def virt2phys(addr: int) -> tuple[int, int, int]: 6 | pd_index = (addr >> 22) & 0x3ff 7 | pt_index = (addr >> 12) & 0x3ff 8 | offset = addr & 0xfff 9 | return (pd_index, pt_index, offset) 10 | 11 | 12 | def main(args: list[str]) -> int: 13 | if len(args) == 1: 14 | addr = int(args[0], 0) 15 | print(virt2phys(addr)) 16 | else: 17 | print("Usage: virt2phys.py [addr]") 18 | return 1 19 | 20 | return 0 21 | 22 | 23 | if __name__ == '__main__': 24 | sys.exit(main(sys.argv[1:])) 25 | --------------------------------------------------------------------------------