===========================
     APEX Boot Loader
       Boot Images
===========================

This README explains some of the features and implementation details
of handling boot image formats.  From the start, APEX has worked with
raw, binary data for kernels and ramdisk images.  Around the 1.6.x
versions, support for U-BOOT and an APEX image format were added to
improve interoperability and error detection.


Image Formats and APEX Commands
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

The supported image formats are handled uniformly.  Whether it is a
U-BOOT image or an APEX image, the NEW 'image' command will
transparently process either format.  The standard copy and checksum
commands will operate on the raw data of the image without attempting
to comprehend the image format iteslf.  The new image command performs
operations on images that interpret the header.

  load     - load the data of an imate into memory to the addresses
             specified in the image header
  checksum - verify header and data checksums
  show     - display information about an image


APEX Image Format
~~~~~~~~~~~~~~~~~

This is a tagged image format designed to be easy to load, extensible,
and compatible with stream IO.  APEX images have the following form:

  IMAGE
  +--------+-----+---------+-----+---------+---------+-----+-----+
  | HEADER | CRC | PAYLOAD | CRC | PADDING | PAYLOAD | CRC | ... |
  +--------+-----+---------+-----+---------+---------+-----+-----+

The HEADER, and the first CRC are required.  The PAYLOADs are optional
and there may be more than one.  The header must specify the length of
each PAYLOAD.  The CRC immediately following the header protects whole
header including the SIGNATURE.  Each PAYLOAD is protected by the CRC
that follows it.

The CRC polynomial is the same for the header and the PAYLOADs, but
the computation of the CRC values is slightly different between them.
The header CRC is computed over the whole HEADER, from signature to
the last padding byte before the CRC such that computing the CRC of
every byte in the header including the CRC will yield a zero.

The CRC computation for each PAYLOAD is compatible with the POSIX
cksum program.  It is the CRC over the data bytes in the PAYLOAD
followed by the significant bytes of the binary integer for the
PAYLOAD length in LSB order.  The CRC is the one's complement of this
result which will match the CRC value returned by the cksum command
over the PAYLOAD data.  The image file is padded between the PAYLOAD
CRC to force the next PAYLOAD to begin on an even 16 byte boundary.

The header begins with a four byte SIGNATURE and a single byte
HEADER_SIZE that, when multiplied by 16, specifies the size of the
HEADER including the SIGNATURE, HEADER_SIZE and the CRC.  A
HEADER_SIZE value of zero is reserved and invalid.  The rest of the
header is a sequence of tagged fields followed by the CRC32 checksum
in the last four bytes.  The HEADER is padded between the last FIELD
and the CRC32 to round the HEADER to an even multiple of 16 bytes.


  HEADER
  +-----------+-------------+-------+-----+---------+-------+
  | SIGNATURE | HEADER_SIZE | FIELD | ... | PADDING | CRC32 |
  +-----------+-------------+-------+-----+---------+-------+


The signature identifies that the file is an APEX image as well as
specifying the version number of the format; in this case, '0'.  The
format is designed such that there ought not be a reason to revise it,
but the option is left open.

  SIGNATURE (4B)
  +------+------+------+------+
  | 0x41 | 0x69 | 0x30 | 0xb9 |
  +------+------+------+------+


FIELDs begin with a one byte TAG that is a combination of a field ID
and a two bit encoding of the field SIZE.

  TAG (1B)
  +---+---+---+---+---+---+---+---+
  |        FIELD_ID       | SIZE  |
  +---+---+---+---+---+---+---+---+
    7   6   5   4   3   2   1   0

The SIZE field encodes as follows:

  1 1  - Field has no bytes following the TAG.
  1 0  - Field has one data byte following the TAG.
  0 1  - Field has 4 bytes of data following the TAG.
  0 0  - First byte after the TAG defines the length of data
         following the TAG.

Four byte DATA usually carry 32 bit integers.  These values must be
stored in MSB order.  To be more precise, multi-byte values in the
header are always stored in network order, MSB first.

