Building a BSD home router (pt. 2): The serial console (excursion)

The previous post touched on the topic of why you might want to build your own router, discussed some hardware considerations and showed how to assemble an APU2 bundle. Now that the box is ready for use, we have to do something with it – but there’s a small problem.

People who want to play with inexpensive hardware love their Raspberry Pis. Those make a great little toy: Just attach a keyboard and a monitor, insert an SD card and you’re done. Power on the device and you can start tinkering. With the APU2 it’s not that much harder actually, but it works quite differently. Why? Take a closer look at its backc and you’ll see that the outer left port is not VGA as you might have thought when you saw it from a different angle. It’s a COM port. There are two USB ports which would allow to attach a keyboard (the board doesn’t have a keyboard controller, though, which means that wouldn’t be of much use). But how to attach a screen to it? The RPi offers HDMI output, the APU2 does not. No VGA, no DVI, no HDMI and no DisplayPort either!

So how to access this thing? Typing blindly? Of course not. This post is about the serial console and since they call the COM port a serial port, too, it’s not too hard to figure out what we’re going to use. If you were born after 1980 (like me), chances are that you’ve never used a serial console before. Or rather you might not know exactly what it actually is. Heck, the younger ones might not even have heard about it! So if you’re either old enough or for whatever reason have experience with the serial console you could skip a lot of the following text. If you know what the real TTYs were, what a terminal and a system console is, this whole post probably isn’t going to teach you anything new. But since there are more and more younger people around for whom this is entirely new territory, I’m going to explain not only what we have to do in case of the APU2 but also a bit about how this all came to be.

Once upon a time… in 2017

Huh, 2017? That’s this year! Exactly. But then this headline doesn’t make sense, does it? Trust me, it does. Consider this:

% uname -a
FreeBSD pc0.local 11.1-PRERELEASE FreeBSD 11.1-PRERELEASE #0 r319447: Fri Jun  2 03:47:52 CEST 2017     root@pc0.local:/usr/obj/usr/src/sys/GENERIC  amd64

% ls /dev/tty*
/dev/ttyu2      /dev/ttyv0      /dev/ttyv3      /dev/ttyv6      /dev/ttyv9
/dev/ttyu2.init /dev/ttyv1      /dev/ttyv4      /dev/ttyv7      /dev/ttyva
/dev/ttyu2.lock /dev/ttyv2      /dev/ttyv5      /dev/ttyv8      /dev/ttyvb

Here’s an up-to-date FreeBSD system and it has quite some device nodes that bear “tty” in their name. The abbreviation TTY means Teletypewriter (or “teletype” for short) and with that we’re speaking of a technology that has its roots far back in the first half of the 19th (!) century. As I stated in my first post about FreeBSD 4.11 and legacy systems: Once some technology is established and in use, it’s extremely hard to get rid of it again. And while it’s hard to believe that concepts from almost two hundred years ago still influence today’s Unix machines, there’s some truth to it.

So what is a teletypewriter? Think a classical typewriter first. One of those mechanical machines that allow to type text instead of writing it: You press a key and that makes a small metal arm swing and its end hammer against the paper. That end bears an embossed letter. Between this head with the letter (or rather: character) and the paper there’s an ink ribbon and thus your key press results in a readable imprint on the paper.

Man has long striven to be able to transfer information across a long distance. Morse code made it possible to encode text and then send a message e.g. via optical means like blinking light. The telegraph (from Greek tele + graphein = far + write) achieves the same goal, however by sending signals over a cable.

A simple teletypewriter combines both: Imagine a typewriter with all the usual keys but no paper that is connected to a remote device which has the paper feed, ink ribbon and so on but no keys. This second device is called a teleprinter. The big limitation to this is that the information flow is one-way only.

Where computers fit into this

Sounds familiar? Sure thing: The keyboard that you use essentially does exactly that! Now consider a more advanced approach where two teletypewriters that both have input and output capabilities are connected to each other. In this bi-directional use you can type something that the person on the other end can read as well as write an answer which then you can read (and write again).

It’s obvious how this supports distributing information across large distances. But what does all this have to do with the COM port? Please bear with me. The first type of computers were big and extremely expensive mainframe machines. It makes sense that not everybody would be allowed physical access to them. Thus you wouldn’t sit down before them and attach a screen and keyboard! Instead you’d use a teletype in another room to interact with it. You input any commands and get a response in form of the printed output. More sophisticated teletypes allowed saving input or output on punch cards or read them in again and send the data.

Whatever combination of gear that allows sending and receiving data to/from a computer is called a terminal. Bi-directional typewriters are sometimes referenced as “hard-copy terminals” (because they printed the output on paper). While it’s hard to believe, this procedure has been state of the art at some point in time. Obviously this is not ideal, wasting a lot of paper. Fortunately there’s a solution for this: Enter the electronic terminal! Those replaced the printing on paper with displaying on a screen.

