changeset 518:f109c324cca4

Massive documentation rewrite. Not quite finished, but better.
author Rob Landley <rob@landley.net>
date Tue, 02 Dec 2008 03:17:23 -0600
parents 89b2e2c55b28
children 1c36145a54d1
files www/about.html www/design.html www/documentation.html www/header.html www/new_platform.html
diffstat 5 files changed, 1957 insertions(+), 1207 deletions(-) [+]
line wrap: on
line diff
--- a/www/about.html	Tue Dec 02 03:02:18 2008 -0600
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,423 +0,0 @@
-<!--#include file="header.html" -->
-
-<h2>What is Firmware Linux?</h2>
-
-<p>Firmware Linux (FWL) is an embedded Linux build system designed to
-eliminate the need for cross compiling, replacing it with native
-compiling under emulation instead.</p>
-
-<p>FWL consists of a series of shell scripts which create a complete
-<a href=downloads/image>bootable linux system</a> for a given target hardware
-platform.  This provides a minimal native Linux build environment for the
-target, loosely based on <a href=http://linuxfromscratch.org>Linux From
-Scratch</a> (stripped down to an embedded variant built from busybox, uClibc,
-gcc, binutils, make, bash, and the Linux kernel).  Running this native build
-environment under an emulator such as QEMU (or on real target hardware if
-applicable) allows fully native builds for arbitrary target platforms to
-be performed on cheap and powerful commodity PC hardware.</p>
-
-<p>The currently supported target hardware platforms include arm, mips, powerpc,
-x86, and x86-64, with partial support for sh4, mips, and sparc.</p>
-
-<p>Firmware Linux is loosely based on <a href=http://linuxfromscratch.org>Linux
-From Scratch</a>, stripped down and rebased on busybox and uClibc.</p>
-
-<p>Intermediate stages of the build (such as the cross compiler and the
-unpackaged root filesystem directory) may also be useful to Linux developers,
-and are also packaged up in the build subdirectory.</p>
-
-<p>The default build provides a native development environment for each target
-platform, eliminating the need for cross compiling in favor of
-<a href="#native_compiling">native compiling under emulation</a>.</p>
-
-<h2>Using the prebuilt binaries</h2>
-
-<h3>system-image-*.tar.bz2</h3>
-
-<p>Each system-image tarball contains an ext2 root filesystem image, a kernel
-configured to run under qemu, and shell scripts to run the system (in various
-modes) under the emulator <a href=http://bellard.org/qemu/>qemu</a>.</p>
-
-<p>To test boot an FWL target system under qemu 0.9.1, download the appropriate
-<a href=downloads/image>prebuilt binary tarball</a> for the target you're
-interested in, extract it, cd into it, and execute one of the following
-shell scripts:</p>
-
-<ul>
-<li><p><b>./run-emulator.sh</b> - This boots the target Linux system under the
-appropriate emulator, with /dev/console hooked to the emulator's stdin and
-stdout.  (I.E. the shell prompt the script gives you after the boot messages is
-running in the emulator.)  Type "cat /proc/cpuinfo" to confirm you're running
-in the emulator, then play around and have fun.</p></li>
-
-<li><p><b>./run-with-home.sh</b> - Wrapper for run-emulator.sh which adds
-a second virtual hard drive mounted on /home.  (If the file "hdb.img"
-doesn't exist on the host, this script automatically creates a 2 gigabyte
-sparse file and formats it ext3.)</p></li>
-
-<li><p><b>./run-with-distcc.sh</b> - Wrapper for run-with-home.sh which
-sets up the appropriate magic so the emulator will automatically call out to
-the cross compiler on the host system via distcc.  This can significantly speed
-up build times under the emulator, while still avoiding most of the complexity
-of cross compiling.  (<a href="#distcc_trick">More info</a>)</p>
-</ul>
-
-<p>The FWL boot script for qemu (/tools/bin/qemu-setup.sh) populates /dev
-from sysfs, sets up an emulated (masquerading) network (so you can wget
-source packages or talk to <a href="#distcc_trick">distcc</a>), and creates
-a few symlinks needed to test build normal software packages (such as making
-/lib point to /tools/lib).  It also mounts /dev/hdb (or /dev/sdb) on /home
-if a second emulated drive is present.</p>
-
-<p>For most platforms, exiting the command shell will exit the emulator.
-(Some, such as powerpc, don't support this yet.  For those you have to kill
-qemu from another window, or exit the xterm.  I'm working on it.)</p>
-
-<p>To use this emulated system as a native build environment, see
-<a href="#native_compiling">native compiling</a>.</p>
-
-<h3>cross-compiler-*.tar.bz2</h3>
-
-<p>The cross compiler created during the FWL build is a relocatable C compiler
-for the target platform.  To use it on its own, download the appropraite
-<a href=downloads/cross-compiler>cross compiler tarball</a> for the host
-you're running on and the target you'd like to compile for.  Extract the
-compiler tarball and add the cross-compiler-$TARGET/bin directory to your
-$PATH, then use $TARGET-gcc as your cross compiler and "$TARGET-" as your CROSS
-prefix for packages with cross compiling support.</p>
-
-<p>For example, if you download cross-compiler-armv4l and extract it into
-your home directory, set "PATH=~/cross-compiler-armv4l/bin:$PATH",
-use armv4l-gcc to build code, and use "CROSS=armv4l-" to set your cross
-compiler prefix.</p>
-
-<p>Note that this cross compiler does not support C++.  If you need C++ support,
-use the <a href="#native_compiling">native compiling</a> environment.</p>
-
-<h3>mini-native-*.tar.bz2</h3>
-
-<p>If you want to run this system on <a href="#real_hardware">real hardware</a>,
-you'll generally have to tweak and repackage the root filesystem.  To make this
-easier, tarballs of each target's prebuilt root filesystem
-<a href=downloads/mini-native>are available</a>.</p>
-
-<p>This root filesystem is a minimal native build environment for the target
-platform.  This means it contains a compiler and associated build tools capable
-of building a complete new Linux system under itself, although you may have
-to bootstrap your way up (I.E. building things like zlib or perl before
-building momre complicated packages).</p>
-
-<p>The vast majority of the space taken up by this filesystem is the
-development toolchain and associated support files (mostly header files and
-libraries).</p>
-
-<p>If you're doing anything fancy, you'll probably want to rebuild it from
-source.</p>
-
-<h2>Building from source</h2>
-
-<p>To build FWL, download the most recent <a href=downloads>source tarball</a>,
-extract it, cd into it, and run "./build.sh".  This script takes one argument,
-which is the target to build for.  Run it with no arguments to see
-available targets.  The resulting files are created in the "build" directory,
-including all the downloadable tarballs.  (To perform a clean build,
-"rm -rf build" and re-run build.sh.)</p>
-
-<p>By default, this Linux system is a <a href=downloads/mini-native>minimal
-native build environment</a> for the target platform.  It contains a compiler
-and associated build tools capable of building a complete new Linux system under
-itself.  This is is to support <a href="#native_compiling">native compiling</a>,
-which allows you to build a new (possibly smaller) root filesystem for your
-target.</p>
-
-<p>If you don't want to bother with that, set the environment variable
-"BUILD_SHORT=1" before running the build to skip building the native
-toolchain.  This results in a much, much smaller root filesystem, and also
-moves it up out of the /tools directory, but makes adding additional
-software to the resulting system much more difficult (as it must be done
-via cross compiling).</p>
-
-<p>See <a href="#native_compiling">native compiling under emulation</a>
-and <a href="#customize">customizing mini-native</a> for more information.</p>
-
-<h2>How building from source works</h2>
-
-<h3>build.sh and forkbomb.sh</h3>
-
-<p>The build.sh script is a simple wrapper which calls the other
-scripts in sequence:</p>
-<ol>
-<li>download.sh</li>
-<li>host-tools.sh</li>
-<li>cross-compiler.sh $TARGET</li>
-<li>mini-native.sh $TARGET</li>
-<li>package-mini-native.sh $TARGET</li>
-</ol>
-
-<p>Another script, forkbomb.sh, performs a similar function but builds all
-supported targets at once.</p>
-
-<h3>The other scripts</h3>
-
-<ul>
-<li><p><b>include.sh</b> - Common functions.</p>
-
-<p>This script is not run directly, but is instead included from the other
-scripts to set up the build directory and provide common functions like
-"setupfor" and "cleanup".  See <a href="#anatomy_of_include">anatomy of
-include.sh</a> for details.</li>
-
-<li><p><b>download.sh</b> - Download source packages into sources/packages.</p>
-
-<p>This script does not take any arguments, and writes its output into the
-sources/packages directory.</p>
-
-<p>This script consists of a list of URLs and associated sha1sum values of all
-the source packages used by the build.  It calls the "download" function out
-of include.sh to wget each package from its source location (or one of the
-mirrors listed in the download function) for which the specified sha1sum
-doesn't match.  (If a package's sha1sum is set blank, any value is accepted
-and the package will only be downloaded if it doesn't exist.)</li>
-
-<p>Re-running this script will re-validate each sha1sum, but won't download
-new packages as long as the sha1sums match.  It automatically deletes any files
-from sources/packages which are no longer listed in the download script, such
-as old package versions.</p>
-
-<li><p><b>host-tools.sh</b> - Compile various packages to be used during the
-build, installing them into build/host.</p>
-
-<p>This script does not take any arguments.  In theory this is an optional
-step, and may be omitted.  (In practice, package-mini-native.sh currently needs
-User Mode Linux and won't run without it.  See the description of that script
-for details.)</p>
-
-<p>The primary purpose of the host-tools.sh script is to isolate the build from
-dependencies on the host distribution.  It does this by building host versions
-of the same command line utilities that will exist in the final mini-native
-development environment, and by creating symlinks to the host versions of the
-remaining tools (thus enumerating exactly which ones those are).</p>
-
-<p>This allows build.sh set the $PATH to point only to the build/host directory,
-so no other tools from the host are used.  (In reality, a few such as /bin/bash
-are referred to by absolute path, but it's not a big issue.)  This helps to
-ensure that the resulting Linux system can rebuild itself under itself,
-because it already did.</p>
-
-<p>A secondary purpose of host-tools.sh is to build packages (such as distcc
-and User Mode Linux) which may not be installed on the host system.</p>
-
-<p>Note that this script no longer attempts to build qemu, due to the
-unreasonable requirement of installing gcc 3.x on the host.  The FWL build
-scripts do not use qemu (except as an optional test at the end of
-cross-compiler.sh which is skipped if qemu is not available).  You will need
-to install qemu (or find real hardware) to run the resulting images, but they
-should build just fine without it.</p>
-
-<p>See <a href="#anatomy_of_host_tools">anatomy of host-tools.sh</a> for
-more information.</p>
-
-<p>Currently, host-tools.sh builds toybox and busybox, and creates symlinks to
-the host's compiler toolchain (ar, as, nm, cc, gcc, make, ld), plus a few
-utilities that still need to be added to toybox (bzip2, find, install, od,
-sort, diff).  Note that until that last category is eliminated, rebuilding the
-system under itself requires natively building and installing the bzip2,
-coreutils, and diffutils packages as a bootstrapping step.</li>
-
-<li><p><b>cross-compiler.sh</b> - Build a cross compiler (binutils, gcc, uClibc,
-linux kernel headers, and a wrapper script).
-
-<p>This script takes one argument: the architecture to build for.</p>
-
-
-
-<p>Along the way, the build produces a
-<a href=downloads/cross-compiler>relocatable cross compiler for the target
-hardware</a>.  Additional packages can be added to 
-
-However, cross compiling additional packages is
-<a href=/writing/docs/cross-compiling.html>not recommended</a> because
-the defaultroot filesystem of the bootable system contains development
-tools, and can act as a <a href=downloads/mini-native>native build
-environment</a> capable of compiling software on the target.  (To overcome
-most of the speed penalty of emulation, use
-<a href="#distcc_trick">run-with-distcc.sh</a> script.)</p>
-
-<p>Thus the easy way to build software for a target is to compile
-
-To use FWL, download...
-
-<p>This bootable Linux system contains development tools, and can act as a
-<a href=downloads/mini-native>minimal native build environment</a>.  If you
-run it under an emulator (or on real hardware) you can compile
-  Along the way, the build produces a
-<a href=downloads/cross-compiler>relocatable cross compiler for the target
-hardware</a>, and also a <a href=downloads/mini-native>native build
-environment</a> capable of compiling software on the target.</p>
-
-<p>The build system is a series of shell scripts which download, compile,
-install, and use the appropriate source packages to generate the output files.
-These shell scripts are designed to be easily read and modified.</p>
-
-<p>The system built by these scripts consists of the following source
-packages:</p>
-
-<ul>
-<li>linux 2.6.25</li>
-<li>busybox 1.2.2</li>
-<li>uclibc 0.9.29</li>
-<li>gcc 4.1.2</li>
-<li>binutils 2.17</li>
-<li>make 3.81</li>
-<li>bash 2.05b</li>
-</ul>
-
-<p>Firmware Linux is licensed under GPL version 2.  Its component packages are
-licensed under their respective licenses (mostly GPL and LGPL).</p>
-
-<h2>How do I use it?</h2>
-
-<p><b>build.sh</b>: Start here.  This is the master script which runs all the
-other build stages.  It takes one argument, the platform to build for.  (Run it
-with no arguments to see a list of supported platforms.)  The individual stage
-scripts can also be run individually, with the same argument as build.sh.</p>
-
-<p><b>download.sh</b>: This script checks the sources/packages directory for
-source tarballs, and downloads any that are missing or have invalid SHA1
-checksums.  It also deletes any old files in sources/packages not used by the
-current build version, and populates sources/build-links with
-version-independent symlinks for use by later build stages.</p>
-
-<p><b>cross-compiler.sh</b>: This script produces a cross compiler for the
-indicated target platform.  The working copy is produced in the build
-directory, and a copy is saved as "cross-compiler-$ARCH.tar.bz2" for use
-outside the build system.  This cross compiler is fully relocatable (using the
-wrapper script in sources/toys/gcc-uClibc.c), so and any normal user can
-extract it into their home directory, add cross-compiler-$ARCH/bin to their
-$PATH, and run $ARCH-gcc to create target binaries.  It contains gcc, binutils,
-linux kernel headers, and the uClibc C library.</p>
-
-<p>The cross compiler script also builds squashfs tools, a target platform
-emulator (QEMU), and uses the emulator to confirm that the cross compiler
-works.  This script can take an optional first argument, <b>--short</b>, to
-skip those steps.  This is useful if you want to build several cross compilers
-without multiple copies of QEMU.  (The short build will also delete the
-build/cross-compiler-$ARCH directory after tarring it up, since the result
-isn't usable by later build stages.)</p>
-
-<p><b>mini-native.sh</b>: This script uses the cross compiler to create
-a minimal native build environment for the target platfrom.  This native
-environment consists of just seven packages: busybox, uClibc, the linux kernel,
-gcc, binutils, make, and bash.  This is a fully self-hosting development
-environment, capable of rebuilding itself from source code, organized as a
-<a href=http://www.linuxfromscratch.org>Linux From Scratch</a> /tools
-directory.  It also produces a bootable Linux kernel for the target platform,
-and packages the /tools directory as a squashfs image for use by QEMU.</p>
-
-<p><b>package-mini-native.sh</b>: This script creates an ext2 filesystem image
-for use with qemu.  It currently does this using a User Mode Linux image
-created by the host-tools.sh script.</p>
-
-<p><b>sources/native/setup.sh</b>: A test script to run inside the native
-environment.  Mounts /proc and /sys, populates /dev, switches to a shell with
-command history, etc.  (Not quite a substitute for a real init script, but
-something to play with.)</p>
-
-<p><b>More to come...</b></p>
-
-<h2><a name="native_compiling">Native compiling under emulation</a></h2>
-
-Why do this?
-the distcc trick
-  run-with-distcc.sh
-hdb for working space.
-  run-with-home.sh
-  Building on nfs sucks rocks.
-  Building out of tree with cp -rs
-
-/tools (Linux From Scratch chapter 5).
-  qemu-setup.sh and the /lib symlink.
-
-Deficiencies in the current mini-native filesystem:
-  host-tools.sh, bzip2, coreutils, diffutils.
-
-Building glibc is your problem.
-  It requires perl.  Statically linking "hello world" is 400k.  It's evil.
-  Still, building it natively sucks less than trying to cross compile it.
-  Pretty much follow the non-cross Linux From Scratch procedures.
-
-Building a distro:
-  Linux From Scratch.
-  Gentoo embedded.
-  Debian/ubuntu.
-
-
-anatomy_of_include
-
-<h2><a name="anatomy_of_host_tools">Anatomy of host-tools.sh</a></h2>
-
-<p>Currently, host-tools.sh builds toybox and busybox 1.2.2.  Eventually,
-toybox should completely replace busybox.</p>
-
-<p>It creates symlinks to the host's compiler toolchain, specifically seven
-executalbes: ar, as, nm, cc, gcc, make, ld.</p>
-
-<p>It also creates symlinks to a few utilities that need to be added to toybox.
-Currently, this list is: bzip2, find, install, od, sort, diff.</p>
-
-<p>Note that until that last category is eliminated, rebuilding the
-system under itself requires natively building and installing the bzip2,
-coreutils, and diffutils packages as a bootstrapping step.</li>
-
-<h2><a name="customize">Customizing mini-native</a></h2>
-
-<p>If you don't want to build the native toolchain, set the environment
-variable "BUILD_SHORT=1" before running the build.  This results in a much, much
-smaller root filesystem, and also moves it up out of the /tools directory.
-But it eliminates</p>
-
-
-
-<p>The default <a href=downloads/mini-native>mini-native</a> root filesystem
-is modeled after Linux From Scratch chapter 5.  (This is why it
-lives in a <a href=http://www.linuxfromscratch.org/lfs/view/stable/chapter04/creatingtoolsdir.html>/tools directory</a>.)</p>
-
-BUILD_QUICK
-Not in /tools
-Adding packages (to the script, without the script)
-
-
-build/temp-$ARCH
-build/cross-compiler-$ARCH
-build/mini-native-$ARCH
-build/qemu-image-*.tar
-
-
-<h2><a name="real_hardware">Running on real hardware</a></h2>
-
-<p>To run a system on real hardware (not just under an emulator), you need to
-do several things:</p>
-
-<ol>
-<li>Figure out how to flash your device (often a jtag with openocd)</li>
-<li>Configure and install a bootloader (uboot, apex, etc.)</li>
-<li>Build and install a kernel targeted to your hardware (in the kernel source,
-see arch/$ARCH/configs for default .config files for various boards)</li>
-<li>Package and install the root filesystem appropriately for your system
-(ext2, initramfs, jffs2).</li>
-</ol>
-
-<h2>License</h2>
-
-<p>Firmware Linux is licensed under GPL version 2.  This means that the build
-scripts are licensed under GPL version 2, and each of the component packages
-of the default "mini-native" root filesystem may be redistributed under the
-terms of GPLv2 (and in the case of uClibc, LGPLv2).</p>
-
-<p>Adding your own packages to the resulting system is generally "mere
-aggregation" (see the last paragraph of section 2), and thus not my
-problem.  This license statement is not intended to apply to your packages
-as long as they are not derived works of existing GPLv2 code.</p>
-
-
-<!--#include file="footer.html" -->
--- a/www/design.html	Tue Dec 02 03:02:18 2008 -0600
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,651 +0,0 @@
-<!--#include file="header.html" -->
-
-<h1>The Firmware Linux build process</h1>
-
-<h1>Overview</h1>
-
-<h2>User Interface</h2>
-
-<p>The script "./<b>build.sh</b>" calls the other scripts in the correct
-sequence to perform a full build for one or more architectures.  Its argument
-is the architecture to build, and running it without arguments lists the
-available architectures.  (Configuration information for each architecture is
-in the sources/targets directory.)</p>
-
-<p>Each stage can also be run (or re-run) individually.  The individual stages
-are described in the next section.</p>
-
-<p>
-
-<p>The script "<b>sources/forkbomb.sh</b>" builds all architectures at once.
-Its command line arguments specify whether to build them in series (--nofork) or in
-parallel (--fork).  The output of each architecture's build is saved in a log
-file named "out-$ARCH.txt".  A quick scan of each log for success or failure
-is available with "./forkbomb.sh --stat".  Run it with no arguments to see
-all available options.</p>
-
-<p>Setting the following environment variables to non-blank values can modify
-the behavior of the build:</p>
-
-<ul>
-<li><p><b>NATIVE_NOTOOLCHAIN</b> - This tells mini-native.sh not to
-include a compiler toolchain (binutils, gcc, bash, make, and distcc), but
-instead just build a small uClibc/busybox system.</p>
-
-<p>Setting NATIVE_NOTOOLCHAIN="headers" will leave the libc and kernel
-header files in the appropriate include directory, for use by a compiler such
-as pcc, llvm/clang, or tinycc.  (Building and installing additional tools
-such as "make" remains your problem.)</p>
-</li>
-
-<li><p><b>NATIVE_NOTOOLSDIR</b> - Path to the top level directory within
-the native filesystem.  If this is blank, configure sets this to a default value
-of "/tools", to act as a Linux From Scratch style chroot environment.  For
-a more traditional filesystem layout, set this to "/" or to "/usr".</p></li>
-
-<li><p><b>FWL_RECORD_COMMANDS</b> - Records all command lines used to build each
-package.</p>
-
-<p>Tells host-tools.sh to build a logging wrapper (sources/toys/wrappy.c) and
-populate a directory (build/wrapper) with symlinks to that wrapper for each
-command name in $PATH.  This allows later build stages to write log files in
-the build directory (named "cmdlines.${STAGE_NAME}.${PACKAGE_NAME}") recording
-each command run.  (When build/wrapper exists, include.sh sets the wrapper
-control variables $WRAPPY_LOGDIR, $WRAPPY_LOGPATH, and $WRAPPY_REALPATH,
-then adjusts $PATH to point to the wrapper directory, which makes the wrapper
-append to the appropriate log file before calling the actual command.)</p>
-
-<p>Afterwards, the script "sources/toys/report_recorded_commands.sh" can
-generate a big report on which commands were used to build each package for
-each architecture.  To get a single list of the command names used by
-everything, do:</p>
-
-<blockquote>
-<p>echo $(find build -name "cmdlines.*" | xargs awk '{print $1}' | sort -u)</p>
-</blockquote>
-
-<p>(Note: this will miss things which which call executables at absolute values
-instead of checking $PATH, but the only interesting ones so far are the
-#!/bin/bash type lines at the start of shell scripts.)</p>
-</li>
-
-<li><p><b>CROSS_BUILD_STATIC</b> - Tells cross-compiler.sh to statically link all
-binaries in the cross compiler toolchain it creates.</p>
-
-<p>The prebuilt binary versions in the download directory are statically linked
-against uClibc, by building a mini-native environment and re-running the build
-under that with BUILD_STATIC=1.</p></li>
-
-<li><p><b>FWL_PREFERRED_MIRROR</b> - Tells download.sh to try to download
-packages from this URL first, before falling back to the normal mirror list.
-For example, "FWL_PREFERRED_MIRROR=http://landley.net/code/firmware/mirror".</p></li>
-
-<li><p><b>FWL_USE_TOYBOX</b> - Tells the host-tools.sh and mini-native.sh to
-install the <a href=http://landley.net/code/toybox>toybox</a> implementation
-of commands (where available) instead of the busybox versions.</p></li>
-</ul>
-
-<h1>Implementation</h1>
-
-<p>The top level wrappers (<b>build.sh</b> or <b>forkbomb.sh</b>) call the
-other stages in sequence.  The other stages are <b>download.sh</b>,
-<b>host-tools.sh</b>, <b>cross-compiler.sh</b>, <b>mini-native.sh</b>, and
-<b>package-mini-native.sh</b>.  Each script sources the common file
-<b>include.sh</b>.</p>
-
-<p>In theory, the stages are othogonal.  If you have an existing cross
-compiler, you can add it to the $PATH and skip cross-compiler.sh.  Or you
-can use _just_ cross-compiler.sh to create a cross compiler, and then go build
-something else with it.  The host-tools.sh stage can often be skipped
-entirely.</p>
-
-<h2>Stage 0: Setup</h2>
-
-<p>Before building anything we're going to keep, we need to do some setup
-work.</p>
-
-<ul>
-<li><p><b>include.sh</b> - header file defining common environment variables
-and functions, and performing other miscelanous setup.</li>
-
-<p>This script is not run directly, instead it's included from all the other
-scripts.</p>
-
-<p>For building packages, this file defines the functions:</p>
-<ul>
-<li><p><b>setupfor</b> - extracts a source package (named in the first
-argument) into a temporary directory, and changes the current directory
-to there.</p>
-
-<p>Source code is cached, meaning each package's source tarball is only
-actually extracted once (into build/sources) and the temporary copies
-are directories full of hard links to the cached source.</p>
-</li>
-
-<li><p><b>cleanup</b> - delete temporary copy of source code after build.</p>
-</li>
-</ul>
-
-<li><p><b>download.sh</b> - Download source code packages from the web.</p>
-
-<p>This file is a series of calls to the <b>download</b> function (defined in
-include.sh).  If an existing copy of the tarball matching the sha1sum $SHA1
-doesn't currently exist in the sources/packages directory, it uses wget to
-fetch it from $URL (or a series of fallback mirrors).</p>
-
-<p>A blank value for $SHA1 will accept any file as correct, ignoring its
-contents.</p>
-
-<p>After downloading all tarballs, the function <b>cleanup_oldfiles</b> deletes
-any old files (meaning any files in sources/packages with a timestamp
-before the call to download.sh, such as previous versions left over
-after a package upgrade).</p>
-
-<p>Running this stage with the argument "--extract-all" will extract all
-the tarballs, to preopulate the cache used by setupfor.  (This is primarily
-used to avoid race conditions in forkbomb.sh --fork.)</p>
-
-<li><p><b>host-tools.sh</b> - Set up a known environment on the host</p>
-
-<p>This script populates the <b>build/host</b> directory with
-host versions of the busybox and toybox command line tools (the same ones
-that the target's eventual root filesystem will contain), plus symlinks to the
-host's compiler toolchain.</p>
-
-<p>This allows the calling scripts to trim the $PATH to point to just this
-one directory, which serves several purposes:</p>
-
-<ul>
-
-<li><p><b>Isolation</b> - This prevents the ./configure stages of the source
-packages from finding and including unexpected dependencies on random things
-installed on the host.</p></li>
-
-<li><p><b>Portability</b> - Using a known set of command line utilities
-insulates the build from variations in the host's Linux distribtion (such as
-Ubuntu's /bin/echo lacking suport for the -e option).</p></li>
-
-<li><p><b>Testing</b> - It ensures the resulting system can rebuild itself
-under itself, since the initial build was done with the same tools we
-install into the target's root filesystem.  The initial build acts as a smoke
-test of most of the packages used to create the resulting system, and
-restricting $PATH ensures that no necessary commands are missing.  (Variation
-can still show up between x86/arm/powerpc versions, of course.)</p></li>
-
-<li><p><b>Enumeration</b> - The RECORD_COMMANDS functionality (see
-environment variables, above) starts here and continues into the later build
-scripts.</p></li>
-</ul>
-
-<p>This stage is optional.  You don't need to run this stage if you don't
-want to.  If the build/host directory doesn't exist (or doesn't contain
-a "busybox" executable), the build will use the host's original $PATH.</p>
-</ul>
-
-<h2>Stage 1: Build a cross-compiler.</h2>
-
-<ul>
-<li><p><b>cross-compiler.sh</b> - build a cross compiler for a target.</p></li>
-
-<p>This script builds a cross-compiler, which runs on the host system and
-produces binaries that run on the target system.  (See my
-<a href=http://landley.net/writing/docs/cross-compiling.html>Introduction to
-cross compiling</a> if you're unfamiliar with cross compiling.)</p>
-
-<p>The build requires a cross-compiler even if the host and target system are
-both x86, because the host usually uses different C libraries.  If the host has
-glibc and the target uses uClibc, then the (dynamically linked) target binaries
-we produce won't run on the host.  (Target binaries that won't run on the
-host are what distinguishes cross-compiling from native compiling.  Different
-processors are just one reason for it.)</p>
-
-<p>Building a cross-compiler toolchain requires four packages: binutils,
-gcc, uClibc, and the linux kernel (for header files).</p>
-
-</ul>
-
-<h2>Stage 2: Cross compile a bootable target system.</h2>
-
-<ul>
-<li><p><b>mini-native.sh</b> - Build a minimal native development environment
-for the target system.</p>
-
-<p>This script uses the cross compiler from the previous step to build a kernel
-and root filesystem for the target, including a native compiler toolchain.
-The resulting system should boot and run on the target, or under an
-appropriate emulator.</p>
-
-<p>Because cross-compiling is persnickety and difficult, we do as little of
-it as possible.  Instead we use the cross-compiler to generate the smallest
-possible native build environment for the target, and then run the rest of the
-build in that environment, under an emulator.</p>
-
-<p>This script should perform all the cross compiling anyone ever
-needs to do.  It uses the cross-compiler to generate the simplest possible
-native build environment for the target which is capable of rebuilding itself
-under itself.</p>
-
-<p>Anything else that needs to be built for the target can then be built natively,
-by running this kernel and root filesystem under an emulator and building
-new packages there, bootstrapping up to a full system if necessary.</p>
-
-<p>The emulator we use is QEMU.  The minimal build environment powerful enough
-to boot and compile a complete Linux system requires seven packages: the Linux
-kernel, binutils, gcc, uClibc, BusyBox, make, and bash.  It's packaged
-using the <a href=http://www.linuxfromscratch.org>Linux From Scratch</a>
-/tools directory approach, staying out of the way so the minimal build
-environment doesn't get mixed into the final system.</p>
-
-</li>
-</ul>
-
-<h2>Stage 3: Run the target's native build environment under an emulator to
-build the final system.</h2>
-
-<p>Running a native build under QEMU is much slower than cross-compiling,
-but it's a lot easier and more reliable.</p>
-
-<p>A trick to accelerate the build is to use distcc to call out to the
-cross-compiler, feeding the results back into the emulator through the virtual
-network.  (This is still a TODO item.)</p>
-
-<p>The actual build run under stange 3 can be a fairly straightforward
-<a href=http://www.linuxfromscratch.org>Linux From Scratch</a> approach,
-or another source based Linux build system like Gentoo.</p>
-
-<h2>Stage 4: Package the system into a firmware file.</h2>
-
-<p>The reason for the name Firmware Linux is that the entire operating system
-(kernel, initramfs, and read-only squashfs root filesystem) are glued together
-into a single file.  A modified version of LILO is included which can boot and
-run this file on x86.</p>
-
-<hr>
-
-<h1>Evolution of the firmware Linux build process.</h1>
-
-<h2>The basic theory</h2>
-
-<p>The Linux From Scratch approach is to build a minimal intermediate system
-with just enough packages to be able to compile stuff, chroot into that, and
-build the final system from there.  This isolates the host from the target,
-which means you should be able to build under a wide variety of distributions.
-It also means the final system is built with a known set of tools, so you get
-a consistent result.</p>
-
-<p>A minimal build environment consists of a C library, a compiler, and BusyBox.
-So in theory you just need three packages:</p>
-
-<ul>
-  <li>A C library (uClibc)</li>
-  <li>A toolchain (tcc)</li>
-  <li>BusyBox</li>
-</ul>
-
-<p>Unfortunately, that doesn't work yet.</p>
-
-<h2>Some differences between theory and reality.</h2>
-
-<h3>Environmental dependencies.</h3>
-
-<p>Environmental dependencies are things that need to be installed before you
-can build or run a given package.  Lots of packages depend on things like zlib,
-SDL, texinfo, and all sorts of other strange things.  (The GnuCash project
-stalled years ago after it released a version with so many environmental
-dependencies it was impossible to build or install.  Environmental dependencies
-have a complexity cost, and are thus something to be minimized.)</p>
-
-<p>A good build system will scan its environment to figure out what it has
-available, and disable functionality that depends on stuff that isn't
-available.  (This is generally done with autoconf, which is disgusting but
-suffers from a lack of alternatives.)  That way, the complexity cost is
-optional: you can build a minimal version of the package if that's all you
-need.</p>
-
-<p>A really good build system can be told that the environment
-it's building in and the environment the result will run in are different,
-so just because it finds zlib on the build system doesn't mean that the
-target system will have zlib installed on it.  (And even if it does, it may not
-be the same version.  This is one of the big things that makes cross-compiling
-such a pain.  One big reason for statically linking programs is to eliminate
-this kind of environmental dependency.)</p>
-
-<p>The Firmware Linux build process is structured the way it is to eliminate
-as many environmental dependencies as possible.  Some are unavoidable (such as
-C libraries needing kernel headers or gcc needing binutils), but the
-intermediate system is the minimal fully functional Linux development
-environment I currently know how to build, and then we switch into that and
-work our way back up from there by building more packages in the new
-environment.</p>
-
-<h3>Resolving environmental dependencies.</h3>
-
-<p><b>To build uClibc you need kernel headers</b> identifying the syscalls and
-such it can make to the OS.  Way back when you could use the kernel headers
-straight out of the Linux kernel 2.4 tarball and they'd work fine, but sometime
-during 2.5 the kernel developers decided that exporting a sane API to userspace
-wasn't the kernel's job, and stopped doing it.</p>
-
-<p>The 0.8x series of Firmware Linux used
-<a href=http://ep09.pld-linux.org/~mmazur/linux-libc-headers/>kernel
-headers manually cleaned up by Mariusz Mazur</a>, but after the 2.6.12 kernel
-he had an attack of real life and fell too far behind to catch up again.</p>
-
-<p>The current practice is to use the Linux kernel's "make headers_install"
-target, created by David Woodhouse.  This runs various scripts against the
-kernel headers to sanitize them for use by userspace.  This was merged in
-2.6.18-rc1, and was more or less debugged by 2.6.19.  So can use the Linux
-Kernel tarball as a source of headers again.</p>
-
-<p>Another problem is that the busybox shell situation is a mess with four
-implementations that share little or no code (depending on how they're
-configured).  The first question when trying to fix them is "which of the four
-do you fix?", and I'm just not going there.  So until bbsh goes in we
-<b>substitute bash</b>.</p>
-
-<p>Finally, <b>most packages expect gcc</b>.  The tcc project isn't a drop-in
-gcc replacement yet, and doesn't include a "make" program.  Most importantly,
-tcc development appears stalled because Fabrice Bellard's other major project
-(qemu) is taking up all his time these days.  In 2004 Fabrice
-<a href=http://fabrice.bellard.free.fr/tcc/tccboot.html>built a modified Linux
-kernel with tcc</a>, and
-<a href=http://fabrice.bellard.free.fr/tcc/tccboot_readme.html>listed</a>
-what needed to be upgraded in TCC to build an unmodified kernel, but
-since then he hardly seems to have touched tcc.  Hopefully, someday he'll get
-back to it and put out a 1.0 release of tcc that's a drop-in gcc replacment.
-(And if he does, I'll add a make implementation to toybox so we don't need
-to use any of the gnu toolchain).  But in the meantime the only open source
-compiler that can build a complete Linux system is still the gnu compiler.</p>
-
-<p>The gnu compiler actually consists of three packages <b>(binutils, gcc, and
-make)</b>, which is why it's generally called the gnu "toolchain".  (The split
-between binutils and gcc is for purely historical reasons, and you have
-to match the right versions with each other or things break.)</p>
-
-<p>This means that to compile a minimal build environment, you need seven
-packages, and to actually run the result we use an eighth package (QEMU).</p>
-
-<p>This can actually be made to work.  The next question is how?</p>
-
-<h2>Additional complications</h2>
-
-<h3>Cross-compiling and avoiding root access</h3>
-
-<p>The first problem is that we're cross-compiling.  We can't help it.
-You're cross-compiling any time you create target binaries that won't run on
-the host system.  Even when both the host and target are on the same processor,
-if they're sufficiently different that one can't run the other's binaries, then
-you're cross-compiling.  In our case, the host is usually running both a
-different C library and an older kernel version than the target, even when
-it's the same processor.</p>
-
-<p>The second problem is that we want to avoid requiring root access to build
-Firmware Linux.  If the build can run as a normal user, it's a lot more
-portable and a lot less likely to muck up the host system if something goes
-wrong.  This means we can't modify the host's / directory (making anything
-that requires absolute paths problematic).  We also can't mknod, chown, chgrp,
-mount (for --bind, loopback, tmpfs)...</p>
-
-<p>In addition, the gnu toolchain (gcc/binutils) is chock-full of hardwired
-assumptions, such as what C library it's linking binaries against, where to look
-for #included headers, where to look for libraries, the absolute path the
-compiler is installed at...  Silliest of all, it assumes that if the host and
-target use the same processor, you're not cross-compiling (even if they have
-a different C library and a different kernel, and even if you ./configure it
-for cross-compiling it switches that back off because it knows better than
-you do).  This makes it very brittle, and it also tends to leak its assumptions
-into the programs it builds.  New versions may someday fix this, but for now we
-have to hit it on the head repeatedly with a metal bar to get anything remotely
-useful out of it, and run it in a separate filesystem (chroot environment) so
-it can't reach out and grab the wrong headers or wrong libraries despite
-everything we've told it.</p>
-
-<p>The absolute paths problem affects target binaries because all dynamically
-linked apps expect their shared library loader to live at an absolute path
-(in this case /lib/ld-uClibc.so.0).  This directory is only writeable by root,
-and even if we could install it there polluting the host like that is just
-ugly.</p>
-
-<p>The Firmware Linux build has to assume it's cross-compiling because the host
-is generally running glibc, and the target is running uClibc, so the libraries
-the target binaries need aren't installed on the host.  Even if they're
-statically linked (which also mitigates the absolute paths problem somewhat),
-the target often has a newer kernel than the host, so the set of syscalls
-uClibc makes (thinking it's talking to the new kernel, since that's what the
-ABI the kernel headers it was built against describe) may not be entirely
-understood by the old kernel, leading to segfaults.  (One of the reasons glibc
-is larger than uClibc is it checks the kernel to see if it supports things
-like long filenames or 32-bit device nodes before trying to use them.  uClibc
-should always work on a newer kernel than the one it was built to expect, but
-not necessarily an older one.)</p>
-
-<h2>Ways to make it all work</h2>
-
-<h3>Cross compiling vs native compiling under emulation</h3>
-
-<p>Cross compiling is a pain.  There are a lot of ways to get it to sort of
-kinda work for certain versions of certain packages built on certain versions
-of certain distributions.  But making it reliable or generally applicable is
-hard to do.</p>
-
-<p>I wrote an <a href=/writing/docs/cross-compiling.html>introduction
-to cross-compiling</a> which explains the terminology, plusses and minuses,
-and why you might want to do it.  Keep in mind that I wrote that for a company
-that specializes in cross-compiling.  Personally, I consider cross-compiling
-a necessary evil to be minimized, and that's how Firmware Linux is designed.
-We cross-compile just enough stuff to get a working native build environment
-for the new platform, which we then run under emulation.</p>
-
-<h3>Which emulator?</h3>
-
-<p>The emulator Firmware Linux 0.8x used was User Mode Linux (here's a
-<a href=http://www.landley.net/writing/docs/UML.html>UML mini-howto</a> I wrote
-while getting this to work).  Since we already need the linux-kernel source
-tarball anyway, building User Mode Linux from it was convenient and minimized
-the number of packages we needed to build the minimal system.</p>
-
-<p>The first stage of the build compiled a UML kernel and ran the rest of the
-build under that, using UML's hostfs to mount the parent's root filesystem as
-the root filesystem for the new UML kernel.  This solved both the kernel
-version and the root access problems.  The UML kernel was the new version, and
-supported all the new syscalls and ioctls and such that the uClibc was built to
-expect, translating them to calls to the host system's C library as necessary.
-Processes running under User Mode Linux had root access (at least as far as UML
-was concerned), and although they couldn't write to the hostfs mounted root
-partition, they could create an ext2 image file, loopback mount it, --bind
-mount in directories from the hostfs partition to get the apps they needed,
-and chroot into it.  Which is what the build did.</p>
-
-<p>Current Firmware Linux has switched to a different emulator, QEMU, because
-as long as we're we're cross-compiling anyway we might as well have the
-ability to cross-compile for non-x86 targets.  We still build a new kernel
-to run the uClibc binaries with the new kernel ABI, we just build a bootable
-kernel and run it under QEMU.</p>
-
-<p>The main difference with QEMU is a sharper dividing line between the host
-system and the emulated target.  Under UML we could switch to the emulated
-system early and still run host binaries (via the hostfs mount).  This meant
-we could be much more relaxed about cross compiling, because we had one
-environment that ran both types of binaries.  But this doesn't work if we're
-building an ARM, PPC, or x86-64 system on an x86 host.</p>
-
-<p>Instead, we need to sequence more carefully.  We build a cross-compiler,
-use that to cross-compile a minimal intermediate system from the seven packages
-listed earlier, and build a kernel and QEMU.  Then we run the kernel under QEMU
-with the new intermediate system, and have it build the rest natively.</p>
-
-<p>It's possible to use other emulators instead of QEMU, and I have a todo
-item to look at armulator from uClinux.  (I looked at another nommu system
-simulator at Ottawa Linux Symposium, but after resolving the third unnecessary
-environmental dependency and still not being able to get it to finish compiling
-yet, I gave up.  Armulator may be a patch against an obsolete version of gdb,
-but I could at least get it to build.)</p>
-
-<h1>Packaging</h1>
-
-<p>The single file packaging combines a linux kernel, initramfs, squashfs
-partition, and cryptographic signature.</p>
-
-<p>In Linux 2.6, the kernel and initramfs are already combined into a single
-file.  At the start of this file is either the obsolete floppy boot sector
-(just a stub in 2.6), or an ELF header which has 12 used bytes followed by 8
-unused bytes.  Either way, we can generally use the 4 bytes starting at offset
-12 to store the original length of the kernel image, then append a squashfs
-root partition to the file, followed by a whole-file cryptographic
-signature.</p>
-
-<p>Loading an ELF kernel (such as User Mode Linux or a non-x86 ELF kernel)
-is controlled by the ELF segments, so the appended data is ignored.
-(Note: don't strip the file or the appended data will be lost.)  Loading an x86
-bzImage kernel requires a modified boot loader that can be told the original
-size of the kernel, rather than querying the current file length (which would
-be too long).  Hence the patch to Lilo allowing a "length=xxx" argument in the
-config file.</p>
-
-<p>Upon boot, the kernel runs the initramfs code which finds the firmware
-file.  In the case of User Mode Linux, the symlink /proc/self/exe points
-to the path of the file.  A bootable kernel needs a command line argument
-of the form firmware=device:/path/to/file (it can lookup the device in
-/sys/block and create a temporary device node to mount it with; this is
-in expectation of dynamic major/minor happening sooner or later).
-Once the file is found, /dev/loop0 is bound to it with an offset (losetup -o,
-with a value extracted from the 4 bytes stored at offset 12 in the file), and
-the resulting squashfs is used as the new root partition.</p>
-
-<p>The cryptographic signature can be verified on boot, but more importantly
-it can be verified when upgrading the firmware.  New firmware images can
-be installed beside old firmware, and LILO can be updated with boot options
-for both firmware, with a default pointing to the _old_ firmware.  The
-lilo -R option sets the command line for the next boot only, and that can
-be used to boot into the new firmware.  The new firmware can run whatever
-self-diagnostic is desired before permanently changing the default.  If the
-new firmware doesn't boot (or fails its diagnostic), power cycle the machine
-and the old firmware comes up.  (Note that grub does not have an equivalent
-for LILO's -R option; which would mean that if the new firmware doesn't run,
-you have a brick.)</p>
-
-<h2>Filesystem Layout</h2>
-
-<p>Firmware Linux's directory hierarchy is a bit idiosyncratic: some redundant
-directories have been merged, with symlinks from the standard positions
-pointing to their new positions.  On the bright side, this makes it easy to
-make the root partition read-only.</p>
-
-<h3>Simplifying the $PATH.</h3>
-
-<p>The set "bin->usr/bin, sbin->usr/sbin, lib->usr/lib" all serve to consolidate
-all the executables under /usr.  This has a bunch of nice effects: making a
-a read-only run-from-CD filesystem easier to do, allowing du /usr to show
-the whole system size, allowing everything outside of there to be mounted
-noexec, and of course having just one place to look for everything.  (Normal
-executables are in /usr/bin.  Root only executables are in /usr/sbin.
-Libraries are in /usr/lib.)</p>
-
-<p>For those of you wondering why /bin and /usr/sbin were split in the first
-place, the answer is it's because Ken Thompson and Dennis Ritchie ran out
-of space on the original 2.5 megabyte RK-05 disk pack their root partition
-lived on in 1971, and leaked the OS into their second RK-05 disk pack where
-the user home directories lived.  When they got more disk space, they created
-a new direct (/home) and moved all the user home directories there.</p>
-
-<p>The real reason we kept it is tradition.  The execuse is that the root
-partition contains early boot stuff and /usr may get mounted later, but these
-days we use initial ramdisks (initrd and initramfs) to handle that sort of
-thing.  The version skew issues of actually trying to mix and match different
-versions of /lib/libc.so.* living on a local hard drive with a /usr/bin/*
-from the network mount are not pretty.</p>
-
-<p>I.E. The seperation is just a historical relic, and I've consolidated it in
-the name of simplicity.</p>
-
-<p>On a related note, there's no reason for "/opt".  After the original Unix
-leaked into /usr, Unix shipped out into the world in semi-standardized forms
-(Version 7, System III, the Berkeley Software Distribution...) and sites that
-installed these wanted places to add their own packages to the system without
-mixing their additions in with the base system.  So they created "/usr/local"
-and created a third instance of bin/sbin/lib and so on under there.  Then
-Linux distributors wanted a place to install optional packages, and they had
-/bin, /usr/bin, and /usr/local/bin to choose from, but the problem with each
-of those is that they were already in use and thus might be cluttered by who
-knows what.  So a new directory was created, /opt, for "optional" packages
-like firefox or open office.</p>
-
-<p>It's only a matter of time before somebody suggests /opt/local, and I'm
-not humoring this.  Executables for everybody go in /usr/bin, ones usable
-only by root go in /usr/sbin.  There's no /usr/local or /opt.  /bin and
-/sbin are symlinks to the corresponding /usr directories, but there's no
-reason to put them in the $PATH.</p>
-
-<h3>Consolidating writeable directories.</h3>
-
-<p>All the editable stuff has been moved under "var", starting with symlinking
-tmp->var/tmp.  Although /tmp is much less useful these days than it used to
-be, some things (like X) still love to stick things like named pipes in there.
-Long ago in the days of little hard drive space and even less ram, people made
-extensive use of temporary files and they threw them in /tmp because ~home
-had an ironclad quota.  These days, putting anything in /tmp with a predictable
-filename is a security issue (symlink attacks, you can be made to overwrite
-any arbitrary file you have access to).  Most temporary files for things
-like the printer or email migrated to /var/spool (where there are
-persistent subdirectories with known ownership and permissions) or in the
-user's home directory under something like "~/.kde".</p>
-
-<p>The theoretical difference between /tmp and /var/tmp is that the contents
-of /tmp should be deleted by the system init scripts on every
-reboot, but the contents of /var/tmp may be preserved across reboots.  Except
-there's no guarantee that the contents of any temp directory won't be deleted.
-So any program that actually depends on the contents of /var/tmp being
-preserved across a reboot is obviously broken, and there's no reason not to
-just symlink them together.</p>
-
-<p>(I case it hasn't become apparent yet, there's 30 years of accumulated cruft
-in the standards, convering a lot of cases that don't apply outside of
-supercomputing centers where 500 people share accounts on a mainframe that
-has a dedicated support staff.  They serve no purpose on a laptop, let alone
-an embedded system.)</p>
-
-<p>The corner case is /etc, which can be writeable (we symlink it to
-var/etc) or a read-only part of the / partition.   It's really a question of
-whether you want to update configuration information and user accounts in a
-running system, or whether that stuff should be fixed before deploying.
-We're doing some cleanup, but leaving /etc writeable (as a symlink to
-/var/etc).  Firmware Linux symlinks /etc/mtab->/proc/mounts, which
-is required by modern stuff like shared subtrees.  If you want a read-only
-/etc, use "find /etc -type f | xargs ls -lt" to see what gets updated on the
-live system.  Some specific cases are that /etc/adjtime was moved to /var
-by LSB and /etc/resolv.conf should be a symlink somewhere writeable.</p>
-
-<h3>The resulting mount points</h3>
-
-<p>The result of all this is that a running system can have / be mounted read
-only (with /usr living under that), /var can be ramfs or tmpfs with a tarball
-extracted to initialize it on boot, /dev can be ramfs/tmpfs managed by udev or
-mdev (with /dev/pts as devpts under that: note that /dev/shm naturally inherits
-/dev's tmpfs and some things like User Mode Linux get upset if /dev/shm is
-mounted noexec), /proc can be procfs, /sys can bs sysfs.  Optionally, /home
-can be be an actual writeable filesystem on a hard drive or the network.</p>
-
-<p>Remember to
-put root's home directory somewhere writeable (I.E. /root should move to
-either /var/root or /home/root, change the passwd entry to do this), and life
-is good.</p>
-
-
-<!--
-<p>Firmware Linux is an embedded Linux distribution builder, which creates a
-bootable single file Linux system based on uClibc and BusyBox/toybox.  It's
-basically a shell script that builds a complete Linux system from source code
-for an arbitrary target hardware platform.</p>
-
-<p>The FWL script starts by building a cross-compiler for the appropriate
-target.  Then it cross-compiles a small Linux system for the target, which
-is capable of acting as a native development environment when run on the
-appropriate hardware (or under an emulator such as QEMU).  Finally the
-build script creates an ext2 root filesystem image, and packages it with
-a kernel configured to boot under QEMU and shell scripts to invoke qemu
-appropriately.</p>
--->
-
-
-
-<!--#include file="footer.html" -->
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/www/documentation.html	Tue Dec 02 03:17:23 2008 -0600
@@ -0,0 +1,1956 @@
+<!--#include file="header.html" -->
+
+<h1>Documentation for Firmware Linux</h1>
+
+<p>Note, this documentation is currently under construction.  This is three
+files concatenated together, with their contents in the process of being
+reorganized and rewritten.  Some of it's up to date, some isn't.</p>
+
+<ul>
+<li><a href="#what_is_it">What is Firmware Linux?</a></li>
+<li><a href="#how_system_image">How do I use system images?</a></li>
+<li><a href="#how_build_source">How do I build my own customized system images from source code?</a></li>
+<li><a href="#how_implemented">How is Firmware Linux implemented?</a></li>
+<li><a href="#why">Why do things this way?</a></li>
+</ul>
+
+<hr />
+<a name="what_is_it"><h1>What is Firmware Linux?</h1></a>
+
+<p>Firmware Linux is an embedded Linux build system, designed to
+replace cross compiling with native compiling under emulation.  It provides
+an easy way to get started with embedded development, building your own code
+against uClibc, and testing it on non-x86 hardware platforms.</p>
+
+<p>This documentation uses the name "Firmware Linux' (or abbreviation "FWL") to
+refer to the <a href=downloads>build system</a>, and calls the output of
+the build a "<a href=downloads/binaries/system-image>system image</a>".
+The build system is implemented as a series of bash scripts and configuration
+files which compile a Linux development system for the specified target and
+package it into a bootable binary image.</p>
+
+<p>These system images provide a simple native Linux development
+environment for a target, built from seven source packages: busybox, uClibc,
+gcc, binutils, make, bash, and the Linux kernel.  This is the smallest
+environment that can rebuild itself entirely from source code, and thus the
+minimum a host system must cross compile in order to create a fully independent
+native development environment for a target.</p>
+
+<p>Booting a development system image under an emulator such as
+<a href=http://bellard.org/qemu/>QEMU</a> allows fully
+native builds for supported target platforms to be performed on cheap and
+powerful commodity PC hardware.  Building and installing additional packages
+(zlib, bison, openssl...) within a system image can provide an arbitrarily
+complex native development environment, without resorting to any additional
+cross compiling.</p>
+
+<p>FWL currently includes full support for arm, mips, powerpc, x86 and x86-64
+targets, and partial support for sh4, mips, and sparc.  The goal for the FWL
+1.0 release is to support every target QEMU can emulate in "system" mode.</p>
+
+<p>Firmware Linux is licensed under GPL version 2.  Its component packages are
+licensed under their respective licenses (mostly GPL and LGPL).</p>
+
+<h2>Optional extra complexity</h2>
+
+<p>Intermediate stages of the build (such as the cross compiler and the
+unpackaged root filesystem directory) may also be useful to Linux developers,
+so tarballs of them are saved during the build.</p>
+
+<p>By default the build cross-compiles some optional extra packages (toybox,
+distcc, uClibc++) and preinstalls them into the target filesystem.  This is
+just a convenience; these packages build and install natively within the
+minimal development system image just fine.<!-- TODO: experimentally confirm
+that, make it configurable, add genext2fs and strace to the list? -->)</p>
+
+<hr />
+<a name="how_system_image"><h1>Using system images</h1></a>
+
+<p>If you want to jump straight to building your own software natively for
+embedded targets, you can <a href=downloads/binaries>download a prebuilt
+binary image</a> instead of running the build scripts to produce your own.</p>
+
+<p>Here are the different types of output produced by the build:</p>
+
+<h2>system-image-*.tar.bz2</h2>
+
+<p>System images boot a complete linux system under an emulator.  Each
+system-image tarball contains an ext2 root filesystem image, a Linux kernel
+configured to run under the emulator <a href=http://bellard.org/qemu/>QEMU</a>,
+and a run-emulator.sh script.</p>
+
+<p>The steps to test boot a system image under qemu 0.9.1 are:</p>
+<ul>
+<li>install QEMU 0.9.1 or later</li>
+<li>download the appropriate <a href=downloads/image>prebuilt binary tarball</a>
+for the target you're interested in</li>
+<li>extract it: <b>tar -xvjf system-image-$TARGET.tar.bz2</b></li>
+<li>cd into it: <b>cd system-image-$TARGET</b></li>
+<li>execute it: <b>./run-emulator.sh</b></li>
+</ul>
+
+<p>This boots the system image under the appropriate emulator, with
+the emulated Linux's /dev/console hooked to stdin and stdout of the emulator
+process.  (I.E. the shell prompt the script gives you after the boot messages
+scroll past is for a shell running inside the emulator.  This lets you pipe
+the output of other programs into the emulator, and capture the emulator's
+output.)</p>
+
+<p>Type "cat /proc/cpuinfo" to confirm you're running in the emulator, then
+play around and have fun.  Type "exit" when done.</p></li>
+
+<p>Inside a system image, you generally wget source code from some URL and
+compile it.  (For example, you can wget the FWL build, extract it, and run it
+inside one of its own system images to trivially prove it can rebuild itself.)
+If you run a web server on your host's loopback interface, you an access it
+inside QEMU using the special address "10.0.2.2".  Example build scripts
+are available in the /usr/src directory.</p>
+
+<h3>Extra space and speed</h3>
+
+<p>The system images by themselves are fairly small (64 megabytes), and don't
+have a lot of scratch space for building or installing other packages.  If a
+file named "<b>hdb.img</b>" exists in the current directory, run-emulator.sh
+will automatically designate it as a second virtual hard drive and attempt to
+mount the whole unpartitioned device on <b>/home</b> inside the emulator.</p>
+
+<p>Some optional command line arguments to run-emulator.sh provide extra
+space and extra speed for compiling more software:</p>
+
+<ul>
+<li><p><b>--make-hdb $MEGABYTES</b> - if the hard drive image to mount on /home
+doesn't already exist, create a sparse file of the indicated size and format
+it ext3.</p></li>
+
+<li><p><b>--with-hdb $FILENAME</b> - use specified $FILENAME from
+the host as the hard drive image to mount on the emulated system's /home
+(instead of the default "hdb.img").  Fail if it doesn't exist, unless
+--make-hdb was also specified.</p></li>
+
+<li><p><b>--with-distcc $CC_PATH</b> - enable the
+<a href="#distcc_trick">distcc accelerator trick</a>.  This option provides
+the path to an appropriate cross compiler directory, so run-emulator.sh can
+launch a distcc daemon on the host's loopback device configured to call that
+cross compiler, and configure the emulated system to call out to that cross
+compiler through distcc.</p></li>
+</ul>
+
+<p>Running an armv4l system image with the cross compiler
+installed in the user's home directory, using a hard drive image in the user's
+home directory (to be created with a size of 2 gigabytes if it doesn't already
+exist) might look like:</p>
+
+<blockquote><pre>
+<b>./run-emulator.sh --make-hdb 2048 --with-hdb ~/blah.img --with-distcc ~/cross-compiler-armv4l</b>
+</pre></blockquote>
+
+<h2>mini-native-*.tar.bz2</h2>
+
+<p>These <a href=downloads/mini-native>tarballs</a> contain the same root
+filesystem as the corresponding system images, just in an archive
+instead of packaged into a filesystem image.</p>
+
+<p>If you want to boot your own system image on real hardware instead of an
+emulator, the appropriate mini-native tarball is a good starting point.  If
+all you want is a native uClibc development environment for your host, try:</p>
+
+<blockquote>
+<pre>
+<b>chroot mini-native-x86_64 /usr/chroot-setup.sh</b>
+</pre>
+</blockquote>
+
+<p>The boot script /usr/qemu-setup.sh or /usr/chroot-setup.sh performs
+minimal setup for the appropriate environment, mounting /proc and /sys and
+such.  It starts a single shell prompt, and automatically cleans up when that
+process exits.</p>
+
+<p>If you're interested in building a more complex development environment
+within this one (adding zlib and perl and such before building more complicated
+packages), the best way to learn how is to read
+<a href=http://www.linuxfromscratch.org/lfs/view/6.4/>Linux
+From Scratch</a>.</p>
+
+<p>Note that mini-native is just one potential filesystem layout; the FWL
+build scripts have several other configurations available when you build from
+source.</p>
+
+<h2>cross-compiler-*.tar.bz2</h2>
+
+<p>The cross compilers created during the FWL build are relocatable C compilers
+for each target platform.  The primary reason for offering each cross compiler
+as a downloadable binary is to implement the <a href="#distcc_trick">distcc
+accelerator trick</a>.  Using them to cross compile additional software is
+supported, but not recommended.</p>
+
+<p>If you'd like to use one for something other than distcc, this documentation
+mostly assumes you already know how.  Briefly:</p>
+
+<ul>
+<li>download the appropriate cross-compiler-$TARGET.tar.bz2</li>
+<li>extract it somewhere (doesn't matter where)</li>
+<li>add the resulting cross-compiler-$TARGET/bin subdirectory to your $PATH</li>
+<li>either use $TARGET-gcc as your compiler, or set your $CROSS_COMPILE prefix
+to "$TARGET-" with a trailing dash.</li>
+</ul>
+
+<p>Also, stock up on asprin and clear a space to beat your head against; you'll
+need both.  See <a href="#why_cross_compiling_sucks">why cross compiling
+sucks</a> for more details.</p>
+
+<p>Note that although this cross compiler has g++, it doesn't
+have uClibc++ in its lib or include subdirectories, which is required to
+build most c++ programs.  If you need extra libraries, it's up to you to
+cross-compile and install them into those directories.</p>
+
+<a name="how_build_source"><h1>How do I build my own customized system images
+from source code?</h1></a>
+
+<p>To build your own root filesystem and system images from source code,
+download and run <a href=downloads>the FWL build scripts</a>.  You'll
+probably want to start with the most recent <a href=downloads>release
+version</a>, although once you've got the hang of it you might want to follow
+the <a href=/hg/firmware>development version</a>.</p>
+
+<p>For a quick start, download the tarball, extract it, cd into it, and run
+"<b>./build.sh</b>".  This script takes one argument, which is the target to
+build for.  Run it with no arguments to list available targets.</p>
+
+<p>This should produce all the tarballs listed in the previous section in the
+the "build" directory.  To perform a clean build, "rm -rf build" and re-run
+build.sh.</p>
+
+<h2>How building from source works</h2>
+
+<p>The build system is a series of shell scripts which download, compile,
+install, and use the appropriate source packages to generate a system
+image.  These shell scripts are designed to be easily read and modified,
+acting both as tools to perform a build and as documentation on how to
+build these packages.</p>
+
+<p>The <b>build.sh</b> script is a simple wrapper which calls the following
+other scripts in sequence:</p>
+<ol>
+<li>download.sh</li>
+<li>host-tools.sh</li>
+<li>cross-compiler.sh $TARGET</li>
+<li>mini-native.sh $TARGET</li>
+<li>package-mini-native.sh $TARGET</li>
+</ol>
+
+<p>In theory, the stages are othogonal.  If you have an existing cross
+compiler, you can add it to the $PATH and skip cross-compiler.sh.  Or you
+can use _just_ cross-compiler.sh to create a cross compiler, and then go build
+something else with it.  The host-tools.sh stage can often be skipped
+entirely.</p>
+
+<h3>Build stages</h3>
+
+<p>The following files control the individual stages of the build.  Each
+may be called individually, from in the top level directory of FWL:</p>
+
+<ul>
+<li><p><b>download.sh</b> - Download source packages from the web.</p>
+
+<p>This script does not take an arguments.  It's a series of calls to a
+download function (defined in sources/include.sh) that checks if an existing
+copy of the tarball matching a defined $SHA1 sum exists in the
+<b>sources/packages</b> directory, and if not uses wget to fetch it from the
+$URL (or else from a series of fallback mirrors).  A blank value for $SHA1
+will accept any file as correct, ignoring its contents.</p>
+
+<p>After downloading all tarballs, the function <b>cleanup_oldfiles</b> deletes
+any unused files from sources/packages (generally previous versions left over
+after a package upgrade while using the development version of the FWL
+build scripts).</p>
+
+<p>Running this stage with the argument "--extract-all" will extract all
+the tarballs at once, to populate the cache used by setupfor.  (This is
+primarily used to avoid race conditions when building multiple architectures
+in parallel with build-all-targets.sh.  This is an esoteric internal
+detail you can safely ignore if you're not doing that.)</p>
+</li>
+
+<li><p><b>host-tools.sh</b> - Set up a known environment on the host</p>
+
+<p>This script does not take an arguments.  In theory this is an optional step,
+and may be omitted, as the binaries produced by this script are not included in
+any of the output tarballs.</p>
+
+<p>This script populates the <b>build/host</b> directory with
+host versions of the busybox and toybox command line tools (the same ones
+that the target's eventual root filesystem will contain), plus symlinks to the
+host's compiler toolchain.</p>
+
+<p>This allows the calling scripts to trim the $PATH to point to just this
+one directory, which serves several purposes:</p>
+
+<ul>
+
+<li><p><b>Isolation</b> - This prevents the ./configure stages of the source
+packages from finding and including unexpected dependencies on random things
+installed on the host.</p></li>
+
+<li><p><b>Portability</b> - Using a known set of command line utilities
+insulates the build from variations in the host's Linux distribtion (such as
+Ubuntu's /bin/echo lacking suport for the -e option).</p></li>
+
+<li><p><b>Testing</b> - It ensures the resulting system can rebuild itself
+under itself, since the initial build was done with the same tools we
+install into the target's root filesystem.  The initial build acts as a smoke
+test of most of the packages used to create the resulting system, and
+restricting $PATH ensures that no necessary commands are missing.  (Variation
+can still show up between x86/arm/powerpc versions, of course.)</p>
+
+<p>It also moves most failures to the beginning.  If anything's going to
+break, it's usually the host-tools build.  After that runs, we're mostly
+in a known and tested state.</li>
+
+<li><p><b>Dependency tracking</b> - If we don't explicitly know everything
+we need to build ourselves in the first place, we can't be sure we added
+it to the final system to get a self-hosting environment.</p></li>
+</ul>
+
+<p>A secondary purpose of host-tools.sh is to build packages (such as distcc
+and genext2fs) which might not be installed on the host system.  Some of
+these aren't needed by build.sh but may be used by later run-emulator.sh
+invocations (such as the ./run-build-image.sh script).</p>
+
+<p>Note that this script does not attempt to build qemu, due to the
+unreasonable requirement of installing gcc 3.x on the host.  The FWL build
+scripts do not use qemu (except as an optional test at the end of
+cross-compiler.sh which is skipped if qemu is not available).  You will need
+to install qemu (or another emulator, or find real hardware) to use the
+resulting system images, but they should build just fine without it.</p>
+
+<p>This stage is optional.  You don't need to run this stage if you don't
+want to.  If the build/host directory doesn't exist (or doesn't contain
+a "busybox" executable), the build will use the host's original $PATH.</p>
+</ul>
+
+<li><p><b>cross-compiler.sh</b> - Build a cross compiler for the target, for
+use by mini-native.sh and the distcc accelerator.</p>
+
+<p>In order to build binaries for the target, the build must first create
+a cross compiler to build those target binaries with.  This script creates
+that cross compiler.  If you already have a cross compiler, you can
+supply it here (the easy way is to create a build/cross-compiler-$TARGET/bin
+directory and put "$TARGET-gcc" style symlinks in it) and skip this step.</p>
+
+<p>This script takes one argument: the architecture to build for.  It
+produces a cross compiler that runs on the host system and produces binaries
+that run on the target system.  This cross compiler is created using the
+source packages binutils, gcc, uClibc, the Linux kernel headers, and a
+compiler wrapper to make the compiler relocatable.<</p>
+
+<p>The reason for the compiler wrapper is that by default, gcc hardwires
+lots of absolute paths into itself, and thus only runs properly in the
+directory it was built in.  The compiler wrapper rewrites its command line
+to prevent gcc from using its built-in (broken) path logic.</p>
+
+<p>The build requires a cross-compiler even if the host and target system use
+the same processor because the host and target may use different C libraries.
+If the host has glibc and the target uses uClibc, then the (dynamically linked)
+target binaries the compiler produces won't run on the host.  (Target binaries
+that won't run on the host are what distinguishes cross-compiling from native
+compiling.  Different processors are just one reason for it: glibc vs uClibc
+is another, ELF vs binflat or a.out executable format is a third...)</p>
+
+<p>This script produces produces a working cross compiler in the build
+directory, and saves a tarball of it as "cross-compiler-$TARGET.tar.bz2"
+for use outside the build system.  This cross compiler is fully relocatable
+(because of the compiler wrapper), so any normal user can extract it into their
+home directory, add cross-compiler-$TARGET/bin to their $PATH, and run
+$TARGET-gcc to create target binaries.</p>
+</li>
+
+<li><p><b>mini-native.sh</b> - Use the cross compiler to create
+a minimal native build environment for the target platfrom.<p>
+
+<p>This script takes one argument: the architecture to build for.</p>
+
+<p>This script uses the cross compiler found at
+build/cross-compiler-$ARCH/bin (with $ARCH- prefixes) to build a root
+filesystem for the target, as well as a target Linux kernel configured for
+use with qemu.  A usable cross compiler is left in the build directory by
+the cross-compiler.sh script, or you can install your own.</p>
+
+<p>The basic root filesystem consists of busybox and uClibc.  If the
+configuration variable NATIVE_TOOLCHAIN is set (this is enabled by
+default), this script adds a native compiler to the target, consisting of
+linux kernel headers, gcc, binutils, make, and bash.  It also adds distcc
+to potentially distribute work to cross compilers living outside the emulator.
+This provides a minimal native development environment, which may be expanded
+by building and installing more packages under the existing root filesystem.</p>
+</li>
+
+<li><p><b>package-mini-native.sh</b> - Create an ext2 filesystem image
+of the native root filesystem.</li>
+
+<p>This script takes one argument: the architecture to package.</p>
+
+<p>This uses genext2fs to create an ext2 filesystem image from the
+build/mini-native-$ARCH directory left by running mini-native.sh, and
+creates a system-image-tarball containing the result.  It first compiles
+genext2fs and adds it to build/host if the host system hasn't already got a
+copy.</p>
+
+<p>This script also generates a run-emulator.sh script to call the appropriate
+emulator, using the architecture's configuration information.</p>
+</li>
+
+<li><p><b>run-from-build.sh</b> - Runs a system image you compiled from
+source.</p>
+
+<p>Calls run-emulator.sh in the appropriate build/system-image-$TARGET
+directory, with a 2 gigabyte <b>hdb.img</b> for /home and distcc connected
+to build/cross-compiler/$TARGET.  Between runs it calls e2fsck on the
+system image's root filesystem.</p>
+
+<p>This is not technically a build stage, as it isn't called from build.sh,
+but it's offered as a convenience for users.  It uses the existing
+cross-compiler and system-image directories in build/ and doesn't mess
+with the tarballs that were created from them.</p>
+</li>
+</ul>
+
+<p>The following generally aren't called directly, but are used by the rest of
+the build.</p>
+
+<ul>
+<li><p><b>config</b> - User definable configuration variables</li></p>
+
+<p>This file contains environment variables which you can set to customize
+the FWL build process.  Setting any of these variables to a nonblank value
+changes the build.</p>
+
+<ul>
+<li><p><b>NATIVE_TOOLCHAIN</b> - This tells mini-native.sh to
+include a compiler toolchain (binutils, gcc, bash, make, and distcc).
+Without this, it builds a small uClibc/busybox system.  This is the only
+variable enabled by default in config.</p>
+
+<p>Setting NATIVE_TOOLCHAIN="headers" will leave the libc and kernel
+header files in the appropriate include directory, for use by some other native
+compiler.  Building and installing additional tools (such as "make", or a
+compiler such as pcc, llvm/clang, or tinycc) then becomes your problem.</p>
+</li>
+
+<li><p><b>NATIVE_TOOLSDIR</b> - This tells mini-native.sh to change the
+directory layout to conform to a Linux From Scratch "intermediate" system, with
+everything under a /tools directory.  (This provides a cleaner environment
+for creating a new completely customized system at the root level.)</p>
+</li>
+
+<li><p><b>RECORD_COMMANDS</b> - Records all command lines used to build each
+package.</p>
+
+<p>This inserts a logging wrapper in the $PATH which logs the command lines
+used by the build.  Afterwards, the script
+"sources/toys/report_recorded_commands.sh" can generate a big report on which
+commands were used to build each package for each architecture.  To get a
+single list of the command names used by everything, do:</p>
+
+<blockquote>
+<p>echo $(find build -name "cmdlines.*" | xargs awk '{print $1}' | sort -u)</p>
+</blockquote>
+
+<p>(Note: this will miss things which which call executables at absolute values
+instead of checking $PATH, but the only interesting ones so far are the
+#!/bin/bash type lines at the start of shell scripts.)</p>
+</li>
+
+<li><p><b>CROSS_BUILD_STATIC</b> - Tells cross-compiler.sh to statically link
+all binaries in the cross compiler toolchain it creates.</p>
+
+<p>The prebuilt binary versions in the download directory are statically linked
+against uClibc, by building a mini-native environment and re-running the build
+under that with CROSS_BUILD_STATIC=1.  The sources/build-all-targets.sh
+script can do this automatically with the "--use-static-host $TARGET"
+argument.  (Requires QEMU installed.)</p></li>
+
+<li><p><b>PREFERRED_MIRROR</b> - Tells download.sh to try to download
+packages from this URL first, before falling back to the normal mirror list.
+For example, "PREFERRED_MIRROR=http://impactlinux.com/fwl/mirror".</p></li>
+
+<li><p><b>USE_TOYBOX</b> - Tells the host-tools.sh and mini-native.sh to
+install the <a href=http://impactlinux.com/code/toybox>toybox</a> implementation
+of commands (where available) instead of the busybox versions.  This is an
+alternate (simpler) implementation of many commands.</p>
+
+<p>Currently FWL always uses the toybox "patch" command, because the busybox
+version can't apply patches at offsets.</p>
+</li>
+
+<li><p><b>USE_UNSTABLE</b> - Lists packages to build alternate "unstable"
+versions for.</p>
+
+<p>The value of this config entry is a comma separate list of packages.</p>
+
+<p>Many packages in download.sh have an UNSTABLE= tag providing a URL to an
+alternate version.  Generally these link to newer versions, often unstable
+development versions, for testing purposes.</p>
+
+<p>In addition to changing the download location, using alternate versions of
+packages prepends an "alt-" in front of the package name in various places
+(such as the patches from the sources/patches directory and the configuration
+files used from sources/targets).  It changes the behavior of the
+"download" and "setupfor" shell functions.</p>
+</li>
+
+<li><p><b>USE_COLOR</b> - Color code the various build stages.</li>
+
+<p>Enabling this provides a quick visual indicator of which build stage is in
+progress.</p>
+
+<p>This is disabled by default both because its utility is a matter of taste,
+and because finding a half-dozen different colors that work on both white and
+black backgrounds is hard, and gnome-terminal can't produce an actual black
+background.  (In its default palette, "black" is a fairly light grey.)</p>
+</li>
+</ul>
+</li>
+
+<li><p><b>sources/build-all-targets.sh</b> - Build all supported targets
+at once.</p>
+
+<p>This performs a similar function to build.sh, but for all targets instead
+of just one.  It can build targets in parallel with the --fork option, logs the
+output of the various build stages, and generates a README.</p>
+
+<p>This script populates a second output directory, buildall, with its output.
+This is probably only of interest to FWL's developers.</p>
+</li>
+</ul>
+
+<hr>
+<a name="how_implemented"><h1>How is Firmware Linux implemented?</h1></a>
+
+<h2>Directory layout</h2>
+
+<p>The top level directory of FWL contains the user interface of FWL (scripts
+the user is expected to call or edit), and the "sources" directory containing
+code that isn't expected to be directly called by end users.</p>
+Important directories under sources include:</p>
+
+<ul>
+<li><p><b>sources/targets</b> - Configuration information for each target.</p>
+
+<p>Adding a new target to FWL involves creating a new directory under here
+(which determines the name of the target), and adding two miniconfig files
+(for linux and uClibc), and a "details" file defining environment variables.</p>
+</li>
+
+<li><p><b>sources/packages</b> - Source tarballs for the packages to be built.
+This directory starts empty, and is populated by download.sh.</p></li>
+
+<li><p><b>sources/native</b> - This directory hierarchy is copied into the
+target verbatim (under /usr).  It contains the boot script and some sample
+source code.</p></li>
+
+<li><p><b>sources/toys</b> - Build utilities, mostly original code written for
+FWL.  Not necessarily specific to this project, but can't be downloaded from
+somewhere else.</p></li>
+</ul>
+
+<p>Output files from running the build scripts, and all temporary files, go
+in the "build" subdirectory. This entire directory can be deleted between
+builds.</p>
+
+<ul>
+<li><p><b>build/sources</b> - cached copies of the extracted source tarballs,
+so setupfor can "cp -lfR" instead of having to re-extract and re-patch the
+source each time.</p></li>
+
+<li><p><b>build/host</b> - Output of host-tools.sh.  If this directory
+exists and contains a "busybox" executable, include.sh will set the $PATH to
+point only to this directory.</p></li>
+
+<li><p><b>build/temp-$TARGET</b> - Temporary directory for building each
+target.  Feel free to delete this between runs, it should be empty unless
+a build broke, in which case it has the source tree that failed to
+build.  (The temporary directory for host-tools.sh is "host-temp", in case
+someday somebody creates a $TARGET named "host".)</p></li>
+
+<li><p><b>build/cross-compiler-$TARGET</b> - Output directory for
+cross-compiler.sh.  The corresponding cross-compiler tarball is just an
+archive of this directory.  Used by mini-native.sh.</p></li>
+
+<li><p><b>build/mini-native-$TARGET</b> - Output directory for mini-native.sh.
+The corresponding mini-native tarball is just an archive of this directory.
+Used by package-mini-native.sh.</p></li>
+
+<li><p><b>build/system-image-$TARGET</b> - Output directory for
+package-mini-native.sh.  The corresponding system-image tarball is just an
+archive of this directory.  Used by run-from-build.sh.</li>
+</ul>
+
+<h2>Shared infrastructure</h2>
+
+<p>The top level file for the behind-the-scenes plumbing is
+<b>sources/include.sh</b>.  This script is not run directly, but is instead
+included from the other scripts.  It does a bunch of things:</p>
+
+<ul>
+<li><p>Its command line argument is the architecture to build.
+If run with no arguments, it outputs all available architectures by
+listing the subdirectories under sources/targets.  (The special environment
+variable $NO_ARCH tells it to skip that part; this is used by download.sh
+and host-tools.sh which are architecture independent.)</p>
+</li>
+
+<li><p>It parses the "config" file at the top directory, reading in the user
+defined configuration variables.  (You can also supply these as environment
+variables, if you want to specify them for just one run.)</p></li>
+
+<li><p>It sets several other environment variables, specifying things like the
+$SOURCE and $BUILD directories, and detecting the number of $CPUS.</p></li>
+
+<li><p>It adjusts the $PATH.  If build/host exists and contains a busybox
+executable (meaning host-tools.sh did its thing already), $PATH is set to just
+that directory.</p></li>
+
+<li><p>If host-tools.sh ran with $RECORD_COMMANDS, it sets the $PATH to
+point to the logging wrapper directory.  ($WRAPPY_LOGPATH specifies where
+the logging wrapper should write its log file, and $WRAPPY_REALPATH says where
+to find the actual commands the logging wrapper hands off to.)</p></li>
+</ul>
+
+<p>It also reads <b>sources/functions.sh</b>, which provides shell functions
+used by the rest of the build, including:</p>
+
+<ul>
+<li><p><b>download</b> - Used by download.sh.  Calls wget if necessary, uses
+sha1sum to verify the files.  Treat as a fancy call to "wget".</p></li>
+
+<li><p><b>dienow</b> - abort the current script, exiting with an error message.
+(Can even exit from nested shell functions.)  Treat as a fancy "exit".</li>
+
+<li><p><b>setupfor</b> - extract a source package (named in the
+first argument) into a temporary directory, and change the current directory
+to there.  Treat as a fancy "tar -xvjf" followed by cd.</p>
+
+<p>Source code is cached, meaning each package's source tarball is only
+actually extracted and patched once (into build/sources) and the temporary
+copies are directories full of hard links to the cached source.</p>
+</li>
+
+<li><p><b>cleanup</b> - delete temporary copy of source code after build.
+Treat as a fancy "rm -rf".  (If the exit code of the last command was nonzero,
+it calls dienow instead of deleting the source code that didn't build
+properly, to preserve the evidence of what went wrong.)</p></li>
+</ul>
+
+<p>Most of what include.sh does is optional.  A lot of it's there to speed up
+and simplify the rest of the build.  (You don't really need to call "make -j"
+for parallel bilds, and can re-extract and re-patch source code each time
+you need it rather than cacheing the extracted version.)  Most of the rest is
+error checking, from "dienow" to the sha1sum checking in "download".</p>
+
+<p>None of this should be important to understanding how to build or install
+any of the actual packages.  It just abstracts away repetitive, uninteresting
+bits.</p>
+
+<h2>Downloading source code</h2>
+
+<p>The FWL source distribution does not include any third party source
+tarballs.  Instead, these are downloaded by running download.sh, which calls
+the shell function <b>download</b>, which calls wget as necessary.  The
+download.sh script is just a series of calls to the download function.</p>
+
+<p>The first thing download.sh does is check for the --extract option,
+and if present set the environment variable EXTRACT_ALL, which tells
+each call to the download function to call the extract shell function on
+the appropriate tarball to prepopulate the source cache.  (See "Extracting
+source code", below.)</p>
+
+<p>Each call to the download function is controlled by the following
+<b>environment variables</b>:<p>
+
+<ul>
+<li><p><b>URL</b> - The URL from which to download this source package
+into the sources/packages directory.</p>
+
+<p>In addition to specifying a web location, this URL specifies the name of the
+source package to fetch.  If this source tarball cannot be fetched from this
+location, download tries to download the file from a series of fallback mirrors,
+most importantly http://impactlinux.com/firmware/mirror which should have every
+source tarball used by the build.</p></li>
+
+<p>The package name is the filename at the end of URL minus any version
+information and file type extensions, so "bash-2.04b.tar.bz2" becomes "bash".
+The shell function "basename" uses a rather complicated regex to
+extract the package name from a URL.  The package name is used by things
+like setupfor, allowing the build scripts to mostly ignore the versions of
+the packages they build.</p></li>
+
+<li><p><b>SHA1</b> - The sha1sum of the source tarball to fetch.</p>
+
+<p>If this value is blank, the sha1sum calculated from the file will be
+displayed but not verified.  This means any file will be accepted as correct
+as long as it exists with the right name, but the build won't be able to
+detect corrupted or truncated files.</p>
+
+<p>When updating to a new version of a package, a common trick is to update
+the URL and blank the SHA1, run ./download.sh to fetch the new file, cut and
+paste the SHA1 value displayed after the download to set the SHA1 variable,
+and then re-run ./download.sh to confirm they match.</p></li>
+
+<li><p><b>PREFERRED_MIRROR</b></p> - This contains the URL of a mirror site
+to be checked _before_ downloading from the actual $URL specified in
+download.sh.</p>
+
+<p>This allows download.sh to fetch some or all of its packages from a local
+mirror of the files, instead of going out to the net.  Any files not found
+in this mirror will be fetched from the standard URL, and the fallback mirrors
+as necessary.</p>
+
+<p>(Note: inside qemu the special address 10.0.2.2 passes through connections
+to 127.0.0.1 on the host, so if you run a web server on hour host's loopback
+address you can easily pass source code into the emulator without going out
+to an external network.)</p>
+
+<li><p><b>UNSTABLE</b> - URL to an alternate version of the file, for
+testing purposes.</p>
+
+<p>This version is only downloaded when USE_UNSTABLE contains the name of this
+package in its package list.  It doesn't fall back to check the mirror list,
+and is not affected by PREFERRED_MIRROR.</p>
+
+<p>Unstable packages are saved as a tarball called "alt-$PACKAGE-0" plus the
+file type extension, so the name to save is based on the filename in the
+normal $URL rather than on what the $UNSTABLE address points to.  (So even if
+your UNSTABLE address ends with "snapshot.tgz" or "tip.tar.bz2", it will
+still wind up somewhere the rest of the build can find it.)</p>
+</ul>
+
+<p>At the end of download.sh is a call to the shell function cleanup_oldfiles,
+which deletes unused files.  The include.sh snapshots the current time in
+the variable $START_TIME, and download calls "touch" to update the timestamp on
+each file it verifies the sha1sum of.  Then cleanup_oldfiles deletes every
+file from sources/packages with a date older than $START_TIME.</p>
+
+<p>Note that download updates the timestamp on stable packages when
+downloading corresponding unstable stable packages, so cleanup_oldfiles
+won't delete them.  In this special case they're not considered "unused
+files", but it won't verify their integrity or fetch them if they're not
+already there.  If a package is not in the USE_UNSTABLE list, download.sh won't
+update the timestamp on unstable source tarballs, leaving them marked as
+unused and thus deleted by cleanup_oldfiles.</p>
+
+<h2>Extracting source code</h2>
+
+<p>The function "setupfor" extracts <b>sources/packages/$PACKAGENAME-*</b>
+tarballs.  (If $PACKAGENAME is found in the comma separated $USE_UNSTABLE list,
+the build adds an "alt-" prefix to the package name.)  This populates a
+corresponding directory under build/sources, and applies all the
+<b>sources/patches/$PACKAGENAME-*.patch</b> files in alphabetical order.
+(So if a package has multiple patches that need to be applied in a specific
+order, name them something like "bash-001-dothingy.patch",
+"bash-002-next.patch" to control this.)  The trailing "-" before filename
+wildcards prevents collisions between things like "uClibc" and "uClibc++".</p>
+
+<p>FWL implements source cacheing.  The first call to setupfor extracts the
+package into build/sources, and then creates a directory of hard links in the
+current target's build/temp-$TARGET directory with cp -lfR.  Later setupfor
+calls just create the directory of hard links from the existing source tree.
+(This is a hybrid approach between building "out of tree" and building
+in-tree.)</p>
+
+<p>The <b>./download.sh --extract</b> option prepopulates the source cache,
+extracting and patching each source tarball.  This is useful for
+scripts such as sources/build-all-targets.sh which perform multiple builds in
+parallel.</p>
+
+<p>The reason for keeping extracted source tarballs around is that extracting
+and patching tarballs is a fairly expensive operation, which uses a significant
+amount of disk space and doesn't parallelize well.  (It tends to be disk
+limited as much as CPU limited, so trying for more parallelism wouldn't
+necessarily help.)  In addition, the same packages are repeatedly extracted:
+the cross-compiler and mini-native stages use many of the same packages, and
+some packages (such as the Linux kernel) are extracted and removed repeatedly
+to grab things like kernel headers separately from actually building a
+bootable kernel.  (Also, different architectures build the exact same
+packages, with the same set of patches.  Even patches to fix a bug on a single
+architecture are applied for all architectures; if this causes a problem, it's
+not a mergeable patch capable of going upstream.)</p>
+
+<h2>Building host tools</h2>
+
+<p>The host-tools.sh script sets up the host environment.  Usually the
+host environment is already in a usable state, but this script explicitly
+enumerates exactly what we need to build, and provides our own (known)
+versions of everything except the host compiler toolchain in the directory
+<b>build/host</b>.  Once we've finished, the $PATH can be set to just that
+directory.</p>
+
+<p>The build calls seven commands from the host compiler toolchain: ar, as,
+nm, cc, gcc, make, and ld.  All those have to be in the $PATH, so host-tools.sh
+creates symlinks to those from the original $PATH.</p>
+
+<p>Next host-tools.sh builds toybox for the "patch" command, because busybox
+patch can't simple handle offsets and is thus extremely brittle in the face of
+new package versions.  (This is different from "fuzz factor", which removes
+context lines to find a place to insert a patch, and tends to break a lot.)
+If USE_TOYBOX is enabled, a defconfig toybox is used and all commands are
+installed.</p>
+
+<p>Next host-tools builds a "defconfig" busybox and installs it into
+build/host.  This provides all the other commands the build needs.</p>
+
+<h3>What's the minimum the build actually needs?</h3>
+
+<p>When building a new system, environmental dependencies are a big issue.
+Figuring out what package needs what, and what order to build things in,
+is the hardest part of putting together a system.</p>
+
+<p>Running the build without build/host calls lots of extra commands, including
+perl, pod2man, flex, bison, info, m4, and so on.  This is because the
+./configure stages of the various packages detect optional functionality,
+and use it.  One big reason to limit the build environment is to consistently
+produce the same output files, no matter what's installed on the host.</p>
+
+<p>The minimal list of commands needed to build a working system image is
+1) a working toolchain (ar, as, nm, cc, gcc, make, ld), 2) /bin/bash (and
+a symlink /bin/sh pointing to it), 3) the following command line utilities
+in the $PATH:</p>
+
+<blockquote>
+<p>
+awk basename bzip2 cat chmod chown cmp cp cut date dd diff
+dirname echo egrep env expr find grep gzip hostname id install ln ls mkdir
+mktemp mv od patch pwd readlink rm rmdir sed sha1sum sleep sort tail tar
+touch tr true uname uniq wc which whoami xargs yes
+</p>
+</blockquote>
+
+<p>These commands are supplied by current versions of busybox.</p>
+
+<p>Bash has been the standard Linux shell since before the 0.0.1 release in
+1991, and is installed by default on all Linux systems.  (Ubuntu broke its
+/bin/sh symlink to point to the Defective Annoying SHell, so many scripts call
+#!/bin/bash explicitly now rather than relying on a broken symlink.)  We
+can't stop the build from relying on the host version of this tool; editing
+$PATH has no effect on the #!/bin/bash lines of shell scripts.</p>
+
+<p>The minimal set of commands necessary to build a system image was
+determined experimentally, by running a build with $RECORD_COMMANDS and
+then removing commands from the list and checking the effect this had on
+the build.  (Note that the minimal set varies slightly from target to
+target.)</p>
+
+<p><b>$RECORD_COMMANDS</b> tells host-tools.sh to set up a logging wrapper
+that intercepts each command line in the build and writes it to a log file, so
+you can see what the build actually uses.  (Note that when host-tools.sh
+sets up build/wrapper, it doesn't set up build/host, so the build still uses
+the host system's original command line utilities instead of building busybox
+versions.  If you'd like to record the build using build/host commands,
+run host-too.sh without $RECORD_COMMANDS set and then run it again with
+$RECORD_COMMANDS to set up the logging wrapper pointing to the busybox
+tools.)</p>
+
+<p>The way $RECORD_COMMANDS works is by building a logging wrapper
+(sources/toys/wrappy.c) and populating a directory (build/wrapper) with
+symlinks to that logging wrapper for each command name in $PATH.  When later
+build stages run commands, the wraper appends the command line to the log file
+(specified in the environment variable $WRAPPY_LOGPATH, host-tools.sh sets
+this to "$BUILD/cmdlines.$STAGE_NAME.$PACKAGE_NAME"), recording
+each command run.  The logging wrapper then searches $WRAPPY_REALPATH to find
+the actual command to hand its command line off to.</p>
+
+<h2>Building a cross compiler</h2>
+
+<p>We cross compile so you don't have to.  The point of this project is to
+make cross compiling go away, but you need to do some to get past it.  So
+let's get it over with.</p>
+
+<p>The <b>cross-compiler.sh</b> script builds a cross compiler.  Its output
+goes into <b>build/cross-compiler-$TARGET</b> directory, which is
+deleted at the start of the build if it already exists, so re-running this
+script always does a clean build.</p>
+
+<p>Creating a cross compiler is a five step process:</p>
+
+<ul>
+<li><p><b>binutils</b> - Build assembler and linker for the target platform.</p>
+
+<p>This package has no interesting dependencies, and thus can be the first
+thing you build for a target.</p>
+</li>
+
+<li><p><b>gcc</b> - Build C/C++ compiler for the target platform.</p>
+
+<p>This package needs binutils, and must be built after that.  It does not
+need a C library, so can be built before that.</p>
+
+<p>The mini-native build doesn't require C++ support, but the build adds
+gcc-g++ to the basic gcc-core and enables C++ support so the
+<a href="#distcc_trick">distcc accelerator trick</a> can speed up C++
+builds.</p>
+
+<p>We create an "xgcc" symlink pointing to the host compiler to force gcc
+not to attempt to rebuild itself with itself.  (It needed to be able to
+build xgcc with the host compiler, but doesn't trust the host compiler to
+build an actual binary to deploy.  Note that this xgcc builds _host_ binaries,
+not target binaries.)</p>
+</li>
+
+<li><p><b>compiler wrapper</b> - Install a wrapper around gcc to enforce sane
+path logic.</p>
+
+<p>This builds a wrapper for gcc from "sources/toys/gcc-uClibc.c".  This
+compiler wrapper rewrites the gcc command line to start with --nostdinc and
+--nostdlib, and then explicitly adds the correct header and library search
+paths, and when linking adds the correct object files and libraries.</p>
+
+<p>It needs to do this because gcc's path logic has been consistently broken
+for about two decades now.  (See <a href="#why_cross_compiling_sucks">why
+cross compiling sucks</a> for more details.)</p>
+
+<p>The compiler hands off the new command line to $ARCH-rawgcc, so the
+old $ARCH-gcc gets renamed to that and the wrapper gets the old name.</p>
+
+<p>To allow the compiler wrapper to easily find the headers and libraries,
+the build moves them to known locations.  The system headers and libraries
+go into "include" and "lib" directories at the same level as the "bin"
+directory containing the wrapper script, and gcc's own headers and libraries
+go into "gcc/include" and "gcc/lib".  The wrapper then finds itself (using
+argv[0] and if necessary searching the $PATH it inherits), and backs up one
+level to find the headers and libraries it needs to add to the gcc path.</p>
+</li>
+
+<li><p><b>linux</b> - kernel headers.</p>
+
+<p>This package doesn't have any prerequisites, but C libraries need it
+to build themselves.  (Kernel headers define the system call API for the
+Linux kernel.)</p>
+</li>
+
+<li><p><b>uClibc</b> - uClibc (micro C library).</p>
+
+<p>This package is target code that needs to be built with a cross compiler
+(gcc and binutils), and also needs kernel headers.  It requires all three of
+the other packages, and thus must be built last.</p>
+
+<p>Note that we only build a standard C library.  We don't build/install
+a standard C++ library (uClibc++), because distcc doesn't need headers
+or libraries in the cross compiler.  Thus the cross compiler has enough
+C++ support to be used from the native environment via distcc, but not
+enough to cross compile C++ code on its own.</p>
+
+<p>The compiler wrapper actually uses links to "libc.so", which is a linker
+script pointing to libuClibc.so.0.  We patch uClibc so it doesn't put absolute
+paths into its libc.so; without them the linker searches the supplied library
+search paths, and thus the compiler may be installed in an arbitrary
+location.</p>
+</li>
+</ul>
+
+<p>Afterwards the build strips some of the binaries, tars up the result,
+and performs some quick sanity tests (building dynamic and static versions
+of hello world.  If the target configuration lists a version of QEMU to
+test individual binaries under on the host, it runs the static version
+to make sure it outputs "Hello world".</p>
+<hr>
+
+<h2>Building a minimal native development environment for the target system</h2>
+
+<p>The <b>mini-native.sh</b> script uses the cross compiler from the previous
+step to build a kernel and root filesystem for the target.  The resulting
+system should boot and run under an emulator, or on real target hardware.</p>
+
+<p>Because cross-compiling is persnickety and difficult, we do as little of
+it as possible.  This script should perform all the cross compiling anyone ever
+needs to do.  It uses the cross-compiler to generate the simplest possible
+native build environment for the target which is capable of rebuilding itself
+under itself.</p>
+
+<p>Anything else that needs to be built for the target can then be built
+natively, by running this kernel and root filesystem under an emulator and
+building new packages there, bootstrapping up to a full system if necessary.
+The emulator we use for this is QEMU.  Producing a minimal build environment
+powerful enough to boot and compile a complete Linux system requires seven
+packages: the Linux kernel, binutils, gcc, uClibc, BusyBox, make, and bash.
+We build a few more than that, but those are optional extras.</p>
+
+<p>This root filesystem can also be packaged using the
+<a href=http://www.linuxfromscratch.org/lfs>Linux From Scratch</a>
+/tools directory approach, staying out of the way so the minimal build
+environment doesn't get mixed into the final system, by setting the
+$NATIVE_TOOLSDIR environment variable.  If you don't know why you'd want
+to do that, you probably don't want to.</p>
+
+<p>In either configuration, the main target directory the build installs
+files into is held in the environment variable "$TOOLS".  If $NATIVE_TOOLSDIR
+is set this will be "/tools" in the new root filesystem, otherwise it'll
+be "/usr".</p>
+
+<p>The steps the script goes through are:</p>
+
+<ul>
+<li><p><b>directory setup</b> - Create empty directories for the basic
+filesystem layout.</p>
+
+<p>If $NATIVE_TOOLSDIR is set, build script will create a Linux From Scratch
+style intermediate system by moving the filesystem layout under /tools,
+which means skipping the top level directories and installing most files
+into /tools instead of /usr.  This also sets the variable
+$UCLIBC_DYNAMIC_LINKER to tell the compiler wrapper to create binaries that
+depend on shared libraries in /tools rather than the default
+"/lib/ld-uClibc.so.0".  (With the /tools layout, the qemu-setup.sh script can
+recreate most of the top level directories at runtime, often as symlinks
+into /tools.)</p>
+</li>
+
+<li><p><b>Copy sources/native</b> - The most important thing here is
+the qemu-setup.sh script, but there's also example source code in the
+src directory.</p></li>
+
+<li><p><b>Linux kernel</b> - Build a kernel that can boot under QEMU.</p>
+
+<p>We need kernel headers to build uClibc, so install those while we've got the
+kernel tarball extracted.  (We could grab these files directly from the cross
+compiler, but we rebuild from source to keep the layers cleanly separated.)</p>
+
+<p>The kernel build uses <b>sources/targets/$ARCH/miniconfig-linux</b>
+to configure the kernel for the appropriate QEMU target, and the
+$KERNEL_PATH variable to figure out which kernel image file to use.</p></li>
+
+<li><p><b>uClibc</b> - Build standard C library.</p>
+
+<p>The binaries in the target system are dynamically linked, so we need
+shared libraries installed.  Again, we could grab these files out of the cross
+compiler, but we rebuild from source to keep the layers cleanly separated.</p>
+
+<p>We unconditionally install the development files (headers and static
+libraries), and delete them later if $NATIVE_TOOLCHAIN isn't set.</p>
+</li>
+
+<li><p><b>toybox</b> - Build optional command line utilities.</p>
+
+<p>This isn't strictly required.  If $USE_TOYBOX isn't set, this only
+installs symlinks for the "patch" command and "oneit" commands.  (The
+oneit command is similar to init=/bin/sh, except it allows terminal control
+to work and shuts the system down cleanly on exit.  It's used by
+qemu-setup.sh to provide a more forgiving command line.)</p>
+
+<p>If $USE_TOYBOX is set, this installs toybox versions of many commands
+instead of the busybox versions.  These tend to be simpler, more
+straightforward implementations than the busybox versions.  (Note: your author
+is biased here.)</p>
+</li>
+
+<li><p><b>busybox</b> - Build busybox command line utilities.</p>
+
+<p>This provides the bulk of the command line utlities for the new
+system.</p>
+
+<p>Once upon a time, "make defconfig" provided the largest sane configuration
+in busybox, enabling every working command and feature that didn't have
+undesirable side effects (such as debugging options) or require special
+configuration to use (such as SELINUX).  Unfortunately, over time this goal
+was lost and make defconfig bit-rotted into a fairly random configuration.</p>
+
+<p>To recapture the original "largest sane configuration" goal, the build
+starts with "<b>make allyesconfig</b>" and applies
+<b>sources/trimconfig-busybox</b> to remove features that would otherwise
+cause problems.  The trimconfig file has comments in it if you're wondering
+why specific features are disabled.</p>
+</li>
+
+<li><p><b>Check $NATIVE_TOOLCHAIN</b> - Build a native development toolchain
+only if $NATIVE_TOOLCHAIN is set.</p>
+
+<p>$NATIVE_TOOLCHAIN is the only configuration option set by default.  You
+can disable it in "config" if you want to build skeletal target system and
+add your own software to it by hand.</p>
+
+<p>If it is enabled, the following happens:</p>
+<ul>
+<li><p><b>binutils</b> - Build a native assembler and linker.</p></li>
+
+<li><p><b>gcc and libsupc++</b> - Build a native C and C++ compiler.</p>
+
+<p>This process is still a bit tangled.  The fundamental reason for this
+is that the gcc build process is pathologically misdesigned.  (See
+<a href="#gcc_sucks">what the hell is wrong with gcc</a> for a long
+digression into the details.)</p>
+
+<p>The secondary reason is that libstdc++ is built into gcc, which makes as much
+sense as building glibc into gcc.  GCC's C++ support is not cleanly separated
+into layers, so replacing their built-in libstdc++ with the much smaller
+uClibc++ requires performing additional surgery on the gcc build process
+to get it to stop being actively stupid.  (For simplicity we punted on this
+while building the cross compiler, but now we need to make it work.)</p>
+
+<p>So after beating gcc over the head with almost a dozen different environment
+variables and a bunch of ./configure options to get it to cross compile like
+a normal program, we then have to chdir into the <b>libsupc++</b> subdirectory
+to build a static library which uClibc++ needs in order to interface properly
+with the compiler.  (It defines things like stack unwinding and the current
+exception model, which the C++ library needs to know but which gcc doesn't
+cleanly export for external use.)  Logically this step belongs with the
+uClibc++ build, but we have to export this information from the gcc source
+directory because that's where it lives.</p>
+
+<p>We also clean up after a bug where gcc uses multilib directories (such as
+/lib64) on some systems even when we explicitly told it we didn't
+want multilib.  (This package isn't very good at taking "no" for an answer.)
+And we create a "cc" symlink to gcc, because some packages use that as their
+compiler and SUSv3 says we should have one.</p>
+</li>
+
+<li><p><b>compiler wrapper</b> - Wrap gcc, to control path logic.</p>
+
+<p>The native build still installs the compiler wrapper
+(from sources/toys/gcc-uClibc.c) to rewrite gcc's command line arguments
+and bypass its built-in path logic.  In theory native
+compiling is less tricky and the final location we're installing the compiler
+at is known at compile time, so we could just patch the compiler's source
+code to check the right paths.  But going there rapidly turns into a nightmare
+of tangled historical scar tissue, and breaks in new and exciting ways
+with each new gcc release.  The only way to get gcc to use sane paths is to
+take path decisions out of its hands entirely.</p>
+
+<p>This does the same header/library shuffling and symlink creation as
+the cross compiler did, but without a prefix on the symlink names this
+time.</p>
+</li>
+
+<li><p><b>uClibc++</b> - Build micro standard c++ library.</p>
+
+<p>C++ has its own standard library, and its own standard header files,
+without which the overloaded bit shift operators can't even perform I/O.
+The package uClibc++ provides much smaller and simpler versions of these
+than the libstdc++-v3 metastasized through gcc-g++.</p>
+
+<p>This package mostly builds out of the box, assuming the cross compiler has
+minimal c++ support and you have the right pliers to extract libsupc++ from
+the gcc build.  We start with the defconfig, switch off TLS and LONG_DOUBLE
+support that uClibc doesn't currently provide, and blank the RUNTIME_PREFIX
+so it installs where we tell it to.  Then we shuffle the libraries around
+so the compiler wrapper can find them and make symlinks from the generic
+"libstdc++.{so,a}" names to the corresponding libuClibc++ files.</p>
+</li>
+
+<li><p><b>make</b> - Build make</p>
+
+<p>A toolchain doesn't do you much good without the "make" command.  Fairly
+straightforward to build.</p>
+</li>
+
+<li><p><b>bash</b> - The standard Linux command shell.</li>
+
+<p>Bash has been the standard Linux command shell since 1991, and
+lots of scripts explicitly say #!/bin/bash.  In addition, bash extensions
+like curly brace filename expansion are in common use.</p>
+
+<p>Someday, busybox might provide a decent replacement for bash, but since
+busybox has four different shells (lash, hush, msh, ash) which don't share a
+lot of code, development is fragmented and proceeds slowly.  A bash replacement
+will need to be callable as "#!/bin/bash" since debian pointed #!/bin/sh at the
+Defective Annoying SHell and greatly discouraged use of that symlink.</p>
+
+<p>We intentionally build an older version of bash (2.04b) which is
+sufficient for our purposes, and much smaller and simpler than the
+current bash 3.x monsters.  We have to hardwire a few things ./configure
+entries because this version doesn't like cross compiling, and we do so
+by supplying a config.cache file with the appropriate entries.  It also doesn't
+work if you try to build in parallel, so we don't supply -j.</p>
+</li>
+
+<li><p><b>distcc</b> - command to distribute compiles across a network
+cluster.</li>
+
+<p>We install this for <a href="#distcc_trick">the distc accelerator
+trick</a>.  It's entirely optional.</p>
+
+<p>We create a $TOOLS/distcc directory full of symlinks to distcc with the
+names of gcc, cc, g++, and c++.  Inserting that directory at the start of the
+$PATH makes the build use distcc in place of the normal native compiler.</p>
+</li>
+</ul>
+
+<p>That's everything in the $NATIVE_TOOLCHAIN.  The rest is minor cleanup
+and packaging.</p>
+
+<li><p><b>Build static and dynamic hello world binaries</b></p>
+
+<p>These are installed into $TOOLS/bin as hello-dynamic and hello-static.
+These are debugging tools: If you can't boot the system to a shell prompt,
+try running hello-static as init to see if it runs and gives you output.
+If that works try hello-dynamic to see if shared libraries are loading.</p></li>
+
+<li><p><b>Strip some binaries</b> to save space.</p></li>
+
+<li><p><b>Create the mini-native tarball</b> - we're done.</p></li>
+</ul>
+
+<p>In theory, you can add more packages to mini-native.sh, or run another
+similar script to use the cross compiler to produce output into the
+mini-native directory.  In practice, this is not recommended.  Cross
+compiling is an endless sinkhole of frustration, and the easiest way to
+deal with it is not to go there.</p>
+
+<h2>Packaging up a system image to run under emulation</h2>
+
+<p>The <b>package-mini-native.sh</b> script packages a system image for
+use by QEMU.  Its output goes into <b>build/system-image-$TARGET</b>
+directory, which is deleted at the start of the build if it already exists,
+so re-running this script always does a clean build.</p>
+
+<p>The steps here are:</p>
+
+<ul>
+<li><p><b>use genext2fs</b> to package the output of mini-native.sh as an 64
+megabyte ext2 image.</p></li>
+
+<li><p><b>create run-emulator.sh</b> by appending an emulator invocation
+command line to </b>sources/toys/run-emulator.sh</b>.</p>
+
+<p>This calls a shell function "emulator_command" from the target architecture
+definition, passing in the name of the ext2 image containing the root filesystem
+and the kernel image to boot.  A shell function "qemu_defaults" is defined
+to let emulator_command grab logs of common boilerplate, such as kernel
+command line options.  (In theory run_emulator is free to use a different
+emulator, or even output a command to send the files to real hardware
+through a network connection or jtag or some such.)</p>
+
+<p>The path for some or the run-emulator.sh kernel command line
+arguments is also adjusted based on $NATIVE_TOOLSDIR.</p>
+</li>
+
+<li><p>For the powerpc architecture, ppc_rom.bin is copied from
+sources/toys.  (This architecture needs a custom boot rom for qemu
+to be able to boot a bzImage via -kernel.)</p></li>
+
+<li><p>Tar up the result</p></li>
+</ul>
+
+<h2>Running on real hardware</a></h2>
+
+<p>To run a system on real hardware (not just under an emulator), you need to
+do several things.  Dealing with myriad individual devices is beyond the scope
+of this project, but the general theory is:</p>
+
+<ul>
+<li><p>Figure out how to flash your device (often a jtag with openocd)</p></li>
+
+<li><p>Configure and install a bootloader (uboot, apex, etc.)</p></li>
+
+<li><p>Build and install a kernel targeted to your hardware (in the kernel
+source, see arch/$ARCH/configs for default .config files for various
+boards)</p></li>
+
+<li><p>Package and install the root filesystem appropriately for your system
+(ext2, initramfs, jffs2).</p></li>
+</ul>
+
+<hr>
+
+<a name="why"><h1>Why do things this way</h1></a>
+
+<p>This section has some historical information.  It describes the evolution
+of the firmware Linux build process, but hasn't been brought up to date
+in all the particulars.</p>
+
+<h2>The basic theory</h2>
+
+<p>The Linux From Scratch approach is to build a minimal intermediate system
+with just enough packages to be able to compile stuff, chroot into that, and
+build the final system from there.  This isolates the host from the target,
+which means you should be able to build under a wide variety of distributions.
+It also means the final system is built with a known set of tools, so you get
+a consistent result.</p>
+
+<p>A minimal build environment consists of a C library, a compiler, and BusyBox.
+So in theory you just need three packages:</p>
+
+<ul>
+  <li>A C library (uClibc)</li>
+  <li>A toolchain (tcc)</li>
+  <li>BusyBox</li>
+</ul>
+
+<p>Unfortunately, that doesn't work yet.</p>
+
+<h2>Some differences between theory and reality.</h2>
+
+<h3>Environmental dependencies.</h3>
+
+<p>Environmental dependencies are things that need to be installed before you
+can build or run a given package.  Lots of packages depend on things like zlib,
+SDL, texinfo, and all sorts of other strange things.  (The GnuCash project
+stalled years ago after it released a version with so many environmental
+dependencies it was impossible to build or install.  Environmental dependencies
+have a complexity cost, and are thus something to be minimized.)</p>
+
+<p>A good build system will scan its environment to figure out what it has
+available, and disable functionality that depends on stuff that isn't
+available.  (This is generally done with autoconf, which is disgusting but
+suffers from a lack of alternatives.)  That way, the complexity cost is
+optional: you can build a minimal version of the package if that's all you
+need.</p>
+
+<p>A really good build system can be told that the environment
+it's building in and the environment the result will run in are different,
+so just because it finds zlib on the build system doesn't mean that the
+target system will have zlib installed on it.  (And even if it does, it may not
+be the same version.  This is one of the big things that makes cross-compiling
+such a pain.  One big reason for statically linking programs is to eliminate
+this kind of environmental dependency.)</p>
+
+<p>The Firmware Linux build process is structured the way it is to eliminate
+as many environmental dependencies as possible.  Some are unavoidable (such as
+C libraries needing kernel headers or gcc needing binutils), but the
+intermediate system is the minimal fully functional Linux development
+environment I currently know how to build, and then we switch into that and
+work our way back up from there by building more packages in the new
+environment.</p>
+
+<h3>Resolving environmental dependencies.</h3>
+
+<p><b>To build uClibc you need kernel headers</b> identifying the syscalls and
+such it can make to the OS.  Way back when you could use the kernel headers
+straight out of the Linux kernel 2.4 tarball and they'd work fine, but sometime
+during 2.5 the kernel developers decided that exporting a sane API to userspace
+wasn't the kernel's job, and stopped doing it.</p>
+
+<p>The 0.8x series of Firmware Linux used
+<a href=http://ep09.pld-linux.org/~mmazur/linux-libc-headers/>kernel
+headers manually cleaned up by Mariusz Mazur</a>, but after the 2.6.12 kernel
+he had an attack of real life and fell too far behind to catch up again.</p>
+
+<p>The current practice is to use the Linux kernel's "make headers_install"
+target, created by David Woodhouse.  This runs various scripts against the
+kernel headers to sanitize them for use by userspace.  This was merged in
+2.6.18-rc1, and was more or less debugged by 2.6.19.  So can use the Linux
+Kernel tarball as a source of headers again.</p>
+
+<p>Another problem is that the busybox shell situation is a mess with four
+implementations that share little or no code (depending on how they're
+configured).  The first question when trying to fix them is "which of the four
+do you fix?", and I'm just not going there.  So until bbsh goes in we
+<b>substitute bash</b>.</p>
+
+<p>Finally, <b>most packages expect gcc</b>.  The tcc project isn't a drop-in
+gcc replacement yet, and doesn't include a "make" program.  Most importantly,
+tcc development appears stalled because Fabrice Bellard's other major project
+(qemu) is taking up all his time these days.  In 2004 Fabrice
+<a href=http://fabrice.bellard.free.fr/tcc/tccboot.html>built a modified Linux
+kernel with tcc</a>, and
+<a href=http://fabrice.bellard.free.fr/tcc/tccboot_readme.html>listed</a>
+what needed to be upgraded in TCC to build an unmodified kernel, but
+since then he hardly seems to have touched tcc.  Hopefully, someday he'll get
+back to it and put out a 1.0 release of tcc that's a drop-in gcc replacment.
+(And if he does, I'll add a make implementation to toybox so we don't need
+to use any of the gnu toolchain).  But in the meantime the only open source
+compiler that can build a complete Linux system is still the gnu compiler.</p>
+
+<p>The gnu compiler actually consists of three packages <b>(binutils, gcc, and
+make)</b>, which is why it's generally called the gnu "toolchain".  (The split
+between binutils and gcc is for purely historical reasons, and you have
+to match the right versions with each other or things break.)</p>
+
+<p>This means that to compile a minimal build environment, you need seven
+packages, and to actually run the result we use an eighth package (QEMU).</p>
+
+<p>This can actually be made to work.  The next question is how?</p>
+
+<h2>Additional complications</h2>
+
+<h3>Cross-compiling and avoiding root access</h3>
+
+<p>The first problem is that we're cross-compiling.  We can't help it.
+You're cross-compiling any time you create target binaries that won't run on
+the host system.  Even when both the host and target are on the same processor,
+if they're sufficiently different that one can't run the other's binaries, then
+you're cross-compiling.  In our case, the host is usually running both a
+different C library and an older kernel version than the target, even when
+it's the same processor.</p>
+
+<p>The second problem is that we want to avoid requiring root access to build
+Firmware Linux.  If the build can run as a normal user, it's a lot more
+portable and a lot less likely to muck up the host system if something goes
+wrong.  This means we can't modify the host's / directory (making anything
+that requires absolute paths problematic).  We also can't mknod, chown, chgrp,
+mount (for --bind, loopback, tmpfs)...</p>
+
+<p>In addition, the gnu toolchain (gcc/binutils) is chock-full of hardwired
+assumptions, such as what C library it's linking binaries against, where to look
+for #included headers, where to look for libraries, the absolute path the
+compiler is installed at...  Silliest of all, it assumes that if the host and
+target use the same processor, you're not cross-compiling (even if they have
+a different C library and a different kernel, and even if you ./configure it
+for cross-compiling it switches that back off because it knows better than
+you do).  This makes it very brittle, and it also tends to leak its assumptions
+into the programs it builds.  New versions may someday fix this, but for now we
+have to hit it on the head repeatedly with a metal bar to get anything remotely
+useful out of it, and run it in a separate filesystem (chroot environment) so
+it can't reach out and grab the wrong headers or wrong libraries despite
+everything we've told it.</p>
+
+<p>The absolute paths problem affects target binaries because all dynamically
+linked apps expect their shared library loader to live at an absolute path
+(in this case /lib/ld-uClibc.so.0).  This directory is only writeable by root,
+and even if we could install it there polluting the host like that is just
+ugly.</p>
+
+<p>The Firmware Linux build has to assume it's cross-compiling because the host
+is generally running glibc, and the target is running uClibc, so the libraries
+the target binaries need aren't installed on the host.  Even if they're
+statically linked (which also mitigates the absolute paths problem somewhat),
+the target often has a newer kernel than the host, so the set of syscalls
+uClibc makes (thinking it's talking to the new kernel, since that's what the
+ABI the kernel headers it was built against describe) may not be entirely
+understood by the old kernel, leading to segfaults.  (One of the reasons glibc
+is larger than uClibc is it checks the kernel to see if it supports things
+like long filenames or 32-bit device nodes before trying to use them.  uClibc
+should always work on a newer kernel than the one it was built to expect, but
+not necessarily an older one.)</p>
+
+<h2>Ways to make it all work</h2>
+
+<h3>Cross compiling vs native compiling under emulation</h3>
+
+<p>Cross compiling is a pain.  There are a lot of ways to get it to sort of
+kinda work for certain versions of certain packages built on certain versions
+of certain distributions.  But making it reliable or generally applicable is
+hard to do.</p>
+
+<p>I wrote an <a href=/writing/docs/cross-compiling.html>introduction
+to cross-compiling</a> which explains the terminology, plusses and minuses,
+and why you might want to do it.  Keep in mind that I wrote that for a company
+that specializes in cross-compiling.  Personally, I consider cross-compiling
+a necessary evil to be minimized, and that's how Firmware Linux is designed.
+We cross-compile just enough stuff to get a working native build environment
+for the new platform, which we then run under emulation.</p>
+
+<h3>Which emulator?</h3>
+
+<p>The emulator Firmware Linux 0.8x used was User Mode Linux (here's a
+<a href=http://www.landley.net/writing/docs/UML.html>UML mini-howto</a> I wrote
+while getting this to work).  Since we already need the linux-kernel source
+tarball anyway, building User Mode Linux from it was convenient and minimized
+the number of packages we needed to build the minimal system.</p>
+
+<p>The first stage of the build compiled a UML kernel and ran the rest of the
+build under that, using UML's hostfs to mount the parent's root filesystem as
+the root filesystem for the new UML kernel.  This solved both the kernel
+version and the root access problems.  The UML kernel was the new version, and
+supported all the new syscalls and ioctls and such that the uClibc was built to
+expect, translating them to calls to the host system's C library as necessary.
+Processes running under User Mode Linux had root access (at least as far as UML
+was concerned), and although they couldn't write to the hostfs mounted root
+partition, they could create an ext2 image file, loopback mount it, --bind
+mount in directories from the hostfs partition to get the apps they needed,
+and chroot into it.  Which is what the build did.</p>
+
+<p>Current Firmware Linux has switched to a different emulator, QEMU, because
+as long as we're we're cross-compiling anyway we might as well have the
+ability to cross-compile for non-x86 targets.  We still build a new kernel
+to run the uClibc binaries with the new kernel ABI, we just build a bootable
+kernel and run it under QEMU.</p>
+
+<p>The main difference with QEMU is a sharper dividing line between the host
+system and the emulated target.  Under UML we could switch to the emulated
+system early and still run host binaries (via the hostfs mount).  This meant
+we could be much more relaxed about cross compiling, because we had one
+environment that ran both types of binaries.  But this doesn't work if we're
+building an ARM, PPC, or x86-64 system on an x86 host.</p>
+
+<p>Instead, we need to sequence more carefully.  We build a cross-compiler,
+use that to cross-compile a minimal intermediate system from the seven packages
+listed earlier, and build a kernel and QEMU.  Then we run the kernel under QEMU
+with the new intermediate system, and have it build the rest natively.</p>
+
+<p>It's possible to use other emulators instead of QEMU, and I have a todo
+item to look at armulator from uClinux.  (I looked at another nommu system
+simulator at Ottawa Linux Symposium, but after resolving the third unnecessary
+environmental dependency and still not being able to get it to finish compiling
+yet, I gave up.  Armulator may be a patch against an obsolete version of gdb,
+but I could at least get it to build.)</p>
+
+<h1>Packaging</h1>
+
+<p>The single file packaging combines a linux kernel, initramfs, squashfs
+partition, and cryptographic signature.</p>
+
+<p>In Linux 2.6, the kernel and initramfs are already combined into a single
+file.  At the start of this file is either the obsolete floppy boot sector
+(just a stub in 2.6), or an ELF header which has 12 used bytes followed by 8
+unused bytes.  Either way, we can generally use the 4 bytes starting at offset
+12 to store the original length of the kernel image, then append a squashfs
+root partition to the file, followed by a whole-file cryptographic
+signature.</p>
+
+<p>Loading an ELF kernel (such as User Mode Linux or a non-x86 ELF kernel)
+is controlled by the ELF segments, so the appended data is ignored.
+(Note: don't strip the file or the appended data will be lost.)  Loading an x86
+bzImage kernel requires a modified boot loader that can be told the original
+size of the kernel, rather than querying the current file length (which would
+be too long).  Hence the patch to Lilo allowing a "length=xxx" argument in the
+config file.</p>
+
+<p>Upon boot, the kernel runs the initramfs code which finds the firmware
+file.  In the case of User Mode Linux, the symlink /proc/self/exe points
+to the path of the file.  A bootable kernel needs a command line argument
+of the form firmware=device:/path/to/file (it can lookup the device in
+/sys/block and create a temporary device node to mount it with; this is
+in expectation of dynamic major/minor happening sooner or later).
+Once the file is found, /dev/loop0 is bound to it with an offset (losetup -o,
+with a value extracted from the 4 bytes stored at offset 12 in the file), and
+the resulting squashfs is used as the new root partition.</p>
+
+<p>The cryptographic signature can be verified on boot, but more importantly
+it can be verified when upgrading the firmware.  New firmware images can
+be installed beside old firmware, and LILO can be updated with boot options
+for both firmware, with a default pointing to the _old_ firmware.  The
+lilo -R option sets the command line for the next boot only, and that can
+be used to boot into the new firmware.  The new firmware can run whatever
+self-diagnostic is desired before permanently changing the default.  If the
+new firmware doesn't boot (or fails its diagnostic), power cycle the machine
+and the old firmware comes up.  (Note that grub does not have an equivalent
+for LILO's -R option; which would mean that if the new firmware doesn't run,
+you have a brick.)</p>
+
+<h2>Filesystem Layout</h2>
+
+<p>Firmware Linux's directory hierarchy is a bit idiosyncratic: some redundant
+directories have been merged, with symlinks from the standard positions
+pointing to their new positions.  On the bright side, this makes it easy to
+make the root partition read-only.</p>
+
+<h3>Simplifying the $PATH.</h3>
+
+<p>The set "bin->usr/bin, sbin->usr/sbin, lib->usr/lib" all serve to consolidate
+all the executables under /usr.  This has a bunch of nice effects: making a
+a read-only run-from-CD filesystem easier to do, allowing du /usr to show
+the whole system size, allowing everything outside of there to be mounted
+noexec, and of course having just one place to look for everything.  (Normal
+executables are in /usr/bin.  Root only executables are in /usr/sbin.
+Libraries are in /usr/lib.)</p>
+
+<p>For those of you wondering why /bin and /usr/sbin were split in the first
+place, the answer is it's because Ken Thompson and Dennis Ritchie ran out
+of space on the original 2.5 megabyte RK-05 disk pack their root partition
+lived on in 1971, and leaked the OS into their second RK-05 disk pack where
+the user home directories lived.  When they got more disk space, they created
+a new direct (/home) and moved all the user home directories there.</p>
+
+<p>The real reason we kept it is tradition.  The execuse is that the root
+partition contains early boot stuff and /usr may get mounted later, but these
+days we use initial ramdisks (initrd and initramfs) to handle that sort of
+thing.  The version skew issues of actually trying to mix and match different
+versions of /lib/libc.so.* living on a local hard drive with a /usr/bin/*
+from the network mount are not pretty.</p>
+
+<p>I.E. The seperation is just a historical relic, and I've consolidated it in
+the name of simplicity.</p>
+
+<p>On a related note, there's no reason for "/opt".  After the original Unix
+leaked into /usr, Unix shipped out into the world in semi-standardized forms
+(Version 7, System III, the Berkeley Software Distribution...) and sites that
+installed these wanted places to add their own packages to the system without
+mixing their additions in with the base system.  So they created "/usr/local"
+and created a third instance of bin/sbin/lib and so on under there.  Then
+Linux distributors wanted a place to install optional packages, and they had
+/bin, /usr/bin, and /usr/local/bin to choose from, but the problem with each
+of those is that they were already in use and thus might be cluttered by who
+knows what.  So a new directory was created, /opt, for "optional" packages
+like firefox or open office.</p>
+
+<p>It's only a matter of time before somebody suggests /opt/local, and I'm
+not humoring this.  Executables for everybody go in /usr/bin, ones usable
+only by root go in /usr/sbin.  There's no /usr/local or /opt.  /bin and
+/sbin are symlinks to the corresponding /usr directories, but there's no
+reason to put them in the $PATH.</p>
+
+<h3>Consolidating writeable directories.</h3>
+
+<p>All the editable stuff has been moved under "var", starting with symlinking
+tmp->var/tmp.  Although /tmp is much less useful these days than it used to
+be, some things (like X) still love to stick things like named pipes in there.
+Long ago in the days of little hard drive space and even less ram, people made
+extensive use of temporary files and they threw them in /tmp because ~home
+had an ironclad quota.  These days, putting anything in /tmp with a predictable
+filename is a security issue (symlink attacks, you can be made to overwrite
+any arbitrary file you have access to).  Most temporary files for things
+like the printer or email migrated to /var/spool (where there are
+persistent subdirectories with known ownership and permissions) or in the
+user's home directory under something like "~/.kde".</p>
+
+<p>The theoretical difference between /tmp and /var/tmp is that the contents
+of /tmp should be deleted by the system init scripts on every
+reboot, but the contents of /var/tmp may be preserved across reboots.  Except
+there's no guarantee that the contents of any temp directory won't be deleted.
+So any program that actually depends on the contents of /var/tmp being
+preserved across a reboot is obviously broken, and there's no reason not to
+just symlink them together.</p>
+
+<p>(I case it hasn't become apparent yet, there's 30 years of accumulated cruft
+in the standards, convering a lot of cases that don't apply outside of
+supercomputing centers where 500 people share accounts on a mainframe that
+has a dedicated support staff.  They serve no purpose on a laptop, let alone
+an embedded system.)</p>
+
+<p>The corner case is /etc, which can be writeable (we symlink it to
+var/etc) or a read-only part of the / partition.   It's really a question of
+whether you want to update configuration information and user accounts in a
+running system, or whether that stuff should be fixed before deploying.
+We're doing some cleanup, but leaving /etc writeable (as a symlink to
+/var/etc).  Firmware Linux symlinks /etc/mtab->/proc/mounts, which
+is required by modern stuff like shared subtrees.  If you want a read-only
+/etc, use "find /etc -type f | xargs ls -lt" to see what gets updated on the
+live system.  Some specific cases are that /etc/adjtime was moved to /var
+by LSB and /etc/resolv.conf should be a symlink somewhere writeable.</p>
+
+<h3>The resulting mount points</h3>
+
+<p>The result of all this is that a running system can have / be mounted read
+only (with /usr living under that), /var can be ramfs or tmpfs with a tarball
+extracted to initialize it on boot, /dev can be ramfs/tmpfs managed by udev or
+mdev (with /dev/pts as devpts under that: note that /dev/shm naturally inherits
+/dev's tmpfs and some things like User Mode Linux get upset if /dev/shm is
+mounted noexec), /proc can be procfs, /sys can bs sysfs.  Optionally, /home
+can be be an actual writeable filesystem on a hard drive or the network.</p>
+
+<p>Remember to
+put root's home directory somewhere writeable (I.E. /root should move to
+either /var/root or /home/root, change the passwd entry to do this), and life
+is good.</p>
+
+
+<p>Firmware Linux is an embedded Linux distribution builder, which creates a
+bootable single file Linux system based on uClibc and BusyBox/toybox.  It's
+basically a shell script that builds a complete Linux system from source code
+for an arbitrary target hardware platform.</p>
+
+<p>The FWL script starts by building a cross-compiler for the appropriate
+target.  Then it cross-compiles a small Linux system for the target, which
+is capable of acting as a native development environment when run on the
+appropriate hardware (or under an emulator such as QEMU).  Finally the
+build script creates an ext2 root filesystem image, and packages it with
+a kernel configured to boot under QEMU and shell scripts to invoke qemu
+appropriately.</p>
+
+
+<p>The FWL boot script for qemu (/tools/bin/qemu-setup.sh) populates /dev
+from sysfs, sets up an emulated (masquerading) network (so you can wget
+source packages or talk to <a href="#distcc_trick">distcc</a>), and creates
+a few symlinks needed to test build normal software packages (such as making
+/lib point to /tools/lib).  It also mounts /dev/hdb (or /dev/sdb) on /home
+if a second emulated drive is present.</p>
+
+<p>For most platforms, exiting the command shell will exit the emulator.
+(Some, such as powerpc, don't support this yet.  For those you have to kill
+qemu from another window, or exit the xterm.  I'm working on it.)</p>
+
+<p>To use this emulated system as a native build environment, see
+<a href="#native_compiling">native compiling</a>.</p>
+
+
+<a name="new_platform"><h1>Setting up a new platform</h1></a>
+
+<p>The differences between platforms are confined to a single directory,
+sources/targets.  Each subdirectory under that contains all the configuration
+information for a specific target platform FWL can produce system images
+for.  The same scripts build the same packages for each platform, differing
+only in which configuration directory they pull data from.</p>
+
+<p>Each target configuration directory has three interesting files:</p>
+
+<ul>
+<li><p><b>details</b> - sets a bunch of environment variables</li>
+<li><p><b>miniconfig-uClibc</b> - configuration for uClibc.</li>
+<li><p><b>miniconfig-linux</b> - configuration for the Linux kernel</li>
+</ul>
+
+<p>These configuration files are read and processed by the script
+<b>include.sh</b>.</p>
+
+<h2>Target name.</h2>
+
+<p>The name of the target directory is saved in the variable "$ARCH", and
+used to form a "tuple" for gcc and binutils by appending "-unknown-linux" to
+the directory name.  So the first thing to do is find out what platform name
+gcc and binutils want for your target platform, and name your target directory
+appropriately.</p>
+
+<p>(Note: if your platform really can't use an "${ARCH}-unknown-linux" style
+tuple, and instead needs a tuple like "bfin-elf", you can set the variable
+CROSS_TARGET in the "details" file to override the default value and feed
+some other --target to gcc and binutils.  You really shouldn't have to do
+this unless gcc doesn't yet fully support Linux on your platform.  Try the
+default first, and fix it if necessary.)</p>
+
+<p>The name of the target directory is also used in the name of the various
+directories generated during the build (temp-$ARCH, cross-compiler-$ARCH,
+and mini-native-$ARCH, all in the build/ directory), and as the prefix of the
+cross compiler binaries ($ARCH-gcc and friends).</p>
+
+<h2>$ARCH/details</h2>
+
+<p>The following environment variables may be set in the "<b>details</b>"
+file:</p>
+
+<ul>
+<li><p><b>CROSS_TARGET</b> - By default this is set to "${ARCH}-unknown-linux".</p>
+
+<p>This is used by binutils and gcc.  If your target really can't use that
+tuple name (perhaps needing a tuple like "bfin-elf" instead), you can set the
+variable CROSS_TARGET in the "details" file to override the default value and
+feed some other --target to gcc and binutils.</p>
+
+<p>You usually shouldn't have to set this yourself unless gcc doesn't yet fully
+support Linux on your platform.  Try the default first, and fix it if
+necessary.</p>
+</li>
+
+<li><p><b>KARCH</b> - architecture value for the Linux kernel (ARCH=$KARCH).</p>
+
+<p>The Linux kernel uses different names for architectures than gcc or binutils
+do.  To see all your options, list the "arch" directory of the linux kernel
+source.</p>
+</li>
+
+<li><p><b>KERNEL_PATH</b> - Path in the linux kernel source tree where the
+bootable kernel image is generated.</p>
+
+<p>This is the file saved out of the kernel build, to be fed to qemu's -kernel
+option.  Usually "arch/${KARCH}/boot/zImage", but
+sometimes bzImage or image in that directory, sometimes vmlinux in the top
+level directory...</p>
+</li>
+
+<li><p><b>GCC_FLAGS</b> - Any extra flags needed by gcc.</p>
+
+<p>Usually blank, but sometimes used to specify a floating point coprocessor
+or ABI.</p>
+</li>
+
+<li><p><b>BINUTILS_FLAGS</b> - Any extra flags needed by binutils.</p>
+
+<p>Usually blank.</p>
+</li>
+
+<li><p><b>QEMU_TEST</b> - Optional emulator for sanity test.</p>
+
+<p>At the end of the cross compiler build, a quick sanity
+test builds static and dynamic "Hello world!" executables with the new cross
+compiler.  If QEMU_TEST isn't blank and a file qemu-$QEMU_TEST
+exists in the $PATH, the cross compiler build script will then run qemu's
+application emulation against the static version of "hello world" as an
+additional sanity test, to make sure it runs on the target processor and
+outputs "Hello world!".</p>
+
+<p>Leave it blank to skip this test.</p>
+</li>
+
+<li><p><b>emulator_command</b> - Shell function run to generate the actual
+emulator invocation at the end of the run-$ARCH.sh shell script in the system
+image tarball.</p>
+
+<p>This is actually a shell function, not an environment variable.  The
+function should output an emulator command line to stdout (generally
+using "echo").  The function receives three arguments: $1 is the name of the
+ext2 image containing the root filesystem, $2 is the name of the kernel image,
+$3 is a set of
+platform-independent kernel command line arguments (currently "rw
+init=/tools/bin/sh panic=1 PATH=/tools/bin") to which emulator_command should
+append at least root= and console= arguments.</p>
+
+  This function is called from
+include.sh.</p>
+
+
+</ul>
+
+<p>The <b>details</b> file also defines the shell function
+<b>emulator_command</b>, which is run to generate the actual emulator
+invocation at the end of the run-$ARCH.sh shell script in the system image
+tarball.  The function should
+output an emulator command line to stdout (generally using "echo").  The
+function receives three arguments: $1 is the name of the ext2 image containing
+the root filesystem, $2 is the name of the kernel image, $3 is a set of
+platform-independent kernel command line arguments (currently "rw
+init=/tools/bin/sh panic=1 PATH=/tools/bin") to which emulator_command should
+append at least root= and console= arguments.</p>
+
+  This function is called from
+include.sh.</p>
+
+<a name="miniconfig"><h2>miniconfig-linux</h2>
+<p>The Linux kernel needs a configuration file to build.  Firmware Linux
+uses the "miniconfig" file format, which contains only the configuration
+symbols a user would have to switch on in menuconfig if they started from
+allnoconfig.</p>
+
+<p>This file is written as a "here" document, ala:</p>
+<blockquote>
+<pre>
+cat > "${WORK}"/miniconfig-linux << 'EOF'
+[insert file contents here]
+EOF
+</pre>
+</blockquote>
+
+<p>To generate a miniconfig, first configure your kernel with menuconfig,
+then copy the resulting .config file to a temporary filename (such as
+"tempfile").  Then run the miniconfig.sh script in the sources/toys directory
+with the temporary file name as your argument and with the environment variable
+ARCH set to the $KARCH value in your new config file (and exported if
+necessary).  This should produce a new file, "mini.config", which is your
+.config file converted to miniconfig format.</p>
+
+<p>For example, to produce a miniconfig for a given platform:</p>
+<blockquote>
+<pre>
+make ARCH=$KARCH menuconfig
+mv .config tempfile
+ARCH=$KARCH miniconfig.sh tempfile
+ls -l mini.config
+</pre>
+</blockquote>
+
+<p>To expand a mini.config back into a full .config file (to build a kernel
+by hand, or for further editing with menuconfig), you can go:</p>
+
+<blockquote>
+<pre>
+make ARCH=$KARCH allnoconfig KCONFIG_ALLCONFIG=mini.config
+</pre>
+</blockquote>
+
+<p>Remember to supply an actual value for $KARCH.</p>
+
+<h2>miniconfig-uClibc</h2>
+
+<p>Just like the Linux kernel, uClibc needs a .config file to build, and
+so the Firmware Linux configuration file supplies a miniconfig.  Note that
+uClibc doesn't require an ARCH= value, because all its architecture information
+is stored in the config file.  Otherwise the procedure for creating and using
+it is the same as for the Linux kernel, just with a different filename and
+contents.</p>
+
+<p>Note that Firmware Linux patches uClibc to work with miniconfig files,
+the base uClibc 0.9.29 release doesn't support miniconfig files yet.</p>
+
+<hr>
+
+<!--
+
+<p>This root filesystem acts as a minimal native build environment for the
+target platform.  This means it contains a compiler and associated build
+tools capable of building a complete new Linux system under itself.  If you're
+interested in building a more complex development environment within this one,
+see the <a href=http://www.linuxfromscratch.org/lfs/view/6.4/>Linux From
+Scratch</a> project for ideas on how to bootstrap your way up (adding
+zlip and perl and such before building more complicated packages).</p>
+
+<p>Note that FWL can build a LFS "temporary system", but that the packaged
+mini-native tarballs and system images are not configured that way.</p>
+
+<p>The vast majority of the space taken up by this filesystem is the
+development toolchain and associated support files (mostly header files and
+libraries).</p>
+
+<p>If you're doing anything fancy, you'll probably want to rebuild it from
+source.</p>
+
+GCC is bad at cross compiling.
+
+<p>A cross compiler reads input files and writes output files.  So does a
+docbook to PDF converter; this is nothing special.  A program can take both
+explicit and implicit input.  Explicit input is listed on the command line,
+or perhaps piped into stdin.  Implicit input in the case of the docbook->pdf
+converter would include fonts and stylesheets, which might live at some
+common path on the host, or be handed out by a server.</p>
+
+<p>Compilers take implicit input from five places:</p>
+
+  compiler #includes
+  system library #includes
+  compiler libs
+  system libs
+ 
+
+<p>In theory, someday busybox may provide a decent /bin/bash replacement,
+but unfortunately busybox shell development is terminally fragmented (between
+lash, hush, msh, and ash, which do not share significant amounts of code),
+so don't hold your breath.</p>
+
+<pre>
+  variables for invoking download
+    mirrors
+  --extract, setupfor, cacheing
+  why hard links instead of symlinks
+    Packages that modify distributed source files without breaking links: bad.
+
+  CPUS, make -j  (As much parallelism as possible; SMP increasing.)
+
+  Minimal native build environment, seven packages.
+    Why bash?
+      Busybox ash buggy.  Busybox has four shells, not one scalable shell.
+      Older version of bash, smaller and simpler.
+
+  sources/native
+    src
+    qemu-setup.sh/chroot-setup.sh
+</pre>
+
+<hr>
+
+<h2><a name="native_compiling">Native compiling under emulation</a></h2>
+
+<pre>
+Why do this?
+the distcc trick
+  run-with-distcc.sh
+hdb for working space.
+  run-with-home.sh
+  Building on nfs sucks rocks.
+  Building out of tree with cp -rs
+
+/tools (Linux From Scratch chapter 5).
+  qemu-setup.sh and the /lib symlink.
+
+Deficiencies in the current mini-native filesystem:
+  host-tools.sh, bzip2, coreutils, diffutils.
+
+Building glibc is your problem.
+  It requires perl.  Statically linking "hello world" is 400k.  It's evil.
+  Still, building it natively sucks less than trying to cross compile it.
+  Pretty much follow the non-cross Linux From Scratch procedures.
+
+Building a distro:
+  Linux From Scratch.
+  Gentoo embedded.
+  Debian/ubuntu.
+
+anatomy_of_include
+</pre>
+
+<h2><a name="customize">Customizing mini-native</a></h2>
+
+Adding packages (to the script, without the script)
+
+build/temp-$ARCH
+build/cross-compiler-$ARCH
+build/mini-native-$ARCH
+build/qemu-image-*.tar
+
+
+<a name="gcc_sucks><h2>What the hell is wrong with GCC?</h2></a>
+
+<p>First of all, gcc wants to build itself with itself.  When you build
+gcc it wants to compile a temporary version of itself, and then build
+itself again with that temporary compiler, and then build itself a _third_
+time with the second compiler.
+
+-->
+
+
+
+
+<!--#include file="footer.html" -->
--- a/www/header.html	Tue Dec 02 03:02:18 2008 -0600
+++ b/www/header.html	Tue Dec 02 03:17:23 2008 -0600
@@ -15,9 +15,7 @@
   <ul>
     <li><a href="index.html">Intro</a></li>
     <li><a href="news.html">News</a></li>
-    <li><a href="about.html">What is it?</a></li>
-    <li><a href="design.html">Design Docs</a></li>
-    <li><a href="new_platform.html">Porting</a></li>
+    <li><a href="documentation.html">Documentation</a></li>
     <li><a href="downloads/README">README</a></li>
   </ul>
   <b>Download</b>
--- a/www/new_platform.html	Tue Dec 02 03:02:18 2008 -0600
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,130 +0,0 @@
-<!--#include file="header.html" -->
-
-<h2>Setting up a new platform</h2>
-
-<p>The differences between platforms are confined to a single file, which is
-the platform configuration file in the <b>sources/configs</b> directory.  The
-same scripts build the same packages for each platform, differing only in
-which configuration file they read.</p>
-
-<p>Each configuration file sets some environment variables, defines one
-shell function, and writes two data files.  The name of the configuration file
-is also significant.</p>
-
-<p>Configuration files are read and processed by the script
-<b>include.sh</b>.</p>
-
-<h2>Naming your configuration file.</h2>
-
-<p>The name of the platform configuration file is used to form a "tuple" for
-gcc and binutils by appending "-unknown-linux" to the filename.  So the first
-thing to do is find out what platform name gcc and binutils want for your
-target platform, and name your config file appropriately.</p>
-
-<p>(Note: if your platform really can't use an "${ARCH}-unknown-linux" style
-tuple, and instead needs a tuple like "bfin-elf", you can set the variable
-CROSS_TARGET in the config file to override the default value and feed
-some other --target to gcc and binutils.  You really shouldn't have to do
-this unless gcc doesn't yet fully support Linux on your platform.  Try the
-default first, and fix it if necessary.)</p>
-
-<p>The name of the configuration file is also used in the name of the various
-directories generated during the build (temp-$NAME, cross-compiler-$NAME,
-and mini-native-$NAME, all in the build/ directory), and as the prefix of the
-cross compiler binaries ($NAME-gcc and friends).</p>
-
-<h2>Setting environment variables.</h2>
-<p>The following environment variables are usually set in a configuration
-file:</p>
-<ul>
-<li><b>KARCH</b> - architecture value for the Linux kernel (ARCH=$KARCH).  The
-Linux kernel uses different names for architectures than gcc or binutils
-do.  To see all your options, list the "arch" directory of the linux kernel
-source.</li>
-<li><b>KERNEL_PATH</b> - Path in the linux kernel source tree where the bootable
-kernel image is generated.  This is the file saved out of the kernel build, to
-be fed to qemu's -kernel option.  Usually "arch/${KARCH}/boot/zImage", but
-sometimes bzImage or image in that directory, sometimes vmlinux in the top
-level directory...</li>
-<li><b>GCC_FLAGS</b> - Any extra flags needed by gcc.  Usually blank, but
-sometimes used to specify a floating point coprocessor or ABI.</li>
-<li><b>BINUTILS_FLAGS</b> - Any extra flags needed by binutils.  Usually
-blank.</li>
-<li><b>QEMU_TEST</b> - At the end of the cross compiler build, a quick sanity
-test builds static and dynamic "Hello world!" executables with the new cross
-compiler.  Optionally, if QEMU_TEST isn't blank and a file qemu-$QEMU_TEST
-exists in the $PATH, the cross compiler build script will then run qemu's
-application emulation against the static version of "hello world" as an
-additional sanity test, to make sure it runs on the target processor and
-outputs "Hello world!".  Leave it blank to skip this test.</li>
-</ul>
-
-<h2>emulator_command</h2>
-
-<p>The shell function <b>emulator_command()</b> is used to generate
-the run-$ARCH.sh shell script in the build directory.  The function should
-output an emulator command line to stdout (generally using "echo").  The
-function receives three arguments: $1 is the name of the ext2 image containing
-the root filesystem, $2 is the name of the kernel image, $3 is a set of
-platform-independent kernel command line arguments (currently "rw
-init=/tools/bin/sh panic=1 PATH=/tools/bin") to which emulator_command should
-append at least root= and console= arguments.  This function is called from
-include.sh.</p>
-
-<a name="miniconfig"><h2>miniconfig-linux</h2>
-<p>The Linux kernel needs a configuration file to build.  Firmware Linux
-uses the "miniconfig" file format, which contains only the configuration
-symbols a user would have to switch on in menuconfig if they started from
-allnoconfig.</p>
-
-<p>This file is written as a "here" document, ala:</p>
-<blockquote>
-<pre>
-cat > "${WORK}"/miniconfig-linux << 'EOF'
-[insert file contents here]
-EOF
-</pre>
-</blockquote>
-
-<p>To generate a miniconfig, first configure your kernel with menuconfig,
-then copy the resulting .config file to a temporary filename (such as
-"tempfile").  Then run the miniconfig.sh script in the sources/toys directory
-with the temporary file name as your argument and with the environment variable
-ARCH set to the $KARCH value in your new config file (and exported if
-necessary).  This should produce a new file, "mini.config", which is your
-.config file converted to miniconfig format.</p>
-
-<p>For example, to produce a miniconfig for a given platform:</p>
-<blockquote>
-<pre>
-make ARCH=$KARCH menuconfig
-mv .config tempfile
-ARCH=$KARCH miniconfig.sh tempfile
-ls -l mini.config
-</pre>
-</blockquote>
-
-<p>To expand a mini.config back into a full .config file (to build a kernel
-by hand, or for further editing with menuconfig), you can go:</p>
-
-<blockquote>
-<pre>
-make ARCH=$KARCH allnoconfig KCONFIG_ALLCONFIG=mini.config
-</pre>
-</blockquote>
-
-<p>Remember to supply an actual value for $KARCH.</p>
-
-<h2>miniconfig-uClibc</h2>
-
-<p>Just like the Linux kernel, uClibc needs a .config file to build, and
-so the Firmware Linux configuration file supplies a miniconfig.  Note that
-uClibc doesn't require an ARCH= value, because all its architecture information
-is stored in the config file.  Otherwise the procedure for creating and using
-it is the same as for the Linux kernel, just with a different filename and
-contents.</p>
-
-<p>Note that Firmware Linux patches uClibc to work with miniconfig files,
-the base uClibc 0.9.29 release doesn't support miniconfig files yet.</p>
-
-<!--#include file="footer.html" -->