Setting up a fully-fledged virtual Debian/m68k GNU/Linux environment for development

January 03, 2014 | 9 Minute Read

Intro

One of the courses of this semester is ACSO: “Architettura dei Calcolatori e Sistemi Operativi” (Computers’ Architecture and Operating Systems).

Part of the course focuses on assembly programming using good old Motorola’s M68k.

Despite the fact that as processor it is dead and buried, I have to say that I’m having a nice time writing code for this processor using Easy68K.

Easy68K is great and it does a lot of nice things.

Thank Thor, it works great using Wine, but something fails from time to time, resulting in a poor user experience (tip: try running some piece of code when a second monitor is connected to your computer and enjoy it exploding).

Also, it lacks a good set of editor shortcut.

For short: yeah, it’s cool but it’s not GNU Emacs.

How do I emacsify everything?

Simple: let’s get a m68k-based system, install some sort of POSIX-compatible operating system, and let’s get GNU Emacs running upon it, yay!

Should we go for something real? Actually, I would. But it’s too messy and it would require me to port some existing operating system to it, and I’m not quite proficient with operating systems (yet) to do that.

Let’s go for something virtual instead. My first choice was the beloved qemu, but it was a mess to get working (I couldn’t get it working) and there’s practically no existing documentation for qemu-m68k.

Instead, Aranym has proven to be a very good candidate for the job: it can virtualize a mmu-enabled m68k-based system, can use a variable amount of ram, can provide network interfaces to guest operating systems and can use multiple virtual drives. Since it uses SDL for graphic rendering, it can easily be run without an X server in windowless mode (think of providing shell accounts).

Ok then, where do we begin from?

The emulator

First step is installing Aranym on our system. In Ubuntu 12.04 LTS it’s as simple as typing:

apt-get install aranym

Aranym will be downloaded and installed in your system.

The operating system

Here lies a problem for the long run: there are different operating systems available for the m86k: all the various flavours of GNU/Linux (Debian and Gentoo in particular) the good old NetBSD and OpenBSD. Minor operating systems exists for m68k, but they are not that much interesting.

What’s the problem with operating systems, so? The problem is that there is a lack of documentation about installation of the aforementioned OSes using the various platforms.

Thank Thor, somewhere someone updated Debian’s m68k page and rebuilt a Debian/68k image, and added some instructions to get everything working: here’s Debian Wiki’s page on aranym.

The operating system of choice here is thus Debian, which comes in handy as I alredy know most of the system.

The first step now is to download a preinstalled image of Debian: Ara2012D.txz.

Pick one of the mirrors listed on debian-wiki’s page, download it and extract it somewhere:

manu@nadia:~/m68k$ wget http://people.debian.org/~tg/f/m68k/Ara2012D.txz

manu@nadia:~/m68k$ xz -dc Ara2012D.txz | tar -xvf -

manu@nadia:~/m68k$ cd Ara2012D

The system is very minimal, and has been installed using debootstrap with --variant=minbase. See “The hard disc image” section for more details.

Other utils

In order to end with a fully-fledged system, we need additional packages:

manu@nadia:~$ sudo apt-get install bridge-utils

Why do we need bridge-utils? No system can be defined fully-fledged without networking. Also, I like messing up with networking ;)

Startup

At this point we have everything we need in order to get it working, let’s fire it up!

The Debian hard disk image we downloaded previously comes with a configuration file for Aranym which will be very helpful, since saved me from digging the man pages (I had to dig them up anyway when I was messing up with networking). It works pretty ok, but networking didn’t work out of the box for me. It’s gonna boot up and work ok, but networking won’t work. More on this later.

Let’s fire it up:

manu@nadia:~/m68k/Ara2012D$ taskset 0×01 aranym-mmu -l -c aranym.cfg

Here you go, here’s your Debian/68k system!

Root’s password is, guess what, ‘root’.

“First steps” section in Debian’s wiki will provide a good starting point.

After you’ve changed root’s password, hostname and installed some packages, it’s time to net up networking.

Oh, before you go mad: when I tried this, I realized there’s no vim or nano on that system. Yup, nothing at all, but there’s the good old ed, which is a PITA to learn and use on the fly. Editing /etc/network/interfaces using ed has been a pain, mostly. Good news though: I’ve seen while trying things for this post that the system ships the glorious mc, and watching the process tree (there’s no pstree, but “ps aux” will work just fine) suggested me that there’s “jupp” — https://www.mirbsd.org/jupp.htm). Yeah, thank me, you really should.

