Tag Archives: Linux

Installing OmniOS KVM/QEMU guest onto a Linux host zvol

I originally wanted to install Solaris x86 as a KVM guest, but had problems getting the network to function. The installation itself was easy enough, but all attempts to get networking to work failed. So I decided to try an Illumos distribution, as that would meet the requirements I was looking for.

Since OpenIndiana is the de facto Illumos distribution, I started with that. Unfortunately, it turned out to have the same problem. So I decided to try OmniOS, only to discover it too had the same problem. At this point, I wasn’t sure if it was my Linux KVM that was at fault, since three operating systems failed with the same problem. However, since I have several other operating systems running as KVM guests on Linux and they all work fine, I was still inclined to think it was the distro.

Neither Solaris x86 or OpenIndiana had any new updates, but my OmniOS distro was a little old – I had downloaded the OmniOS_Text_r151012.iso ISO sometime ago. So I checked and found a newer version – OmniOS_Text_r151014.iso. After downloading and installing it, I had a functional network! Based on this, I can only conclude that the reasons Solaris x86 and OpenIndiana failed are due to internal problems with those distros, and not some problem with Linux KVM. Either that or there is some magic KVM setting I’m not familiar with that is needed to get them to work (and I tried a bunch of them).

Installing OmniOS is pretty straight forward. Aside from answering a couple of questions, the installation is totally automatic. The only thing you need to do after installation is manually configure the network. Here are the commands I used to install OmniOS as a KVM guest under Linux.

Create the zvol:

zfs create -p -V 16G rpool/kvm/omnios11/disk0

Create the VM:

qemu-system-x86_64 -enable-kvm -cpu host -m 8192M -drive format=raw,file=/dev/zvol/rpool/kvm/omnios11/disk0 -cdrom OmniOS_Text_r151014.iso -boot d -smp 2

Start the VM:

qemu-system-x86_64 -enable-kvm -cpu host -m 8192M -drive format=raw,file=/dev/zvol/rpool/kvm/omnios11/disk0 -net nic,model=e1000,netdev=net0 -netdev tap,id=net0 -smp 2

Once the VM is started, login as root with no password and configure networking:

ipadm create-if e1000g0
ipadm create-addr -T static -a e1000g0/v4
route -p add default
echo 'nameserver' >> /etc/resolv.conf
cp /etc/nsswitch.dns /etc/nsswitch.conf

You can find more information on setting up OmniOS here:


Installing FreeBSD KVM/QEMU guest onto a Linux host zvol

This configuration is so simple, it’s hardly worth blogging about. But if for no other reason than to keep the commands I used handy, here it is.

Create the zvol:

zfs create -p -V 16G rpool/kvm/freebsd10/disk0

Create the VM:

qemu-system-x86_64 -enable-kvm -m 4096M -drive format=raw,file=/dev/zvol/rpool/kvm/freebsd10/disk0 -cdrom FreeBSD-10.2-RELEASE-amd64-dvd1.iso -boot d

Start the VM:

qemu-system-x86_64 -enable-kvm -m 4096M -drive format=raw,file=/dev/zvol/rpool/kvm/freebsd10/disk0 -netdev user,id=net0 -device e1000,netdev=net0 -smp 2

That’s it!

If you prefer to use bridge networking, use the below command instead:

qemu-system-x86_64 -enable-kvm -m 4096M -drive format=raw,file=/dev/zvol/rpool/kvm/freebsd10/disk0 -net nic,model=e1000,netdev=net0 -netdev tap,id=net0 -smp 2

For more details on bridge networking, see my previous post.

Using bridged networking with KVM/QEMU guests on a Linux host

Using KVM to virtualize guest operating systems under Linux is great, but the default networking configuration doesn’t allow incoming connections to the VM. This is not peculiar to KVM – this is the default for most (all?) virtualization technologies, including VirtualBox.

If, like me, you need to access you guest VM’s from the outside, then you need to setup bridge networking. There are plenty of resources on the web on how to do this, and this blog is simply a quick overview of the steps I took to enable bridge networking under KVM. It will serve as a reminder to my self of the steps I took, and possibly help others out as well.

