The active development path is macOS + Homebrew cross-toolchain + QEMU. Apple Silicon and Intel Macs are both supported.
# 1. Install toolchain brew install x86_64-elf-binutils x86_64-elf-gcc bmake qemu mtools i686-elf-grub # 2. Clone git clone https://github.com/cwolsen7905/UbixOS.git cd UbixOS # 3. Build kernel + userland bmake # 4. Create disk image bmake image # 5. Run in QEMU bmake run
QEMU opens a VGA window. At the login prompt use root / user.
Serial debug output streams to serial.log.
| PACKAGE | PURPOSE |
|---|---|
x86_64-elf-binutils | Cross binutils (as, ld, ar, objcopy) targeting bare i386 ELF |
x86_64-elf-gcc | Cross GCC; used with -m32 to produce i386 output. The Makefile sets this up automatically on Darwin. |
bmake | BSD make — required. GNU make will not work; the Makefiles use BSD-specific syntax. |
qemu | x86 emulator (qemu-system-i386) |
mtools | FAT image tools (mformat, mcopy, mmd) used by mkimage.sh |
i686-elf-grub | GRUB2 bootloader embedded into the disk image |
/opt/homebrew on Apple Silicon
and /usr/local on Intel. tools/mkimage.sh uses the Apple Silicon path by default.
On Intel Mac, edit the GRUB_LIB variable near the top of tools/mkimage.sh.
| COMMAND | ACTION |
|---|---|
bmake | Build kernel + full userland |
bmake kernel | Build kernel only (faster when only sys/ changed) |
bmake world | Build userland only (lib/, bin/, libexec/) |
bmake image | Create ubixos.img — 256 MB raw disk image with GRUB + FAT32 partition |
bmake kernel-to-image | Hot-patch kernel into an existing image via mcopy (faster iteration) |
bmake run | Launch QEMU; VGA window, serial to serial.log |
bmake run-debug | Headless QEMU, serial to stdout. Press Ctrl-A X to exit. |
bmake clean | Remove all build artifacts |
bmake run launches the following QEMU command:
qemu-system-i386 -m 256 \ -drive file=ubixos.img,format=raw,if=ide,index=0 \ -serial file:serial.log \ -vga std \ -device pcnet -net user
Kernel kprintf output goes to both the VGA console and COM1.
Watch it live in a second terminal:
tail -f serial.log
login: root password: user
Add -s -S to enable the GDB stub and halt at startup:
qemu-system-i386 -m 256 \ -drive file=ubixos.img,format=raw,if=ide,index=0 \ -serial file:serial.log -vga std \ -device pcnet -net user \ -s -S
Then connect from a second terminal:
x86_64-elf-gdb sys/compile/kernel (gdb) target remote localhost:1234 (gdb) continue
.vscode/launch.json — it automates the QEMU + GDB connection.
For source-level stepping, build with -O0 by editing sys/Makefile.
brew install bmake export PATH="/opt/homebrew/bin:$PATH" # Apple Silicon # or export PATH="/usr/local/bin:$PATH" # Intel Mac
The GRUB_LIB path in tools/mkimage.sh is version-specific. Find the real path:
find /opt/homebrew/Cellar/i686-elf-grub -name boot.img
Then update the GRUB_LIB variable at the top of tools/mkimage.sh.
-mno-sse -mno-sse2 -mno-mmx -mno-3dnow.
The kernel never sets CR4.OSFXSR, so any XMM instruction triggers fault 6 (#UD).
Verify the relevant Makefile includes those flags.
The runtime linker (libexec/ld) looks for libraries at sys:/lib/.
Ensure bmake world && bmake image ran successfully and that
build/lib/ is populated before creating the image.
Check serial.log — the kernel prints its boot sequence over serial
before anything appears on VGA. A very early crash will show nothing on screen;
verify bmake image completed without errors and that
sys/compile/kernel is non-zero in size.
The original development workflow targets FreeBSD with a native i386 toolchain.
No cross-compiler prefix is needed — CROSS_PREFIX is empty on non-Darwin hosts.
# FreeBSD — use plain make (which is bmake) make make kernel make world make install # installs to /ubixos + /ubixos_fat
make install ROOT=/mnt/ubixos ROOT_FAT=/mnt/ubixos_fat
| PATH | CONTENTS |
|---|---|
sys/compile/kernel | Final kernel ELF binary |
build/bin/ | Userland executables |
build/lib/ | Shared and static libraries |
build/libexec/ | Runtime dynamic linker (ld.so) |
ubixos.img | Bootable QEMU disk image |
serial.log | QEMU COM1 output (created by bmake run) |