The Technology Magazine.

Full width home advertisement



Post Page Advertisement [Top]

Linux Boot Play-byPlay: Theory Of Operation

The PC-Router boot process is based (like all LRP boot processes) on the Intel x86 method of booting.  The process is described below using syslinux as the boot loader:

1.Your BIOS determines what device is the boot device (CD-ROM drive, Floppy, hard disk)

2.Your BIOS finds track 0, sector 1 at physical address 0x7C00

3.BIOS blindly loads the first sector (512 bytes) into memory at 0x9000.  The first sector could be one of the following things:

a. the raw Linux bootsector - the linux kernel has a tiny piece of assembler code at it’s head that knows how to make the BIOS calls to hardware to load the rest of the kernel and decompress itself.  The raw Linux bootsector must, obviously, be where the BIOS wants to find the bootsector: track 0, sector 1, phys addr 0x7C00.

b. another bootsector - a tiny piece of code that provides a choice of which Linux kernel (if more than one exists) to start, knows where on the disk that Linux kernel is and provides for sending options to the kernel at boot time.

When booting from a hard drive the boot loader checks the partition table in the master boot record (the designated boot sector for a hard drive since a hard drive may have more than one partition each with its own boot sector) and determines which partition is marked as “active” or the bootable partition.  The boot loader then reads the boot sector from that partition and runs the code.

This type of code is called a boot loader.  Some popular boot loaders are: (LILO, GRUB, and syslinux - the boot loader used in LRP).  The PCR CD uses this method.  Since the amount of space is limited in the first sector of the disk the boot loader actually starts another larger executable that performs the work described above.  For the PCR CD this executable is called ldlinux.sys.  The rest of this documentation assumes we are using this boot process.

c. a bootsector virus ;-)

4.ldlinux.sys reads its configuration file (syslinux.cfg) and...

5....optionally builds a menu for the user to select which kernel to load.The menu created by syslinux is derived from another set of text files.

6.(User selects an option from the menu if a selection is allowed)

7.Based on the option selected ldlinux.sys loads the archive specified in the append statement and decompresses it to a RAM disk as initrd (the initial RAM disk)
The RAM disk created by ldlinux.sys is a read-only block device.  The initrd is used to make low-level drivers, such as SCSI drivers, available to the kernel so that the kernel can mount the real root file system on disk later.  initrd is mounted as read-only because the linux kernel apparently checks this file system first for integrity using the fsck utility.  Normally, fsck operates on non-mounted devices.  To allow fsck to perform, even while the initial RAM disk has been mounted, it is initially mounted read-only.

8....finds the right Linux kernel to load and loads it into a specific point in memory, and...

9....invokes the kernel with the command line switches specified for the option selected in the syslinux.cfg file.

10.When the kernel first starts a small portion of code at the beginning of the kernel de-compresses the rest of the kernel.  The kernel starts in what is considered a two-phased system boot-up.

11.Once de-compressed the kernel starts off in 16-bit real mode and initializes itself - “checks for 10 fingers and 10 toes” - whether it was invoked correctly by the boot loader.

a.kernel starts in “real mode”

b.checks how much memory it has available to use

c.checks/asks for available video modes

d.checks for hard disks

e.checks for a mouse

f.flushes the keyboard

12.Then it restarts itself in 32-bit protected mode and checks hardware, loads drivers, etc.  This is referred to in the kernel comments as the architecture-dependant initialization setup.

a.sets paging

b.puts boot parameters and command lines switches in a safe place

c.finds out real capabilities of CPU

d.counts any other CPUs

e.finds out real capabilities of coprocessor

f.starts other CPUs if they exist

13.Next, the kernel goes into what is sometimes called the Architecture Dependant setup.
Why does the kernel take initrd and copy it to another place in memory as /dev/ram0?  Firstly, we tell him to load a floppy image into RAM with the argument (load_ramdisk=1).  Also, we tell the kernel to load initrd as the root file system at /dev/ram0 with the argument root=dev/ram0.

a.start_kernel process called

                                                          i.the two 8259 (IRQ) chips are initialized

b.performs more architecture specific tasks:

                                                          i.gets the boot parameters and options saved earlier

                                                         ii.initializes the ram disk procedures

                                                        iii.sets a bunch of memory parameters based off any memory switches in command line

                                                        iv.builds page tables

                                                         v.reserves memory to be used by INITRD (initial RAM disk)

                                                        vi.reserves video RAM

                                                       vii.reserve I/O RAM for peripherals

                                                      viii.jump back to architecture-independent mode

c.parse through command line options

d.calls a bunch of initialization C programs that:

                                                          i.enable interrupts

                                                         ii.turn on timing functions

                                                        iii.turn on software IRQs

                                                        iv.turn on the console (messages start actually appearing on screen now)

