Linux on 3Com Audrey

This could very likely kill your Audrey, I killed one of mine, now you are warned

These are mostly random pieces of documentation written before I forget them

Why Linux on the Audrey ?


The Audrey would be kind of the ideal engine for Home-automation, Low-power Stand-alone you could easily add an i2c bus and you could control the world

It should probably all be done under the hat of a MythTV frontend. - Well Audrey is probably not powerfull enough for mpeg4 video, but the other applications should be OK, and Myth-homeautomation does not exists, but it would seem to be an efficient way to have all of House Audio/Video/Automation in one system available anywhere in a house.

The Audrey is a dead-end without an open-source O.S. This is good since you can buy them relatively cheap at ebay.com., but this is bad too because what you invest in it will eventually be lost. Once you had Linux on the Audrey you are in control, and it would be relatively easy to migrate to future hardware should something better pop up.

The 3Com/Audrey Hardware

The 3com/Audrey is a National Semiconductor GX1 + CS5530 + PC97317 design. It is a fairly complete PC with For an inside view of Audrey look here A closer look reveils that the main chips are

The 16 Mb Flash PROM under QNX

The Audrey has a 16 Mbyte Flash prom which is accessable from QNX as 3 devices

The IFS file-system, 512 Kbytes

The QNX OS Image is a small filesystem called IFS (Image File System) where files are stored back to back and there is a header which points out what file contains the startup-code where to load it and the initial Program Counter. QNX has tools to create an IFS-file and to see and extract its content. The mkifs and dumpifs tools runs only natively under QNX. These are not opensource but it is pretty easy to figure out how it all fits together.

The main QNX flash filesystem

As this is not supported in Linux we have no intention to use the QNX flash filesystem. Since we cannot fit a Linux kernel and an initrd with the functionality we like into the 512 Kbytes used for the IFS, we will claim some of teh QNX flash filesystem space for that, the rest will be used to hold a Linux MTD filesystem,

The Audrey BIOS

The role of the BIOS is as usual to initialize the hardware, load an operating system and pass control on to the operating system. This is normally very closed source but a good guess is that it contains a BIOS, a VGA_BIOS and what QNX calls a an IPL (Initial Program Loader). The VGA-BIOS can be located at address 0x20000 - 0x24000 (32 Kbytes), when QNX_IPL calls the startup-code in IFS the VGA-BIOS is loaded at address 0xc0000 so it looks very normal. The VGA-BIOS can probably be reused in the newest version of LinuxBIOS. If the above guess is right and it contains a full BIOS another strategy to get another OS onto the Audrey would be to somehow disable the BIOS call to the QNX_IPL

The 16 Mb Flash PROM under Linux

Under Linux the Flash will partitioned as seen from these lines in driver/mtd/maps/audrey.c
/*
 * 512k + 512k LinuxBIOS and Backup
 * 1 Mb Linux kernel
 * 13 3/4 Mb User File System
 * 256k original QNX BIOS at the end
 */
        {
                name:           "LinuxBIOS initrd.gz",
                size:           0x80000,
                offset:         0,
        }, {
                name:           "backup LinuxBIOS initrd.gz",
                size:           0x80000,
                offset:         MTDPART_OFS_APPEND,
        }, {
                name:           "kernel",
                size:           0x100000,
                offset:         MTDPART_OFS_APPEND,
        }, {
                name:           "User FS",
                size:           0xdc0000,
                offset:         MTDPART_OFS_APPEND,
        }, {
                name:           "QNX-BIOS",
                size:           0x40000,
                offset:         MTDPART_OFS_APPEND,
                mask_flags:     MTD_WRITEABLE,  /* force read-only */
        }

The boot Proces when booting QNX

The IFS file-system under QNX contains boot code and enough of the QNX operating system to get things going, it is actually a pretty nice and simple system to make anything from a standalone embedded system as the the 3Com/Audrey to a PC-based devellopment system.

The IPL finds the IFS at the start of the flash PROM, copies the whole IFS to 0x400400 in RAM and jumps to the entry specified the IFS header, you can change these values and the IPL will load it all at another address. Since this is well away from where the Linux kernel will be placed during its boot process we just keep this.

The Overall design of Booting Linux

In the first phase we will This setup has the added advantage that it is relatively easy to revert to a QNX based Audrey. As long as the last 256k kBytes of The flash PROM is not destroyed you should be able to install either QNX or Linux again.