Networking

Ok, let me be clear on this point: these settings work for me, but I do not assure anything.

The concept here is simple: the virtual network interface card the guest operating system sees is hooked into a virtual interface created using TAP drivers. Tap interface could now be bridged to internet-connected interface. To be 100% honest, i know very little about bridge and didn’t embrace this solution. Instead, I’ve given static ips in a 192.168.68.0/24 network to both the virtual tap interface on my laptop and to eth0 interface inside the emulated system (with my laptop being 192.168.68.1  and guest being 192.168.68.2).

Then I set up a simple NAT using iptables.

My entry in my aranym.cfg for networking is:

[ETH0]
Type = bridge
Tunnel = tap0

My entry in /etc/network/interfaces for tap0 is:

auto tap0
iface tap0 inet static
address 192.168.68.1
pointopoint 192.168.68.2
netmask 255.255.255.255
tunctl_user manu
up iptables -t nat -A POSTROUTING -s 192.168.68.2/32 -j MASQUERADE

up echo 1 > /proc/sys/net/ipv4/ip_forward
down iptables -t nat -D POSTROUTING -s 192.168.68.2/32 -j MASQUERADE

Configuration for the guest system is pretty straightforward.

Links

Here is a list of web pages that helped me a lot during my messing up with the various pieces of software:

What now ?

Part of the final exam consists in converting a piece of C code into 68000 assembly code.

Our professor provided us with some PDF files covering the topic, and provided us with some example.

By the way, it’s nice to see theory put in practice, and it is nice to see real world C code being translated into m68k assembly.

So let’s write a piece of C code and let GCC translate it for us into assembly code:

Let’s say the code is:

#include 

char stringa[] = "asm is the way, lel\0" ;

int main(void) {

        // char *stringa = "asm is the way, lel\0" ;

        char *p ;
        p = stringa ;

        while (*p != '\0') {
                if (*p >= 'a' && *p <= 'z')
                        *(p) -= 32 ;
                p++ ;
        }

        printf("%s\n", stringa)  ;

        return 0 ;
}

We now want to see how would GCC translate that into assembly code.

Short explaination about gcc command line interface options: gcc, as many other program do, has a lot of options in order to meet a lot of different needs. Amon the options we’re gonna use, there are two specific options: -S and -O. The former will tell gcc to translate our C code into assembly and use the resulting source as its output without going any further in the compilation process. Le latter option let us specify the Optimization level: higher optimization means faster execution of our code at the cost of slower compilation process and not 1:1 match of assembly code with our C code. We do not want that, since it would make difficult for us to see what did Gcc do.

If you want to know more about GCC optimization, see “Options that control optimization“, from the GCC documentation.

So, let’s almost-compile our code:

gcc -O0 -S -o prova.s prova.c

Here is our assembly code:

#NO_APP
        .file   "prova.c"
        .globl  stringa
        .data
        .type   stringa, @object
        .size   stringa, 21
stringa:
        .string "asm is the way, lel"
        .string ""
        .text
        .align  2
        .globl  main
        .type   main, @function
main:
        link.w %fp,#-4
        move.l #stringa,-4(%fp)
        jra .L2
.L4:
        move.l -4(%fp),%d0
        move.l %d0,%a0
        move.b (%a0),%d0
        cmp.b #96,%d0
        jle .L3
        move.l -4(%fp),%d0
        move.l %d0,%a0
        move.b (%a0),%d0
        cmp.b #122,%d0
        jgt .L3
        move.l -4(%fp),%d0
        move.l %d0,%a0
        move.b (%a0),%d0
        add.b #-32,%d0
        move.b %d0,%d1
        move.l -4(%fp),%d0
        move.l %d0,%a0
        move.b %d1,(%a0)
.L3:
        addq.l #1,-4(%fp)
.L2:
        move.l -4(%fp),%d0
        move.l %d0,%a0
        move.b (%a0),%d0
        tst.b %d0
        jne .L4
        pea stringa
        jsr puts
        addq.l #4,%sp
        unlk %fp
        rts
        .size   main, .-main
        .ident  "GCC: (Debian 4.8.2-5+m68k.1) 4.8.2"
        .section        .note.GNU-stack,"",@progbits

We can notice different things from this assembly. More on this in the next edit :P
TO be continued ;)