contents of INITRD is moved to /dev/ram0
The Linux kernel has built-in routines that build a RAM disk, then transfer the contents of the original root disk(ette) to the RAM disk.  Afterwards, the kernel switches to this RAM disk.  That was intended to make kernel operation faster and more stable in multi-diskette configurations. In order for this feature to work the filesystem of the root must be either the minix file system or the ext2 file system.  The desired size the RAM disk must also be specified - it must be at least as large as the diskette/image containing the root file system.

                                                        vi.memory pools cleared

                                                       vii.builds /proc file system

                                                      viii.allows forking and sets limits on the number of threads

                                                        ix.sets caching and buffers

                                                         x.initializes inodes (for the filesystem)

                                                        xi.initializes interprocess calls

e.starts the INIT process.  INIT does:

                                                          i.kills any processes already orphaned

                                                         ii.initializing a bunch of devices

1.Power ManagementI, DE drives, SCSI drives, networking drivers, PCI, video drivers, sound drivers, etc

                                                        iii.Sets up file systems (vfat, minix, ext2...)

                                                        iv.mounts the root file system

                                                         v.mounts the dev file system

                                                        vi.if using a hard drive-based filesystem then the kernel switches to /dev/hda1 and pivots /dev/ram0 to /initrd

14.Linux is now started. 

15.INIT is started as PID 1.  Processes continue to start through Sys V INIT scripts.

What is a Boot Loader?

A boot loader is a small piece of code that runs automatically before the main kernel.

This is by virtue of the fact that Intel architecture computers rather blindly execute code at a specific location on the boot disk (called a bootstrap).  This code may or may not be an 'operating system' proper.

The boot loader is that portion of code that is executed that allows the user some level of control of what OS to load and what options are invoked for that OS.

Typical boot loaders seen with Linux are: Grub (Grand Unified Boot loader, Syslinux, ISOLinux, LILO (Linux Loader), MILO, SILO, Loadlin)

Boot loaders typically can be configured to initialize devices then load the kernel while passing command-line arguments to it.  For example, we can configure the kernel to use completely different partitions as its 'root'. Additionally, the boot loader can load other things in memory that will later be used by the kernel.


Obviously, the boot loader needs to read disks.  It does this through direct BIOS calls (like INT13h).  So any device recognized by the BIOS is probably a target for the boot loader. 

One little problem related to BIOS:  Since many BIOSes only reserve 10 bits to represent cylinders for INT13h calls boot loaders that rely on BIOS completely (like LILO) must be able to find their target kernels within the first 8Gb of the hard disk.  If you have a large disk and you place Linux after the 8Gb limit your BIOS (and thus LILO) won’t know how to address that space.


Boot loaders need to initialize all the RAM that is necessary to get the kernel running off to a good start.  A boot loader uses various algorithms to determine how much memory is available.  Alternately you may have to tell the boot loader how much memory is to be used by the kernel.

A Serial Port

The kernel dumps debugging data or communicates with a serial device, by default.  The boot loader finds a serial device then initializes it so that it will be available to the kernel.

Call the Kernel Image

Obviously we have to call the kernel.

What is the Initial RAM Disk?

The initrd (initial RAM disk) is a mini-root filesystem that is loaded into memory by the boot loader then copied to an initialized filesystem on a RAM disk built by the kernel.

The kernel refers to this initrd when loading drivers and modules that were not compiled into the kernel itself.  An example of such drivers would be disk or network card drivers.  The initrd allows the kernel to be compiled smaller.

Eventually the kernel replaces the initrd root filesystem with the real root filesystem that may exist elsewhere.  This is called a pivot_­root.  Sometimes the original initrd filesystem is placed in a subdirectory under the new root structure.  This allows process that were started before the pivot_root operation to continue running.

Usually the initrd is in existence as the root filesystem just long enough so that the kernel can find and load the modules it needs to access resources on the machine.