Below is a list of the sites I used for setting up bridged networking with KVM under Linux:


In a nutshell, setting up a bridge on Linux means installing the necessary bridge software and editing the /etc/network/interfaces file, both of which are described here:


If you’re like me, seeing a working config file gets you a long way, so below is my /etc/network/interfaces file. For reasons not related to bridging, my network is setup as a class B network, so you will probably have to adjust the various addresses accordingly:

$ cat /etc/network/interfaces

# interfaces(5) file used by ifup(8) and ifdown(8)
auto lo
iface lo inet loopback

iface eth0 inet manual

auto br0
iface br0 inet static
    dns-search mydomain.com
    bridge_ports eth0
    bridge_stp off
    bridge_fd 0
    bridge_maxwait 0

Once bridging is setup on the Linux host, all that needs to be done is start QEMU with the correct network options, and then edit the guest network settings. The options to use for QEMU are:

-net nic,vlan=0
-net tap,vlan=0,ifname=tap0

Note that these options replace the existing QEMU network options, and are not to be used in conjunction with them.

It is these args that inform QEMU that you wish to use bridged networking.

To use bridge networking on Windows 7, add the above two arguments to your QEMU start line and then setup your network manually within Windows 7. For example, if you use this command for non-bridge networking:

qemu-system-x86_64 -enable-kvm -m 8192M -cpu host -drive file=/dev/zvol/rpool/kvm/windows7/disk0 -netdev user,id=vlan0 -net nic,model=e1000,netdev=vlan0 -smp 2

Then use this for bridged networking:

qemu-system-x86_64 -enable-kvm -m 8192M -cpu host -drive file=/dev/zvol/rpool/kvm/windows7/disk0 -net nic,vlan=0 -net tap,vlan=0,ifname=tap0 -smp 2

Note that this assumes you have previously setup bridge networking support in Linux. Also, you must run QEMU as root in order to use bridge networking.

To use bridge networking on OS X Mountain Lion, use the above two arguments for networking in your QEMU start line. For example:

qemu-system-x86_64 -enable-kvm -m 4096 -cpu core2duo -machine q35 -usb -device usb-kbd -device usb-mouse -device isa-applesmc,osk="ourhardworkbythesewordsguardedpleasedontsteal(c)AppleComputerInc" -kernel ./chameleon_svn2534_boot -smbios type=2 -device ide-drive,bus=ide.2,drive=MacHDD -drive id=MacHDD,if=none,format=raw,file=/dev/zvol/rpool/kvm/mountain-lion/disk0 -net nic,vlan=0 -net tap,vlan=0,ifname=tap0 -monitor stdio -smp 2

And then setup your network manually within Mountain Lion using these commands:

sudo ifconfig bridge0 create
sudo ifconfig bridge0 addm en0
sudo ifconfig bridge0 up

These commands aren’t necessary, but may be useful if you make a mistake:

sudo ifconfig bridge0 down
sudo ifconfig bridge0 deletem en0
sudo ifconfig bridge0 destroy

To use bridge networking on OS X Mavericks, use the OS X Network utility as described in the above posts to add a bridge, making sure to add your Ethernet device (en0) to it. Then add use the two QEMU networking options above in your QEMU command-line along with the virtio driver. For example:

qemu-system-x86_64 -enable-kvm -m 4096 -cpu core2duo -machine q35 -usb -device usb-kbd -device usb-mouse -device isa-applesmc,osk="ourhardworkbythesewordsguardedpleasedontsteal(c)AppleComputerInc" -kernel ./chameleon_svn2534_boot -smbios type=2 -device ide-drive,bus=ide.2,drive=MacHDD -drive id=MacHDD,if=none,format=raw,file=/dev/zvol/rpool/kvm/mavericks/disk0 -net nic,model=virtio,vlan=0 -net tap,vlan=0,ifname=tap0 -monitor stdio -smp 2

