How Computers BOOT From Power Button to Operating
In this blog post, we'll use an x86 Linux system as an example.
After pressing the power button, And CPU powers up the it start executing not from the address 0x0000 0000 but 16 bytes back from the top of the address space aka 0xFFFF FFF0, And at this
address mapped by your motherboard to a ROM (Read only memory) and at this predefined address the BiOS or UEFI code lives.
💡 BIOS (Basic Input/Output System) is the older firmware interface used to boot computers, while UEFI (Unified Extensible Firmware Interface) is the modern replacement that offers faster boot times, support for larger drives, and enhanced security features. UEFI also provides a graphical user interface and is designed to overcome the limitations of BIOS.
The BIOS is the system firmware pre-installed on an EPROM or similar chip. Its primary role at startup is to initialize and test the system's hardware components—such as RAM, storage devices, graphics card, and other important devices. It ensures everything is functioning correctly and ready for operation.
The very first action the BIOS performs is a Power-On Self-Test, or POST. After that, the BIOS searches for bootable devices such as SSDs, HDDs, USB drives, or CDs. The search order can be configured in the BIOS settings. When it finds a bootable device, it looks for a specific sector: the Master Boot Record (MBR), This sector is curcial as it contains what’s called the boot-loader. This a piece of code that can fit into a 512 byte sector.
💡 If you’re working with UEFI, it works differently—loading the OS bootloader from the EFI System Partition (ESP) instead.
The BIOS loads this 512-byte sector into memory at address 0x00007C00 and jumps to it, starting the execution of the bootloader which loader the system
The memory at
0x00000000is primarily used for system-level structures, and it is set up by the BIOS/UEFI firmware during system initialization.
💡 Generally, this 512-byte sector is called a first-stage bootloader because it loads a more advanced bootloader like GRUB or U-Boot, which is called a second-stage bootloader.
https://github.com/rhboot/grub2/blob/fedora-39/grub-core/boot/i386/pc/boot.S
This is the assembly file that runs first after control is handed over to GRUB.
Boot loader Key jobs are:
- Locate the operating system kernel on the disk
- Load the kernel into the computer’s memory
- Handing over the control to the kernel
From here, the kernel finishes the startup process. The kernel's main job is managing hardware and loading drivers, which provide an abstraction layer for hardware communication.
But how does Linux know which devices exist and which drivers to load? The kernel uses Devicetree (dt), which is passed to it by the bootloader just before control is handed over.
Devicetree is a file that generally ends with .dtb (device tree blob). It contains what are known as static drivers.
The Device Tree (DT) is a data structure that describes hardware configuration. It provides a way to separate hardware configuration from the Linux kernel code, allowing for data-driven board and device support rather than hard-coded settings.
Linux uses DT data for three major purposes:
- platform identification,
- runtime configuration, and
- device population.
You can read more here: Linux and the Devicetree.
After loading the drivers and kernel modules, the kernel initiates Systemd (the init process), which is the first process to be executed and making it the parent of all other processes.
Systemd checks for any remaining drivers that need to be loaded, mounts file systems and disks, starts essential background processes like networking, sound, graphics, and power management, then it runs Startup Scripts and finally loads your desktop environment.
And there you have it! The journey of a computer's boot process, from the initial power button press through BIOS/UEFI, bootloader, kernel initialization, and finally to your working desktop environment.