To avoid beeing dependend of QNX, and to add other facilities a small library to access the MyFS filesystem has been written (myfs.c myfs.h - 330 + 95). This library is used by LinuxBIOS when booting, and by the two tools mkmyfs, dumpmyfs to create and examine a MyFS filesystem (mkmyfs.c dumpmyfs.c - 384 + 115 lines),

When The Audrey boots the BIOS looks for an IFS compatible filesystem at the start of the Flash and hands over control to the file specified there.

The key is our booter program which will be the program that is called from the BIOS and which will eventually launch LINUX. This booter is called as if it was the QNX IPL (Initial Program Loader)

Since it would be nice one-day to have control of all the hardware and boot-proces it is natural to go for LinuxBIOS as the frame-work for the booting process. LinuxBIOS already has support for the type of hardware found in the Audrey, and can have its own little filesytem in ROM to get hold of the kernel etc. We want to be compatible with QNX_IFS, which is achieved by having our own version of linuxbiosmain.c (diff to the original is 390 lines) which uses the myfs-library.

MyFS, mkmyfs and dumpmyfs

MyFS is basicly just another tar/ar/cpio/elf/a.out format, containing a header, and a number of files stored back-to-back with a number of checksums, the address where it is to be loaded, and an address to jump to. From the outside MyFS is compatible wth IFS. Mkmyfs can create an MyFS, and dumpmyfs can be used to see and extract the content. Lets go through an example
 dumpmyfs -v  MyFS-audrey
Checksums: header+startup=0xa66e1005   myfs=0x42a07284
qnxipl_head = 0x4002a000, myfs_head = 0x4002f23c
 
   Offset      Size  Name
 
        0       100  QNXIPL-header preboot_sz: 0x0 header_sz: 0x100 startup_sz: 0x523c
                    stored_sz: 0x78f58 fs_sz: 0x73d1c fs_paddr: 0x0
                    image_paddr: 0x400400 ram_paddr: 0x400400 ram_sz: 0x78f58
 
      100      523c  startup-code startup_vaddr: 0x400500
     5260     73c66  initrd.gz mode=1, inode_sz=32
 ff080000    100000  linux.bin.gz mode=2, inode_sz=36
    78f18        39  cmdline mode=1, inode_sz=28
The -v adds verbosity to the output -vv would add even more etc.. To here are four files plus information to where it should be loaded.

The MyFS would be stored in the Flash PROM at address 0xff000000 where the QNX IPL will find it, and validate that the Checksums are as expected. A very simple way to make a backup MyFS would be to just place another MyFS image somewhere above, which the QNX IPL would find if there were errors in the first one.

The IPL will copy the MyFS to RAM starting at ram_addr the size is there too. finally it will jump to address startup_vaddr

Each file has a mode field we use this so that mode=2 (this is not compatible with IFS) indicates that the content of the file in question is at a physical address, in this example linux.gz can be found at addr. 0xf080000, To specify where the vga_bios can be found an entry as the one below could be used

 fffe0000      4000  vga_bios mode=2
To create an MyFS file with the all of the above files the following command will do, -v gives the full story
 ./mkmyfs -v -l 0x400400 \
	-o MyFS-audrey
	-s work/linuxbios.strip \
	initrd.gz \
	linux.bin.gz@0xff080000:0x100000 \
	cmdline \
	vga_bios@0xfffe0000:0x4000
Position:      0 => Buf: struct qnxipl_header 0x804ca98 (256)
Position:    100 => Fil: work/linuxbios.strip (20792)
Position:   5238 => Chk: (0xa66e0f8d)
Position:   523c => Buf: struct myfs_inode: initrd.gz 0x804ca00 (32)
Position:   525c => Chk: (0xb0f976b9)
Position:   5260 => Fil: initrd.gz (474214)
Position:  78ec4 => Chk: (0x8afb4718)
Position:  78ec8 => Buf: struct myfs_inode: linux.bin.gz 0x804ca28 (36)
Position:  78eec => Chk: (0x3447c01d)
Position:  78ef0 => Fil: linux.bin.gz (physmapped)
Position:  78ef0 => Chk: (0x0)
Position:  78ef4 => Buf: struct myfs_inode: cmdline 0x804ca50 (28)
Position:  78f10 => Chk: (0x1fceaa73)
Position:  78f14 => Fil: cmdline (57)
Position:  78f4c => Chk: (0x42a07284)
Position:  78f50 => Buf: struct myfs_inode: vga_bios 0x804ca70 (32)
Position:  78f70 => Chk: (0xb9c8759b)
Position:  78f74 => Fil: vga_bios (physmapped)
Position:  78f74 => Chk: (0x0)
Position:  78f78 => Buf: trailing ones 0xbfffe5cc (4)

