Commit 16055cd2 authored by bzt's avatar bzt

Initial commit

# Debug files
# OS/Z - an operating system for hackers
# Use is subject to license terms. Copyright (c) 2017 bzt (bztsrc@gitlab), CC-by-nc-sa
# --- common configuration ---
# x86_64 or aarch64
ARCH = x86_64
# x86_64: ibmpc, acpi aarch64: rpi
PLATFORM = ibmpc
# --- disk layout ---
#setting this to 1 will create a partition for root fs instead of initrd file
#size of partitions in kilobytes
#EFI doesn't like smaller ESP partitions than
# 1024k with FAT12, 4096k with FAT16 and 33792k with FAT32
#RPi doesn't like smaller paritions than
# 8256k with FAT16 and 33792k with FAT32
#ESPSIZE = 33792
ESPSIZE = 8256
# --- build system ---
# OS/Z - an operating system for hackers
# Use is subject to license terms. Copyright (c) 2017 bzt (bztsrc@gitlab), CC-by-nc-sa
include Config
export O = @
all: chkconf clrdd todogen util boot system apps usrs images
# housekeeping
ifeq ($(ARCH),aarch64)
ifneq ($(PLATFORM),rpi)
@echo Invalid ARCH and PLATFORM combination in Config, PLATFORM != rpi
ifeq ($(PLATFORM),rpi)
@echo Invalid ARCH and PLATFORM combination in Config, ARCH != aarch64
@rm bin/disk.dd bin/osZ-latest-$(ARCH)-$(PLATFORM).dd 2>/dev/null || true
@echo " --- Error fixes ---" >TODO.txt
@grep -ni 'FIXME:' `find . 2>/dev/null|grep -v './bin'` 2>/dev/null | grep -v Binary | grep -v grep >>TODO.txt || true
@echo " --- Features ---" >>TODO.txt
@grep -ni 'TODO:' `find . 2>/dev/null|grep -v './bin'` 2>/dev/null | grep -v Binary | grep -v grep >>TODO.txt || true
# boot loader
boot: loader/bootboot.bin loader/bootboot.efi
@echo "LOADER"
@make -e --no-print-directory -C loader/$(ARCH)-rpi | grep -v 'Nothing to be done' | grep -v 'rm bootboot'
@echo "LOADER"
@make -e --no-print-directory -C loader/$(ARCH)-bios | grep -v 'Nothing to be done' | grep -v 'rm bootboot'
@echo "LOADER"
@make -e --no-print-directory -C loader/$(ARCH)-efi | grep -v 'Nothing to be done' | grep -v 'rm bootboot'
# utilities to use during compilation
util: tools
@cat etc/sys/etc/os-release | grep -v ^BUILD | grep -v ^ARCH | grep -v ^PLATFORM >/tmp/os-release
@mv /tmp/os-release etc/sys/etc/os-release
@date +'BUILD = "%Y-%m-%d %H:%M:%S UTC"' >>etc/sys/etc/os-release
@echo 'ARCH = "$(ARCH)"' >>etc/sys/etc/os-release
@echo 'PLATFORM = "$(PLATFORM)"' >>etc/sys/etc/os-release
@echo "TOOLS"
@make --no-print-directory -e -C tools all | grep -v 'Nothing to be done' || true
# the core
system: src
@echo "CORE"
@make -e --no-print-directory -C src system | grep -v 'Nothing to be done' || true
# user space programs
apps: src
@echo "BASE"
@make -e --no-print-directory -C src libs | grep -v 'Nothing to be done' || true
@make -e --no-print-directory -C src apps | grep -v 'Nothing to be done' || true
@echo "DRIVERS"
@make -e --no-print-directory -C src drivers | grep -v 'Nothing to be done' || true
ifeq ($(DEBUG),1)
@make -e --no-print-directory -C src gensyms 2>&1 | grep -v 'Nothing to be done' | grep -v 'No rule to make target' || true
usrs: usr
@make -e --no-print-directory -C usr all | grep -v 'Nothing to be done' || true
# disk image stuff
images: tools
@echo "IMAGES"
@make -e --no-print-directory -C tools images | grep -v 'Nothing to be done' | grep -v 'lowercase' || true
bin/disk.vdi: vdi
vdi: images
@make -e --no-print-directory -C tools vdi | grep -v 'Nothing to be done' || true
bin/disk.vmdk: vmdk
vmdk: images
@make -e --no-print-directory -C tools vmdk | grep -v 'Nothing to be done' || true
@rm bin/disk.dd.lock 2>/dev/null || true
@rm bin/disk.dd 2>/dev/null || true
@make -e --no-print-directory -C src clean
@make -e --no-print-directory -C tools clean
@make -e --no-print-directory -C tools imgclean
# testing
debug: bin/osZ-latest-$(ARCH)-$(PLATFORM).dd
ifeq ($(DEBUG),1)
@#qemu-system-x86_64 -s -S -name OS/Z -sdl -m 32 -d guest_errors -hda bin/osZ-latest-$(ARCH)-$(PLATFORM).dd -cpu IvyBridge,+ssse3,+avx,+x2apic -serial stdio
qemu-system-x86_64 -s -S -name OS/Z -bios /usr/share/qemu/bios-TianoCoreEFI.bin -m 64 -hda bin/osZ-latest-$(ARCH)-$(PLATFORM).dd -serial stdio
@echo Compiled without debugging symbols! Set DEBUG = 1 in Config and recompile.
@gdb -w -x "etc/script.gdb" || true
@pkill qemu
ifeq ($(ARCH),x86_64)
test: testq
test: testr
@echo "TEST"
qemu-system-x86_64 -name OS/Z -bios /usr/share/qemu/bios-TianoCoreEFI.bin -m 64 -hda fat:bin/ESP -enable-kvm -cpu host,+ssse3,+avx,+x2apic -serial mon:stdio
teste: bin/osZ-latest-$(ARCH)-$(PLATFORM).dd
@echo "TEST"
@#qemu-system-x86_64 -name OS/Z -bios /usr/share/qemu/bios-TianoCoreEFI.bin -m 64 -hda bin/osZ-latest-$(ARCH)-$(PLATFORM).dd -option-rom loader/bootboot.rom -d guest_errors -enable-kvm -cpu host,+avx,+x2apic -serial mon:stdio
qemu-system-x86_64 -name OS/Z -bios /usr/share/qemu/bios-TianoCoreEFI.bin -m 64 -hda bin/osZ-latest-$(ARCH)-$(PLATFORM).dd -option-rom bin/initrd.rom -enable-kvm -cpu host,+ssse3,+avx,+x2apic -serial mon:stdio
testq: bin/osZ-latest-$(ARCH)-$(PLATFORM).dd
@echo "TEST"
@#qemu-system-x86_64 -no-hpet -name OS/Z -sdl -m 32 -d guest_errors -hda bin/osZ-latest-$(ARCH)-$(PLATFORM).dd -option-rom loader/bootboot.bin -enable-kvm -cpu host,+avx,+x2apic,enforce -serial mon:stdio
@#qemu-system-x86_64 -no-hpet -name OS/Z -sdl -m 32 -d guest_errors -hda bin/osZ-latest-$(ARCH)-$(PLATFORM).dd -option-rom loader/bootboot.bin -enable-kvm -machine kernel-irqchip=on -cpu host,+avx,+x2apic,enforce -serial mon:stdio
@#qemu-system-x86_64 -name OS/Z -sdl -m 32 -d guest_errors -hda bin/osZ-latest-$(ARCH)-$(PLATFORM).dd -enable-kvm -cpu host,+ssse3,+avx,+x2apic -serial mon:stdio
qemu-system-x86_64 -name OS/Z -sdl -m 32 -d guest_errors,int -drive file=bin/osZ-latest-$(ARCH)-$(PLATFORM).dd,format=raw -enable-kvm -cpu host,+ssse3,+avx,+x2apic -serial mon:stdio
testb: bin/osZ-latest-$(ARCH)-$(PLATFORM).dd
@echo "TEST"
@rm bin/disk.dd.lock 2>/dev/null || true
@ln -s osZ-latest-$(ARCH)-$(PLATFORM).dd bin/disk.dd 2>/dev/null || true
@#stupid bochs panic when symbols not found...
@cat etc/bochs.rc | grep -v debug_symbols >etc/b
@mv etc/b etc/bochs.rc
ifneq ($(wildcard bin/core.sym),)
echo "debug_symbols: file=bin/core.sym, offset=0" >>etc/bochs.rc
ifneq ($(wildcard /usr/local/bin/bochs),)
/usr/local/bin/bochs -f etc/bochs.rc -q
bochs -f etc/bochs.rc -q
@rm bin/disk.dd.lock 2>/dev/null || true
@rm bin/disk.dd 2>/dev/null || true
testv: bin/disk.vdi
@echo "TEST"
VBoxManage startvm "OS/Z"
testr: bin/osZ-latest-aarch64-rpi.dd
@echo "TEST"
qemu-system-aarch64 -name OS/Z -sdl -M raspi3 -kernel loader/bootboot.img -drive file=bin/osZ-latest-$(ARCH)-$(PLATFORM).dd,if=sd,format=raw -serial mon:stdio -d int
OS/Z - an operating system for hackers
<img align="left" style="margin-right:10px;" alt="OS/Z" src="">
<a href="">Download live images</a>, <small>(~8 Mbyte)</small><br>
<a href="">Documentation</a><br>
<a href="">Support</a><br><br>
OS/Z is a POSIXish hobby OS project. As such it demostrates [different concepts to POSIX](
for those who like hacking with OSes, like the good fellows on [OSDEV]( It's aim is
to be small, elegant, [portable]( and to be able to handle enormous amounts of data in
a user friendly way. To achieve that goal, I've eliminated as many limits as possible by design.
For example only storage capacity limits the number of inodes on a disk. And only amount of RAM limits the number of
concurent tasks at any given time. If I couldn't eliminate a hard limit, I've
created a [boot option]( for it so that you can tweek it without
recompilation. This makes OS/Z a very scalable system.
- [GNU toolchain](
- Microkernel architecture with an effective [messaging system](
- Single disk image for [booting]( from BIOS or from UEFI or on Raspberry Pi 3.
- [Higher half kernel]( mapping, full 64 bit support
- It's [filesystem]( can handle YottaBytes of data (unimagineable as of writing)
- ELF64 object format support
- UNICODE support with UTF-8
Hardware Requirements
- 10 Mb free disk space
- 32 Mb RAM
- 800 x 600 / ARGB display
- IBM PC with x86_64 processor - or -
- Raspberry Pi 3 with AArch64 processor
- [Supported devices](
The [latest live dd image]( should boot OS/Z in emulators and on real machines. For example type
qemu-system-x86_64 -hda bin/osZ-latest-x86_64-ibmpc.dd
For more options, see [Testing How To]( I usually test the image
with [qemu](, [bochs]( and [virtualbox](
The boot loader, the [BOOTBOOT]( Protocol and the
[on disk format of FS/Z]( are licensed under MIT licence.
All the other parts of OS/Z (including my [FS/Z]( implementation) licensed under CC-by-nc-sa-4.0:
Copyright (c) 2016-2018 bzt (bztsrc@gitlab) [CC-by-nc-sa-4.0](
**You are free to**:
- **Share** — copy and redistribute the material in any medium or format
- **Adapt** — remix, transform, and build upon the material
The licensor cannot revoke these freedoms as long as you follow
the license terms.
**Under the following terms**:
- **Attribution** — You must give appropriate credit, provide a link to
the license, and indicate if changes were made. You may do so in
any reasonable manner, but not in any way that suggests the
licensor endorses you or your use.
- **NonCommercial** — You may not use the material for commercial purposes.
- **ShareAlike** — If you remix, transform, or build upon the material,
you must distribute your contributions under the same license as
the original.
qsort: Copyright The Regents of the University of California
BOOTBOOT, FS/Z, OS/Z, bztalloc: bzt
--- Error fixes ---
./src/drivers/fs/fsz/main.c:196: // FIXME: block end reached, load next block from sdblk and alter dirent pointer
./src/fs/main.c:345: //FIXME: no sprintf yet
./src/core/msg.c:269: /* FIXME: naive implementation, no checks */
./src/lib/libc/stdio.c:43: // FIXME: use fprintf(stderr,...
--- Features ---
./docs/ write howto
./src/init/services.c:36: // TODO: load and start user services
./src/drivers/fs/fsz/main.c:142: // TODO: extents
./src/drivers/fs/fsz/main.c:235: // TODO: if loc->creat, then create dir or path
./src/fs/vfs.c:575: // TODO: handle up directory
./src/fs/vfs.c:578: // TODO: detect file system in image
./src/core/x86_64/disasm.h:1216: //TODO: esc
./src/core/x86_64/libk.S:157:// TODO: use SSE2 copy
./src/core/x86_64/ibmpc/platform.c:118:// TODO: enumerate bus and load drivers
./src/core/msg.c:101: /* TODO: use mq_buffstart properly as a circular buffer */
./src/core/msg.c:124: // TODO: use vmm_map()
./src/core/msg.c:205: // TODO: save memory dump to fs
./src/core/sched.c:164: /* TODO: memory -> swap (except tcb) */
./src/core/sched.c:180: /* TODO: swap -> memory */
./src/lib/libc/aarch64/stdlib.S:213: /* TODO: getentropy */
./src/lib/libc/x86_64/stdlib.S:354: /* TODO: getentropy */
OS/Z Documentation
Developer's Corner
Materials interesting for developers.
* [Memory Management]( in OS/Z
* The [FS/Z]( file system, and it's [on disk format](
* About [processes](
* [Scheduler](
* Using [messages]( at different levels (aka. syscalls in OS/Z)
* How a [keypress]( is processed
* [Security]( checks
* Differences to [POSIX](
* [Porting]( to new platforms
* [Compilation](
* [Boot procedure](
* [Testing](
* [Debugging](
* [Developing](
SysAdmin's Playground
Documentation on how to operate OS/Z.
* Available [device drivers](
* [Services]( hierarchy and details
* [Virtual File System]( and paths
* [Boot options](
* Invoking [Rescue Shell](
* [Install]( OS/Z on a USB stick and package management
* Manage and initialize [services](
User's Guide
Information for end users.
* [User Interface](
OS/Z Boot Process
OS/Z uses the [BOOTBOOT]( protocol to get the system running.
The compatible [loader]( is loaded by the firmware as the last step of POST.
On every platforms, the loader initializes the hardware (including the framebuffer), loads initrd and locates `sys/core` inside.
When found, it maps that at the top of the address space (-2M..0) and passes control to it.
First of all we have to clearify that `core` consist of two parts: one is platform independent, the other part is
architecture and platform specific (see [porting](
During boot, the execution is jumping forth and back from one part to the another.
The entry point that the loader calls is `_start`, which can be found in [src/core/(platform)/start.S](
It disables interrupts, sets up segments registers, stack frame and checks required CPU features. It also initializes [kprintf](, so that it can call kpanic if needed.
Finally jumps to the C startup code `main()` in [src/core/main.c]( which is a platform independent code.
That platform independent `main()` does the following:
1. as OS/Z is polite, greets you with a "OS/Z starting..." message, then
2. `env_init` parses the [environment variables]( in [src/core/env.c]( passed by the loader.
3. `pmm_init()` sets up Physical Memory Manager in [src/core/pmm.c](
4. `sys_init()` initializes [system services](, in [src/core/sys.c](, which loads `IDLE` task
and enumerates system buses to locate and load [device drivers]( It will also initialize
the [IRQ Routing Table]( (IRT).
5. second service is the file system service, `service_init(SRV_FS)` in [src/core/service.c]( which is a normal system service, except it has the initrd entirely mapped in in it's bss.
6. user interface is initialized with `service_init(SRV_UI)` in [src/core/service.c]( These first three services (aka `IDLE`, `FS`, `UI`) are mandatory, unlike the rest.
7. loads additional, non-critical tasks by several `service_init()` calls in [src/core/service.c]( like the `syslog`, `inet`, `sound` and `init` system services.
8. drops supervisor privileges by calling `sys_enable()` in [src/core/sys.c](
That last function switches to the first task, and then the scheduler, `sched_pick` in [src/core/sched.c](
chooses driver and service tasks one by one until all of them blocks. Note that pre-emption is not enabled at this point.
Driver tasks perform hardware initialization and they fill up the IRT.
When the `IDLE` task first scheduled, it will call `sys_ready()` in [src/core/sys.c](, which
1. enables IRQs with entries in IRT. It also enables timer IRQ and with that pre-emption may begin.
2. finally sends a SYS_mountfs message to "FS" task in the name of "init" task.
The control is passed to ["FS" task](, which receives the
SYS_mountfs message and parses [fstab](
When mounting finished, it notifies the ["init" task]( and
normal operation begins.
(NOTE: If OS/Z was compiled with debug support and `debug=tests` passed in [environment](,
then `core` loads [system test]( instead of `sys/init`,
which will perform various unit and functionality tests.)
User land
The first real 100% userspace process is started by the [init]( system service.
If rescueshell was requested in [environment](, then init
starts [bin/sh]( If it is the first run ever, then starts `bin/identity`
to query computer identity such as hostname from the user. Finally starts all user servies. User services are classic
UNIX daemons, among others the user session service that provides a login prompt.
End game
When the `init` system service quits, the execution is [passed back]( to `core`.
Then OS/Z says 'Good Bye' with `kprintf_reboot()` or with `kprintf_poweroff()` (depending on the exit status), and the platform
dependent part restarts or turns off the computer.
OS/Z Boot Options
Environment configuration file
The boot options are kept on the first bootable partition on the first bootable disk under `FS0:\BOOTBOOT\CONFIG` or `/sys/config`. When you're
creating a disk image, the contents of that file are taken from [etc/sys/config](
This file is a plain ASCII file with `key=value` pairs, parsed by [core/env.c](
and [libc/env.c]( No whitespaces allowed, and each pair is separated by a newline (0x0A) character.
The file can't be longer than a page (4096 bytes on x86_64 and AArch64). You can put comments in it with '#", '//' and '/*'.
Keys are ASCII names without spaces, values can be decimal and hexadecimal [numbers, booleans or strings](
Boot Parameters
| Parameter | Default | Type | Subsystem | Description |
| --------- | :------: | ---- | --------- | ----------- |
| screen | 1024x768 | num<i>x</i>num | [loader]( | required screen resolution, minimum 640x480 |
| kernel | sys/core | string | loader | the name of kernel executable on initrd |
| debug | 0 | decimal | core | specifies which debug information to show (if [compiled with debugging](, see below) |
| nrphymax | 2 | number | core | the number of pages to store physical RAM fragments (16 bytes each) |
| nrmqmax | 1 | number | core | the number of pages for Message Queue (64 bytes each) |
| nrlogmax | 8 | number | core | the number of pages for early syslog buffer |
| quantum | 100 | number | core | scheduler frequency, a task can allocate CPU continously for (quantum) timer interrupts. |
| display | 0 | number | core | selects output mode, see below |
| syslog | true | boolean | core | disable syslog [service]( |
| networking | true | boolean | core | disable inet service |
| sound | true | boolean | core | disable sound service |
| pathmax | 512 | number | fs | Maximum length of path, minimum 256 |
| cachelines | 16 | number | fs | Number of block cache lines, minimum 16 |
| cachelimit | 5 | percentage | fs | Flush and free up block cache if free RAM drops below this limit, 1%-50% |
| fps | 10 | number | ui | requested frame rate |
| keymap | en_us | string | ui | keyboard layout, see [etc/kbd]( |
| lefthanded | false | boolean | ui | swap pointers |
| identity | false | boolean | init | run first time setup before servies to get machine's identity |
| rescueshell | false | boolean | init | if true, starts `/bin/sh` instead of user services |
| clock | 0 | number | platform | override autodetected clock source |
| hpet | - | hexdec | platform | x86_64-acpi override autodetected HPET address |
| apic | - | hexdec | platform | x86_64-acpi override autodetected LAPIC address |
| ioapic | - | hexdec | platform | x86_64-acpi override autodetected IOAPIC address |
This can be a numeric value, or a comma separated list of flags, see [debug.h](
| Value | Flag | Define | Description |
| ----: | ---- | ------ | ----------- |
| 0 | | DBG_NONE | no debug information |
| 1 | me | DBG_MEMMAP | dump memory map on console (also dumped to syslog) |
| 2 | ta | DBG_TASKS | dump [system services]( with TCB physical addresses |
| 4 | el | DBG_ELF | debug [ELF loading]( |
| 8 | ri | DBG_RTIMPORT | debug [run-time linker]( imported values |
| 16 | re | DBG_RTEXPORT | debug run-time linker exported values |
| 32 | ir | DBG_IRQ | dump [IRQ Routing Table]( |
| 64 | de | DBG_DEVICES | dump [System Tables]( and [PCI devices]( |
| 128 | sc | DBG_SCHED | debug [scheduler]( |
| 256 | ms | DBG_MSG | debug [message sending]( |
| 512 | lo | DBG_LOG | dump [early syslog]( |
| 1024 | pm | DBG_PMM | debug [physical memory manager]( |
| 2048 | vm | DBG_VMM | debug [virtual memory manager]( |
| 4096 | ma | DBG_MALLOC | debug [libc memory allocation]( |
| 8192 | bl | DBG_BLKIO | debug [block level I/O]( |
| 16384 | fi | DBG_FILEIO | debug [file level I/O]( |
| 32768 | fs | DBG_FS | debug [file systems]( |
| 65536 | ca | DBG_CACHE | debug [block cache]( |
| 131072| te | DBG_TESTS | run [tests]( instead of [init]( task |
Most of these only available when compiled with [DEBUG = 1]( Normally you can only use two to troubleshoot boot: DBG_DEVICES and DBG_LOG.
A numeric value or exactly one flag.
| Value | Flag | Define | Description |
| ----: | ---- | ------ | ----------- |
| 0 | mc | DSP_MONO_COLOR | a simple 2D pixelbuffer with 32xRGB0 color pixels |
| 1 | sm,an | DSP_STEREO_MONO | two 2D pixelbuffers*, they are converted grayscale and a red-cyan filtering applied, anaglyph |
| 2 | sc,re | DSP_STEREO_COLOR | two 2D pixelbuffers*, the way of combining left and right eye's view is 100% driver specific, real 3D |
(* the two buffers are concatenated in a one big double heighted buffer)
Clock Source
Either a numeric value or exactly one flag.
| Value | Flag | Platform | Description |
| ----: | ---- | -------- | ----------- |
| 0 | | - | auto detect |
| 1 | hp | x86_64-acpi | High Precision Event Timer (default) |
| 2 | pi | x86_64-acpi | Programmable Interval Timer (fallback) |
| 2 | pi | x86_64-ibmpc | Programmable Interval Timer (default) |
| 3 | rt | x86_64-ibmpc | Real Time Clock |
| 1 | ar | aarch64-rpi | Built-in ARM CPU timer (default) |
| 2 | sy | aarch64-rpi | BCM2837 System Timer |
OS/Z Compilation
- GNU toolchain (make, gcc, binutils (gas, ld, objcopy, strip), see [tools/](
- bash or dash (shell scripts are used to [generate different files]( during compilation)
- optionally fasm (for recompiling BIOS booting)
The `core` is always compiled for a specific [machine](,
which can be controlled in [Config]( with `ARCH` and `PLATFORM` variables.
Valid combinations are:
| ARCH | PLATFORM | Description |
| ---- | -------- | ----------- |
| x86_64 | ibmpc | For old machines, uses PIC and PIT (or RTC), enumerates PCI bus |
| x86_64 | acpi | For new machines, APIC, x2APIC, IOAPIC, HPET and parses ACPI tables |
| aarch64 | rpi | Raspberry Pi 3+ |
The make system is created in a way that you can say `make all` in almost every directory. If you do that in the top level
directory, it will compile everything and will also build disk image for you, but surpressing messages. In subdirectories make
will always display the full command executed during compilation.
For example if you enter `src/fs` and issue `make all` there, then only the filesystem subsystem will be recompiled, and
you'll be able to see the exact commands used.
So to compile all the things, simply type
$ make all
You should see something similar to this:
$ make all
src mkfs.c
src elftool.c
gen x86_64/ibmpc/isrs.S (PIC, numirq 32, idtsz 4096)
lnk sys/core (x86_64-ibmpc)
lnk sys/lib/ (x86_64)
src sys/ui
src sys/bin/sh
src sys/bin/test
src sys/bin/sys
src sys/syslog
src sys/sound
src sys/fs
src sys/inet
src sys/init
src sys/drv/fs/
src sys/drv/fs/
src sys/drv/fs/
src sys/drv/fs/
src sys/drv/fs/
src sys/drv/input/
src sys/drv/display/
src sys/driver
mkfs initrd
mkfs boot (ESP)
mkfs usr
mkfs var
mkfs home
mkfs bin/osZ-latest-x86_64-ibmpc.dd
Non-EFI loader
If you want to recompile `loader/boot.bin` and `loader/bootboot.bin`, you'll need [fasm](
Unfortunately GAS is not good enough at mixing 16, 32 and 64 bit instuctions, which is necessary for BIOS booting. To keep
my promise that you'll only need the GNU toolchain, I've added those pre-compiled binaries to the source.
See what you've done!
The live disk image is generated to [bin/osZ-(ver)-(arch)-(platform).dd]( Use the
`dd` command to write it on a USB stick or boot with qemu, bochs or VirtualBox.
$ dd if=bin/osZ-latest-x86_64-acpi.dd of=/dev/sdc
$ make testq
$ make testb