Technologic_Systems_TS-72xx
This article is still a Stub. You can help Gentoo-Wiki by expanding it.
| Laptops • TV Tuner Cards • Wireless • Servers • Storage • Other Hardware • Motherboards • Related |
Introduction
Jump here if you just want to download the binaries.
The purpose of this HowTo is to port Embedded Gentoo [1] to the TS72xx series of ARM (Wikipedia:ARM Architecture) single board computers (SBC) [2] from Technologic Systems.The procedure loosely follows the 'from scratch' method of Mike Frysinger (vapier) [3] but with conserably more detail. The 'Linux From Scratch' [4] documentation was loosely referenced as well. Although this document concentrates on installation specifically for the TS72xx series boards with maverick-crunch (Wikipedia:MaverickCrunch) and the GNU-EABI (Wikipedia:EABI), it could potentially also be generalized to any other new architecture if the arm/maverick/eabi-specific parts are omitted.
If you are unfamiliar with the ARM EABI, then you might want to read the following first - [5], [6].Also, for detail about the TS72xx hardware itself, and the relevent ARM / Cirrus documentation, see [7], [8], [9].
Overview
What this HowTo Covers
This how-to will address the following topics:
- building a redistributable EABI / Maverick cross toolchain and root filesystem for the TS7000 community (i.e. a 'full distro')
- patching and building a modern linux kernel for ts72xx boards
What this HowTo Does Not Cover
Here are some things that this article does not cover
- Buiding a redistributable uClibc / EABI / Maverick cross-toolchain and root filesystem (i.e. a 'tiny distro')
- Providing a Java and Fortan compiler in said cross-toolchain (still in development in the gcc community)
- Discuss ways of automating board deployment with OpenVPN and SSH for distributed management using unique client / host keys
- Discuss suitable distributed package management systems with automatic updates
Each of the above (aside from the GCC business) will be part of my project for the next couple of weeks. I probably will not have this system finely tuned for slightly longer, but I expect to have a proof of concept done by then. Aside from the maverick and ts72xx ebuild overlays, I have not made any significant code / patch changes except to make it 'just work'. All patches can be viewed if you download the ebuilds in the overlays that are mentioned below.
What Needs Touching-Up
- For some reason, even though --with-fpu=maverick is passed to GCC during configure, it still does not apply -mfpu=maverick as a default compile option
- For political correctness sake, I should probably put together a longer list of credit for patches... but really there are SO many sources. You can easily find them yourself just by Googling.
The 'full distro' in this case is basically equivalent to the Debian-256 distribution from Technologic Systems. This filesystem is ~ 400MB and is therefore not suitable for on-board flash. If this filesystem is to be used, then it should be installed on a USB storage device or SD-card, as the case may be. Note that this filesystem is only so large because it includes all headers, man pages, a full native toolchain, and so on. I will address stripping this filesystem at a later date.
Typically, 'full distros' do not attempt to reduce filesystem size. Therefore, a full GNU userland is created. Common system applications are not replaced by the BusyBox (Wikipedia:BusyBox) counterparts. Similarly, uClibc (Wikipedia:uClibc) is not used to decrease the size of the system C library, but rather the full Glibc. Furthermore, packages installed to this root filesystem will contain includes, man pages, and other such clutter, whereby a 'tiny distro' will usually attempt to install only the shared libraries, binaries, and minimal configuration files for a runnable system.
Assumptions
This how-to assumes that you have
- A TS72xx board along with the appropriate serial cable, power supply, & ethernet cable
- root privileges on your Gentoo Linux build machine
- a working network connection for both workstation & board
- a USB storage device - 2GB should be much more than enough (you might need to extract the portage tree onto it for the last few steps)
Creating the Cross-Toolchain
| Code: Export necessary environment variables |
export MYHOST=armv4tl-maverick-linux-gnueabi export SRVR="http://vaiprime.visibleassets.com/~cfriedt" |
Below we will emerge our cross-toolchain. It is absolutely imperative that you do not forget the -D__MAVERICK__ CFLAG when creating the cross-glibc. Due to the way the patch is set-up, if this is not defined for glibc, then none of the glibc maverick-crunch features will be used! Unfortunately, portage does not as of yet have a built-in method of organizing per-package environment variables (i.e. CFLAGS) for automated installation. That means every time you re-build glibc you must remember to define __MAVERICK__! Otherwise your glibc will provide a completely incorrect float/double math library with unexpected results (well... any float op will return 0). I believe Ned Ludd had devised a separate env.d subsystem for automating environment variables (i.e. CFLAGS,CXXFLAGS,etc) for portage, but it is not yet integrated into the main portage package.
I modified portage to recognize the GCC_EXTRA_ECONF environment variable. Why? Well, if you set --with-cpu as an option, expecting GCC to target a specific processor by default, then glibc infers that it should optimize the code for that CPU as well. If you are creating a cross-toolchain, then that is obviously impossible, because GCC would optimize code for, say, arm920t, while glibc (which has i686 compatible objects) would refuse and say 'that target is not supported in this architecture', or something of that sort.
| Code: Crossdev |
CROSSDEV_OVERLAY="/usr/local/portage/crossdev_overlay"
MAVERICK_OVERLAY="/usr/local/portage/maverick_overlay"
OVERLAY_SRC="${SRVR}/overlays"
rm -Rf ${MAVERICK_OVERLAY} &&
mkdir -p ${MAVERICK_OVERLAY} &&
wget -O - ${OVERLAY_SRC}/maverick.tar.bz2 | \
tar xpjf - -C ${MAVERICK_OVERLAY}
unset PKGDIR
# this is necessary for recognizing GCC_EXTRA_ECONF
PORTDIR_OVERLAY="${MAVERICK_OVERLAY}" \
emerge -v1 =sys-devel/crossdev-0.9.18-r7
# emerge the cross-toolchain
PORTDIR_OVERLAY="${CROSSDEV_OVERLAY} ${MAVERICK_OVERLAY}" \
CFLAGS="-O2 -pipe -D__MAVERICK__" \
GCC_EXTRA_ECONF="--with-cpu=arm920t --with-tune=arm920t \
--with-fpu=maverick --with-float-abi=softfp \
--enable-__cxa_atexit --with-system-zlib \
--without-included-gettext --enable-threads=posix \
--enable-clocale=gnu" \
USE="-gcj -gtk -fortran -mudflap" \
FEATURES="buildpkg" \
crossdev -S --ex-gdb \
--l 2.5-r4 --g 4.1.2 --b 2.17-r1 \
${MYHOST}
|
Because of the 'buildpkg' feature, binary packages for the cross-toolchain will have already been made and stored in ${PKGDIR}/cross/${MYHOST}. There you will find a binary package for gcc, glibc, linux-headers, binutils, and gdb. These binary packages form a portable cross-toolchain.
Xmerge: The Emerge Wrapper
Create /usr/sbin/xmerge [10]
| File: /usr/sbin/xmerge |
#!/bin/sh
export CBUILD=$(portageq envvar CHOST)
export PORTAGE_CONFIGROOT=${SYSROOT}
if [ "$1" = "--root" ] ; then
export ROOT=$2
shift 2
else
export ROOT=${SYSROOT}
fi
exec emerge "$@"
|
chmod +x /usr/sbin/xmerge
Populating the ${SYSROOT}
Portage Configuration
Export Environment Variables
| Code: Environment Variables Used by Xmerge / Emerge |
export SYSROOT=/usr/${MYHOST}
export PKGDIR=${SYSROOT}/var/tmp/binpkgs
|
For each ofthe packages installed below, you will find a precompiled binary tbz2 package in ${PKGDIR}. These binary packages will form your binary package repository.
Set Up the PORTDIR_OVERLAY
| Code: Prepare the PORTDIR_OVERLAY |
PORTDIR_OLAY=${SYSROOT}/usr/local/portage
export PORTDIR_OVERLAY="${PORTDIR_OLAY}/ts72xx_overlay \
${PORTDIR_OLAY}/maverick_overlay"
mkdir -p ${PORTDIR_OVERLAY}
wget -O - ${SRVR}/overlays/ts72xx.tar.bz2 | \
tar xpjf - -C ${PORTDIR_OLAY}/ts72xx_overlay
wget -O - ${SRVR}/overlays/maverick.tar.bz2 | \
tar xpjf - -C ${PORTDIR_OLAY}/maverick_overlay
|
Create ${SYSROOT}/etc/make.conf
Note: I guess I found a 'bug' in gcc. The problem is that in the INSTALL documentation, it says that if you configure gcc with --with-cpu=x,--with-fpu=y,--with-float-abi=z, then it will produce binaries using that combination by default. This is not the case as I discovered. After running the same lame mp3 encoding test that Martin Guy used, the time taken was equivalent to that of soft-float. If i recompiled lame with the -m options that I thought were set by default, then gcc produced the expected maverick-enabled code. Any idea why that would be the case, gcc people?
Maybe this is actually a bug in binutils. Who knows, but until its fixed, you need to apply CFLAGS as shown below.
mkdir -p ${SYSROOT}/etc/portage
| File: Edit ${SYSROOT}/etc/make.conf |
ACCEPT_KEYWORDS="arm"
ARCH=arm
CHOST="armv4tl-maverick-linux-gnueabi"
# for some reason we need to include the -m options that GCC was supposed to have enabled by default
# -D__MAVERICK__ is required for compiling glibc, no others, but it's easier to have here
CFLAGS="-O2 -pipe -mcpu=arm920t -mtune=arm920t -mfpu=maverick -mfoat-abi=softfp -D__MAVERICK__"
CXXFLAGS="${CFLAGS}"
MAKEOPTS="-j2"
EMERGE_DEFAULT_OPTS="-k"
VIDEO_CARDS="none"
LCD_DEVICES=""
ALSA_PCM_PLUGINS=""
FEATURES="buildpkg -ccache -confcache"
PORTDIR_OVERLAY="/usr/local/portage/ts72xx_overlay /usr/local/portage/maverick_overlay"
PKGDIR=/var/tmp/binpkgs
# Note! If internationalization is required, set nls and unicode below
USE="-acl berkdb -bitmap-fonts bzip2 -cli -cracklib crypt -cups fortran gcj gmp -iconv -ipv6 \
-isdnlog -midi mpfr -mudflap ncurses -nls nptl nptlonly -openmp -pam pcre perl -ppds -pppd \
python readline -reflection -session slang -spl ssl tcpd -truetype-fonts -type1-fonts -unicode \
-xorg zlib"
|
Edit Locale Information (Optional)
If you need to generate certain locale data, then add locale codes to the file below.
| File: Edit ${SYSROOT}/etc/locale.gen |
en_US ISO-8859-1 en_US.UTF-8 UTF-8 en_CA ISO-8859-1 en_CA.UTF-8 UTF-8 de_DE ISO-8859-1 de_DE@euro ISO-8859-15 fr_FR ISO-8859-1 fr_FR@euro ISO-8859-15 fr_CA ISO-8859-1 fr_CA UTF-8 |
Edit Package-Specific Use Flags / Keywords
I have marked several of the core system applications to be made static. This prevents important programs from bailing out in case a shared library is accidentally deleted. The static variable should not be overly used since the size of statically compiled binaries are much larger.
| File: Edit ${SYSROOT}/etc/portage/package.use |
net-wireless/wireless-tools multicall net-misc/iputils static sys-devel/patch static sys-apps/grep static sys-apps/net-tools static sys-apps/baselayout static unicode sys-apps/debianutils static app-arch/tar static app-arch/bzip2 static app-arch/gzip static net-misc/rsync static net-misc/wget static sys-apps/coreutils static sys-devel/make static sys-apps/diffutils static sys-fs/e2fsprogs static sys-apps/texinfo static sys-apps/findutils static sys-apps/sed static sys-apps/sysvinit static net-firewall/iptables static net-misc/openvpn ssl threads sys-apps/busybox savedconfig static -debug -make-symlinks -pam net-misc/dhcp static app-admin/eselect bash-completion ### the packages below require a portage overlay & patches # note: psmisc needs to be patched for cross-compiling (rpl_malloc) =sys-process/psmisc-22.5-r2 gnu-malloc =net-libs/libnfsidmap-0.19 gnu-malloc # gcc needs the arm/sysv.S patch for @progbits # also added externalize-jar patch sys-devel/gcc fortran gcj -gtk -mudflap |
| File: Edit ${SYSROOT}/etc/portage/package.keywords |
=sys-apps/busybox-1.8.2 =app-arch/fastjar-0.95 =net-wireless/wpa_supplicant-0.5.8 =net-misc/openvpn-2.1_rc7 |
Busybox Savedconfig
| Code: Make a BusyBox Savedconfig File |
mkdir -p ${SYSROOT}/etc/portage/savedconfig/sys-apps
wget -O ${SYSROOT}/etc/portage/savedconfig/sys-apps/busybox-1.8.2 \
${SRVR}/configs/busybox-1.8.2.config
|
Create make.profile and make.globals
| Code: Make the make.profile Symlink and make.globals File |
cd ${SYSROOT}/etc
cp /etc/make.globals .
ln -sf /usr/portage/profiles/default-linux/arm/2007.0 make.profile
|
Emerge System Packages
The following list of packages is not simply the 'system' group (omitting the compiler, libc, os-headers,and binutils). It is also a carefully tested list of packages that are known to cross-compile, which may on occasion require extra patching, as apparent in the ts72xx overlay.
On one hand that spares you, the builder, the time it takes to organize this ordering from scratch. On the other hand, it also means there are other 'system' packages that will not properly cross compile, such as perl. Those packages must go through the extremely slow process of native compilation later on.
I've taken the liberty to add a few extra programs that are not part of the 'system' group but useful nonetheless.
| Code: Emerge the System Packages |
PKGS="sys-libs/ncurses sys-libs/zlib sys-libs/db sys-apps/tcp-wrappers dev-libs/gmp sys-libs/com_err sys-devel/m4 sys-devel/gnuconfig sys-apps/sysvinit sys-devel/autoconf-wrapper sys-devel/automake-wrapper sys-apps/shadow sys-apps/sed dev-libs/popt sys-libs/timezone-data sys-apps/sandbox dev-libs/expat dev-libs/libevent =net-libs/libnfsidmap-0.19 sys-libs/ss sys-fs/e2fsprogs =net-fs/nfs-utils-1.1.0-r1 sys-apps/findutils virtual/libiconv dev-libs/libpcre sys-apps/grep sys-apps/net-tools sys-apps/kbd net-misc/iputils =sys-apps/busybox-1.8.2 sys-devel/patch sys-devel/flex sys-apps/gawk sys-apps/file sys-apps/which app-arch/fastjar net-misc/dhcpcd app-arch/gzip app-arch/bzip2 app-arch/cpio =app-arch/tar-1.18-r2 app-portage/portage-utils net-firewall/iptables sys-libs/readline sys-apps/texinfo app-shells/bash sys-apps/coreutils app-editors/nano virtual/init net-misc/rsync net-nds/portmap sys-process/procps =sys-process/psmisc-22.5-r2 sys-devel/bison sys-apps/less dev-libs/mpfr sys-apps/groff virtual/editor net-wireless/wireless-tools sys-apps/man sys-apps/util-linux sys-apps/man-pages sys-apps/diffutils =dev-lang/python-2.4.4-r6 dev-libs/openssl net-misc/openssh net-misc/wget net-wireless/wpa_supplicant dev-python/python-fchksum dev-python/pycrypto app-admin/python-updater sys-apps/portage dev-libs/libxml2 sys-devel/autoconf sys-devel/automake sys-devel/libtool sys-apps/debianutils sys-apps/mktemp sys-apps/baselayout sys-apps/module-init-tools sys-fs/udev =app-arch/fastjar-0.95 sys-devel/gcc-config sys-devel/binutils-config dev-libs/lzo net-misc/openvpn net-misc/ntp app-misc/screen app-editors/hexedit app-admin/eselect" CFLAGS="-O2 -pipe" xmerge -av1 --nodeps $PKGS xmerge -av1 --nodeps media-sound/lame # for some reason make will not compile -O2 with maverick/eabi CFLAGS="-pipe" xmerge -av1 --nodeps sys-devel/make |
Package the Native Toolchain
It is VERY important that these packages should be emerged with the -B option. This option instructs emerge to create binary packages only and not to install anything to ${SYSROOT}. If the -B option is not passed then portions of the cross-toolchain could be overwritten, rendering it useless (namely the libc and os-headers).
If internationalization support is necessary, you should have added "nls" to USE in ${SYSROOT}/etc/make.conf, edited ${SYSROOT}/etc/locale.gen, and you should remove the LANG variable below.
| Code: Package the Native Toolchain |
USE="-gcj -fortran" \ EXTRA_ECONF="--enable-shared \ --with-system-zlib --without-included-gettext \ --enable-threads=posix --enable-clocale=gnu \ --with-tune=arm920t --enable-__cxa_atexit \ --with-fpu=maverick --with-float-abi=softfp \ --with-cpu=arm920t" \ xmerge --nodeps -avB1 =sys-devel/gcc-4.1.2 LANG="C" xmerge -avB1 --nodeps =sys-libs/glibc-2.5-r4 xmerge -avB1 =sys-devel/binutils-2.17-r1 \ sys-kernel/linux-headers sys-devel/gdb |
Now, it's safe to say ROOT=${SYSROOT} etc-update
Preparing the System Configuration Files
Clock & Timezone Options
| File: Edit ${SYSROOT}/etc/conf.d/clock |
... CLOCK="local" ... TIMEZONE="Europe/Berlin" #or wherever you live ... |
| Code: Make the ${SYSROOT}/etc/localtime Symlink |
cd ${SYSROOT}/etc
rm -f localtime
ln -sf ../usr/share/zoneinfo/Europe/Berlin localtime
|
Local Filesystem Options
| File: Edit ${SYSROOT}/etc/fstab (so that it looks exactly like this) |
/dev/sda1 / ext2 defaults 0 0 # NOTE: The next line is critical for boot! proc /proc proc defaults 0 0 # NOTE: The next line is critical for glibc/posix shared memory to work shm /dev/shm tmpfs nodev,nosuid,noexec 0 0 |
Assuming that you will be using a USB storage device for the root filesystem, then you can keep the ${SYSROOT}/etc/fstab exactly as shown above. However, if you are using a TS7300, then you might prefer an SD card. In that case, change /dev/sda1 to /dev/mmcblk0p1. The TS7300 has a slightly different boot scheme than the TS72xx series of devices, and they might not be 100% covered by this HowTo as of yet.
Add ttyAM0 to Relevent Files
| Code: Edit ${SYSROOT}/etc/inittab |
... # TERMINALS c1:12345:respawn:/sbin/agetty 38400 tty1 linux #c2:2345:respawn:/sbin/agetty 38400 tty2 linux #c3:2345:respawn:/sbin/agetty 38400 tty3 linux #c4:2345:respawn:/sbin/agetty 38400 tty4 linux #c5:2345:respawn:/sbin/agetty 38400 tty5 linux #c6:2345:respawn:/sbin/agetty 38400 tty6 linux ... # SERIAL CONSOLES s0:12345:respawn:/sbin/agetty 115200 ttyAM0 vt100 # ARM-specific #s0:12345:respawn:/sbin/agetty 9600 ttyS0 vt100 #s1:12345:respawn:/sbin/agetty 9600 ttyS1 vt100 ... |
Make the /bin/ash Symlink
| Code: Create a ${SYSROOT}/bin/ash -> busybox Symlink |
cd ${SYSROOT}/bin
ln -sf busybox ash
|
If trouble ever arises with the userland and normal login is not possible, pass "console=ttyAM0,115200 root=/dev/sda1 rootdelay=5s init=/bin/ash" as the kernel command line at the Redboot prompt. Since busybox is compiled statically, it should allow you to sort out the issue without having to do a major overhaul of the system.
Add Static Device Nodes
| Code: Create Static ${SYSROOT}/dev nodes |
cd ${SYSROOT}/dev
mknod -m 600 mem c 1 1
mknod -m 666 null c 1 3
mknod -m 666 zero c 1 5
mknod -m 644 random c 1 8
for i in `seq 0 6`; do mknod -m 600 tty${i} c 4 ${i}; done
for i in `seq 0 2`; do
mknod -m 660 ttyAM${i} c 204 $((16+${i}));
done
mknod -m 666 tty c 5 0
mkdir -p ttys && cd ttys
for i in `seq 0 2`; do ln -sf ${i} ../ttyAM${i}; done
cd ..
mknod -m 600 console c 5 1
ln -sf /proc/self/fd fd
ln -sf fd/0 stdin
ln -sf fd/1 stdout
ln -sf fd/2 stderr
# and a few additional of our own
mknod -m 400 urandom c 1 9
mknod -m 660 sda b 8 0
mknod -m 660 sda1 c 8 1
mknod -m 660 sda2 c 8 2
mkdir misc
ln -sf misc/rtc rtc
# This is specifically for the rtc-m48t86 module
mknod -m 664 misc/rtc c 254 1
mknod -m 660 hpet c 10 228
mknod -m 640 kmem c 1 2
mknod -m 660 kmsg c 1 11
|
Adjust the Hostname
| Code: Edit ${SYSROOT}/etc/conf.d/hostname |
echo "HOSTNAME=ts72xx" > ${SYSROOT}/etc/conf.d/hostname
|
Static nodes are necessary in case the init process does not properly start Udev (or an equivalent device manager). This is the case when Bash is cross-compiled (for the glibc distro)
Edit SSHD Settings
| File: Edit ${SYSROOT}/etc/ssh/sshd_config |
... PermitRootLogin yes ... PasswordAuthentication no ... UseDNS no ... |
Later on, an asymmetric authentication system will be set up for SSH using public keys on a per-device basis.
Remove the Root Password for Local Logins (Optional)
If you are completely opposed to root login on the terminal, then leave the /etc/securetty file with the default entries. The rest of this installation procedure assumes that root can at least log in on ttyAM0.
If you would like to allow root to login on the first terminal device (ttyAM0), then
| Code: Add ttyAM0 to ${SYSROOT}/etc/securetty |
echo ttyAM0 >> ${SYSROOT}/etc/securetty
|
If you are feeling bold and would like to allow for password-less root login on the terminal, then
| File: Edit ${SYSROOT}/etc/password |
root::0:0:root:/root:/bin/bash ... |
With any of the settings above, there is still no way for root to login remotely via password authentication.
Add the SSH User/Group and Root's .ssh Folder
| Code: So SSH will start |
echo 'sshd:x:22:22:added by portage for openssh:/var/empty:/sbin/nologin' >> ${SYSROOT}/etc/passwd
echo 'sshd:*:9797:0:::::' >> ${SYSROOT}/etc/shadow
echo 'sshd:x:22:' >> ${SYSROOT}/etc/group
mkdir -p ${SYSROOT}/root/.ssh
chown -R root:root ${SYSROOT}/root/.ssh
chmod -R u+rw,go-rwx ${SYSROOT}/root/.ssh
|
Perform rc-updates
| Code: Perform RC-Updates |
for i in consolefont keymaps; do
ROOT=${SYSROOT} rc-update del ${i} boot
done
for i in netmount; do
ROOT=${SYSROOT} rc-update del ${i} default
done
for i in net.eth0; do
ROOT=${SYSROOT} rc-update add ${i} default
done
|
Note: I have purposely left out SSHD from the startup because I do not want /etc/init.d/sshd to generate host keys automatically. The reasoning might not be fully apparent right now, but the idea is that several of these embedded devices are going to be deployed from a manufacturing station and all of the keys need to be done at the same time and entered into databases.
Also, for the sake of having a redistributable root filesystem, there should be no ssh keys generated before deployment.
If you would prefer to just have the ssh server running from the start (after 'logging in for the second time'), then add 'sshd' behind 'net.eth0' above.
Add Convenient Ctrl+Left Ctrl+Right Bash Macros
| File: Edit ${SYSROOT}/root/.inputrc |
"\e[1;5C": forward-word "\e[1;5D": backward-word "\e[5C": forward-word "\e[5D": backward-word "\e\e[C": forward-word "\e\e[D": backward-word |
Perform an Etc-Update on ${SYSROOT}
| Code: Etc-Update |
ROOT=${SYSROOT} etc-update
|
Creating the USB Root Filesystem
Good work so far! Up until now, everything has been isolated on your workstation. At this point, we'll via the basics like formatting the USB device and also build that list of 'system' packages that would not originally cross compile.
After all of the system packages are compiled, we'll copy those from the board back into our BPR, and then create a complete filesystem image. This is the 'full distro' that can be used during development of your embedded system. Some warning should be given, because this must be done before any unique keys are assigned to the filesystem in order ot avoid security risks.
The 'full distro' will come in 2 flavours:
- One with all binaries, all libraries (static + shared), man pages, headers, and a native toolchain.
- One with all binaries and shared libraries, but without static libraries, man pages, headers, or a toolchain.
The latter can be used for a 'small' distro based on the full glibc userland (as opposed to a 'tiny' uClibc userland).
Formatting the USB Storage Device
- Insert your USB storage device into your workstation
- If it is automatically mounted, then unmount it
- Assuming that the USB storage device is identified as /dev/sdd (check 'dmesg' for yours), adjust the partition layout as follows (using 'cfdisk /dev/sdd' or something similar)
- Delete any existing partitions
- Create a new primary partition allocated at the beginning of the disk using all but ~64 MB of the space
- Change the FS type to 'Linux' or 0x83
- Mark the partition with the 'bootable' flag
- Create a new primary partition using the remaining space
- Change the FS type to 'Linux Swap' or 0x82
- Write the changes to disk
- You may be required to remove and re-insert the disk so that the partition table is re-scanned. Please unmount any partitions that may have been re-mounted.
- Format the first partition with an ext2 filesystem
| Code: Formatting the Root Filesystem |
# the -m option is optional but I would # rather not sacrifice disk space mkfs.ext2 -L "Gen2-ts72xx-full" -m 0 /dev/sdd1mkfs.ext2 \ -L "Gen2-ts72xx-full" -m 0 /dev/sdd1 |
- Format the second partition as swap
| Code: Formatting the Swap Partition |
mkswap -L "swap" /dev/sdd2 |
Populating the Root Partition
Copy the ${SYSROOT}
Once again, remove and re-insert the USB storage device. Make a note of where the device was automounted. If the device was not automounted, then do this manually. Assign the variable MNTPNT as the location where the USB storage device was mounted.
To install the 'full' distro, use
| Code: Copy the ${SYSROOT} to the Root Partition |
xmerge --root ${MNTPNT} -Kav1 \
$PKGS sys-devel/gcc sys-devel/binutils \
sys-kernel/linux-headers sys-libs/glibc sys-devel/gdb
rsync -avr ${SYSROOT}/etc/ ${MNTPNT}/etc
rsync -avr ${SYSROOT}/dev/ ${MNTPNT}/dev
rsync -av ${SYSROOT}/bin/ash ${MNTPNT}/bin
ROOT=${MNTPNT} gcc-config 1
ROOT=${MNTPNT} binutils-config 1
ROOT=${MNTPNT} etc-update
|
Copy Relevant Bash Files
Because of a nasty little bug in bash, where it doesn't properly interpret signalling, it is necessary to build bash natively on the board itself. This is a fairly cumbersome process, but there are a couple of steps we can do to prepare for it.
| Code: Copy Relevant Bash Files |
mkdir -p ${MNTPNT}/root/bash/distfiles
cp -aR /usr/portage/app-shells/bash/files ${MNTPNT}/root/bash
cp /usr/portage/distfiles/bash32-* ${MNTPNT}/root/bash/distfiles
cp /usr/portage/distfiles/bash-3.2.tar.gz ${MNTPNT}/root/bash/distfiles
wget -O ${MNTPNT}/root/bash/build-bash-3.2_p17-r1.sh \
${SRVR}/scripts/build-bash-3.2_p17-r1.sh
|
Don't unmount the partition quite yet.
Building the Linux Kernel
The Linux kernel (even as of 2.6.23.1) needs to have several patches applied in order to properly run on the TS72xx boards. I have made a collection of these patches and also provided a script to automatically apply all of the necessary patches to make life easier.
The patches include:
- A modified version of Brenton Saunder's discontigmem patch
- Several patches from Lennart Buytenhek (many thanks Lennart)
- A couple from Charlie, and myself
- Several miscellaneous patches from OpenEmbedded
| Code: Fetch, Patch, and Build the Linux Kernel |
cd ~
KVL=2.6.23.1
KVS=2.6
wget ftp://ftp.kernel.org/pub/linux/kernel/v${KVS}/linux-${KVL}.tar.bz2
wget ${SRVR}/scripts/linux-${KVL}-apply-ts72xx-patches.sh
tar xjf linux-${KVL}.tar.bz2
sh linux-${KVL}-apply-ts72xx-patches.sh linux-${KVL}
wget -O linux-${KVL}/.config ${SRVR}/configs/linux-${KVL}-ts72xx-eabi.config
cd linux-${KVL}
make ARCH=arm CROSS_COMPILE=${MYHOST}- menuconfig
# when you're satisfied with the kernel options
make ARCH=arm CROSS_COMPILE=${MYHOST}-
make ARCH=arm CROSS_COMPILER=${MYHOST}- \
INSTALL_MOD_PATH=${MNTPNT} modules_install
|
Now you may safely unmount the ${MNTPNT}.
| Code: Unmount the Root Partition |
umount ${MNTPNT}
|
Making the Kernel Image Available to RedBoot
There are a few different options to make the linux kernel image available to RedBoot. Two of them will be addressed here, namely
- Using a local TFTP server (network)
- Using the Xmodem protocol (serial)
The preferred method is to set up a TFTP service on the local network. TFTP transfers are fast but require a TFTP server on the local network. Xmodem is the alternative - it requires nothing more than a terminal client supporting the xmodem protocol over a serial cable, but these transfers are much slower. If you plan on uploading the kernel image to boards frequently, the best option is to set up a TFTP server. There are many different terminal clients available, and one of them will be necessary on the build machine.
Creating a TFTP Root (Optional)
Open a completely new terminal window on your workstation and login as root. Emerge the TFTP server
| Code: Install a TFTP server |
TFTPROOT=/tftproot
emerge -av1 net-ftp/tftp-hpa
echo "INTFTPD_PATH=\"${TFTPROOT}\"" > /etc/conf.d/in.tftpd
echo 'INTFTPD_OPTS="-s ${INTFTPD_PATH}"' >> /etc/conf.d/in.tftpd
mkdir -p ${TFTPROOT}
cp ~/linux-2.6.23.1/arch/arm/boot/zImage /tftproot
/etc/init.d/in.tftpd restart
|
Logging in for the First Time
Loading the Linux Kernel into RAM
- With your board initially powered-off, connect it via serial cable to your workstation.
- Start a terminal client program such as minicom. Remember to set line-wrapping on (Ctrl+a,w in minicom).
- Insert your newly populated USB storage device into either of the USB ports on the TS72xx.
- Power on the board, you should see an initialization message like the one below
| Code: Powering-up the TS72xx |
>> TS-NANDBOOT, Rev 1.00 - built 14:57:51, Dec 30 2004 >> Copyright (C) 2004, Technologic Systems >> TS-BOOTROM, Rev 1.06 - built 14:21:24, Dec 5 2005 >> Copyright (C) 2005, Technologic Systems >> TS-7260: Rev E0 CPU, Rev D PLD, 64MB SDRAM >> TS-5620: detected, battery OK, time ( 12:20:34, Feb 17 2008 ) + |
- Once you see a '+' sign, hit Ctrl+c to enter the RedBoot prompt. If you miss the 2 second window to do this, then cycle the power on the board once more and try again.
Loading the Kernel via TFTP
- If you opted to use the TFTP method, you will need to set the IP address of the board from within the RedBoot prompt. This will depend on your local network topology. You should know the broadcast address, subnet mask, and the TFTP server IP address. When choosing an IP address of the board, ensure that it is not already in use on the network.
| Code: Loading the Kernel using the TFTP Protocol |
Redboot> ip_address -l <board_ip>/<netmask_len> -h <tftp_ip> Redboot> load -r -b 0x00218000 zImage-eabi |
Loading the Kernel via Xmodem
- If you opted for using Xmodem, then
| Code: Loading the Kernel using the Xmodem Protocol |
Redboot> load -r -b 0x00218000 -m xmodem |
You now have about 10 seconds to initiate the xmodem file transfer. If using Minicom,
- hit Ctrl+x,s
- navigate to the directory where your kernel image is located (hit g)
- highlight the kernel image (using up/down/space)
- hit enter
Running the Linux Kernel from RedBoot
| Code: Running the Linux Kernel from Redboot |
Redboot> exec -c "console=ttyAM0,115200 root=/dev/sda1 rootdelay=5s" |
The Initial Environment
After the Linux kernel boots up for the first time and enters the environment, the first login will not appear to be fully functional. That is actually very true. None of the familiar Gentoo init.d scripts will run. This is due to a bug in the way that bash deals with signals and foreground processes and some oddity of Python (which? there are so many!). This is a well known bug, and it can only be resolved by compiling bash natively.
First, log in as root. Then,
| Code: Some Initialization Steps |
mount -o rw,remount,noatime / mount -t proc none /proc mount -t sysfs none /sys ldconfig |
Next, you should double-check that floating-point is working with this very simple test program.
| File: Edit double_test.c |
#include <stdio.h>
#include <math.h>
int main()
{
printf( "x = %f\n", 4.0 * exp(-0.5) / sqrt(2.0) );
return 0;
}
|
Compile the test program with 'gcc -lm -o double_test double_test.c'. Run it with ./double_test. If the output variable x is 1.715528, then your floating point 'works'. If the output is zero or some other value then your floating point does not work. Did you forget to define __MAVERICK__ when building glibc?
For The Paranoid
paranoia.c still shows some areas for improvement for floating point. There are many many potential reasons that the maverick toolchain does not score 100% and they range from the maverick engine itself, to exception unwinding, etc.
Recently Cirrus has abandoned the task of providing a functional gcc for their boards with full floating point support. There is talk of a Savannah.org project to finish the job, so hopefully that will be fruitful. Two other sets of gcc patches are discussed on the Debian wiki and on the linux-cirrus list.
For The Skeptical
For lack of a better test to see whether MaverickCrunch was actually enabled, and I wasn't just being fooled by soft-float, I ran the same test that Martin Guy used. The test was to time the encoding of a 16-bit stereo 44.1 kHz WAV into a 128 kbps MP3. [11]
| Code: Output of the Lame MP3 Encoder |
ts72xx shm # cd /dev/shm && cp ~/H-lame.wav .
ts72xx shm # lame -b 128 H-lame.wav H-lame.mp3
LAME 3.97 32bits (http://www.mp3dev.org/)
Using polyphase lowpass filter, transition band: 16538 Hz - 17071 Hz
Encoding H-lame.wav to H-lame.mp3
Encoding as 44.1 kHz 128 kbps j-stereo MPEG-1 Layer III (11x) qval=3
Frame | CPU time/estim | REAL time/estim | play/CPU | ETA
1403/1403 (100%)| 2:21/ 2:21| 2:21/ 2:21| 0.2597x| 0:00
-------------------------------------------------------------------------------
kbps MS % long switch short %
128.0 100.0 92.9 4.5 2.6
Writing LAME Tag...done
ReplayGain: -51.0dB
|
Encoding the audio takes 2 minutes and 21 seconds, which is on par with Martin's tests. Thanks for the reference times Martin ;-)
Actually, when I first performed this test, the encoding time was ~ 6 minutes, which implied that lame was still relying on softfp. This implies that gcc does not actually set the default -m options when configured --with-cpu=arm920t, --with-fpu=maverick, etc, leading me to put the -m options I was expecting in the CFLAGS variable in ${SYSROOT}/etc/make.conf. If I hadn't have done this test, I probably would have gone on quasi-believing that it was actually using the MaverickCrunch fpu. All is fixed now though ;-) }}
Re-Compile Bash
We're almost there. I applaud you for getting this far! Now run the bash build script and take (several) moments to appreciate the beauty of cross-compilation (and how native/embedded compilation can be so much slower!).
| Code: Build Bash |
cd /root/bash
sh build-bash-3.2_p17-r1.sh
chsh -s /bin/ash
exit
# login again
cp bash/bash-install/bin/bash* /bin
chsh -s /bin/bash
exit
# login again
echo My SHELL is ${SHELL} - Tada'!'
qpkg -P ~ bash
rm -Rf bash
|
The chsh command is needed to change the login shell before overwriting the previous version of bash. This is necessary because bash would otherwise still be in use, resulting in a message like "cp: cannot create regular file `/bin/bash': Text file busy". It's a good thing we installed a static busybox beforehand and had that handy /bin/ash symlink!
Exit from the environment by saying 'umount / && exit', and then power down the board. Remove the USB storage device and insert it back into your workstation. Move the re-compiled bash from the board to your package repository, so that you can skip bash re-compilation next time.
| Code: Copy the Re-Compiled Bash into ${PKGDIR}/All |
mv ${MNTPNT}/root/bash-3.2_p17-r1.tbz2 \
${SYSROOT}/var/tmp/binpkgs/All
umount ${MNTPNT}
|
Logging in for the Second Time
Re-insert your USB storage device into the board and follow the instructions for booting again. This time you should notice the more familiar init sequence of a Gentoo System! The only thing preventing that in the first place was really just a bash bug. I hope one of these days that bug is fixed.
Compile the Remaining System Packages
The few remaining packages required for the 'system' group are libperl, perl, PodParser, Test-Harness, and perl-cleaner. Aside from those, I would also like to emerge the latest stable versions of tar, python, and pycrypto, since the RM160 hash can only be done with >=Python-2.5. Also, I would like to install a full GCC - with fortran,gcc,g++,and gcj support. This was quite difficult to successfully cross compile, but natively compiling should be functional, if not very time consuming.
TODO - This requires that the portage tree be either mounted via NFS or copied onto the USB device... write some steps
| Code: Emerge the Remaining Few |
emerge -av1 --nodeps libperl perl PodParser Test-Harness perl-cleaner tar python pycrypto gcc |
Packaging The 'Full' Distro
After the rest of the 'system' packages have been compiled and installed on the USB device, copy them back to ${PKGDIR}/All.
TODO ... will get to writing it shortly
Give Me the Binaries Already
Please don't forget to read
http://vaiprime.visibleassets.com/~cfriedt/binpkgs/READ and http://vaiprime.visibleassets.com/~cfriedt/toolchains/READ
Toolchain
Here is the gcc-3.4.6/glibc-2.3.2/binutils-2.15 toolchain that I use.
The files are all stored in Gentoo tbz2 format so that they can be installed using qmerge.
Installing the Toolchain
I have working toolchains for
- i686-pc-linux-gnu
- arm-unknown-linux-gnu
- armv4tl-maverick-linux-gnueabi
- amd64-pc-linux-gnu
- arm-unknown-linux-gnu
- armv4tl-maverick-linux-gnueabi
Eventually I would also like to have cross-toolchains for ppc, ppc-mac and intel-mac as well - that should hopefully cover most of the development platforms that people might be using!
| Code: Instaling the Toolchain |
CHOST=i686-pc-linux-gnu
CTARGET=armv4tl-maverick-linux-gnueabi
SRVR=http://vaiprime.visibleassets.com/~cfriedt
export PORTAGE_BINHOST=${SRVR}/toolchains/${CHOST}/${CTARGET}/All
export QMERGE=1
qmerge -fv \
cross-${CTARGET}/binutils-2.17-r1 \
cross-${CTARGET}/gcc-4.1.2 \
cross-${CTARGET}/linux-headers-2.6.23-r3 \
cross-${CTARGET}/glibc-2.5-r4 \
cross-${CTARGET}/gdb-6.7.1-r2
unset CHOST CTARGET SRVR PORTAGE_BINHOST QMERGE
|
Naturally, you should also have created and exported ${SYSROOT}, as well as ${SYSROOT}/etc/make.conf, ${SYSROOT}/etc/make.profile, ${SYSROOT}/etc/portage/package.use, ${SYSROOT}/etc/portage/package.keywords, ${SYSROOT}/etc/portage/package.unmask, ${SYSROOT}/etc/portage/package.mask, ${SYSROOT}/usr/sbin/xmerge and so on. Templates for all of those files were explained above in detail.
Host Binaries
Here are the host binaries that I've built.
They are also stored in the Gentoo tbz2 format so that they can be installed using qmerge.
Installing the Host Binaries
Assuming that you're using a TS72xx board, create the make.conf below:
| File: /etc/make.conf |
CHOST=armv4lt-maverick-linux-gnueabi PKGDIR=/tmp/binpkgs PORTAGE_TMPDIR=/tmp INSTALL_MASK="*.a *.la *.h .keep* /usr/share /usr/include /etc" PORTAGE_BINHOST="http://vaiprime.visibleassets.com/~cfriedt/binpkgs/arm-unknown-linux-gnu/All" |
Next, do the 1 time setup below:
| Code: One-Time Setup |
mkdir -p /var
cd /var
rm -Rf db cache
ln -sf ../tmp/db db
ln -sf ../tmp/cache cache
mount -t ramfs none /tmp
cd /tmp
wget http://vaiprime.visibleassets.com/~cfriedt/binpkgs/arm-unknown-linux-gnu/All/portage-utils-0.1.28.tbz2
applets="./usr/bin/qcheck ./usr/bin/qxpak ./usr/bin/qgrep ./usr/bin/q ./usr/bin/qpkg ./usr/bin/qlop \
./usr/bin/qsearch ./usr/bin/qsize ./usr/bin/qglsa ./usr/bin/qatom ./usr/bin/quse ./usr/bin/qlist \
./usr/bin/qcache ./usr/bin/qdepends ./usr/bin/qfile ./usr/bin/qtbz2 ./usr/bin/qmerge"
tar xpvjf portage-utils*tbz2 ${applets} -C /
cd / && umount /tmp
|
Each time you want to install a package, you should
| Code: Before Using Qmerge |
mount -t ramfs none /tmp mkdir -p /tmp/binpkgs /tmp/db/pkg /tmp/portage /tmp/cache export QMERGE=1 |
Note: INSTALL_MASK sometimes needs to be set on a per-package basis. It can be somewhat tricky to manage actually, which is why I've chosen the simple example below.
| Code: Example Qmerge Usage |
qmerge -KOv lzo qlist lzo qmerge -Uv lzo |
| Code: After Using Qmerge |
unset QMERGE cd / umount /tmp |
I would also strongly recommend having a read-only root filesystem. This will prevent unforeseeable writes to the flash filesystem which could extend the lifetime of the board. This basically means that before using qmerge, you would need to say remount -o remount,rw / code>, and then when you're done, say remount -o remount,ro / code>.
Where to Go From Here
I hope you enjoyed this HowTo.
The next one that I write will be detailed instructions on how to reduce the size of the 'full' filesystem to make it a 'small' filesystem, but not quite a 'tiny' filesystem.
The 'small' filesystem will still have a glibc userland and many bloated binaries (instead of using BusyBox). Although BusyBox is still installed in this distro as it is.
Perhaps before that point, I should get some work done on a 'commissioning' system, with detailed instructions on how to automate the assignment of host keys for SSH and OpenVPN so that these boards can be manufactured en masse for a distributed embedded environment. A slight challenge will be reducing the encryption level in either OpenVPN or the SSH daemon to reduce channel latency - there is definitely such a thing as encryption overkill.
The next part after that will be somehow organizing qmerge as an on-board package manager. The real challenge there is reducing the size of /var/db - at the moment it uses filesystem nodes for the database entries, which is a major waste of space. I should be able to reduce space slightly by using a db format such as sqlite (all in one file) and then applying gzip or bzip2 compression. Theoretically, it should be possible to just gzip or bzip2 compress the filesystem where the package database is located. That option will probably be an initial step since its much easier. Eventually all of this will be tied in with organizing a binary package repository (BPR) for distribution in the embedded environment and automated updates.
Finally, when that's done, I'll do everything with a uClibc userland, busybox, dropbear, etc, in order to minimize the footprint and get everything installed in ~ 4 MB!
Throughout this project I will be maintaining my own BPR. When things have reached some level of stability, then I would be very glad to open up the BPR to all ;-)
Ciao 4 Now
Links
Browse categories > Gentoo Linux Wiki > Wiki maintenance > Stub
Browse categories > Hardware > Manufacturer > Technologic Systems
Browse categories > Hardware > Motherboard
Created by NickStallman.net, Luxury Homes Australia
Real estate agents should be using interactive floor plans and list their apartments, townhouses and units.

