kboot - A Boot Loader Based on kexec
====================================

Written 2005-2007 by Werner Almesberger
Distributed under the terms of version 2 of the GPL, see below.


Overview
========

This is a very rough prototype that illustrates some of the basic
concepts and provides a platform for developing more sophisticated
functionality.

The command-line interface is currently implemented as a shell
script, which makes it a little slow on some machines.

kboot can currently boot Linux kernels, execute a number of shell
commands in the boot environment, and automatically mounts file
systems when they are referenced in a path to the kernel, or in a
"cd" command. It speaks NFS, HTTP, and SSH fluently.

There are many "must have" features, which haven't been implemented
yet, such as

- file name completion
- booting of non-Linux operating systems

See TODO for the current list of missing features (not all of them
are top priority, though).

Most of the configuration is explained in config/README, not in this
file.


Copying
-------

This package is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

See the file COPYING.GPL for details.


Installation
============

kboot builds some or all of the following packages:

 - the Linux kernel
 - the GNU tool chain (gcc and binutils)
 - the uClibc small C library
 - BusyBox, a collection of frequently used programs
 - udev, the user-space /dev manager
 - the kexec tools
 - the dropbear SSH client and daemon
 - kbd, the keyboard utilities

In principle, all that's needed to build kboot is to copy a .config
file yielding a 2.6.16.1 kernel (that runs on the current machine)
to the file local-kernel-config in the kboot directory, and run
"make".

For fine-tuning the build process, see below. Note that gcc is built
twice: first for the host system, then for the kboot environment.
The first build is needed to provide a well-known context for
uClibc. The second build yields a compiler that uses uClibc instead
of glibc, which is then used to build the kboot user space.

The kernel configuration must contain all essential drivers, without
using modules.


Why yet another "build the world" system ?
------------------------------------------

There are various packages that can be used to build an independent
root file system. Typically they come in in the form of a
cross-development environment. Examples include crosstool (the
tool chain and glibc only), buildroot (a basic root file system),
and OpenEmbedded (a large set of packages).

Unfortunately, none of them currently quite satisfies all the key
requirements of the build process of kboot, which are:

 - the ability to use a small C library,
 - support for the i386 and amd64 architecture,
 - tight control over the versions of components, and
 - a minimum of manual configuration. In particular, no interactive
   configuration.

Because of the huge number of subtle dependencies between packages,
the build system must be able to ensure that only packages are
combined which are known to inter-operate. Similarly, we try to
minimize external dependencies, such as the use of revision control
systems as a download mechanism.


Directory structure
-------------------

At build time, kboot uses the following subdirectories:

config/
    Home of all user-provided configuration files. Please see
    config/README for details.

scripts/
    The "kboot" shell and various scripts used during the build
    process.

keymaps/
    Binary keymaps generated with "make keymaps".

patches/
    Any patches used when building 3rd party packages.

dl/
    Cache for all the downloaded packages.

build/
    Temporary structure containing the tools chains. This directory
    is created during the build process.
  
root/
    A copy of kboot's root file system. This directory is created
    during the build process, and is sometimes emptied or removed
    by "make config".

    For experiments, this environment can be entered with

    # make try

    which does a  chroot root /init  and also unmounts root/proc,
    root/sys, and root/mnt/root, and resets the terminal. The
    kboot environment can be left by entering an EOF (press ^D on
    a new line).

    If SSH server functionality is enabled, the server is started
    on port 2222 instead of the usual 22.

    If a keymap is set, it will be loaded, even if not running on
    the console.

root-meta/
    Meta-information about the content of root/. This directory
    is created during the build and configuration process.


Downloading
-----------

The kboot build process automatically downloads the sources for
all the packages. To download everything at once, and then
proceed without accessing the network, run

% make download

Packages can also be downloaded or copied manually. For this,
please check first that you have the exact version expected,
or they will be downloaded anyway:

% make packages

Then copy or symlink the source package into dl/. Then, for
each package, do a

% touch dl/<package-file-name>.ok

e.g.

% cp /some/where/foo-2.3.tar.bz2 dl/
% touch dl/foo-2.3.tar.bz2.ok

Note that some packages end in .bz2, while others end in .gz !


Configuring kboot
-----------------

kboot uses a number of configuration files. Most of them are copies
of files already existing on the host. Please see config/README for
details.

Once the configuration files are in place, run "make config" to
complement and propagate the information. After changing any of the
configuration files, you should also run "make config", followed by
"make", to process the changes.

Note that, unlike all other steps of the build process, "make
config" may stop to ask questions. The answers are recorded, so
that the questions are only asked once. To be asked again, run
"make reconfig".


Package configuration
---------------------

kboot automatically configures all packages. In the case of packages
that use the same configuration system as the Linux kernel, this is
done by first running

% make defconfig

appending all the settings to override (independent of whether this
actually causes a change or not), and incorporating them with

% make oldconfig

The overridden settings are in kboot's Makefile. Note that, when
changing them, other configuration options may become enabled, for
which no defaults are available in the configuration file. When
this happens, the configuration process will stop and ask for user
input. To avoid such interruptions in the future, the new options
should then also be added to kboot's Makefile.


Keyboard configuration
----------------------

If the console uses a keyboard layout different from the one the
firmware assumes, kboot can load a different keymap, as follows:

- build the keymaps and the keymap converter:
  make keymaps

- choose one keymap from keymaps/ and copy it to config/, e.g.
  cp keymaps/es.bkeymap config/

  Note: if there is more than one keymap in config/, "make" will
        fail with an error.

- run "make". If "make" does not notice the change and rebuilds
  the initramfs (kboot-root.cpio.gz), touch a file in config/ and
  try again, e.g.
  touch config/kboot.conf
  make


Build results
-------------

The kboot build produces two outputs: a bootable kernel, and an
initramfs containing the boot environment. These two items need to
be added to a boot loader like LILO or GRUB. kboot does not (yet)
install a first-stage boot loader.

The bootable kernel is in the usual location in the kernel source
tree, e.g., linux-2.6.13.2/arch/i386/boot/bzImage

The initramfs is stored in the file kboot-root.cpio.gz


Setting up the boot loader
--------------------------

The boot loader must be set up to load kboot's kernel, with the
initramfs as an initrd. If using LILO, the entry may look like
this:

image = /home/kboot/linux-2.6.13.2/arch/i386/boot/bzImage
  label = kboot
  initrd = /home/kboot/kboot-root.cpio.gz

or, if copying the files to /boot:

image = /boot/bzImage.kboot
  label = kboot
  initrd = /boot/kboot-root.cpio.gz


Using kboot
===========

After starting, kboot displays its prompt on the system console.
If a timeout is set, a key producing input (e.g., [Space], a
letter, [Del], etc., but not [Shift], [Alt], and such) must be
pressed in time to keep kboot from automatically proceeding with
the default. See the entries on "default", "delay", and "timeout"
in config/README for details.

If configured accordingly, kboot can also be accessed via SSH. It
listens on port 22, and the default user name is "kboot". SSH
configuration is described in further detail in config/README.

A kernel is booted by specifying its name, followed by any
arguments that should be passed on the boot command line.

The kernel name can have the following forms:

label
    A pre-defined expansion, see above. Label names are
    case-sensitive.
    Example: b26161 root=/dev/hda3

/path/to/kernel
    An absolute path to the kernel, stored in the booted system.
    kboot automatically mounts the file systems needed to access
    the kernel image, according to the fstab file provided when
    building the initramfs.
    Example: /home/k/linux-2.6.16.1/arch/i386/boot/bzImage

//path/to/kernel
   An absolute path to a kernel stored on kboot's temporary file
   system. If this path leads out to the booted file system, the
   usual automatic mounting is done.
   Example:
        cd //tmp
	wget http://some.host.net/kernel.rar
	unrar x kernel.rar
	//tmp/bzImage

relative/path/to/kernel
    As above, but the path is relative to the current directory,
    which can be on the booted file system, or on kboot's
    temporary file system.
    Example:
	cd /home/k/linux-2.6.13.1/arch/i386/boot
	bzImage root=/dev/sda1

device:/path/on/device
device:path/on/device
    A file on an explicitly named device. The device can be
    specified with the path to a device file, or simply with the
    name of the file in /dev.
    Example: sda6:kernels/bzImage.old

host:/path
   A file on an NFS server. The address can be specified in the
   numeric format, or as a name.
   Example: server.my.org:/kernels/bzImage

http://host/path/to/file
http://host:port/path/to/file
   A file on an HTTP server.
   Example: cat http://www.kernel.org/kdist/finger_banner

ftp://host/path/to/file
ftp://host:port/path/to/file
   A file on an FTP server.
   Example: ftp://ftp.kernel.org/pub/linux/kernel/v2.6/linux-2.6.13.3.bin
     (just kidding)

tftp://host/path/to/file
tftp://host:port/path/to/file
   A file on a TFTP server.
   Example: tftp://bootserver.my.net/kernel-0a000001

kboot recognizes the following "internal" commands:

cd directory
    Change to the specified directory. Automatic mounting and the
    distinction of / and // are applied like for kernel images.
    Also the device:... and host:... forms can be used with "cd".

pwd
    Print the current directory.

Any other command is handed to the shell for execution. In
particular, a shell with command-line editing and file name
completion can be be obtained by simply typing "sh".


Troubleshooting
---------------

Sometimes, a bad configuration can render kboot unusable. There are
three types of means to recover from such problems:

- pass the parameter  kboot=local  on the boot command line.
  This makes kboot use only the configuration files obtained at
  build time, so any errors that have been introduced later in
  files on the real root file system (if kboot uses them) will
  be avoided.

- pass the parameter  rdinit=/bin/sh  on the boot command line.
  This bypasses kboot entirely and starts a shell that operates in
  the system environment of kboot. From this shell, recovery can
  be attempted.

- press Ctrl-C before the "kboot:" prompt appears.
  Like with the above option, a shell is started. This method for
  getting a shell is particularly useful if the first-stage boot
  loader does not support a boot command line.


Known bugs
==========

There are many of them. The most glaring ones:

- some operations are of the type "Try X. If it fails, try Y instead."
  This can sometimes yield stray error messages (if X fails and shows
  its errors), or hide errors (if X redirects its stderr to /dev/null).

- the tty is only temporarily switched to raw mode, so any input
  between kboot prompts will echo, and lead to confusing output.

- path names containing spaces and other special characters can cause
  confusion all over the place