A good example of the value of this concept can be seen in how a HP/Compaq ML370 might boot up when running Linux.  The kernel will start up but the kernel may not have the Compaq Smart-Array driver compiled into it.  In this case the kernel refers to its root filesystem from the initial RAM disk which contains the Smart-Array driver.  Once the Smart-Array driver is loaded the kernel can mount the real root filesystem from the logical drives held in the Smart-Array.  The original root (that contained the Compaq Smart-Array driver is then swapped to a sub-directory in the new root filesystem so that the disk processes can still reference it.

What is the Root disk?

The filesystem that will be mounted at “/.”  The root filesystem contains all the files necessary for a fully initialized Linux kernel to run.  The root disk may not contain the kernel image.  The kernel image may be contained in the boot disk (see below).

The kernel must be told where to find its root filesystem.  If it can’t find a root filesystem at the point where it was told it will halt.

What is the Boot disk?

A filesystem that contains the necessary structures to start the kernel.  This filesystem may or may not contain enough of a filesystem to completely start the OS.

Consider a Linux distribution that is booted from floppy disks: the complete OS may not fit on one diskette.  So, the Linux kernel was designed so that the complete startup process could span multiple disks.

The first disk would be considered the boot diskette – containing the kernel.  The kernel is told that its root filesystem (see above) exists elsewhere.  The kernel then searches a filesystem derived from a second diskette for the root filesystem.

Why we need to know the difference between a boot and root disk:

The only reason we are interested in this obscure differentiation between boot and root is because lots of Linux documentation refers to the the two functional differences via boot and root terminologies.

What is the INIT process?

INIT is a process invoked by the kernel that is designed to start and stop system services, load modules, start networking, mount filesystems and disks.  The INIT process runs with a PID of 1.

This makes sense because Linux itself is just the kernel.  The kernel is primarily concerned with hardware abstraction, handling I/O, and process scheduling.  It doesn’t do anything much beyond that.  Thus, for the kernel to be useful to us, the end user, we need to start invoking processes and services that actually do stuff.

The INIT process comes in two major flavors: Sys-V INIT (what’s used by Red Hat, PC Router), and the BSD-style init process.  We will focus on Sys-V INIT since it has emerged as the Linux standard.

The Linux kernel first looks for its init in /sbin then /etc.  INIT in itself could be anything runnable: a script or binary executable, for example.  As a third and last alternative, the Linux kernel will attempt to start /bin/sh (a shell) if it cannot find an init in /sbin or /etc.


This is the file that configures the init process.


The initialization script run by the init process that starts and stop daemons based on run-levels.

Run levels

Represent pre-set states that a Unix (System V) box can be in.  These states determine what processes are run by default (if any):

·         0 – Halted

·         1 or S – Single User

·         2 – Not used in Linux

·         3 – Multi-User

·         4 – Not used

·         5 – Full Multi-User with X Windows (default run level for a typical desktop installation of Red Hat with KDE)

·         6 – Reboot

For each one of these states there exists a directory that contains little scripts that indicate which processes are stopped or started and in what order they are stopped or started.

The INIT process starts /etc/rc.sysinit that determines what the default run level is (based on a variable in /etc/inittab), then proceeds to execute each script in the corresponding directory in alpha-numeric order.

When the Administrator desires to change run levels INIT proceeds to the corresponding directory and runs each script in order.

The scripts are actually symbolic links named with the following syntax:

A start script = S[preference #][daemon/process_name] i.e. S99sshd

A kill script = K[preference #][daemon/process_name] i.e. K99apmd

When rc.sysinit sees an S it knows that it’s supposed to start a service so it appends a “start” switch after the call to the symbolic link.  Thus: “S99sshd start.”  When rc.sysinit sees a K it knows that it’s supposed to stop a service so it appends a “stop” switch after the call to the symbolic link.

Thus the script links are named in such a way so that they are alpha-numerically ordered in the same order as they are intended to be executed.

The files found in each rc#.d directory is linked to the actual scripts in the init.d directory.  These scripts are actually the preferred way to start and stop services and daemons so the Administrator should get into the habit of calling the /etc/rc.d/init.d scripts in the same manner as rc.sysinit.

The rc.local script is where we put things that should only be run once.

After all the init scripts are run the INIT process starts a getty.

Why use run levels?

Some people set up their machines to be kind of multi-personality.  To enable the machine as a server put the box in run level 3.  To enable the box as a workstation put the machine in run level 5.  To service the box put the machine in run level 1.  Run level 1 is single user mode.  This means that all networking support processes are stopped by default.  You can put a Linux box in run level 1, take out a NIC, replace the driver (whatever), then put the Linux box back in run level 5 or 3.

This is somewhat equivalent to how NT works when you pause a service except theres not thought necessary in Linux.  If you had an Exchange\File server you would have to know what services to stop and restart possible what order to restart


The chkconfig utility supplied by Red Hat allows the administrator to control what services are stopped and started through a command line interface.


You can use the telinit command to switch run levels.  Use the syntax: telinit [runlevel].

At the LILO boot prompt you can type linux [runlevel | single] where linux is the image name and run level is the number of the run level.  The ‘single’ tag starts Linux up in runlevel S (which is the same as run level 1 in Red Hat distros).


·         Find the rcN.d directory for the default run-level of your system and do a ls -l to see what the files are links to

·         Change the number of gettys that run on your system.

·         Remove any subsystems that you don't need from your default run-level.  See how little you can get away with starting.

No comments:

Post a Comment

Dear visitor,
Please do not post spam. All comments will be moderated before approval.

Bottom Ad [Post Page]

| Designed by