Installing OS X KVM/QEMU guest onto a Linux host zvol

First off, let me start by saying that most of what you read in this post is information I’ve gathered from other sources. Why then have a blog about the subject? Because for some reason, none of the procedures on the other sites completely worked for me. Using the knowledge learned from other sites, along with a few minor tweaks and trial and error, I finally got a sequence that worked for me. This blog will serve as a reminder to me of what I did should I need to do it again and may also help other people who are in the same situation I was in.

In my quest to get an OS X KVM guest under Linux, I visited many, many sites. I can’t be 100% sure that I’ve included all those sites below, but here is a list of sites I’m positive I’ve frequented in order to get OS X running under KVM. 90% of what I present here is a derivative of their work:


I have tested the procedure below with Mountain Lion, Mavericks and Yosemite. For Mavericks and Yosemite, there are extra steps needed to get networking going, but the steps are manageable.

The first problem I encountered was how to create a usable ISO image from the OS X installers obtained through the App Store. Some of the sites claimed you could simply use dd under Linux, while others said you could use the Mac Disk Utility to extract the image. Yet other sites had long sequences of commands and/or scripts to run that would create the ISO for you. There is even a createinstallmedia command on Mavericks and Yosemite. For whatever reason, none of these worked for me. The installation method either failed altogether or presented me with this error when trying to create the VM:

With Mountain Lion or Mavericks:

Can't find /mach_kernel

With Yosemite:

Can't find /System/Library/Kernels/kernel

Since having an ISO image of OS X is step #1, I do not know how other people have gotten OS X to work under KVM by following the directions on the web for creating an ISO. I’m assuming all those people can’t be wrong and I must be the problem, but since I couldn’t get a working ISO using the procedures they describe, I’ve slightly modified those procedures to get a working ISO. To me, it seems the problem is that the bootloader used to bootstrap the system (more on that later) can’t/isn’t looking for the kernel inside of the package (which makes perfect sense to me). To compensate, I’ve extracted the kernel from the package and put them where the bootloader wants them to be.

Note that you will need a Mac in order to create the ISO images as described below. I’m sure there is a way to achieve the same results using Windows or Linux, but since all of the posts I’ve read used a Mac, and I happen to have a Hackintosh that I recently built handy, I just created the ISO on my Hackintosh. If you have another way to create the ISO or already have a working one, then you can skip the ISO creation stuff.

From poking around the OS X installers and reading other posts, I learned that the kernel name and location changed in Yosemite, so that explains why I get two different errors. The next question is why isn’t the kernel present in the OS X Installer? Examining the installer does indeed show there is no /mach_kernel in the Mountain Lion or Mavericks installer, or /System/Library/Kernels/kernel in the Yosemite installer. However, digging a little deeper, I learned that the kernels do exist in a .pkg file inside of the installer. For Mountain Lion and Mavericks, that package is BaseSystemBinaries.pkg. For Yosemite, it’s Essentials.pkg. After downloading the OS X Installer from the App Store, the packages containing the kernel can be found by:

1) Right-clicking the “Install OS X Mountain Lion|Mavericks|Yosemite” icon in Finder
2) Selecting “Show Package Contents”
3) Opening the resulting “Contents” folder
4) Opening the “SharedSupport” folder
5) Double-clicking the “InstallESD.dmg” icon
6) Opening the “Packages” folder

If you install the Pacifist program from https://www.charlessoft.com, you can then right-click the correct package (BaseSystemBinaries.pkg or Essentials.pkg) and select “Open With->Pacifist”. From there, you can select the “mach_kernel” file for Mountain Lion or Mavericks and hit “Extract To…” to extract the kernel. For Yosemite, you extract “System/Library/Kernels/kernel” instead.

With the kernel now extracted, I figured I could copy it to the correct place needed by the bootloader and get past the above error. To accomplish this, I slightly modified the script that can be found here: http://forums.appleinsider.com/t/159955/howto-create-bootable-mavericks-iso. Basically, I inserted a line in the script to copy the kernel into the ISO during creation:

cp -rp ~/Desktop/mach_kernel /Volumes/install_build

Here is the script in its entirety, with my one-line change:

# Mount the installer image:
hdiutil attach /Applications/Install\ OS\ X\ Mountain\ Lion.app/Contents/SharedSupport/InstallESD.dmg -noverify -nobrowse -mountpoint /Volumes/install_app

# Convert the boot image to a sparse bundle:
hdiutil convert /Volumes/install_app/BaseSystem.dmg -format UDSP -o /tmp/mountain-lion

# Increase the sparse bundle capacity for packages, kernel, etc.:
hdiutil resize -size 8g /tmp/mountain-lion.sparseimage

# Mount the sparse bundle target for further processing:
hdiutil attach /tmp/mountain-lion.sparseimage -noverify -nobrowse -mountpoint /Volumes/install_build

# Remove Package link and replace with actual files:
rm /Volumes/install_build/System/Installation/Packages
cp -rp /Volumes/install_app/Packages /Volumes/install_build/System/Installation/

cp -rp ~/Desktop/mach_kernel /Volumes/install_build/

# Unmount both the installer image and the target sparse bundle:
hdiutil detach /Volumes/install_app
hdiutil detach /Volumes/install_build

# Resize the partition in the sparse bundle to remove any free space:
hdiutil resize -size $(hdiutil resize -limits /tmp/mountain-lion.sparseimage | tail -n 1 | awk '{ print $1 }')b /tmp/mountain-lion.sparseimage

# Convert the sparse bundle to ISO/CD master:
hdiutil convert /tmp/mountain-lion.sparseimage -format UDTO -o /tmp/mountain-lion

# Remove the sparse bundle:
rm /tmp/mountain-lion.sparseimage

# Rename the ISO and move it to the desktop:
mv /tmp/mountain-lion.cdr ~/Desktop/mountain-lion.iso

Be sure to have the kernel you extracted in your Desktop directory, or edit the script accordingly.

After running the script, you will have a mountain-lion.iso under Desktop that is suitable for creating a KVM OS X guest. With a few edits around the operating system names, this script also works with Mavericks and Yosemite, but for Yosemite, the extracted kernel name is “kernel” and needs to be copied to /System/Library/Kernels instead:

cp -rp ~/Desktop/kernel /Volumes/install_build/System/Library/Kernels

Note that once created, you can also burn the ISO to a DVD and restore it later using dd:

dd if=/dev/cdrom of=mountain-lion.iso

This will prevent you from having to repeat this procedure should you need to do it again at a later time.

With the ISO creation done, it is now time to create a zvol. You can do that with the following command:

zfs create -p -V 60G rpool/kvm/mountain-lion/disk0

This will create a 60GB zvol named mountain-lion in the rpool zpool, under dataset kvm/mountain-lion. You can of course substitute the names and size as with your own values.

Next, it’s time to create the actual VM. From what I’ve read, you need to be running kernel version 3.15 or later, as well as QEMU 2.2 or later. I’m not sure if this is true, but I heeded the warning and upgraded both my kernel and QEMU versions.

Before continuing, you need a copy of the Chameleon bootloader. You can find it on some of the above links, or download it here:

Chameleon Bootloader

Assuming you have all the necessary tools installed (KVM, QEMU, etc.), creating the VM is as simple as:

qemu-system-x86_64 \
-enable-kvm -m 4096 \
-cpu core2duo \
-machine q35 \
-usb -device usb-kbd \
-device usb-mouse \
-device isa-applesmc,osk="ourhardworkbythesewordsguardedpleasedontsteal(c)AppleComputerInc" \
-kernel ./chameleon_svn2534_boot \
-smbios type=2 \
-device ide-drive,bus=ide.2,drive=MacHDD \
-drive id=MacHDD,if=none,format=raw,file=/dev/zvol/rpool/kvm/mountain-lion/disk0 \
-net nic,model=e1000,netdev=net0 \
-netdev tap,id=net0 \
-monitor stdio \
-device ide-drive,bus=ide.0,drive=MacDVD \
-drive id=MacDVD,if=none,snapshot=on,file=./mountain-lion.iso
-smp 2

