The IXP4xx is a series of XScale ARM chips from Intel that was created as part of their legacy when acquireing Digitals StrongARM line. This SoC has an ARMv5TE Big Endian ISA. It can sometimes be hard to find the right tools. The typical userspace is built using OpenWrt or OpenEmbedded.
As of kernel v6.1 we finalized modernization of the IXP4xx port in the Linux kernel to use device tree and modern drivers for the entire set of systems supported by the Linux kernel boardfiles, and the boardfiles were consequently deleted.
A major reason why IXP4xx silicon is still produced and deployed is the operating conditions. If you look at for example the Gateworks Cambria GW2358-4 network processor (apparently still for sale for new designs in 2017) you notice the strictly military operating conditions:
- Temperature: -40°C to +85°C
- Humidity (non-condensing): 20% to 90%
- MTBF (mean time before failure): 60 Years at 55°C
It is pretty easy for an experienced ARM kernel hacker to get any of these devices running with the latest kernel and full hardware support. Most of the heavy lifting is already done and landed upstream.
The UARTs on the IXP4xx uses 115200 baud.
Getting OpenWRT up on it
At one point IXP4xx support was been deleted from OpenWrt, but we brought it back on 2023-10-25. It is now once again part of the OpenWrt code repository.
It is pretty straight forward to build and develop on the latest OpenWrt for IXP4xx:
- Clone the latest OpenWRT git tree
- cd openwrt
- make menuconfig
- Target system Intel IXP4xx
- Target profile [YOUR DESIRED ROUTER]
- Exit and save config
- make
- (build build build build)
- Usable images appears in
- bin/targets/ixp4xx/generic/openwrt-ixp4xx-[YOUR_DESIRED_ROUTER]-zImage
- bin/targets/ixp4xx/generic/openwrt-ixp4xx-[YOUR_DESIRED_ROUTER]-squashfs.bin
- You want to place the zImage in the linux partition of your flash and the squashfs in the rootfs partition.
Booting the mainline kernel with OpenWrt
It can be really handy to be able to boot the mainline (upstream) Linux kernel for developing proper patches and submitting, so naturally I have a way to do this. It's not as trivial as using or flashing OpenWrt and requires UART access and TFTP boot of the kernel, but if you are convenient with this, here is how to do it:
You need a proper toolchain in your $PATH, I just generally use the one that is generated from OpenWrt (available in the main menuconfig). Here is for example this big-endian ARMv4 GCC 12.3.0 toolchain for XScale that was created using OpenWrt.
Just like OpenWrt I compulsively use Makefile scripting to build my images. Using this works like so:
- Download and take a look at my ixp4.mak Makefile
- Place this ixp4.mak in the root of your kernel tree, Torvalds latest HEAD usually works fine
- Inspect the variables at the top of the file:
- CROSS_COMPILE is the prefix of the toolchain to be used and this should be in your $PATH, e.g. armeb-openwrt-linux-gcc --version or so provides something meaningful.
- rootfs is needed if you want to try to boot from initramfs, I usually just generate that initramfs from OpenWrt as well. (Target Images ---> [*] cpio.gz, then gunzip the result because the kernel likes it uncompressed.) If you want to boot from a storage card such as a USB drive or MMC/SD this is not needed.
- variant is where you uncomment (or add!) the device tree binary (inside the kernel) which you want to attach to the kernel. You just need to reference it, the kernel contains the device tree, mostly. For a new device tree you need to point it out.
- tftproot is some location where the resulting zImage will be copied so you don't need more manual steps.
- firmware_dir is a place where you find the NPE firmware, if you want to compile it into the kernel instead of reading it from the rootfs. Either works, I developed this method to compile it into the kernel when experimenting with NFS rootfs.
- Inspect the options for the config makerule:
- config-base config-mainlined config-openwrt likely turns on the configs that OpenWrt needs to boot and general nice features. config-ksmbd is another nice feature that enables the in-kernel SMB daemon.
- config-<MY BOARD NAME> does the obvious: configures kernel features needed on that very board.
- config-firmware compiles the firmware into the kernel, if you want to load it from the rootfs just remove this makefile rule from config.
- config-initramfs configures the initramfs to be compiled into the kernel, do not combine with other rootfs options, obviously.
- config-ext4-rootfs sets up the device to boot from /dev/sda1 using an ext4 rootfs, do not combine with other rootfs options, obviously.
- config-nfsroot - good luck with that (you're gonna need it: it doesn't work because OpenWrt is not engineered for it).
- make -f ixp4.mak config && make -f ixp4.mak build
- Out comes (hopefully) a zImage that you can boot from TFTP and it should do what you want.
- It will not be possible to mount a rootfs from NOR flash using just the mainline kernel: this is because OpenWrt has a out-of-tree code bundle called "mtdsplit" which splits the flash into linux kernel and rootfs. The best way to boot to userspace is to use an external rootfs on USB or on some systems Compact Flash. A .tar.gz root filesystem can be generated easily from OpenWrt.
USRobotics USR8200
As the USRobotics router has users, I have tried to create a device tree and a test image for it.
Files:
- RedBoot for flash for USR8200
- RAM resident RedBoot for USR8200
- openwrt-ixp4xx-usrobotics_usr8200-squashfs-kernel.bin a kernel firmware to be flashed into the flash partition "linux" using Redboot.
- openwrt-ixp4xx-usrobotics_usr8200-squashfs-rootfs.bin a root filesystem to be flashed into the flash partition "rootfs" using Redboot.
Links:
- USR8200 on OpenWrt
- USR8200 Hardware description from the old OpenWrt Wiki
- Description for RedBoot installation use the images provided for the MI424-WR router this requires the RedBoot binary and the Jungo image script.
- GPL source code for all USR products
Boot the zImage like this:
- Connect a UART
- Break into Redboot by hammering CTRL+C at boot
- Set up a TFTP server and put the zImage-usr8200 into the server root
ip_address -l 192.168.1.35 -h 192.168.1.2 load -r -v -b 0x00080000 -h 192.168.1.2 zImage-usr8200 exec 0x00080000
Gateworks Avila GW2348-4
- openwrt-ixp4xx-avila-squashfs-kernel.bin a kernel firmware to be flashed into the flash partition "linux" using Redboot like below.
- openwrt-ixp4xx-avila-squashfs-rootfs.bin a root filesystem to be flashed into the flash partition "rootfs" using Redboot like below.
Break into Redboot by hammering CTRL+C as soon as you plug in the power and see a + appear in the console.
The flash needs one big consecutive space to use for the combined Linux kernel and rootfs. I have repartitioned my flash because the "linux" partition could not fit my kernel.
I did it like this:
RedBoot> fis list Name FLASH addr Mem addr Length Entry point RedBoot 0x50000000 0x50000000 0x00080000 0x00000000 zimage 0x50080000 0x01600000 0x00160000 0x01600000 ramdisk 0x501E0000 0x00800000 0x002C0000 0x00800000 FIS directory 0x50FE0000 0x50FE0000 0x0001F000 0x00000000 RedBoot config 0x50FFF000 0x50FFF000 0x00001000 0x00000000 RedBoot> fis unlock zimage ... Unlock from 0x50080000-0x501e0000: ........... RedBoot> fis delete zimage Delete image 'zimage' - continue (y/n)? y ... Erase from 0x50080000-0x501e0000: ........... ... Unlock from 0x50fe0000-0x51000000: . ... Erase from 0x50fe0000-0x51000000: . ... Program from 0x03fd0000-0x03ff0000 at 0x50fe0000: . ... Lock from 0x50fe0000-0x51000000: . RedBoot> fis unlock ramdisk ... Unlock from 0x501e0000-0x504a0000: ...................... RedBoot> fis delete ramdisk Delete image 'ramdisk' - continue (y/n)? y ... Erase from 0x501e0000-0x504a0000: ...................... ... Unlock from 0x50fe0000-0x51000000: . ... Erase from 0x50fe0000-0x51000000: . ... Program from 0x03fd0000-0x03ff0000 at 0x50fe0000: . ... Lock from 0x50fe0000-0x51000000: . RedBoot> fis create -b 0x00080000 -l 0x00400000 -s 0x00400000 -f 0x50080000 -e 0x00080000 -r 0x00080000 -n linux ... Unlock from 0x50fe0000-0x51000000: . ... Erase from 0x50fe0000-0x51000000: . ... Program from 0x03fd0000-0x03ff0000 at 0x50fe0000: . ... Lock from 0x50fe0000-0x51000000: . RedBoot> fis create -b 0x00080000 -l 0xb60000 -s 0x00400000 -f 0x50480000 -e 0x00031000 -r 0x00080000 -n rootfs ... Unlock from 0x50fe0000-0x51000000: . ... Erase from 0x50fe0000-0x51000000: . ... Program from 0x03fd0000-0x03ff0000 at 0x50fe0000: . ... Lock from 0x50fe0000-0x51000000: . RedBoot> fis list Name FLASH addr Mem addr Length Entry point RedBoot 0x50000000 0x50000000 0x00080000 0x00000000 linux 0x50080000 0x00080000 0x00400000 0x00080000 rootfs 0x50480000 0x00080000 0x00B60000 0x00031000 FIS directory 0x50FE0000 0x50FE0000 0x0001F000 0x00000000 RedBoot config 0x50FFF000 0x50FFF000 0x00001000 0x00000000
Here I also had to set up the boot script:
RedBoot> fconfig Run script at boot: true Boot script: .. fis load ramdisk .. fis load zimage .. exec Enter script, terminate with empty line >> fis load linux >> exec >> (...)
Just select the default for the rest of the script options.
Next download a kernel to the device and flash it into the "linux" slot, and a rootfs and flash it into the "rootfs" slot:
RedBoot> ip_address -l 192.168.1.35 -h 192.168.1.2 RedBoot> load -r -v -b 0x00080000 -h 192.168.1.2 openwrt-ixp4xx-avila-squashfs-kernel.bin RedBoot> fis unlock linux RedBoot> fis write -f 0x50080000 -b 0x00080000 -l 0x0033791e RedBoot> fis lock linux RedBoot> load -r -v -b 0x00080000 -h 192.168.1.2 openwrt-ixp4xx-avila-squashfs-rootfs.bin RedBoot> fis unlock rootfs RedBoot> fis write -f 0x50480000 -b 0x00080000 -l 0x340000 RedBoot> fis lock rootfs RedBoot> reset
Gateworks Cambria GW2358-4
- openwrt-ixp4xx-cambria-squashfs-kernel.bin a kernel firmware to be flashed into the flash partition "linux" using Redboot like below.
- openwrt-ixp4xx-cambria-squashfs-rootfs.bin a root filesystem to be flashed into the flash partition "rootfs" using Redboot like below.
Break into Redboot by hammering CTRL+C as soon as you plug in the power and see a + appear in the console.
The flash needs one big consecutive space to use for the combined Linux kernel and rootfs. I have repartitioned my flash because the "linux" partition could not fit my kernel.
I did it like this:
RedBoot> fis list Name FLASH addr Mem addr Length Entry point RedBoot 0x50000000 0x50000000 0x00080000 0x00000000 linux 0x50080000 0x00031000 0x00100000 0x00031000 rootfs 0x50180000 0x00031000 0x00180000 0x00031000 RedBoot> fis unlock linux ... Unlock from 0x50080000-0x50180000: ........ RedBoot> fis delete linux Delete image 'linux' - continue (y/n)? y ... Erase from 0x50080000-0x50180000: ........ ... Unlock from 0x51fe0000-0x52000000: . ... Erase from 0x51fe0000-0x52000000: . ... Program from 0x07fd0000-0x07ff0000 at 0x51fe0000: . ... Lock from 0x51fe0000-0x52000000: . RedBoot> fis unlock rootfs ... Unlock from 0x50180000-0x50300000: ............ RedBoot> fis delete rootfs Delete image 'rootfs' - continue (y/n)? y ... Erase from 0x50180000-0x50300000: ............ ... Unlock from 0x51fe0000-0x52000000: . ... Erase from 0x51fe0000-0x52000000: . ... Program from 0x07fd0000-0x07ff0000 at 0x51fe0000: . ... Lock from 0x51fe0000-0x52000000: . RedBoot> fis create -b 0x00080000 -l 0x00400000 -s 0x00400000 -f 0x50080000 -e 0x00080000 -r 0x00080000 -n linux ... Unlock from 0x51fe0000-0x52000000: . ... Erase from 0x51fe0000-0x52000000: . ... Program from 0x07fd0000-0x07ff0000 at 0x51fe0000: . ... Lock from 0x51fe0000-0x52000000: . RedBoot> fis create -b 0x00080000 -l 0x01b60000 -s 0x00400000 -f 0x50480000 -e 0x00031000 -r 0x00080000 -n rootfs ... Unlock from 0x51fe0000-0x52000000: . ... Erase from 0x51fe0000-0x52000000: . ... Program from 0x07fd0000-0x07ff0000 at 0x51fe0000: . ... Lock from 0x51fe0000-0x52000000: .
Next download a kernel to the device and flash it into the "linux" slot, and a rootfs and flash it into the "rootfs" slot:
RedBoot> ip_address -l 192.168.1.35 -h 192.168.1.2 RedBoot> load -r -v -b 0x00080000 -h 192.168.1.2 openwrt-ixp4xx-cambria-squashfs-kernel.bin Raw file loaded 0x00080000-0x0033ac8a, assumed entry at 0x00080000 RedBoot> fis unlock linux RedBoot> fis write -f 0x50080000 -b 0x00080000 -l 0x0033ac8a RedBoot> fis lock linux RedBoot> load -r -v -b 0x00080000 -h 192.168.1.2 openwrt-ixp4xx-cambria-squashfs-rootfs.bin RedBoot> fis unlock rootfs RedBoot> fis write -f 0x50480000 -b 0x00080000 -l 0x002a0000 RedBoot> fis lock rootfs RedBoot> reset
Notice how the lengths of the images are adjusted to the downloaded files. I'm sorry that I don't know any better way to flash the kernel and rootfs on these devices.
NSLU2
The Linksys NSLU2 also known as "the slug" is a NAS box which has ethernet and two USB 2.0 plugs to run USB disk enclosures for storage. The simplicity of this platform created a huge hobbyist hacking community in the mid-2000s.
NSLU2 is one of the device that will be resurrected into OpenWrt. I have pre-release images here that makes it possible to use kernel v6.6 from 2024-05-20, with a snapshot of OpenWrt along with LuCI and KSMBD on the NSLU2 booting from an external hard drive or USB stick:
- IXP4xx rootfs - format a hard drive or USB stick with one partition (/dev/sda1) and format that partition with ext4. Then extract this rootfs into that partion. Plug the device into the USB 2.0 port of the NSLU2 (the port closest to the power plug). This rootfs has been processed to not start odhcpd, dnsmasq or firewall.
- openwrt-ixp4xx-nslu2-squashfs-factory.bin a firmware to be flashed
into the flash using the upslug2 tool like this:
- Hold down reset key and turn device on, wait until the LED turns red, release reset key and the LED starts blinking red. If the LED starts blinking yellow instead, try to just boot the device normally (to userspace) once and then retry.
- On your host on the same network:
upslug2 -d enp7s0 -i openwrt-ixp4xx-nslu2-squashfs-factory.bin
This version of OpenWrt will just grab a IP number from DHCP so you can check your router to see which IP it got.
You can create a local share on the hard drive by getting onto
the NSLU2 with ssh root@192.168.1.n and do something like:
mkdir ksmbd chown nobody ksmbd chgrp nogroup ksmbdThen set up the share using the LuCI Web UI or by logging in to the router and editing /etc/config/ksmbd
I booted this early on from device tree on 2021-11-30 for a test, this is the dmesg!
Vulcan
A zImage for the Vulcan an IXP425-based single-board computer.
IXP4xx Kernel TODO
Switch to using device tree only (fixed for kernel v5.18)- Define some static clocks in the device tree
- Get rid of the no-clock framework hacks in drivers/usb/gadget/udc/pxa25x_udc.c
OpenWRT TODO
Resurrect IXP4xx support using kernel v6.1
Links
- OpenWrt page for IXP4xx
- OpenWrt page for NSLU2
- Up-to-date RedBoot sources that can be built and deployed using contemporary build tools and compilers.
- OpenWrt page for Gateworks Avila GW2342