You don't often think about how your computer starts up or shuts down, until something goes wrong, and then it becomes important.
Given how well standardised the PC boot sequence is, and how much we use computers that use it, I am going to describe the sequence from this perspective. Other systems obey roughly the same structure, but may differ in important details.
BIOS/EFI
When your computer starts, either after being powered on, or after being restarted, it executes a program stored on the motherboard. This is the BIOS or if your if your computer is only a few years old, the EFI program.
This is responsible for performing some basic hardware initialisation so it may then load a more general purpose program.
This is generally a program stored at the beginning of your "first" hard-disk, though GPT partitioned disks are increasingly common, and allow the program to be stored elsewhere, and the BIOS/EFI usually provides a way to select a different device than the "first" hard-disk.
This first program is usually the bootloader, but sometimes this step is skipped and the Operating System's kernel is loaded directly.
Bootloader
The bootloader is responsible for discovering and loading the next stage, while being small enough, quick enough and smart enough to do so according to the user's wishes.
Bootloaders often need to re-discover what the appropriate boot target is, but this allows the flexibility of having your operating system stored somewhere that is more complicated to access than the BIOS/EFI can cope with.
The bootloader must, either by a clever heuristic or sufficient user configuration, locate and load the kernel of your operating system.
At this point it must also locate and load other code. Typically this is the initramfs and device tree. Both are optional in certain circumstances. When running Linux on a PC, the initramfs is almost always used and the device tree is almost never used.
Finally, the bootloader must set up registers pointing to the configuration before starting the kernel. This configuration is usually to point to the initramfs or device tree, but it also includes the kernel command-line.
Kernel initialisation
At this point the Linux kernel sets up the essential hardware and tries to work out where the root file system its userland can be found is.
If the rootfs is stored somewhere easy to recognise, then this information can be passed on the kernel command-line, and there is no need to use an initramfs.
This is often not the case on PC hardware however, as hardware topology is complicated, so the initramfs needs to be used to decide which storage to use as the rootfs.
Early userland in the initramfs
Normally the initramfs is only responsible for finding the rootfs, but it is also possible to run your whole system out of the initramfs and never use a rootfs.
At this point you are running a functional Linux system, which can inspect the kernel command-line to locate and mount the rootfs.
In Linux desktop systems this locates the partition which contains the rootfs by looking at the UUID, but this also allows arbitrarily complicated storage setups, like encrypted storage spread across multiple devices, some of which may even be network connected on a server that needs the user to provide an authentication key.
After the rootfs has been appropriately mounted, the initramfs pivots into the rootfs and executes the init binary, which for the purposes of this article is systemd.
Userland service initialisation
Here is where all the software that the user cares about is started. From the perspective of this article this is very boring, only existing to keep the user happy before they instruct the computer to shut down.
Still, other file systems are mounted here, so the user's files can be stored on a different hard-disk to that of the operating system, to make it easier to backup separately.
Shutting down is managed by an appropriately privileged client using some form of IPC to request the init binary shut down, or by calling the reboot system call directly to skip ahead to kernel finalisation.
Userland service shutdown
init requests that userland services shut themselves down nicely, but after a timeout period it mercilessly kills them.
File systems also need to be cleanly unmounted so that they may write their data back to disk in time.
Not every file system may be cleanly unmounted however, as init is running from one of them. Traditionally this is handled by remounting the rootfs as read-only and hoping for the best.
systemd improved matters by executing a shutdown binary, which makes remounting as read-only more reliable, as it handles the case where the init binary was updated.
Traditionally, at this point the reboot system call is used to jump into
kernel finalisation, but with systemd there is another option if
/run/initramfs
is populated.
Late userland in the shutdownramfs
A semi-recent development (2011) in the boot and shut-down story is that systemd added shutdownramfs support so that the root file system can be cleanly unmounted.
This works by the same pivot facility as we used to go from the
initramfs into the rootfs, but instead of /init
being run to set up the
rootfs, /shutdown
is expected to unmount it.
After this userland is definitely finished, and kernel finalisation is entered with the reboot system call.
Kernel finalisation
Some hardware needs to be nicely shut down, rather than having the power yanked, or some other program attempting to make use of it, so at this point the kernel needs to do some stuff to prevent your computer exploding.
After this is complete, either your computer is shut down or rebooted, dependent on what was passed to the reboot system call.