kernelthread.com

UNIX® on the Game Boy Advance

© Amit Singh. All Rights Reserved.
kernelthread.com Forums Announcement

It is my pleasure to announce that kernelthread.com now has experimental Forums, with the theoretically unapproachable goal of fostering "zero-zealotry, high SNR" discussions on technical and strategic topics in operating systems and related areas. Current forums include Mac OS X, Unix, and Virtualization. Here is a link to the Mission Statement.


Discuss this article on Kernelthread Forums >>>

Introduction

In this document, I discuss "gbaunix", a rather contrived experiment in which I run an ancient version of the UNIX operating system on a popular hand-held video game system using a simulator. I can imagine this to be loosely of interest to a few types of people:

Specifically, I run 5th edition UNIX on the Nintendo Game Boy Advance. I briefly cover the following topics in this discussion:

Game Boy Advance: Overview and Specifications

Nintendo has been in the gaming business since 1889 (yes, 1889; please stop sending me corrections). Their Game Boy line of hand-held video game systems is the most successful in the world, not that Nintendo has had much competition in this domain. Since the Game Boy's introduction in 1989, about 175 million units (counting all versions) have been sold. While the focus of this discussion is the Game Boy Advance (AGB, or GBA, as it is often called), the discussion also applies to the "SP" incarnation, which is similar to the GBA architecturally. Important GBA hardware features include:

The GBA includes several memories for different purposes:

Note that a GamePak ROM has two mirrors (in addition to the "original") in the GBA's memory map. A game cartridge may have multiple ROM banks with different access characteristics (such as wait-states).

The GBA can be booted from a game cartridge or a compatible flash-memory cartridge that you can load your programs on. Alternatively, a GBA (slave) can download bootable code from another GBA (master), or even from a computer. This functionality, known as "multibooting", is present in the GBA's BIOS.

The GBA's hardware is primarily accessible to a programmer through a well-defined memory map. Various I/O registers are mapped to specific memory addresses. Note that memory and ports are accessible through a common address mapping. Moreover, the BIOS contains a variety of functions accessible via software interrupts.

ARM

Just as Nintendo is a mighty contender in the video game market, ARM is a leader in the RISC market. Unless you do not use any electronics, chances are that your life has been touched by an ARM (pun belabored). While Intel is the world's largest semiconductor vendor, its dominance in the PC microprocessor market is often misconstrued as overall dominance in microprocessor technology. The PC market is only a small percentage of the overall microprocessor market, with embedded processors being the majority. This is hardly surprising, since electronics devices far outnumber personal computers. Consider: 782 million ARM-based devices were shipped in 2003 (source: Standard & Poor's). Some other numbers place ARM's RISC market-share to be almost 75%.

Keywords often associated with ARM include "embedded", "high-performance", "low-cost", "power-efficient", and "RISC". ARM designs and licenses RISC-based microprocessor solutions to a maddening array of companies, including conventionally major players (such as Intel).

The first ARM processor was developed at Acorn Computers Limited (Cambridge, U. K.) in the mid 1980s. At that time, ARM stood for "Acorn RISC Machine". The first version of the ARM architecture, or ARMv1, had 26-bit addressing, with no multiplier or coprocessor. The first ARMv1 processor, ARM1, saw limited use as a low-cost secondary component in the BBC microcomputer, and in prototypes of the Archimedes workstation. Nevertheless, this was one of the very first commercial RISC implementations. It is noteworthy that ARM eschewed some key features of the then prevailing Berkeley RISC architecture, such as: delayed branching, register windows, and requiring all instructions to execute in a single cycle each.

On a related note, Apple was attempting to push RISC in the early 90s (see the section titled "AIM for POWER" in "A History Of Apple's Operating Systems"). Apple teamed with Acorn to fund a new company called Advanced RISC Machines, Limited, which became the new ARM. VLSI Technology was a technology partner in this endeavor. ARM Limited's first processor was the ARM6, based on Version 3 of the ARM architecture (ARMv3). It had full 32-bit code and data addressing. An ARM6 processor, a 20 MHz 610, was used in Apple's MessagePad hand-held (Newton).

The GBA's 32-bit processor is an ARM7TDMI, an implementation of Version 4T of the ARM architecture. We look at some of its details in the next section.

The GBA's ARM