Variable length fields are often UTF-8 strings.  These strings must be
null terminated even though doing so is redundant.  Thus, the string
field "Awesome" would require nine DATA bytes.

The length byte for variable length fields has a range from 0 to 127.
Values above 127 are reserved and invalid.  A zero length byte value
is valid and may be used for FIELDs that usually have variable length
data, but are empty in a particular cases.

FIELD_ID's have a range from 0x0 to 0xfc where the lowest two bits are
set to zero.  IDs 0x00 - 0x0c and 0xe0 - 0xf8 are reserved.  ID 0xfc
is a NOP field and a TAG of 0xff must be used as padding in the
header.

  Field IDs
  ~~~~~~~~~

  0x10 | 0 - Image description (V)
  0x14 | 1 - Image creation date (4B)
  0x30 | 1 - Payload length in bytes, must be first for each payload (4B)
  0x34 | 1 - Payload load address (4B)
  0x38 | 1 - Payload entry point (4B)
  0x3c | 2 - Payload type (1B)
             0x01 Linux Kernel
             0x02 Linux Kernel Initrd
  0x40 | 0 - Payload description (V)
  0x44 | 3 - Payload compression (0B)
  0x80 | 1 - Linux Kernel architecture ID (4B)
  0xfc | 3 - NOP; padding (0B)

As a matter of practical implementation, there shall be only one size
encoding for each TAG.  This is both a convention, to make the
generation and parsing of FIELDs easier, and a standardization of the
header data format.  For example, even though a succinct payload
description field, e.g. "One", would require just four bytes, the TAG
is defined as 0x00 such that it always bears a length byte.


U-BOOT Image Format
~~~~~~~~~~~~~~~~~~~

The UBOOT image format was originally designed to carry a single payload.
The file begins with a fixed-length header, 64 bytes followed by the
payload.

  IMAGE
  +--------+---------+
  | HEADER | PAYLOAD |
  +--------+---------+

There is a multi-image format that modifies the basic format with an
NULL terminated array of payload lengths immediately after the header
and followed by the payload data.

  MULTI-IMAGE
  +--------+--------+-----+---+---------+
  | HEADER | LENGTH | ... | 0 | PAYLOAD |
  +--------+--------+-----+---+---------+

In this case, the header is identical, so there is only one CRC for
all payloads, the data_size field of the header refers to the size of
all payloads, there is only one entry point, and there is only one
load address for all payloads.  All payload data is loaded starting at
the load address in the header.  When booting Linux, UBOOT interprets
the first two payloads of a multi-image as a kernel and initrd.  The
load address and length of the initrd will be recorded and passed to
the kernel.  APEX performs the same steps.

The U-BOOT header is a fixed size record with several enumerated
fields.  For the most part, these fields are ignored and are
unimportant when this format is being used to load Linux kernels and
initial ramdisk images. 

  struct header {
    uint32_t magic;			// 0x27 0x05 0x19 0x56
    uint32_t header_crc;
    uint32_t time;
    uint32_t size;
    uint32_t load_address;
    uint32_t entry_point;
    uint32_t crc;			// CRC for all payloads
    uint8_t  os;
    uint8_t  architecture;
    uint8_t  image_type;
    uint8_t  compression;
    char     image_name[32];
  };

Part of the design of the APEX image format is aimed to address some
of the awkward design choices present in the U-BOOT design.

  o The U-BOOT header checksum field is in the middle of the header.
    It must be zeroed when computing the header CRC.
  o The U-BOOT CRC is LSB ordered which makes it incompatible with
    cksum.  It also does not compute to zero when the CRC is appended
    to the end of the calculation.
  o The header is fixed size which illicited the multi-image hack used
    to load the kernel and initrd from a single image.
  o There are several fields in the header that don't pertain to
    loading images for Linux.  These fields cannot be removed.
  o Even with a multi-image format, there is no way to change the load
    address of successive payloads.  All payloads are loaded
    sequentially and  the loader must assume that the first payload is
    the kernel and the second is an initrd.  There is an option to the
    image command that will relocate the initrd of a uBoot image which
    *must* not follow the kernel where the kernel is loaded for
    execution.
