Compile SVGAlib on 32-bit Linux Guest Running in QEMU
Choose OS
We need a 32-bit (x86) build of a Linux image to run SVGALib. The code relies on kernel headers that are found in kernel 2.6.12. Ubuntu 5.10 uses this kernel. I found this match from the table of versions on Wikipedia and downloaded the appropriate x86 release from the old Ubuntu releases archive.
OS: Ubuntu 5.10 Breezy Badger (breezy)
Kernel: 2.6.12-9-386
The kernel version string is the output of the command uname -r
. This combination worked for me, but you may find another version that works too. In the rest of this document, I have substituted uname -r
where the kernel version string is used. For example, if I mention a path x/uname -r
/y, it actually reads, in the context of this document, x/2.6.12-9-386/y. The two back-ticks that enclose the shell command is needed for the shell to be able to run it in place and substitute it with the command's output to form a valid path.
Qemu Guest-OS Setup
Create and prepare the Linux image
Create a Qemu image from the breezy iso.
qemu-img create -f qcow2 breezy32.qcow2 10G
qemu-system-i386 -m 2G -hda breezy32.qcow2 -cdrom ubuntu-5.10-install-i386.iso -boot d -enable-kvm
Mount the root file system that resides on the qcow2 disk image at /tmp/mnt
modprobe nbd max_part=8f
qemu-nbd --connect=/dev/nbd0 os/ubuntu32_10.04_server.qcow2
mount /dev/nbd0p1 /tmp/mnt
If booted at this point the guest OS would have no connection to the internet and the apt would point to repository URLs that are stale. So the first thing to do is edit /etc/network/interfaces and add the line auto eth0 ensuring that the following block of text exists:
auto eth0
iface eth0 inet dhcp
Then we fix the stale URLs by cleaning up the file /etc/apt/sources.list so that only contains these lines
deb http://old-releases.ubuntu.com/ubuntu/ breezy main restricted universe multiverse
deb http://old-releases.ubuntu.com/ubuntu/ breezy-updates main restricted universe multiverse
deb http://old-releases.ubuntu.com/ubuntu/ breezy-security main restricted universe multiverse
We copy the svgalib source from the host to the guest's file system
cp svgalib-1.9.25.tar.gz /tmp/mnt/home/rup/
You may want to create ~/.ssh and copy your public key too, but you will find out later that the OpenSSH server running on breezy is so old that you will not be able to use your key. Using SSH, though, smoothens the workflow.
At the end, dislodge the mount, as Qemu will now need to boot the OS from breezy32.qcow2 so that you can proceed with the rest of the tasks.
umount /tmp/mnt
qemu-nbd --disconnect /dev/nbd0
rmmod nbd
Boot the guest OS, test network, install Emacs and set up an SSH server
qemu-system-i386 -m 2G -hda breezy32.qcow2 -net user,hostfwd=tcp::10021-:22 -net nic -enable-kvm
and peek into its GUI using a VNC viewer
xtightvncviewer 127.0.0.1:5900
Check that the wired network configuration is correct and the internet is reachable. We had edited /etc/network/interfaces and now that the system is up and running, the change should have had taken effect. Wireless doesn't seem to work out of the box on breezy and I haven't tried making it work.
Refresh apt repos and upgrade OS packages
apt-cdrom add
apt-get update
apt-get upgrade
Install emacs and ssh server
apt-get install emacs21 openssh-server
The emacs binary goes to /usr/bin and it may not in breezy's path so add this line to ~/.bash_profile
export PATH=/usr/bin/:$PATH
and reload the file
source ~/.bash_profile
The rest of the work, mostly around building svgalib, until we have compiled svgalib demo binaries, can be done at the command line. So quit the vnc viewer if you want and ssh into the guest
ssh rup@localhost -p 10021
There is no particular reason for the choice of SSH port which, if you remember, also appears in the Qemu incantation.
However, this will complain about key mismatch because breezy is running a very old version of the ssh server. To fix this either use this
ssh -oKexAlgorithms=+diffie-hellman-group1-sha1 rup@localhost -p 10021
or add this to ~/.ssh/config
Host localhost
KexAlgorithms +diffie-hellman-group1-sha1
With the configuration file present, scp works in the usual way
scp -P 10021 xyz rup@localhost:~/
By the way, if on logging and using the remote shell over SSH, you see complaints about a misbehaving terminal, install ncurses-term in the guest
sudo apt install ncurses-term
Install the svgalib build dependencies
apt-get install gcc gcc-3.4 build-essential linux-headers-`uname -r`
The default gcc installation is version 4, and strangely, svgalib, at the point where it builds a kernel module, uses version 3.4. That is why we have gcc-3.4 in the list above.
Build svgalib-1.9.25
cd svgalib-1.9.25
sudo make install
sudo is important. I have not used it in the commands so far because it is fairly easy to deduce when to use it. All svgalib commands must be run as root. Even though the README says that it is not necessary, I think this very old piece of software is missing some context in the modern, virtual ecosystem.
The next steps must be done in order to compile and install a kernel module
cd svgalib-1.9.25/kernel/svgalib_helper
sudo make install
which places a kernel module here
/lib/modules/2.6.12-9-386/kernel/misc/svgalib_helper.ko
and creates the following devices on my machine
/dev/
|_svga
|_svga1
|_svga2
|_svga3
|_svga4
Load the kernel module
sudo modprobe svgalib_helper
which can be done from where you are sitting in the file system; you don't need to be in the directoy where svgalib_helper.ko exists.
Ensure that the module is loaded
lsmod | grep svgalib_helper
svgalib_helper 13348 0
cd back to svgalib-1.9.25/ and build everything
sudo make install >log 2>&1
log should have no errors and end with a note about building the demo programs, so from the same directory run
sudo make demoprogs
Several binaries are created in svgalib-1.9.25/demos/bin and svgalib-1.9.25/threeDKit/bin, out of them I have found that these two run and quit gracefully
sudo ./threeDKit/bin/plane
sudo ./threeDkit/bin/wrap
If you invoke them from your remote shell you can see the output if you VNC into the guest. The shell will tell you which virtual console the output has gone to. The demo first requests the user chose mode resolutions. I picked one from 1-4, others aren't supported in the text-mode resolution Qemu offers the guest by default on my machine. The keys q w a s z x is used to manipulate the 3D view of the model and c to exit the application. If you were in text-mode you will fall back in there. On exit, if you were in a terminal in a graphical desktop the output will get painted over your GUI and drop you back to a clean GUI.
A screenshot shows output of two different svgalib demos (wireframe sphere and aircraft) running in the guest. Both the programs present an identical text screen of options at start, so I have shown one such screen at the top left quadrant.
Changes to the source code
If you are still game for it, here are the two build errors that tripped me and how I got around them.
The first time I ran make, the build stopped at
grep: /lib/modules/2.6.12-9-386/build/include/linux/device.h: No such file or directory
so the Linux source was installed
apt-get install linux-headers-`uname -r`
Then make blurted out
/usr/src/linux-headers-2.6.12-9-386/scripts/gcc-version.sh: line 11: gcc-3.4: command not found
/usr/src/linux-headers-2.6.12-9-386/scripts/gcc-version.sh: line 12: gcc-3.4: command not found
make[2]: gcc-3.4: Command not found
make[2]: Entering directory `/usr/src/linux-headers-2.6.12-9-386'
grep: /lib/modules/2.6.12/build/include/linux/device.h: No such file or directory
So I first install gcc-3.4
apt-get install gcc-3.4
and second, as the suffix "-386" is missing in the kernel version string in the path to the linux headers, I replace the string "KERNELRELEASE" in svgalib-1.9.25/kernel/svgalibhelper/Makefile with the string "SKERNELRELEASE".
References
- My SVGAlib Github repo.
- SVGAlib home page.
- Ubuntu table of versions.
- Ubuntu release archive.
- Hardware specs of my development machine.