Note that for Yosemite, you must disable msrs first by running this command as root:

echo 1 > /sys/module/kvm/parameters/ignore_msrs

After running the above qemu-system-x86_64 command, QEMU will start a VNC session that you can connect to in order to finish the installation. I used the TightVNC viewer on Linux, and usage couldn’t be simpler:

vncviewer localhost:5900

This will connect the VNC viewer to localhost port 5900, which is the default. Note that if you have another QEMU instance running, you may need to change the port number, as they increase sequentially with each instance.

Once connected, you will be a the Chameleon boot prompt. I found that I needed to enter the boot option “GraphicsEnabler=No” in order to get a successful installation, so you may need to do the same. At the boot: prompt, type:

boot: GraphicsEnabler=No

After that, the Mac OS X installation should start. Note that for some reason, the installation exits the VNC viewer shortly after starting, and so you have to reconnect a second time. Once connected the second time, it may be a while before the installation splash screen appears. If after 5 or so minutes it doesn’t appear, simply exit QEMU and try again.

Once you’ve reached the splash screen, the first thing you will notice is that the virtual VNC cursor doesn’t quite follow the real cursor. This makes it painful to navigate the menus, so learning to use the keyboard, particularly the Enter and Space keys, will be beneficial. Later on you can get around this issue by using the native Mac Screen Sharing utility instead of the QEMU VNC server.

Now you can follow the usual directions for installing OS X. Don’t forget to partition your zvol using the Disk Utility during installation!

Once the installation is finished, OS X will reboot and you will be back to the Chameleon boot prompt, but this time with two options to boot. The first option is the ISO installer, named “OS X Base Installer”, and the second option is the KVM VM, and is named Mountain Lion, Mavericks or Yosemite. Be sure to select the VM when booting, else the installer will start all over again. If that happens, simply reboot again and choose the right option.

Finish the installation steps, and if all goes well, you should now have an OS X KVM guest running under Linux!

If you installed Mountian Lion, you are all set. If you installed Mavericks or Yosemite, there are a couple of more steps you need to do in order to get networking functional. Apparently, the e1000 driver does not work under Mavericks or Yosemite and so you must install the virtio driver which you can find in the above links or download it here:

Virtual IO Driver

Now the problem is getting the driver to the guest when you have no network. Fortunately, QEMU provides a mechanism for sharing a FAT folder between the host and guest. Unfortunately, the procedure didn’t work for me. After hours of debugging, it turned out that my problem was the procedure didn’t work with the version of QEMU I was using – 2.3.94, but did work with 2.0.0. So I fired up 2.0.0 just to get the driver over to the guest. To create a shared FAT folder, create a directory named VirtIoNetDrv and download the virtio driver there. Then start QEMU 2.0.0 using the same command above, but with the following two additions:

-device ide-drive,bus=ide.4,drive=fatdrive
-drive id=fatdrive,file=fat:ro:VirtIoNetDrv

Also, change the e1000 line to virtio:
For Mavericks:
-net nic,model=virtio,netdev=net0
For Yosemite:
-net nic,model=virtio,netdev=net0,vectors=0

When the OS X guest starts, you will have a drive mounted from which you can copy the virtio driver from. After copying it somewhere to the guest OS, restart the newer version of QEMU as originally described (without the fatdrive arguments, but with the virtio driver instead of e1000). Install the virtio driver and configure networking. That’s it! I imagine this QEMU quirk will be worked out in a future version, and when it does, you won’t have to fire up an older version. It’s also possible that perhaps the way shared FAT folders work in the newer QEMU has changed, and so the procedures on the web for sharing folders does not work.

After installation, you can start the VM by using a slightly simpler QEMU command:

