Skybolt is a cross-platform, preemptive, multitasking, monolithic, UNIX-like operating system designed to be easy to understand and hack on. It runs on 3 different ISAs and is tested on real hardware.
Skybolt running at 1920x1080 on x86_64.
⚡️ x86_64, aarch64, and riscv64 support.
⚡️ Tested on real X86 PCs (variety of PC laptops and desktops), Raspberry Pi 4B, and Qemu.
⚡️ Higher half 64 bit design.
⚡️ Preemptive multitasking.
⚡️ Userspace tasks.
⚡️ Kernel tasks (for idling, asynchronously repainting the screen, and managing terminals).
⚡️ TAR ramdisk.
⚡️ ELF loader.
⚡️ UART drivers: 16550, PL011.
⚡️ Interrupt controllers: APIC (IOAPIC + LAPIC), ARM GIC, PLIC.
⚡️ Timer drivers: LAPIC timer, ARM generic timer, RISCV s-mode timer.
⚡️ Keyboard driver: PS/2 (PC only).
⚡️ 1920 by 1080 HD graphics (PC only, when booted with GRUB).
⚡️ Contains 100% pure human written code- just the way mom used to make it.
How to build and run the x86_64 release version of Skybolt in Qemu:
- Open dev container: ./dev.sh(or.\windev.batif on Windows)
- In container, make -j PLATFORM=PC CONFIG=RELEASE
- On host OS: ./run.sh pc(or.\winrun.bat pcif on Windows)
Skybolt should boot up in a new window!
Quit Qemu with Ctrl+A followed by X in the terminal you ran run.sh / winrun.bat in.
Building Skybolt always takes the following steps:
- Launch the development container (dev.shon Linux/ macOS,windev.baton Windows)
- Build the kernel in the container with make -j PLATFORM=$(PLATFORM) CONFIG=$(CONFIG)
- To emulate in Qemu, use run.shon Linux/ macOS,winrun.baton Windows
- (Optional) Run in debug mode by adding debugto the end of yourrun.shcommand, then attach a debugger withgdb.shfrom the container
The make step always produces at least two artifacts:
- The kernel ELF, located at bin/skybolt.$(ARCH).$(CONFIG).$(PLATFORM)
- The ramdisk image, located at user/bin/$(ARCH)/fs.tar
Some platforms produce more files than those two; see "Kernel Binaries" below for more.
The development container is available on Docker Hub and GitHub as
jprx/osdev-tools. It will be
automatically installed when you run dev.sh / windev.bat.
Run dev.sh (windev.bat on Windows) to launch the dev container. The
jprx/osdev-tools Docker image has all the tools and debuggers you'll need to
build and debug Skybolt. (If you don't have Docker,
install it first).
Skybolt is always built with the following make invocation:
make -j PLATFORM=$(PLATFORM) CONFIG=$(CONFIG)
Where $(PLATFORM) is one of:
- X86_64(or equivalently,- PC)
- AARCH64(or equivalently,- RASPI)
- RISCV64(or equivalently,- VIRT_RISCV)
And $(CONFIG) is one of:
- RELEASE(runs fast, but hard to debug with GDB)
- DEBUG(runs slow, but easier to debug with GDB)
Build for running:
| Target | Build Command | 
|---|---|
| X86 PC | make PLATFORM=X86_64  CONFIG=RELEASE | 
| Raspberry Pi 4B | make PLATFORM=AARCH64 CONFIG=RELEASE | 
| Qemu virt RISCV | make PLATFORM=RISCV64 CONFIG=RELEASE | 
Build for debugging:
| Target | Build Command | 
|---|---|
| X86 PC | make PLATFORM=X86_64  CONFIG=DEBUG | 
| Raspberry Pi 4B | make PLATFORM=AARCH64 CONFIG=DEBUG | 
| Qemu virt RISCV | make PLATFORM=RISCV64 CONFIG=DEBUG | 
If CONFIG is omitted from the make invocation, the RELEASE variant is built by default.
Ensure qemu is installed on your OS. (Windows users: make sure Qemu is added to your path).
Skybolt is launched with run.sh (winrun.bat on Windows) as follows:
run.sh $(PLATFORM) $(DEBUG_MODE)
Where $(DEBUG_MODE) is one of:
- debugif you want Qemu to wait for a debugger.
- Empty if you don't.
By default, run.sh (and winrun.bat) will try to use the RELEASE version
of the kernel (compiled with CONFIG=RELEASE). However, when running in debug
mode, the scripts will try to launch the DEBUG version of the kernel instead
(compiled with CONFIG=DEBUG).
Setting $(PLATFORM) to one of the following boots Skybolt without graphics (serial output only) using
Qemu's -kernel flag:
- x86
- arm
- riscv
Setting $(PLATFORM) to the following will boot a full PC system emulator,
booting from the Skybolt ISO, using GRUB as the bootloader, and booting with an
emulated display (in a new window) and keyboard:
- pc
The full system (keyboard, display, etc.) is only supported on the X86 PC platform. ARM and RISCV systems are stuck with just using a serial port for now.
Run the RELEASE kernel headlessly, just using the serial port:
| Command | What it gives you | 
|---|---|
| run.sh x86 | Headless X86_64 PC (serial only) | 
| run.sh arm | Headless AARCH64 Raspi (serial only) | 
| run.sh riscv | Headless virt riscv (serial only) | 
Run skybolt.iso with full display, keyboard, and GRUB bootloader (opens a GUI window):
| Command | What it gives you | 
|---|---|
| run.sh pc | Full PC Emulation (keyboard, display) | 
If you want to debug the kernel, add debug to the end of the run.sh (or
winrun.bat) invocation. By default, the DEBUG variant of the kernel will be
used when running in debug mode, so you'll need to make sure you compiled the
kernel with CONFIG=DEBUG.
Instead of starting the system right away, Qemu will wait for you to attach a
debugger. In one window, use run or winrun to start the system, then use
gdb.sh from another terminal inside the dev tools container to attach to
Qemu. From there, you can set breakpoints, use c to start the kernel, or step
through the system using si.
| Command | What it gives you | 
|---|---|
| run.sh x86 debug | Headless X86_64 PC (serial only + debugger) | 
| run.sh arm debug | Headless AARCH64 Raspi (serial only + debugger) | 
| run.sh riscv debug | Headless virt riscv (serial only + debugger) | 
Qemu will wait for a debugger to be attached. In another terminal inside the dev tools container, use gdb.sh to attach
to Qemu on the default port (1234):
| GDB Command | Meaning | 
|---|---|
| gdb.sh x86 | Debug the PC / x86target | 
| gdb.sh arm | Debug the Raspberry Pi / armtarget | 
| gdb.sh riscv | Debug the virt RISCV / riscvtarget | 
gdb.sh must be run from within the dev tools container. Additionally, if
you cloned Skybolt on Windows, make sure you cloned using UNIX line endings,
otherwise gdb.sh won't work in the dev container.
The bin/ directory holds intermediate object files as well as the final kernel image. Kernel ELFs are of the form
skybolt.$(ARCH).$(CONFIG).$(PLATFORM) and are located directly in the bin dir.
Some platforms have further requirements beyond being a 64 bit statically linked ELF file, so more build objects can be produced. These will be described below.
After linking the final kernel at skybolt.x86_64.$(CONFIG).pc, two more files are produced:
- skybolt.x86_64.$(CONFIG).pc.qemuis a 32-bit ELF that can be loaded with Qemu's- -kernelflag. Qemu's- -kernelflag requires 32 bit images, not 64 bit ones- the image contents are identical, just the file type is changed. This kernel is used when running the kernel the "normal" way with- run.sh x86_64.
- skybolt.isois a full GRUB image. When- run.sh pcis called, we use the full ISO instead of just the ELF, so that GRUB is our bootloader instead of Qemu. This ISO image can be used to boot Skybolt on real hardware too.
Raspberry Pi's bootloader needs a flat image, not an ELF. We create it with objcopy:
- skybolt.aarch64.$(CONFIG).raspi.imgis the final image file that should be used for booting, both on real hardware and with Qemu's- -kernelflag. The ELF image is useful only for debugging.
user/ contains all the user programs that end up on-disk inside of Skybolt.
You can make a new program by starting a new C file in user and adding your
program to user/Makefile's list of programs to build. The only header you
should include is skybolt.h which has everything in our "C library" and
definitions for all syscalls. Your program will automatically be built for the
correct architecture and statically linked with the C library.
You can also add whatever files you want to the ramdisk, just toss them in
user/files and add them to the list of files in user/Makefile.
user/libc contains the "C library" used by Skybolt user progrms (currently
just one file). If you add a new syscall, make sure to update skybolt.h and
our libc at user/libc/libc.c.
Ramdisks are built for each ISA in the user/ folder. They can be found at
user/bin/$(ARCH)/fs.tar along with all the files contained in the ramdisk for
that architecture.
WARNING: You should never run untrusted operating systems on hardware you care about. Data loss, permanent system damage, or any other unexpected behavior is highly unlikely, but technically possible.
Skybolt is released under the MIT license:
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
If you want to run Skybolt on real hardware (PC or Raspberry Pi), I suggest you do the following:
- Make sure the hardware you're running on is junk and you don't care if it breaks.
- Remove any hard drives with important information from the system.
- Assume things will go wrong!
Required hardware
- A PC to run the OS on
- A flash drive to install Skybolt to
- A monitor (VGA, HDMI, anything- they should all work)
- A keyboard (PS/2 is the best if your motherboard supports it; USB might work otherwise with legacy USB support). If using a laptop, the builtin keyboard should probably work.
- (Optionally), an RS232 serial cable if you want to use the serial port as well.
Steps:
- In a dev container (dev.shorwindev.bat), build Skybolt withmake -j PLATFORM=PC CONFIG=RELEASE.
- Your Skybolt ISO is at bin/skybolt.iso.
- Use run.sh pc(winrun.bat pcon Windows) to confirm the system boots up from the ISO in an emulator as you'd expect.
- Flash bin/skybolt.isoto a flash drive using your favorite method. (I usedd; Ventoy is another good choice).
- Configure your target PC to use legacy boot mode in your BIOS. If an option exists for legacy PS/2 emulation of USB peripherals, enable it. You want pretty much every "legacy" option enabled. You also likely want secure boot disabled. Expect to tinker with BIOS settings.
- Plug the flash drive into your PC and boot from it.
- You should see Skybolt on the screen!
- If PS/2 emulation is working (or you're using a real PS/2 keyboard) you should be able to type!
- If your computer has an RS232 port, you should be able to hook up a serial cable and attach another computer to it and use Skybolt via serial as well.
Required hardware
- A Raspberry Pi 4B. If you want to use a different kind of Pi, you will.
likely need to modify the device maps in src/platform/raspi.c.
- A UART to USB adapter (eg. an FTDI Adapter).
- An SD Card.
Steps:
- Install 64 bit Linux on the SD card the normal Raspberry Pi way such that your SD card has a valid 64 bit Raspberry Pi filesystem.
- Compile Skybolt with make -j PLATFORM=RASPI CONFIG=RELEASE
- Copy bin/skybolt.aarch64.release.raspi.img(you want the one ending in.img) to your SD card asskybolt.img
- Copy user/bin/aarch64/fs.tarto your SD card asskybolt_disk.tar
- Edit config.txton your SD card add the following to the bottom:
[all]
enable_uart=1
gpio=22-27=np
enable_jtag_gpio=1
kernel=skybolt.img
core_freq_min=500
dtoverlay=disable-bt
dtoverlay=uart1
initramfs skybolt_disk.tar 0x0000000008000000
- Attach your UART adapter to the UART0 pins (6- GND to GND, 8- TX to RX, 10- RX to TX)
- On another device, if using Linux or macOS, open the serial port with the screencommand. Eg. something likescreen /dev/tty.usbserial 115200
- If using Windows, use PuTTY
- The BAUD rate is 115200.
- Power up the Raspberry Pi, you should see a Skybolt shell appear after a few seconds
- (Optional) if you have a JTAG adapter (eg. a J-link) you can attach it as
well and use it to debug the Pi with openocd