The boot Proces when booting Linux

We keep the initial stages as they are, that is the original BIOS is responsible for copying MyFS to RAM and transfer control to it. The difference is that our MyFS contains a LinuxBIOS bootloader, and other files relevant for Linux. The whole process looks like this

Debugging

LinuxBIOS uses the familiar syslog levels to have debug print outs at different verbosity, We use the same for both the programs run under LinuxBIOS and from usermode in user mode one or more -v will raise the level accordingly

A small debugger is included which can be used to peek and poke around in memory and io, f.ex.

 examine("console_loglevel", &console_loglevel, sizeof(console_loglevel);
will make it possible to examine and change console_loglevel. If any button on the Audrey is pressed on power-on the above line will be called and a verbose boot proces can be set, while implementing the code breakpoints like the above is easily inserted at compiletime, where things can be checked to see wheter everything is OK. When you are at an exmanine prompt you can always reset/raise the console_loglevel by pressing ctrl-C

In restrospect I should probably have used a something like gdb This debugger has the following command

D - Display
B - set witdth to 1
W - set witdth to 2
L - set witdth to 4
S - set witdth to 128 - strings
I - IO mode
M - Memory mode
= - change the content
+ - forwards with what we are doing
- - backwords
  - as usual
Q - Break
R - Exit from LinuxBIOS

Booting LinuxBIOS

If you press the button in the upper right, The Original BIOS thinks that you are about to in update the flash PROM from a Compact Flash card and this way you can ????grade your Audrey to QNX the usual way. To follow what happens on the serial console the baudrate should be set to 38400

Otherwise control will be passed onto the startup code in MyFS which in our case i LinuxBIOS. If you press the second button from top right you get a chance to change the console_loglevel from 0x4, changing it to f.ex. 0x6 you could download a new MyFS over the serial port. In the example below a button is pressed and the debuglevel is raised to 6. if the button wasn't pressed all the printing in italics is not printed, and you have no influence on the boot process

3Com IPL
Scanning for Image at FF000000
Image at: FF000000
Image setup
Starting image
                                                                                
LinuxBIOS-1.0.0 Thu Feb 13 15:47:32 GMT 2003 starting...
Copying LinuxBIOS to ram.
Jumping to LinuxBIOS.
Press a button during poweron to raise console_loglevel

console_loglevel=0x6
LinuxBIOS-1.0.0 Thu Feb 13 15:47:32 GMT 2003 booting...
Initializing CPU #0
   Offset      Size  Name
                                                                                
        0       100  QNXIPL-header
      100      52c0  startup-code startup_vaddr: 0x400500
 ff0052e4     73c66  initrd.gz mode=1
 ff080000    100000  linux.bin.gz mode=2
 ff078f9c        39  cmdline mode=1

initrd.gz found on myfs
Download new LinuxBIOS y/n (default n): linux.bin.gz found on myfs
Download new linux.bin.gz y/n (default n): cmdline found on myfs
command line - [S ro debug=9 root=/dev/rd/0 panic=10 console=ttyS0,57600]
Linux version 2.4.19 (peter@mandrake) (gcc version 3.2 (Mandrake Linux 9.0 3.2-3BIOS-provided physical RAM map:

if you answer "y" Audrey expect to receive a gzipped file on the serial console which it will unpack and place at address 0x400400 or 500, if you press a button while this new LinuxBIOS takes over you can set the console_loglevel the usual way.

Downloading IFS or MyFS over serial port to QNX

In the Original QNX_BIOS there is functionality to download an IFS file to be run by Audrey. You need to have a running QNX system (can be downloaded for free from the net. The QNX sendto command will take care of the handshaking, this is probably the safest way to boot-strap Audrey to run Linux

Downloading IFS or MyFS over serial port to LinuxBIOS

When you push the second button on left while powering on the Audrey you have the posibility to download an IFS/MyFS and/or a linux kernel over the serial port. both files has to be gzip-ed. to do the download you would execute:
	gzip < MyFS-audrey >/dev/ttyS0
for some kernel sizes the process will hang, if that happens I have often had succes using this command instead:
	(cat MyFS-audrey; echo peter@lorenzen.us) | gzip >/dev/ttyS0
using gzip as the format makes sure that the download went OK, otherwise it would abort

Configuring Linux

To make a kernel you need to get hold of the following

Configuring Initrd.gz

initrd is a compressed ext2 filesystem which the Linux kernel can use as its root filesystem. In our case initrd is the largest component of MyFS and hence has to be smaller than 512 kByte, but it is amazing what funtionality you can have there using busybox m.m. Initrd can be discarded and a new real root filesystem be mounted f.ex. an NFS-mounted root, after necessary configuration has been done. To create a base root-directory and populate you need

Configuring LinuxBIOS

You will now have a file called MyFS-audrey which can be written into the first 512 Kbyte of the FLASH prom. or downloaded into the Audrey over the serial port.

Hardware port usage

Audrey has a number of buttons some LEDs and since SuperIO chip has a number of general purpose IOpins it was easy to find some of the connections, but some investigation has still to take place the current status is:
on pc97317, GPIO is at 0xe0

 ===> port1 - when booting all are input
GPIO_10      0x1   input?? on-allways
GPIO_11      0x2  OnOff    button   (bottom right
GPIO_12      0x3  Mail     button   (bottom left)
GPIO_13      0x4  Datebook button   (top rigth)
GPIO_14     0x10  Browser  button   (2nd right)
GPIO_15     0x20  Addrbook button   (3rd right)
GPIO_16     0x40  ads7843 Din  - output
GPIO_17     0x80  write to this ports will reset the machine, could be ads7843 IRQ wild guess

 ===> port2 - when booting input on 0xef
GPIO_20      0x1  ads7843 Dout - input
GPIO_21      0x2  ads7843 Clk
GPIO_22      0x4  ads7843 /CS
GPIO_23      0x8   input??
GPIO_24     0x10   output?? is push pull, no internal pull-up,
GPIO_25     0x20   input??
GPIO_26     0x40  Channel button four states 00 01 11 10
GPIO_27     0x80  Channel button to detect rotation

 ===> port3 - when booting  input on 
	
GPIO_30      0x1   input??
GPIO_31      0x2  cs9211 Clk
GPIO_32      0x4   input??
GPIO_33      0x8   input??
GPIO_34     0x10  cs9211 CS
GPIO_35     0x20  cs9211 Din
GPIO_36     0x40  cs9211 Dout
GPIO_37     0x80  ADS7843 /PENIRQ 

 === > port3 bit7 0x80 normal,  press touchscreen 0 /PENIRQ ADS7843 /PENIRQ 

 ===> cs9211 gpio used for LED


 ===> taken from devi-kojak <===

            gpio_pin_Q ???      output is port2 0x10  is push pull, no internal pull-up,
  0x2000000 gpio_pin_   cs9211  Clk
 0x10000000 gpio_pin_   cs9211  CS
 0x40000000 gpio_pin_   cs9211  Din
 0x80000000 gpio_pin_   cs9211  Dout

 When nobuttons pressed you read this on the parrallel port
                       SIOC2 *22=07  -bank0: [0378]   00 87 e4 ff

 Vol UP   when pressed SIOC2 *22=07  -bank0: [0378]   00 8f e4 ff
          hence pressed bit3 0 -> 1
 Vol Down when pressed SIOC2 *22=07  -bank0: [0378]   00 07 e4 ff
          hence pressed bit7 1 -> 0
 Action   when pressed SIOC2 *22=07  -bank0: [0378]   00 c7 e4 ff
4th right hence pressed bit6 0 -> 1

 LED control is unknown, doesn't seem to be port2 0x10

Updating the flash PROM

The Flash PROM in Audrey is soldered in, this makes it highly dangerous to modify the BIOS since there is no easy way back. The Flash can be updated in a number of ways. If anyone have an idea how I can get a working PROM-image back into my dead Audrey I would appreciate very much to hear more. Or if the JTAG signals should be available on a connector on the board. I would imagine they are, since 3Com would have needed a simple way to load the FLASH prom initially. I would think that adding support for Geode under Openwince JTAG would not be too difficult. Alternatively you could fit install a 32 pin BIOS, more on that here could you fit a regular BIOS, there is space and some jumpers labeled BIO NOR Please let me know if you more on this or other ideas.

IBM N2200

I have just got my hands on two of the above, which allready supports LINUX on an allmost identical Hardware base - no LCD-screen no 16 Mb flash, but build in 100Mbit Ethernet. It allready has a BIOS which can boot Linux either from the network via DHCP/NFS or from a Compact-Flash Card containing a normal ext2 filesystem.

PS: The IBM N200 has a JTAG connector

Resources