Silicon Valley 90’s Style: How to Port Unix

Posted on by

(The picture above is one of the pizza-box Sun 3/60s I used. Thanks, Robert Harker! CC BY-SA 2.5.)

When I’m working on an exciting project, waking up early is never a problem. One morning in the late spring of 1990, I climbed out of bed quietly so as to not disturb Betsy. I silently washed, dressed, and gently kissed my sixth-month-old daughter Charlie goodbye. The next step in porting Unix to Adaptive’s STM/18 awaited.

The $1300 a month apartment Betsy and I rented on University Avenue in Palo Alto only came with one parking spot, so I parked on Guinda Street. I didn’t mind though. All the landscaping around that area of Palo Alto was beautiful. I hardly noticed it that day. A team of developers depended on my port of the operating system, so my mind was churning with ideas for the next bit of code.

On my drives home from work on California 101, I would think through whatever bug I happened to be wrestling with at that time. Usually, I could solve the problem by the end of my 15-minute commute from Sea Port Boulevard in Redwood City to our apartment. On the way back to work, I’d redesign the solution or plot an entirely new plan of attack.

By the time I started doing ports of the Unix OS to new hardware, there was a well-established order to the process. Unix wasn’t the first operating system written in a high-level language, but it was the first to be ported to a wide variety of hardware. Somehow, Ken Thompson and Dennis Ritchie avoided tangling the machine’s details with those of the operating system.

Of the kernel, a good 90% was not dependent on features of any particular machine. This combined with an easily retargeted C compiler by Steve Johnson (also a member of the Murray Hill Gang) made moving the system something even I could do.

How does the port go? Let me walk you through what I did back in 1990.

First, collect enough of the target hardware so that you can run the port after it’s finished. For Adaptive and me, this meant a small VME chassis, a repurposed PC/AT power supply, a 5.25" SCSI disk and cable, and the single MVME147 target VME card. The VME chassis was just a printed circuit board with two 96 pin connectors, sides with card guides, and ends to keep everything from falling apart. It was referred to as a cage. We called it a bucket.

Someone had already chosen the MVME147, which was built around the Motorola 68030 processor. Besides being the VME bus controller and having 4 MB of DRAM, the card also had an AMD Lance Ethernet chip and a Western Digital 33C93 SCSI controller. A real-time clock and four serial ports rounded out the target hardware.

The only software on the card was in a couple of EPROMs that contained a debugger. In those days, we were expected to write all the code that ran on the board. A helpful debugger was standard and let you download programs, run them, and do a bit of debugging using breakpoints.

This debugger used a serial port, ran at 9600 baud, and could be connected to a terminal or other serial device. This is the same technology that is on all servers and most network devices. Today, a server has a DB-9 connector, but in those days the connector had 25 pins, not 9. In my VME bucket, I had DB-25s.

That was the target machine, but to do a Unix port you also need a donor machine. In my case, I arrived at my cube on the first day to find a Sun 3/60 on my desk. The VME system had neither video nor a keyboard, only the serial port. The Sun had a large monitor with good graphics, a great keyboard, and the famous optical mouse. It also had a couple of serial ports, unused by the KVM setup.

I dug through my box of junk to find my RS-232 DB-25 light dongle. This was a small plastic part with two DB-25 connectors and half dozen LEDs on it. Each LED gave you the state of a single pin on the serial cable.

I needed to connect the VME bucket to my Sun, so I powered up the bucket, stuck my dongle in the first port, and looked at the LEDs.

The letter to remember was “T”. T for transmit. T for pin two. T for Data Terminal Equipment. The Rx LED was glowing happily, so this was not a DTE but a DCE, the communication side. Originally, DCE was the modem. Serial was invented as a way to cable a terminal to a modem.

I popped the dongle off the VME bucket and, reaching around to the back the plastic pizza box of a Sun, I stuck it on the connector. Rx LED on. Ah, it was also a DCE. This made sense. You could connect a terminal to the Sun and use it like any other computer. You just couldn’t use the graphics stuff.

