Let's assume we're booting from a bank-switched or paged
device (e.g. paged flash, disk device, network, etc.), and
that the image is uncompressed. The IPL needs to handle
these main tasks:
- The IPL must first use a C function to talk to the
device in question. We'll use a serial download for this
discussion. For serial downloads, the IPL uses
image_download_8250(), a function that
specifically knows how to configure and control the 8250
class of serial controllers.
Once the controller is set up, the function's task is to copy
the image via the serial controller to a location in RAM.
- We now have an OS image in RAM. The IPL then uses the
image_scan() function, which takes a start
address and end address as its parameters. It returns the
address at which it found the image:
unsigned long image_scan (unsigned long start,
unsigned long end);
The image_scan() function:
- Scans for a valid OS signature over the range provided.
Note that this can be multiple OS images.
- Copies the startup header from the image to a struct startup_header variable.
- Authenticates the startup signature (STARTUP_HDR_SIGNATURE).
- Performs a checksum on the startup.
- Performs a checksum on the OS image filesystem.
- Saves the address and version number of the OS in case
it's set up to scan for multiple OS images.
- Once the OS image has been found and validated, the
IPL's next function to call is image_setup(),
which takes the address of the image as its parameter and
always returns 0:
int image_setup (unsigned long address)
The image_setup() function:
- Copies the startup header from the image to a
struct startup_header variable.
Although this was performed in image_scan() (and
startup_header is a global), it's necessary here
because image_scan() can scan for multiple
images, which will overwrite this structure.
- Calculates the address to which startup is to be copied,
based on the ram_paddr and paddr_bias
structure members (from the startup header).
- Fills in the imagefs_paddr structure member,
based on where the image is stored. The startup program
relies on this member, because it's the one responsible for
copying the OS image filesystem to its final location in
RAM. The startup program doesn't necessarily know where the
image is stored.
- Copies the final startup structure to the
ram_paddr address, and then copies the startup
program itself.
At this phase, the startup program has been copied to RAM
(and it must always execute from RAM), and the
startup header has been patched with the address of the OS
image.
Note:
Since the startup program is responsible for copying the
image filesystem to its final destination in RAM, the IPL
must copy the image to a location that's
linearly
accessible by the startup program, which has no
knowledge of paged devices (serial, disk, parallel, network,
etc.).
Note also that if the image is compressed, then the IPL
can copy the compressed image to a location that
won't interfere with startup's decompression of the image to
its final destination in RAM. When the image lives in flash
(or ROM or whatever linear storage device), this isn't an
issue. But when the image is stored on a paged device, more
care must be taken in placing the image in a RAM location
that won't interfere with startup's decompression of the
image. Here are the rules:
- Uncompressed
- If the image is uncompressed, then the IPL can copy the
image from the paged device directly to its destined
location. Startup will compare the addresses and realize
that the image doesn't need to be copied.
- Compressed
- If the image is compressed, then startup must copy and
decompress the image using a different location
than the final RAM location.
- The last phase is to jump to the startup entry point.
This is accomplished by calling image_start():
int image_start (unsigned long address);
The image_start() function should never return;
it returns -1 if it fails.
The function jumps to the startup_vaddr address
as defined in the startup header.