qemu-system-x86_64 \
-enable-kvm -m 4096 \
-cpu core2duo \
-machine q35 \
-usb -device usb-kbd \
-device usb-mouse \
-device isa-applesmc,osk="ourhardworkbythesewordsguardedpleasedontsteal(c)AppleComputerInc" \
-kernel ./chameleon_svn2534_boot \
-smbios type=2 \
-device ide-drive,bus=ide.2,drive=MacHDD \
-drive id=MacHDD,if=none,format=raw,file=/dev/zvol/rpool/kvm/mountain-lion/disk0 \
-monitor stdio \
-net nic,model=e1000,netdev=net0 \
-netdev tap,id=net0 \
-smp 2

For Mavericks and Yosemite, don’t forget to substitute virtio for e1000, and for Yosemite only, don’t forget to add the vectors=0 option.

Note that you do not need to use the “GraphicsEnabler=No” option to boot – you can simply press Enter. To avoid having to press Enter at all, you can tell OS X to skip the bootloader prompt. To do so, simply create the file /Extra/org.chameleon.boot.plist with these contents:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">

After that, OS X will boot automatically without the need to press Enter at the bootloader.

As mentioned earlier,when you use the VNC provided with QEMU, the virtual mouse pointer doesn’t follow the native mouse pointer, which makes it difficult to use. This can be fixed by enabling screen sharing through OS X and using that instead. But to do that, you will first need to setup bridge networking, which you can read about in my next post.

Installing Windows 7 KVM/QEMU guest onto a Linux host zvol

Though Linux is my desktop of choice, some of my programming tasks require me to run other operating systems. Rather than have multiple machines running various operating systems and/or a single machine with several boot partitions, I have in the past opted for virtualizing these other operating systems using VirtualBox under Linux. That is, until recently, when I switched from using VirtualBox to KVM/QEMU. There’s nothing wrong with VirtualBox, but for what I do, KVM made more sense. And since I’m running ZFS under Linux, using a zvol for the operating systems seemed a natural fit.

Creating a Windows 7 KVM/QEMU guest on a zvol under Linux is easy. First, create the zvol:

zfs create -p -V 60G rpool/kvm/windows7/disk0

This will create a 60GB zvol named windows7 in dataset kvm in the zpool named rpool. You can of course substitute the zpool/dataset names as you see fit.

With the zvol created, insert a copy of Windows 7 into your CD drive and create the guest:

qemu-system-x86_64 -enable-kvm -m 8192M -cpu host -drive file=/dev/zvol/rpool/kvm/windows7/disk0 -cdrom /dev/cdrom -boot d -smp 2

With any luck, qemu will start the Windows 7 installation. Just follow the instructions as you would a normal Windows installation.

Once installation is complete, you can use this command to start the Windows 7 guest:

qemu-system-x86_64 -enable-kvm -m 8192M -cpu host -drive file=/dev/zvol/rpool/kvm/windows7/disk0 -netdev user,id=vlan0 -net nic,model=e1000,netdev=vlan0 -smp 2

This will give your Windows 7 VM a network using DHCP, in which you can communicate from the VM to the outside world, but not the other way around. If you wish to be able to access your VM from the outside, you will need to use bridge networking instead, which you can read about in my future post.

That’s all there is to it!

Note that the -cpu host option is critical – if you forget it, the installation will give you the dreaded BSOD with a STOP 0x0000005D error. And to use the -cpu host option, you must also specify the -enable-kvm option.

If you’d prefer to install to an image file rather than a zvol, you can do that simply by creating the image using QEMU and then substituting the image file for the zvol:

qemu-img create -f qcow2 windows7.img 60G

qemu-system-x86_64 -enable-kvm -m 8192M -cpu host -drive file=windows7.img -cdrom /dev/cdrom -boot d -smp 2

Installing Ubuntu 14.04 to ZFS root pool

It is possible to install Ubuntu 14.04 to a native ZFS root pool. This procedure has been documented elsewhere, and this post is basically a rehash of the post at https://github.com/zfsonlinux/pkg-zfs/wiki/HOWTO-install-Ubuntu-14.04-or-Later-to-a-Native-ZFS-Root-Filesystem more as a reminder to myself of how to do this again. You may find it useful as well.