The GBA uses an ARM7TDMI processor, with certain ARM features missing. The ARM7TDMI is the most widely-used 32-bit embedded RISC microprocessor. Its architecture (ARMv4T) is almost a decade old (as of 2004). The ARM7TDMI has neither a memory management unit nor a cache. Its nomenclature may be understood as follows:

The ARM7TDMI core has a single 32-bit data bus carrying both instructions and data. Data can be 8, 16, or 32 bits, and only load, store, and swap instructions can access data from memory. There are 31 general-purpose 32-bit registers, 6 status registers, a barrel-shifter, an Arithmetic Logic Unit (ALU), and an enhanced multiplier. All registers are not accessible at the same time. For example, in ARM state, 16 general registers and one or two status registers are accessible at any one time. The processor can operate in seven modes: a user mode that is used for executing most programs, and six privileged modes (Fast Interrupt, Interrupt, Supervisor, Abort, Undefined, and System). The processor has two states: ARM and Thumb (see below).

The GBA has DMA hardware (with 4 channels) external to the processor. While ARM supports two types of interrupt requests: normal (IRQ) and "fast" (FIQ), the GBA only makes use of the normal IRQ.

The ARM7 has a simple three-stage pipeline with the following stages:

At any point during normal operation, while one instruction executes, the next instruction is decoded and a third instruction is fetched.

Thumb

A traditional drawback of RISCs is their relatively poor code density (as compared to CISCs), due to their fixed-length instruction sets. This increases the size of a program's working-set, and leads to poorer cache utilization, more memory traffic, and higher power consumption. Such problems become particularly important in embedded applications. While an efficient solution to the power consumption problem would be multi-pronged (efficient use of parallelism, innovative electronics, etc.), ARM incorporated the "Thumb" architecture into certain processors to improve code density.

