Linux Utilities for the Rio Receiver
Jeff Mock
2/26/1
Software in the Rio Receiver is a mixed open/closed source system.
There is an open source Linux kernel, a closed source player
application, and a closed source driver for the HPNA networking chip.
This page contains instructions for building a usable open source
development environment without any of the closed source elements
shipped with the Rio Receiver.
The Rio Receiver is a fine product as it stands, but it is also
a great platform for learning about embedded Linux on Arm
processors. The box contains an ethernet interface, IR input, an
LCD display, and high quality audio out that can be easily accessed
by a programmer.
The first step is to build a toolchain and kernel.
Once you have built a toolchain and kernel you're ready to setup
some utilties for developing code for the box. The box relies
on NFS to provide the root filesystem from a host computer. For
my purposes I setup an X86 Linux machine to be an NFS server. This
is pretty much the same as setting up a music server on a Linux
machine. I suggest you do this first.
You will also need a connection to the console serial port described
in the above document. This is the only way to get console messages
during booting. Get setup to view console messages from the serial
port before setting up the utilities.
The rest of this document contains tips and patches for building
various unix utilities and assembling them into a filesystem
image for the Rio Receiver. You should be able to boot the
Rio Recevier to a bash prompt, run a tiny version of vi, and
small versions of a variety of unix utilties suitable for developing
applciations for the Rio Receiver.
The patches and scripts mentioned below are can be found here:
ftp://ftp.mock.com/pub/rio-utils/rio-utils-0.1.tgz
To get started quickly, a file system image suitable for booting
the Rio Receiver to a bash prompt with a collection of Unix
utilities is here:
ftp://ftp.mock.com/pub/rio-utils/dev-fs-image.tgz
The instructions below should let you build a filesystem image
identical to the pre-built one above.
Kernel
------
I make a small change to the kernel to assist booting into
a shell prompt. Modify the file linux/init/main.c as follows.
Change this line:
static char * argv_init[MAX_INIT_ARGS+2] = { "init", NULL, };
Change to:
static char * argv_init[MAX_INIT_ARGS+2] = { "-bash", NULL, };
The change makes sure that bash knows that it is a login shell
and runs /etc/profile on startup.
Also change the line:
execve("/bin/sh",argv_init,envp_init);
Change to:
execve("/bin/bash",argv_init,envp_init);
This way the kernel will run bash on startup. Usually the Linux
kernel runs a program called "init" on startup. This has a PID
of 1 and runs other programs as defined in the /etc/inittab file.
For my embedded development environemnt I don't run init to save
memory and the bash shell is run as the first process with a
PID of 1. /etc/profile contains commands to configure the
system when it boots. This would probably change for a real embedded
application but works well for a development environment.
Build libtermcap
----------------
libtermcap is needed by bash and vi. A copy of termcap-2.0.8 can be
found at:
ftp://ftp.mock.com/pub/rio-utils/termcap-2.0.8.tar.gz
Apply the patch file patch.termcap-2.0.8 to fixup the Makefile and build
cd termcap-2.0.8
patch -p1 < ../patch.termcap-2.0.8
make # Do not do a "make install"
Build Bash
----------
There is a copy of bash-2.04 source code at
ftp://ftp.mock.com/pub/rio-utils/bash-2.04.tar.gz
I had a very difficult time using the configuration script
in the bash source to build bash using a cross compiler. It might
be possible, but I couldn't figure out how. My solution for
bash was to run the configuration script as if I were building for
the x86 host machine and then running a Perl script to fix up the
makefiles to build with the arm cross compiler:
cd bash-2.04
./configure # Configure for X86 build
perl ../fix-make # Fix makefiles for cross-compiler build
make # Build bash. DO NOT type 'make install' or you will
# trash the local machines copy of the bash!
You might have to change the Makefile so that the linker knows where
to find libtermcap. This strategy seems to work well, but I wouldn't
advise using the bash for anything mission critical. If it is possible
to do this with options to the configure script please let me know.
Build vi
--------
Elvis-tiny is small nearly full-featured version of vi common to
many Linux rescue disks and the like. It's useful to build it for
the Arm processor and Rio Receiver so you can edit configuration
files and such. You might have to change the Makefile so that the
linker can find libtermcap.
A copy of elvis-tiny is at:
ftp://ftp.mock.com/pub/rio-utils/elvis-tiny_1.4.orig.tar.gz
Apply the patch patch.elvis-tiny-1.4 and build.
Build Busybox
-------------
Busybox is a fairly large collection of unix utilities in a
single executable. This program is common in Unix rescue floppies
and is very useful in embedded applications. A single application
called 'busybox' is built and links are created with the names
of various unix utilities like ls, cp, etc.
A copy of the source for busybox-0.49 is at:
ftp://ftp.mock.com/pub/rio-utils/busybox-0.49.tar.gz
Apply the patch patch.busybox-0.49 to fixup the Makefile, configure
the build, and fix a couple of bugs in "ls".
cd busybox-0.49
patch -p1 < ../patch.busybox-0.49
make # Do not do a "make install"
Build a root filesystem image
-----------------------------
There is a script included called makefs. You will almost certainly
have to edit this to provide paths to the various utilities. This
script will build a root filesystem image containing proper links, /dev
entries, etc. It also stuffs some trivial termcap entries and the
like into /etc. It attempts to be minimal and only provide the
minimum necessary to boot the box into a usable shell prompt.
Take the tar image generated by the script and untar it into the
correct /tftpboot/hostname/ location serving the root filesystem
to the Rio Receiver. Power cycle the receiver and you should be rewarded
with a bash prompt on the console serial port. If this works try
running vi. I use minicom, the /etc/profile file installed sets the
TERM variable to vt102, /etc/termcap currently only contains a
vt102 entry so you may have to edit this for your setup.
Try the "ps" command. If this doesn't list the 6 or 7 processes
(including bash as PID 1), the usual reason is that /etc/profile
did not mount /proc for some reason. Try manually mounting /proc.
The root filesystem should be mounted read/write. Try copying a
file to make sure. If the filesystem is read-only there was
a problem with the mount command in /etc/profile.
If ps, ls, cp, and the like are working try ping and telnet (you
must specify IP addresses, libresolv.so is not installed).
As a final test of the utilities build a "hello, world" C program
on your host machine, copy it to the mounted root filesystem,
and then run the program from the Rio Receiver console:
On host:
% arm-linux-gcc hello.c -o hello
% arm-linux-strip hello # Make it small
% cp hello /tftpboot/hostname/usr/bin
On Rio Receiver console:
bash-2.04# ls -l /usr/bin
-rwxr-xr-x 1 0 0 2580 Feb 26 2001 hello
bash-2.04# hello
Hello, world.
You're now ready to run embedded Linux apps on the Rio Receiver.
Bugs
----
This development environment works pretty well, but there are a
couple of problems I haven't sorted out.
There doesn't seem to be a interrupt character on the bash console.
I cannot mount NFS filesystems other than the root filesystem.
I'm pretty sure the problem is not with busybox "mount" program.
Maybe it's a kernel problem, or maybe something to do with the
system clock on the Rio Receiver always thinking that it's 1970.
Would like to have a telnetd running on the client and would like
to have a more reasonable init running at boot time, but they
need to be really small...