What is a bootloader
Bootloader are used to boot other operating systems, usually each operating system has a set of bootloaders specific for it.
Bootloaders usually contain several ways to boot the OS kernel and also contain commands for debugging and/or modifying the kernel environment.
In this talk we will concentrate on Linux bootloaders.
Since it is usually the first software to run after powerup or reset, it is highly processor and board specific.
Processor and Board specific
- Bootloader starts before any other software starts therefore it is highly processor specific and board specific.
- The bootloader performs the necessary initializations to prepare the system for the Operating system.
- The operating System is more general and usually contains minimum board or processor specific code.
Usually starts from ROM (Flash)
This is the minimal setup required, after that the bootloader starts it's work.
Moves itself to RAM for actual work
We now have RAM and Stack pointer and ready to do the real work. First of all since Flash memory is usually scarce resource and much slower then RAM, we move the actual bootloader code to RAM for actual execution. In many cases Flash memory is located in an address space that is not executable, for example serial flash that you can access by reading repeatativly from one address. Also in many cases, the actual bootloader code is compressed so it must first be uncompressed and then written to RAM.
Minimum peripheral initialization
These initializations are usually just for the bootloader.
The Operating System usually overrides them or not using them at all.
Decide which OS image to start
Bootloaders can usually load one of few kernel images that are known to the bootloader This can be done in embedded systems to make sure we can upgrade a kernel without fear of power loss during upgrade, since we always have a backup kernel that will load. In PC environments this is done to let the user choose among several OS's or give the user a chance to try another kernel without losing his/her current kernel.
Get the kernel
most bootloaders provide several ways to loade the kernel:
- Load kernel image from memory
- Load kernel image from file (If the system has a disk)
- Load kernel image from network using bootp
- Load kernel image to memory using TFTP
Allow manual intervention
bootloaders usually have a way to interrupt automatic loading and insert parameters. This is done by waiting a certain default time before autoloading, during this time the user has to press a specific key (Esc in case of LILO) or any key in case of UBOOT. When a key is pressed, a prompt is displayed and the user has a chance to change certain environment variable or maybe load a different kernel from memory, disk, network etc.
PC boot sequence
From the specified boot device it loads to RAM the first stage (from MBR)
control is transferred to first stage.
First stage bootloader loads the second stage that usually displays the boot menu. The user selects the OS to boot or a default OS is booted after a speficied time. In this stage the user have the option to add boot parameters to kernel. In several cases, the bootloader does not know how to load the OS and transfers the control to another bootloader, this is called chain loading, this is usually done when LILO or GRUB needs to load windows.
Prepare parameters for OS loading
The OS is usually generic and is not specificly tied to one board implementation, so in order for the OS to work as expected, it needs some information about the memory map, clocks etc. These parameters can be compiled into the kernel but this make the kernel very board specific and makes it difficult to replace kernels in the future. Most kernels allow passing information by means of command line and/or in memory structure.
Loads OS Image
The bootloader needs to be able to read and understand the object format of the OS kernel. It will extract the actual memory image from the object file and place it to memory according to the header of the object format and then jump to the entry point (also given in the object header).
In case of Linux which uses MMU the base address is usually virtual address and the bootloader needs to translate it to physical address, this is why we usually can't load linux using a bootloader written for other OS's that don't use MMU such as vxWorks.
Load optional RAM file system (initrd)
In Linux the kernel needs a root file system to work, this root file system can be on a disk or in RAM disk. RAM disk (initrd) is frequently used in linux distributions to keep the kernel small and to load only a required set of modules to work with the hardware. The initial RAM disk is used as a root file system, the init process of the RAM disk, loads the needed modules and then mounts the other filesystems from disk. In embedded system, many times there is no disk at all so the RAM file system is used.
Transfer control to OS kernel in RAM
After all images are loaded into RAM, we can start the OS itself. Starting the OS usually means copying it to a certain location in RAM, filling a memory structure and then transfer control to the OS code. In this stage the bootloader role is done and thus the OS can use the RAM area where the bootloader is.
Starting Linux
Linux must have a file system, this makes programming an embedded linux application easier as it is similar to programming a desktop application, you simply compile your program to a file linked with the appropriate libraries and then run this file. In other embedded operating system you link your application with the kernel itself and thus you actually write a kernel application. However since Linux must have a file system and embedded systems usually does not even have a disk, we use a RAM disk image of the file system. This RAM disk image can be included in the Kernel image as another section in the object file or used as a seperate file. The bootloader must know how to handle it. It must extract the file system image and put it in a certain known RAM location before it trasfers control to the kernel.
No comments:
Post a Comment