Thumb is a 16-bit compressed version of the normal 32-bit ARM instruction set. It includes a subset of the most commonly used 32-bit ARM instructions. While Thumb instructions have 16-bit wide opcodes, they operate on the same 32-bit register set as ARM code, and have most other benefits of the 32-bit core (32-bit address space, 32-bit barrel shifter, 32-bit ALU, etc.) Thumb-enabled processors (such as the GBA's ARM7TDMI) have decompression hardware in the instruction pipeline. The decompressor translates Thumb instructions into equivalent ARM instructions. Thumb code density approaches, and even exceeds, that of many CISC processors. It is much better than ARM in certain contexts, for example (the numbers are approximate):

Typical applications, including those on the GBA (and our experimental code), use a mixture of ARM and Thumb. The ARM7TDMI interprets an instruction stream as ARM or Thumb based on a bit (the "T" bit) in the Current Program Status Register (CPSR). The GBA has a small amount of fast 32-bit memory (the 32 KB IWRAM). Typically, some amount of speed-critical code can be ARM code executing from this memory. The majority of an application's code might not be speed-critical, however, and thus may be Thumb executing from slower memory (such as an GBA GamePak). Nevertheless, as we saw, Thumb code can be faster than ARM code under certain circumstances, so it is not always a straightforward comparison.

High-level Architecture of gbaunix

gbaunix is a 5th edition UNIX system running on the GBA. To achieve this, gbaunix uses SIMH, a highly portable PDP-11 simulator written in C. SIMH also implements simulators for numerous other systems, but I only use the PDP-11 portion. While the GBA has a C runtime via freely available toolchains, the port of SIMH to the GBA requires several additions and a few modifications. The high-level architecture of gbaunix is shown below:

The gbaunix "game cartridge" (or ROM) is the concatenation of a simulator runtime and a UNIX disk image. The latter could be taken as is, or may have additional programs loaded onto it.

The simulator contains SIMH at its core. I have attempted to make minimal modifications to SIMH itself, abstracting GBA specific functionality into a logically separate layer that SIMH talks to. This layer could be thought of as having the following components:

/* gba/gba_kbd.h */ const char *gba_kbdinput[] = { "unix\r", "root\r", "chdir /work\r", "ls -l\r", "./fact 100\r", "cat hanoi.c\r", "./hanoi\r", "./hanoi 3\r", "chdir /tmp\r", "echo 'main() { printf(\"Hello, World!\\n\"); }' \ > hello.c\r", "cc hello.c\r", "./a.out\r", ... /* more commands */ NULL, };

A Subset of a Brief History of UNIX

You can try gbaunix either using a Game Boy Advance emulator, or on a real Game Boy Advance. For the latter, you would need, say, a flash-based cartridge and a flash programmer.

Development

It is more convenient to run gbaunix on a GBA emulator, especially if you want to experiment with it by modifying its source. gbaunix is not greatly optimized yet, and for various reasons, most telling of which is that I am simulating the PDP-11 in software at the instruction level, gbaunix is extremely slow on a real GBA. For example, it takes 2 minutes to go from the boot prompt to the login prompt on real hardware! Many emulators allow you to run them "as fast as possible", resulting in a more pleasant development experience.

My build environment is hosted on Mac OS X. I used the "Boycott Advance" emulator, and the "devkitARM" toolchain, compiled from source on Mac OS X. I tested on real hardware courtesy of a flash cartridge.

As we look at screenshots of gbaunix, we shall discuss a very small subset of the history of UNIX.

Time-Sharing

Project MAC (Multiple Access Computer, Machine-Aided Cognition, Man and Computer) was a research project founded at the Massachusetts Institute of Technology (MIT) in 1963. It would evolve into the Laboratory for Computer Science (LCS), and is today the Computer Science and Artificial Intelligence Laboratory.

The early 60s saw a surge in popular interest in time-sharing. John McCarthy wrote a memo titled "A Time Sharing Operator Program for Our Projected IBM 709" in 1959. Corbató, Merwin-Daggett, and Daley wrote in a 1962 paper that: "... we are in the midst of a third major modification to computer usage: the improvement of man-machine interaction by a process called time-sharing." While they informally defined time-sharing to be something that "increases the efficiency of persons trying to use a computer", they also pointed out a related connotation: multiprogramming, or several people making use of a computer at the same time, is also a consideration. Dennis Ritchie said of UNIX later that "... the cycle of edit-translate-execute-debug is limited by thinking time, not compute time."

Project MAC made seminal contributions to time-sharing systems, including development of the Compatible Time-Sharing System (CTSS, which was first demonstrated even before Project MAC was formed). There were various other time-sharing systems in the mid to late 60s (BBN, DTSS, JOSS, SDC, ...), but a comprehensive history of time-sharing is not within the scope of this discussion. However, one system is of particular interest: Multiplexed Information and Computing Service (MULTICS, or Multics).

Multics

Multics was a joint research project between MIT, Bell Telephone Laboratories (BTL), and General Electric (GE) to create a time-sharing operating system for the GE-645 computer.

At that time, "use" (of a computer) primarily meant programming, and thus, "efficiency" meant being able to program more efficiently and imaginatively: for example, being able to edit, compile, and debug interactively, without unnecessary delays.

Multics was intended to be a utility-like system that could support a large number (about a thousand) of simultaneous users. It had several key design objectives (as discussed in Introduction and Overview of the Multics System, Corbató and Vyssotsky, 1965):

For an example of a PL/I program, see The Towers of Hanoi in PL/I.

BTL withdrew from the Multics project in early 1969.

Multics continued as a commercial product after Honeywell acquired GE's computer assets, and after Bull acquired the Honeywell properties. The system eventually met many of its design objectives. The last Multics site was shut down in 2000. In any case, Multics' design would influence several systems to come.

UNIX

After BTL's withdrawal, there were a few at BTL who had been working on Multics and were restless (Ken Thompson, Dennis Ritchie, Stu Feldman, Doug McIlroy, Bob Morris, and Joe Ossanna). Thompson was working on a "game", Space Travel, on the GE-635. Space Travel had first been written for Multics, and had a FORTRAN port for the General Electric Comprehensive Operating System (GECOS) running on the 635. The game simulated the motion of certain celestial bodies in the Solars System. The player's goal was to land a space ship on a planet or a moon. The GE computer's hardware and software were both ill-equipped to run the game, and playing was expensive in terms of CPU time (although the "money" so spent was only theoretical). Thompson proactively looked for an alternative. He decided to take over a "little-used" DEC PDP-7. This particular unit had 8K 18-bit words of memory and a capable vector display processor. Thompson, with help from Ritchie, rewrote Space Travel in PDP-7 assembly language from scratch (including a floating-point simulator). It ran standalone on the PDP-7.

0th Edition (late 1969)

Thompson and Ritchie did not use any native software on the PDP-7 to write Space Travel, but used a cross-assembler on the GE machine, and used paper tapes to run the program on the PDP. Unhappy with this setup, Thompson began writing an operating system for the PDP-7, starting with a file system. The "cross-assembly on GECOS followed by paper tape" arrangement continued until Thompson had a system capable of hosting development. At this point (late 1969), the system had a kernel, an editor, an assembler, a simple command shell, and some file utilities (cat, cp, rm, etc.) This was UNICS: a pun on Multics whether you think of it as "Uniplexed ULTICS" or a castrated Multics. Later, UNICS became UNIX. This first incarnation of UNIX may be regarded as the 0th edition.

The ancient cp command operated on multiple file name arguments by taking them in pairs. Thus:

# cp file11 file12 file21 file22 ...

The dsw command (contraction for "delete using switches") was used for deleting files interactively.

Multics (and the earlier CTSS) influenced many aspects of UNIX, such as:

Ritchie said in The Unix Time-sharing System — A Retrospective that "In most ways UNIX is a very conservative system. Only a handful of its ideas are genuinely new. In fact, a good case can be made that it is in essence a modern implementation of MIT's CTSS system. The claim is intended as a compliment to both UNIX and CTSS."

PDP-7 UNIX had a file system with i-nodes, although an i-node contained very basic information: the list of physical blocks, and minimal metadata (size, protection mode, and type). While special files and directories were supported, there were no pathnames. There was even buffering in the file system. Some stark limitations included:

The PDP-7 UNIX system also caused the inception of a high-level language, B, which was was influenced by the BCPL programming language. Dennis Ritchie called B "... C without types ... BCPL squeezed into 8k bytes of memory and filtered through Thompson's brain ..." B would eventually lead to C. PDP-7 UNIX, as well as its utility programs, were all written in assembly language.

For an example of a BCPL program, see The Towers of Hanoi in BCPL.

Note that UNIX also ran on the PDP-9.

1969 was also the year that the first ARPANET node became operational, and the first Internet RFC was published.

The UNIX "group" then made efforts to convince BTL to acquire a better machine, the PDP-11. They promised to deliver a document editing and formatting system (meant to run standalone, without UNIX), and were supposed to use UNIX only as a development platform. The first PDP-11 they received was an 11/20, with 24 KB of memory. UNIX ran on the PDP-11 in early 1971. Of its memory, 12 KB was used by the kernel, some by user programs, and rest as a ram disk.

1st Edition (November, 1971)

The 1st edition ran on the PDP-11/20, which had no MMU, nor any hardware protection features. Therefore, it was trivial to crash the operating system. There was no multiprogramming. Pathnames were present. The only (documented) system calls were: break, cemt, chdir, chmod, chown, close, creat, exec, exit, fork, fstat, getuid, gtty, ilgins, intr, link, mkdir, mount, open, quit, read, rele, seek, setuid, smdate, stat, stime, stty, tell, time, umount, unlink, wait, and write.

A few programming languages were supported: Assembly, B, BASIC, and FORTRAN (but no C).

The B (and Assembly) compilation environment consisted of the following:

ComponentDescription
/bin/asassembler (the output of the assembler went to a file called a.out by default)
/bin/ldthe link editor (note that only one person could use ld at a time in a given directory due to its use of temporary files)
/bin/nmprogram for printing the symbol table from the output file of an assembler or loader run
/bin/stripprogram for removing symbols and relocation bits
/bin/un program for printing a list of undefined symbols in an appropriate file
/etc/as2second pass of the PDP-11 assembler
/etc/baB assembler (prog.i —> prog.s)
/etc/bcB compiler (prog.b —> prog.i)
/etc/bilibB interpreter library
/etc/brt1B runtime routines
/etc/brt2B runtime routines
/etc/liba.aassembly language subroutines
/etc/libb.ageneral utility routines for B programs
/usr/b/rca shell script that compiled, by invoking other programs, a B source file (program.b) into executable (a.out). The compilation sequence was program.b —> program.i —> program.s —> a.out

It is noteworthy that the 1st edition did not carry any copyright notice.

The system had impressive documentation. The first edition manual was divided into seven sections:

  1. Commands (programs intended to be invoked directly by the user)
  2. System calls (entries into the UNIX supervisor, accessed via the trap instruction)
  3. Subroutines (intended to be called by user programs)
  4. Special files (files referring to I/O devices)
  5. File formats
  6. User maintained programs
  7. Miscellaneous

Subsequent editions had an eighth section titled System Maintenance.

Each logical page of the manual, a "man page", contained subsections: name, synopsis, description, files, see also, diagnostics, bugs, and owner. The manual was prepared using the UNIX text editor ed, and the roff text formatter.

The first man page was for the cat command.

2nd Edition (June, 1972)

The 2nd edition contained cc, the C compiler, but it was not yet implemented in C. A few new commands, system calls, and subroutines were introduced, such as: :(1), cc, echo(1), exit(1), goto(1), if(1), login(1), m6(1), man(1), mt(1), opr(1), stty(1), tmg(1), tss(1), kill(2), sleep(2), sync(2), atan(3), hypot(3), nlist(3), qsort(3), salloc(3), and sqrt(3).

ComponentDescription
:(1)A command that did nothing (its function was to place a label for the goto command: thus, the shell didn't have to be fixed to ignore lines with :'s.
cc(1)The C compiler.
m6(1)A general purpose macro processor.
opr(1)submit a job for off line printing.
tmg(1)A compiler compiler (TMG was a compiler-writing language).
tss(1)Interface to the Honeywell TSS.
salloc(3)A set of routines for dealing with (almost) arbitrary length strings of words and bytes.

2nd edition UNIX was still unprotected, with no multiprogramming. It did carry a copyright.

3rd Edition (February, 1973)

The 3rd edition was the first UNIX to run on the PDP-11/45, which had hardware segmentation and support for more core memory (256 KB).

3rd edition UNIX had some noteworthy features, such as pipes and multiprogramming. Some other interesting additions included:

ComponentDescription
cdb(1)The C debugger
crypt(3)The password encoding routine
proof(1)A program for comparing two text files (latter day diff)
ps(8)
sno(1)A SNOBOL III compiler and interpreter
speak(1)A word to voice translator that turned a stream of ASCII words into utterances, and output them to a voice synthesizer.
typo(1)Quoted verbatim from the man page: "... hunts through a document for unusual words, typographic errors, and hapax legomena and prints them on the standard output.")
yacc(6)A compiler compiler
4th Edition (November, 1973)

The 4th edition was essentially the 3rd edition written in C. It also supported newer PDP-11 systems (such as the /60 and /70). Implementation in a high-level language resulted in a system about a third bigger than the previous.

A few commands were added, while the B programming language was not included.

An Annotated Demonstration of gbaunix

5th Edition (June, 1974)

I use the 5th edition for gbaunix. It is the oldest UNIX for which a machine readable bootable file system image exists. There also exists the source for the kernel (in fact, we shall later see an example of recompiling the UNIX kernel).

Upon power-on, gbaunix displays some information about the "PDP-11"'s hardware, followed by the @ boot prompt. When you press the START button, the hard-coded keyboard feeder would type unix, the name of the kernel to boot. The boot process will take an extremely long time (about 2 minutes) on real hardware, after which you will get a login prompt.

The semi-colon in the login prompt (;login is also the magazine of the USENIX Association) has to do with a popular terminal (Teletype model 37) in the early 1970s. The ';' escape sequence put that terminal in full-duplex mode. Hence, the UNIX greeting message contained this sequence. A terminal that does not understand this sequence, such as our GBA TTY, would print the semi-colon.

We noted that even the first UNIX had special files: I/O devices represented as files. When such a file was read from or written to, the underlying device was activated. In the accompanying screenshot, /dev/rk0 and /dev/rrk0 are the block and character devices, respectively, corresponding to first moving-head "RK" disk drive. /dev/mem mapped the core memory of the computer into a file. It was possible to patch the running system using a debugger on this device.

glob, contraction for "global", was an external (to the shell) program use by the shell to expand special characters ('*' and '?') in the argument list. glob would expand any metacharacters and invoke the command itself. Upon failing to generate any matches, glob would print the classic UNIX error message: "No match".

Note that certain commands, such as mkfs, were kept in /etc to lessen the probability of them being invoked accidentally, or out of curiosity!

The dc command, an arbitrary precision reverse Polish calculator, made its appearance very early in UNIX. In fact, it was the first program to be tested on the PDP-11, even before UNIX ran on it.

A typical 5th edition kernel was less than 26 KB. Note also the sizes of the shell (5738 bytes) and init (1972 bytes). The system shown here has a minimal rc. /etc/update periodically updated the super block every 30 seconds, so as to ensure that the file system was fairly up to date in case of a crash.

The long format output of ls listed the mode, number of links, owner, size in bytes, time of last modification, and name.

By the time the 5th edition was released, UNIX had a rich programming environment with support for numerous programming languages, such as Algol-68, APL, Assembly, BASIC, C, FORTRAN, M6, PASCAL, Snobol, and TMG. In fact, using gbaunix you can even program on the GBA itself in several languages (in theory, might be painful in real-life). Compilers/interpreters are included on the 5th edition disk image for C, PDP-11 assembly, BASIC, Shell (scripting), and FORTRAN. I have tried Algol-68 too, although you may have to load it onto the disk image.

Following are some more examples of programming in the gbaunix environment (including the obligatory "Towers of Hanoi"):

Some more screenshots, including those of the output of miscellaneous commands, can be seen on the screenshot-overflow page.

Subsequent Editions

The 6th edition (May, 1975) was important in that BSD and XENIX were derived from it. John Lions wrote his famous Commentary based on the 6th edition (A Commentary on the Sixth Edition UNIX Operating System, 1977). Moreover, 6th edition is the earliest UNIX system that is available in machine readable form in its entirety.

The on-line documentation for 5th edition is missing. Only bits and pieces are available of the 4th edition and earlier systems.

Beginning with the 6th edition, the UNIX system proliferated rather rapidly.

Further editions in the BTL lineage were:

BSD

It is also possible to run some other systems on the GBA that normally run under SIMH. However, doing so is increasingly harder (and after a point, impossible) as system requirements increase (more memory required, say).

Following are some screenshots depicting BSD 2.9 running on the GBA:

Optimizing gbaunix

gbaunix has provisions for experimenting with a few potentially performance-affecting aspects. Note that you would need to recompile gbaunix to experiment with these.

Performance-critical code in IWRAM

gbaunix includes an example of compiling certain code as ARM and keeping it in IWRAM. Note that the code that is most likely to benefit from this optimization, if at all, is the CPU simulation code.

DMA

The GBA provides a few methods of performing memory operations, with different performance characteristics and restrictions (alignment, size, overlap, etc.) Those relevant to gbaunix include using DMA channel 3 (general-purpose DMA) for memcpy() and memset(). Moreover, the GBA BIOS contains functions for copying and setting memory via software interrupts. gbaunix includes support for experimenting with these methods.

Caching

As we saw earlier, gbaunix emulates stdio, and in turn, a simulated disk, by making a section of the GBA GamePak ROM appear as a UNIX file. Since we cannot write to the ROM (on real hardware, at least), gbaunix shadows the writes into buffers in RAM, and all subsequent reads and writes first consult the shadow buffers. gbaunix allows you to pre-load the shadow buffers with "hot" areas of the UNIX disk that are written to initially (from power-on until a user logs in, say).

Recompiling the UNIX kernel

While recompiling the UNIX kernel would not have any perceptible performance benefits for gbaunix, doing so is interesting nonetheless, if only to contrast it with today's kernel compilations. We could limit the number of devices the kernel supports, and thus not link in some code, thereby reducing the kernel's footprint somewhat.

Consider the source size of the 5th edition kernel:

I have not even attempted to compile the kernel on the GBA itself: it would take an inordinately long time, and we would certainly run out of shadow-write memory with the current scheme, if not the current GBA specifications.

The following sequence of commands assumes that you have 5th edition UNIX running (on real or simulated hardware), and the UNIX kernel source is in its default location (/usr/sys).

Remove libraries that possibly exist due to a previous compilation:

# chdir /usr/sys # rm -f lib1 # rm -f lib2

Before you begin compilation, you could study and modify tunable parameters in /usr/sys/param.h.

If you get a compiler error (I did with the source tree I have) about an undefined KISA0, define KISA0 (the first kernel i-space address register) in /usr/sys/seg.h.

# echo '\#define KISA 0172340' >> /usr/sys/seg.h

Compile the "main" kernel:

# chdir ken # cc -c -O *.c ... # ar vr ../lib1 main.o alloc.o iget.o prf.o rdwri.o \ slp.o subr.o text.o trap.o sig.o sysent.o clock.o fio.o \ malloc.o nami.o pipe.o sys1.o sys2.o sys3.o sys4.o ...

Compile device drivers, etc. Note that you could choose not to compile some of the files in this directory if you are not including support for the corresponding devices:

# chdir ../dmr # cc -c -O *.c ... # ar vr ../lib2 *.o

Generate system configuration, and link everything to yield the kernel binary:

# chdir ../conf # cc mkconf.c # mv a.out mkconf # echo rk | ./mkconf # cc -c c.c # as l.s # mv a.out l.o # as mch.s # mv a.out mch.o # ld -x l.o mch.o c.o ../lib1 ../lib2 # mv a.out rkunix

rkunix is the newly compiled UNIX kernel. Place it as /rkunix, and type rkunix instead of unix at the boot prompt to test it.

Ideas and Suggestions

Following are some ideas for further work (with mostly academic relevance):

Native port of UNIX to the GBA

It would be a good exercise for operating systems students to attempt a native port of, say, 6th edition UNIX to the GBA. I expect a substantial improvement in performance (as compared to gbaunix) if this were done. Ancient UNIX is a system small enough to be easily understood by one person. The 6th edition kernel source consists of 44 files (The Lions Commentary):

The entire source is less than 9,000 lines if a subset of peripheral device drivers is included. Of this, assembly constitutes about 10%.

While I think it is very feasible to do a native port, it is less trivial than it appears ("only 2 assembly files!"), particularly if you port the C compiler as well.

gbaunix performance improvements

Even though I have included some preliminary hooks for optimization (use of DMA, tweakable caching, placement of certain code in the processor's internal memory, etc.), it is an open problem to come up with an optimization scheme that takes all constraints into account and results in a perceptible performance improvement. You could start by focusing on the code that simulates PDP-11 instructions (pdp11_cpu.c) — that's where the simulator spends most of its time.

An input mechanism for gbaunix

Currently, gbaunix is always in "demo mode", wherein it iterates through a hardcoded (at compile time) sequence of UNIX commands. For more realistic and interactive user experience, an input mechanism could be created (or an existing one incorporated). For example, you could have a modal mechanism in which you compose a command line by choosing characters (via the keypad) displayed on the screen: once done, a button press returns you to UNIX, with your composed command in the TTY's input buffer.

Emulating the original Macintosh on the GBA

The first Macintosh had the following key specifications: 8 MHz 16-bit processor, 128 KB RAM, 64 KB ROM, no cache or interrupts, 400 KB floppy, and monochrome 512x342 display. To recapitulate, the GBA has the following relevant specifications: 16.78 MHz 32-bit processor, 288 KB (32 KB internal + 256 KB external) RAM, 32 MB ROM, and 240x160 display. It should be possible to port a lightweight Macintosh emulator (or perhaps even create one) to the GBA. You might do offscreen scrolling to accommodate the higher resolution, emulate a writable floppy drive via shadow writes, etc.

Other possibilities include porting an 8088 emulator to run some ancient version of DOS.

Download

gbaunix-0.0.tar.bz2

Note that in order to run 5th edition UNIX with gbaunix, you must have an RK05 disk image of 5th edition UNIX, which is not included in the gbaunix distribution. SCO owns the copyright for the 5th edition (and several others). You can download a disk image, after reading and understanding the license and ensuring that you are eligible, from the Unix Archive at the PDP-11 Unix Preservation Society:

http://minnie.tuhs.org/PUPS/

Usage

If you only want to run gbaunix, without recompiling it, you can simply concatenate the pre-compiled executable (unixv5.tmp) in the distribution with the RK05 disk image:

% cat unixv5.tmp disks/unixv5.dsk > unixv5.gba

unixv5.gba is the ready-to-run "game cartridge", which can be used with a Game Boy Advance emulator, or on real hardware.

If you want to compile gbaunix (highly recommended, and the only realistic way to experiment with it), you would need a cross-compilation environment: an ARM toolchain for your platform. You may need to edit the Makefile to set the path to your ARM compiler. The RK05 image must be present as disks/unixv5.dsk in the source tree. Thereafter, simply run make.

References


Discuss this article on Kernelthread Forums >>>