I would need a null modem cable, one with the transmit, receive, and associated pins swapped, just as if each system was talking to a terminal. I pawed around in my junk box for some cable, connectors, and my crimping tool. The pins are small and metal that come in male or female. Each is crimped on the wire with the tool and then inserted into the DB-25 connectors. This makes it easy to move the wires around. I never liked the solder version. Too clumsy.

Soon I had the cable connection between the two boxes. I used the “call Unix” program on SunOS, then snapped on the power to the bucket and instantly saw a prompt for the debugger. The first part of the port was complete.

It always feels good to get hardware in order. It frees you to think about the software bits, and for me that was getting the compiler and tools running on the donor machine.

At the time, there was a chicken and egg problem with porting Unix. It’s almost all written in C, so you need a C compiler for the new machine. To have a C compiler for the machine, you had to modify the Portable C Compiler to generate different code. To modify the PCC to generate different code, you had to have a C compiler running.

In the old days running C compilers was a tad thin on the ground, but by the end of the 80s, finding C compilers was pretty easy.

In this case, of course, I had the Sun already running with C. I didn’t have any source code for the Sun, so I didn’t want to use their compiler. I had a copy of the Portable C Compiler that was modified for the Motorola 32 bit parts, so it was easy to set all that up.

In my box o’ junk I carried a rectangular 1/4 inch tape containing all the sources I needed to load onto donor machines. I tore off the tape into a directory I named “gun” for Generic Unix. Folks had from time to time suggested naming my kernels “Brantix,” but I thought that naming a kernel after oneself was slightly arrogant. This was before you know-who-made it okay.

The toolchain consisted of five main programs with a couple of smaller ones that helped. The first two were the C preprocessor (cpp) and the actual C compiler (ccomp). Cpp is a macro processor that just operates on the text of files and feeds the results into the compiler proper. The compiler would read, scan, parse, and generate a text file with an assembler program equivalent to the original C program.

The assembler output would be read by the program “as” and create a binary object file. The assembler files conventionally called dot-s (.s) files, S for source, dated back to when Unix was all written in assembler. The object files generated were known as dot-oh files (.o), and were small, incomplete object files in the same format as executable files in the binary directory (/bin). Called A-dot-out (a.out) files, these were the simple ancestors of the more complex, Mach-O, ELF, and COFF files. I’ve never liked the later formats. Complexity without benefits.

I say the .o files were incomplete because they always lacked any functions referenced from the library. C didn’t use a large runtime as far as the compiler went, but there were standard things referenced in the library, like the printf function.

The loader (ld) took a list of .o’s and recombined them into a single a.out that was fully resolved. It looked in libraries that were merely Unix archive files (see the ar(1) command on your nearest Unix-like machine) with a .o in each member. A table created by the program ranlib created the table of contents which made ld’s job easier.

I compiled all these programs on the Sun, as well as my modified version of the compiler driver program cc, which I renamed xcc.

After all this, I could create a.out files that should run on the VME target machine. But they were on the Sun. How to get them on the VME board?

I headed home for lunch. In those days I was making more money than ever, but I was also in one of the most expensive places in the country to live. Most days Betsy pushed Charlie and her stroller down Hamilton Avenue, taking a left at Emerson, headed to Whole Foods for our meals.

I would arrive home at lunch and the three of us would eat together, Charlie in her highchair and Betsy and myself enjoying the wonderful fruits, vegetables, and pasta. The best part of living in California is the produce.

After that, the little girl would go down for a nap and I would head back to the office. On the drive back, I began to tackle getting a toehold on the target box.

About the Author

Brantley CoileInventor, coder, and entrepreneur, Brantley Coile invented Stateful packet inspection, network address translation, and Web load balancing used in the Cisco LocalDirector. He went on to create the Coraid line of storage appliances, a product he continues to improve today.

Sign up to have interesting musings delivered direct to your inbox.

Sign Up!

←Previous | Blog Archive