install ubuntu-14.04

apt-get install software-properties-common
apt-add-repository --yes ppa:zfs-native/stable
apt-get update
apt-get install ubuntu-zfs
apt-get install zfs-initramfs
modprobe zfs
dmesg | egrep "SPL|ZFS"

echo '# Create by-id links in /dev for zfs vdev. Needed by grub' > /etc/udev/rules.d/90-zfs-vdev.rules
echo 'KERNEL=="sd*[0-9]", IMPORT{parent}=="ID_*", ENV{ID_FS_TYPE}=="zfs_member", SYMLINK+="$env{ID_BUS}-$env{ID_SERIAL}-part%n"' >> /etc/udev/rules.d/90-zfs-vdev.rules

parted /dev/disk/by-id/scsi-35000c5005627e703
(parted) set 9 bios on

parted /dev/disk/by-id/scsi-35000c5005627d36f
(parted) set 9 bios on

zpool create -f -o ashift=12 rpool scsi-35000c5005627e703-part1 scsi-35000c5005627d36f-part1
zpool export rpool
zpool import -d /dev/disk/by-id rpool
udevadm trigger

zfs create rpool/ROOT
zfs create rpool/ROOT/ubuntu-1
mkdir /mnt/tmp
mount --bind / /mnt/tmp
rsync -avP /mnt/tmp/. /rpool/ROOT/ubuntu-1/.
umount /mnt/tmp

cat /dev/null > /rpool/ROOT/ubuntu-1/etc/fstab

vi /rpool/ROOT/ubuntu-1/etc/default/grub
comment out:
  GRUB_CMDLINE_LINUX="boot=zfs rpool=rpool bootfs=rpool/ROOT/ubuntu-1"

for d in proc sys dev;do mount --bind /$d /rpool/ROOT/ubuntu-1/$d;done
chroot /rpool/ROOT/ubuntu-1/
for d in proc sys dev;do umount /rpool/ROOT/ubuntu-1/$d;done

for d in /dev/sd[a-b];do grub-install --boot-directory=/rpool/ROOT/ubuntu-1/boot $d;done

init 6

Madness and the Minotaur port Q&A

In this entry I’ll be describing the motivation behind porting Minotaur to x86 as well as describing some of the challenges I encountered along the way. Most of this information can be found in the FAQ and other various documents in the source tree, but I am going to recap everything here in an attempt to keep things in one place.

Probably the first question that comes to mind is why port this archaic game in the first place? To answer, we need to go back to 1982. Back then, I had an original TRS-80 Color Computer with 4k of memory. Shortly after, I acquired Madness and the Minotaur as a present. Unfortunately, this game required 16k, and I only had 4k. Since I wanted to use Extended Color Basic with all its fancy features anyway, I went for the 16k upgrade. After the upgrade, I must have played Minotaur for hours, but never did beat it – partially because the game is so difficult, and partially because back then, we saved our data to cassette tape which wasn’t very reliable. Anyone who has used cassette tape for storage knows what I’m talking about. After spending what seemed like hours trying to load your saved game, listening to sounds similar to that made by a modem, 7 out of 10 times the load would fail with the dreaded “CLOADM ?IOERROR”. Sometimes repeated attempts would successfully load the game, but more often than not it wouldn’t help. So that saved game you just spent 10 hours playing was lost forever. Then sometime in 1982, “cheap” ($1200) IBM XT clones began appearing on the market and I traded in my my trusty CoCo for an 8088 clone, learning all about this new MS-DOS operating system, quickly forgetting about Madness and the Minotaur and the days of cassette storage.

Fast-forward 30 years to the Internet age. Sitting around one day, Minotaur popped into my head for no apparent reason and I decided to google it. Lo & behold, there were a couple of links talking about how hard Madness was to beat. One page, http://www.figmentfly.com/madnessandtheminotaur, even had the binary and information on how to run Madness in a simulator. So I downloaded it and tried some of the simulators, but found them too cumbersome to use, especially around saving and restoring the game. One of the links on the figmentfly page was to a disassembled binary by Chris Cantrell (http://www.computerarcheology.com), complete with full commentary.

