ArtOS is a very basic operating system which started from osdev tutorials but which quickly outgrew them.
The aim of this project is simply to learn. If it becomes something I want others to be able to use I will add the typical sections to this README.
Running DOOM (1993) IN USERSPACE! (+ user space apps and shell):
artosdemo-low.webm
Running DOOM (1993):
DOOM.mp4
p.s. it runs smoothly (easily achiving the hardcoded 35 fps) but the video recording and compression makes it look clunky
Loading Screen and Keyboard:
Splash Screen:
Pixel Mode:
Colours:
Hello World:
- Basics
- Boot into hello world
- Text mode terminal newline Character
- Text mode terminal Scrolling
- Colour Art
- Serial PORT1 output from kernel
- Pixel mode text support
- Draw "art" in pixel mode
- Replace grub and multiboot with grub2 and multiboot2
- Interrupts and time
- Interrupt Service Routines (ISR) are targeted on interrupt using a partially filled Interrupt Descriptor Table
- Interrupt Requests (IRQ) can be handled
- IRQ0 targets a timer decrementor to allow for scheduling and waiting.
- Kernel sleep (block until n ticks occur)
- Replace PIC with APIC
- Real time clock implemented
- Configure LAPIC timer for scheduling
- User IO
- Keyboard
- Mouse
- Shell environment
- Hardware detection and support
- SMBIOS detection
- PCI device detection
- IDE detection
- IDE initialisation (currently supports CD ROM only, see storage)
- Initialise frame buffer etc using the multiboot2 data instead of hard coded
- Detection and selection of video modes i.e. reconfiguring the VGA hardware
- Storage
- Attach a RW storage device in Qemu
- Read data from CD ROM using PCI IDE DMA BusMastering
- Use data from CD ROM i.e. parse .iso file system
- Support virtual attached RW storage
- Support path strings or similar filename access (WIP)
- Detect and mount/unmount storage devices on real hardware
- USB storage support
- Filesystem
- Create a directory tree from iso fs data
- Implement a rudimentary filesystem
- implement proper pdclib compliant filehandling
- PDCLIB
- Implement C standard library for kernel space
- Load a file using pdclib
- User space functionality (e.g. exit, raise, signal)
- DOOM
- Play DOOM for ArtOS!
- Play DOOM for ArtOS on real hardware
- Loading from CD ROM instead of baked into the binary
- Loading from boot USB
- Run in user space
- Add sound
- Add save game support
- Optimisations
- Basic SIMD for memcpy, memmove and memset
- Advanced SIMD usage (string operations and vector maths)
- There are many other optimisations to consider
- Path to User Space
- Use Paging/virtual memory
- Proper handling of a scheduler to allow for sleeping of a task
- Implement a standard library for user space
- Run an executable
- Self hosting compiler
- Misc
- Remove resolution specific baked in splash screen with centered graphic (can be scaled) and programatically drawn borders. Bring back the loading bar?
- Stretch goals
- higher half
- 64-bit support
- ARM support (raspberry pi zero?)
- Multithreading
- Networking
- USB support
- Window manager and windows
- Graphics driver(s)
- I need to create some useful tools for the shell
- such as "ls", "cd", "run" etc. This means I need to create the idea of a path/path string within my OS. This requires path lookup support in the kernel.
- i686-elf gcc cross-compiler
- QEMU
- GRUB2
- Multiboot2
- CMake
- Jetbrains CLion
- xorriso
- ventoy
- Public Domain C Library
- DOOM Generic
- workshop
- sdkcraft
The easiest way to build and run ArtOS is to use the provided workshop configurations.
If you are already using workshop and sdkcraft, then skip the installation steps and go right to preparation steps
sudo snap install --channel=6/stable lxd
lxd init --auto
or
sudo snap refresh --channel=6/stable lxd
lxd init --auto
sudo snap install --classic workshop
workshop launch
workshop connect artos/artos-run:desktop
To build and run using cmake:
workshop run build-debug
workshop run qemu
or
workshop run build-release
workshop run qemu
To run ArtOS in qemu and connect remote gdb debugging (after workshop run build-debug for symbols) run one of the following
workshop run debug-os # to debug the kernel
workshop run debug-bart # to debug the shell
workshop run debug-hello # to debug the hello world program
workshop run debug-doom # to debug DOOM
Override build modes using these CMake options (example usage shown below). Defaults shown in parentheses.
-
-DENABLE_SERIAL_LOGGING:BOOL=ON|OFF
Enable kernel serial output (LOG / WRITE / NEWLINE macros) on COM1 for use with QEMU or a hardware serial port. Use this to capture kernel logs toserial.logor an attached serial terminal. (Default: OFF) -
-DASYNC_READ:BOOL=ON|OFF
Enable asynchronous I/O for certain filesystem/read operations. This may change performance characteristics and currently has lower performance in some paths; enable only if you need non-blocking read behavior. (Default: ON) -
-DSIMD:BOOL=ON|OFF
Use SIMD-optimized implementations for low-level memory operations (memcpy / memmove / memset) to improve throughput. Disable to use standard implementations (useful for debugging or portability). (Default: ON) -
-DENABLE_TERMINAL_LOGGING:BOOL=ON|OFF
When logging is enabled, prefer terminal-based logging instead of serial output. This overrides serial logging macros to write to the in-kernel terminal if supported. (Default: OFF)
Example — configure with custom options:
workshop run build-debug \
-DENABLE_SERIAL_LOGGING:BOOL=ON \
-DASYNC_READ:BOOL=OFF \
-DSIMD:BOOL=ON \
-DENABLE_TERMINAL_LOGGING:BOOL=OFFsudo apt-get install
gcc-multilib
g++-multilib
grub-pc-bin
xorriso
mtools
make a disk image using:
qemu-img create external_resources/ArtOS_HDD.img 512M and change 512M to any size you like.
NOTE package names/instructions are for ubuntu noble (24.04) - your mileage may vary!
I suggest using a chroot, container or some other separate environment for building to avoid polluting your host system with x86_32 architecture packages.
For schroot approach:
sudo apt install debootstrap schroot
sudo mkdir -p /srv/chroot/artos
sudo debootstrap noble /srv/chroot/artos http://archive.ubuntu.com/ubuntu/
sudo nano /etc/schroot/chroot.d/artos # or your preferred editor
and populate it with
[artos]
description=ubuntu noble for building artos
directory=/srv/chroot/artos
users=<your current username>
root-users=root,<your current username>
type=directory
profile=desktop
personality=linux
then enter the schroot environment
[sudo] schroot -c artos
you should see your bash prompt change.
Now set up build dependencies inside the schroot
sudo dpkg --add-architecture i386
sudo apt update
sudo apt install -y cmake wget gcc-multilib g++-multilib libc6:i386 libstdc++6:i386 mtools grub-common grub-pc-bin socat xorriso
and then to build (still inside schroot, at root dir of project)
cmake -S ./ -B cmake-build-artos -DCMAKE_TOOLCHAIN_FILE=./toolchain.cmake -DENABLE_SERIAL_LOGGING:BOOL=ON -DENABLE_TERMINAL_LOGGING:BOOL=ON -DCMAKE_BUILD_TYPE=Release
cmake --build cmake-build-artos -t ArtOS
NOTE you can change the flags as you see fit. e.g. -DCMAKE_BUILD_TYPE=Debug
To exit schroot run
exit
In order to run ArtOS, you will need the proper qemu. On ubuntu the package is called qemu-system-x86, but the
executable we need is called qemu-system-i386.
NOTE schroot will not have access to your display manager so you can only run it with no-monitor. To actually interact with ArtOS, please run it directly from your host.
To install qemu on (ubuntu) run
sudo apt install -y qemu-system-x86
and to run ArtOS, you can use this command
qemu-system-i386 -cdrom bin/ArtOS.iso -serial file:serial.log -boot d -s -m 2G -no-reboot
and additional options can be used to, e.g., attach a HDD (not implemented at time of writing) based on the qemu docs
e.g. further above is an example, and here it is broken down:
qemu-system-i386
# specify a cd-rom drive and file
-cdrom
bin/ArtOS.iso
# log serial IO to file
-serial
file:serial.log
# boot from cd-rom first
-boot
d
# `-s` is shorthand for `-gdb tcp::1234` - enabled gdb connections
-s
# Hang on start, allows you to connect gdb before even the first stage boot loader runs.
-S
# add video and specify video memory
-device
VGA,vgamem_mb=32
# specify max system RAM
-m
2G
# don't reboot the system on a cpu panic
-no-reboot
# this is supposed to specify the smbios type, but seems to do nothing :D
-smbios
type=0
# add a .img file as RW storage
-drive
id=disk,file=external_resources/ArtOS_HDD.img,format=raw,if=none
-device
ide-hd,drive=disk,bus=ide.0
# enable CPU register printouts for every interrupt
-d int
qemu-system-i386
-cdrom
bin/ArtOS.iso
-serial
file:serial.log
-boot
d
-s
-S
-device
VGA,vgamem_mb=32
-m
2G
-no-reboot
-smbios
type=0
-drive
id=disk,file=external_resources/ArtOS_HDD.img,format=raw,if=none
-device
ide-hd,drive=disk,bus=ide.0
qemu-system-i386 -cdrom bin/ArtOS.iso -serial file:serial.log -boot a -s -S -device VGA,vgamem_mb=32 -m 2G -no-reboot
-smbios type=0 -drive id=disk,file=external_resources/ArtOS_HDD.img,format=raw,if=none -device
ide-hd,drive=disk,bus=ide.0
After installing multilib, set up the following for each build profile (edit configurations):
example CMake options for File -> settings -> Build, Execution, Deployment -> CMake ->
-DENABLE_SERIAL_LOGGING:BOOL=ON
-DASYNC_READ=ON
-DENABLE_TERMINAL_LOGGING:BOOL=ON
-DSIMD:BOOL=ON
-DCMAKE_TOOLCHAIN_FILE="./toolchain.cmake"
Target is always ArtOS (no extension)
add a new build target: CMake application
Target: ArtOS
Executable: <path/to/>qemu-system-i386 (usually /usr/bin/qemu-system-i386)
Program Arguments (example):
-cdrom
bin/ArtOS.iso
-serial
file:serial.log
-boot
a
-s
-S
-m
2G
-no-reboot
also append this to add a virtual HDD:
-drive
id=disk,file=external_resources/ArtOS_HDD.img,format=raw,if=none
-device
ide-hd,drive=disk,bus=ide.0
Working Directory (optional): <Path/To/Project/Root>
Before launch: Build
Add a new target in edit configurations:
+ -> Remote Debug
Give it a name like remote debug ArtOS
Debugger: Bundled GDB (multiarch)
'target remote' args: localhost:1234
Symbol File: <path/to/project/root>/bin/ArtOS.bin (or path to, e.g., doom.art)
Make a blank file with dd if=/dev/zero of=external_resources/ArtOS_HDD.img bs=1M count=64 (this is 64MB because it's
bs times count)
Give it an ext4 format: mkfs.ext4 -F external_resources/ArtOS_HDD.img [-L ArtOS_RW] where the stuff in square brackets
labels it with a name