Now this is much more of what we’re familiar with, just in a special machine that is connected to the actual computer in a different place. The great thing about those terminals was that they allowed for adding more and more exciting new features. The bad thing was that they added more and more exciting new features. Usually there was no gain in having those features on the client side only. The server side had to know about it, too. Before long there were a lot of terminals out there, all with nice new features but all incompatible with each other…

This sucked. If you had this expensive new terminal that was unknown to your computer however, you couldn’t use its additional features. Good thing that we don’t use terminals today! That makes this an issue of the past. Right, that is a good thing. But no, it’s not a historic issue. Yes, we’ve replaced terminals quite a while ago. But what did we replace them with? Today we use terminal emulators. Your *nix operating system comes with programs that (by default) use the keyboard for input and the screen for output and thus simulate… a terminal.

Terminal emulators

Those terminal emulators can emulate various types of physical terminals and have additional features of their own. So the problems are back (or rather: They were never really gone). How do programs know what features are available? That used to be really tricky (and often lead to discarding features that were not commonly available on all popular terminals…). Let’s take a look at my shell’s environment:

% env
TMUX_PANE=%2
TMUX=/tmp/tmux-1001/default,1164,0
TERM=screen
[...]

My shell is running inside the terminal multiplexer tmux which set the TERM variable to “screen”. GNU screen was a somewhat similar program and since tmux is compatible with it, it announces that terminal-wise it works like screen. What does this look like if I quit tmux?

% env
OSTYPE=FreeBSD
MM_CHARSET=UTF-8
LANG=de_DE.UTF-8
DISPLAY=unix:0.0
[...]
SHELL=/bin/tcsh
WINDOWID=58720259
TERM=xterm
[...]

Here my terminal emulator claims to support the feature set that xterm is known for. I’m not using xterm, but my terminal emulator (terminator) is compatible with it. You probably know htop. I’ve just installed it to make two screenshots of it. This is what it looks like if I run it in my terminal emulator:

htop running with $TERM=xterm

Now let’s claim that we’re using another terminal type, shall we? I’m going to pretend that my terminal is an old, crufty vt100:

% setenv TERM vt100
% htop

Afterwards the application looks like this:

htop running with $TERM=vt100

The difference is pretty obvious – the vt100 did not support color output (among other things). Let’s be even more radical and simply not announce our terminal type to any applications:

% unsetenv TERM
% tmux
open terminal failed: terminal does not support clear

Tmux won’t even run (and htop would screw it all up badly since it obviously doesn’t handle that case properly)! If the terminal type (and thus its capabilities) are unknown, programs need to fallback to the absolute baseline of functionality that each and every terminal is known to support. And that’s disturbingly little… In this case tmux would be unusable because the terminal might not even be able to clear the screen! Yes, not even the seemingly most basic things were implemented in all terminals.

Imagine you’re the author of a simple *nix program. You were supposed to know what terminals existed and what capabilities they had – and to adopt your program to whatever terminal it ran on! Fortunately Bill Joy wrote termcap, a library that helped dealing with various terminals. This extremely important functionality (which originated in BSD Unix, BTW!) evolved over time. Today we have ncurses which does just about everything to make life easy when programming console applications.

(Serial) console

Which leads to the question: What is the console? The system console (or just console) is a device used to imput and output text. A PC’s BIOS offers a console, the boot loader does and the OS kernel does, too: It uses it to print out messages and to take commands. It’s present even when you don’t see it. A system might for example work in so-called headless mode which means that there is nothing attached to the console. Plug in a keyboard and connect a monitor and you can make use of the console.

Unix-like operating systems often configure multiple virtual consoles (also called: virtual terminals). We saw those when we listed the tty* nodes in /dev at the beginning of this blog post. Together those form your computer’s system console to which usually keyboard and screen are attached.

But you need not attach those two devices to the console. You can also attach a serial device to it which can then be used to transfer commands from and messages to another computer that is connected to the other end of the serial cable. Then you can use that other computer’s keyboard to type commands and its screen to read the output. A serial console is simply a console that can make use of a serial connection to redirect the console. If the BIOS of your machine supports it, you can use the serial console to control everything on that machine using another one over a serial connection.

If you’re completely new to it, this probably was quite a bit of information. However we’ve only talked about the very basics here! If you like to know more about how TTYs, pseudo TTYs, processes, jobs and even signals work, I recommend Linus Åkesson’s article The TTY demystified which is an excellent read. He explains much more in-depth how Linux does all this.

What’s next?

In the next post we’ll prepare a USB memstick and attach a serial console to the APU2 to update the firmware.

Advertisements

One thought on “Building a BSD home router (pt. 2): The serial console (excursion)

  1. Pingback: Building a BSD home router (2) | 0ddn1x: tricks with *nix

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s