Looking over Chris’s source made me think that a port to x86 Linux would be the most beneficial thing for me to do – that way I could easily play the game on my Linux box and also implement a simple save/restore mechanism myself. So with that goal in mind, I set out to port Chris’s commented 6809 sources to x86. Technically, I originally made Chris’s source code compilable and relocatable on the 6809 and then used that code for the port, but in the end the result was the same – Madness and the Minotaur running natively on Linux.

So with the question of why the port to Linux answered, the next logical question is why port to assembler, and not some other high-level language like C? The reason for that is two-fold:

1) Considering the age of the original game and its strong ties to the 6809 processor, porting to x86 assembly might actually have been easier than porting to a high-level language first. Some of the reasons for this are the 8-bit nature of the game, where things such as variable size matter. Another reason is the standard assembly practice (at least back then) of using jumps instead of subroutines, as well as tail recursion. Yet another reason would be the popular tricks used back then such as the LXI Trick (which you can read more about here in item #9: http://www.drdobbs.com/embedded-systems/assembly-language-tricks-of-the-trade/184408315. Such tricks, though very useful back then when memory was tight, are hardly needed today and are fading fast from the memory banks of most programmers. Since all of these tricks and practices would need to be unrolled before porting to a higher-level language anyway, assembly seemed the best choice.

2) The second, and perhaps most important reason, is that I now had an excuse to work with assembly again and sharpen my skills. It’s not often these days that I get to use assembly, never mind two assembly languages at the same time – 6809 and x86.

On the subject of assemblers, I imagine some assembly folks will be upset that I chose the GNU assembler for the port rather than NASM. Simply put, I prefer the AT&T assembly style, and since that is the default style on UNIX, it just made sense. Plus the GNU assembler is available on many platforms, though that argument could be made for NASM as well. If anyone really wants a NASM version, there is a Linux utility named intel2gas that can help translate from AT&T to Intel style. Despite its name, the utility also translates from GAS to NASM.

Another assembly decision I had to make was whether to port to 32-bit or 64-bit. I thought 32-bit would reach the most audiences, as there are still a lot of 32-bit architectures out there. Also, the 32-bit version will run just fine on a 64-bit processor, as there is nothing in the program that requires anything greater than 16-bits. 64-bit assembly would be really overkill for this program, and I imagine the resulting binary would be quite bigger. If for some reason a 64-bit port is needed, it should be a simple matter of changing the register names and taking care of overflow/underflow operations from the original 8-bit design.

I also skipped over 16-bit assembly because it is obsolete and would require working with segments. Segments? Enough said.

More to follow …

Madness and the Minotaur for Linux


Does this phrase seem hauntingly familiar? How long has it been since you’ve seen it? 10 years? 20? 30? Here’s an even better question – did you ever beat it? If you’re like most people who played the game, the answer is no. Has it bothered you all these years that you never were able to win? Do you wish you still has your trusty old CoCo so you could play Minotaur? Well today is your lucky day – Madness and the Minotaur has just been ported to Linux by yours truly! And just in time for the Holidays! Now you can drive yourself crazy re-living past memories playing Madness (the name I have given to Minotaur on Linux) on your favorite Linux box – without the aggravation of cassette tape!

Though Madness is stable and playable, by no means do I claim it is bug-free. There are certainly quirks to be worked out and bugs to be fixed, which is one reason for this blog. Despite any potential bugs, you can move around the labyrinth, collect objects, cast spells, kill monsters, save/restore your game and, yes, even win!

So without further ado, here is the link to get yourself up and running with Madness:


From there, you can download the Madness binary, view the sources or clone the Madness repository so you can build the binary yourself.

And for those of you have never played Madness, prepare for what’s sure to be the hardest game you’ve ever played. Despite its age and simplistic two-word interface, Madness is bound to be one of the toughest games you’ve ever played. See if you can beat it without cheating!

As the game says: