When you gently press the power button, eagerly awaiting the Linux system interface to appear, have you ever wondered what journey the underlying hardware undergoes in those few seconds?
This is not a simple loading process, but an epic journey from the 16-bit “primitive era” to the 64-bit “modern civilization”. Today, let us become witnesses, diving into the torrent of code to see every key milestone.
First Stop: The Ancient Starting Point – 16-bit Real Mode
Upon pressing the power button, the CPU resets itself to a mode called “real mode,” which immediately jumps to a special address known as the “reset vector.” Manufacturers typically place a short jump instruction here to transfer control to the firmware on the motherboard.
Then, the following process occurs:
•
POST Self-Test: The BIOS, acting as the system’s “chief steward,” first performs a power-on self-test, carefully checking whether core components such as the CPU, memory, and hard drive are in place.
•
Loading MBR: If a disk is found whose first 512-byte sector ends with the signature bytes, the BIOS considers the device bootable. It then copies this sector to memory at a specified address and jumps there to execute. Since this sector is very small, it usually only contains the code to load the next larger boot component.
•
Process Characteristics: The CPU operates in real mode, accessing only 1MB of memory, without modern memory protection mechanisms, with all programs running in the same space.
At this point, the BIOS’s task is complete, and it hands over control to the bootloader in the MBR.
It is worth noting that UEFI is a modern alternative. It is still responsible for booting the machine, but it can directly recognize the file system and load larger boot programs without executing the old “first sector” operation. UEFI also passes richer information to the operating system.
Their goal is the same: to hand over control to a bootloader capable of loading Linux.
Second Stop: The Guide – The Bootloader’s Relay
The space in the MBR is too small to accommodate the first-stage code of bootloaders like GRUB. It acts like a guide holding a rudimentary map (Stage 1), only able to lead you to the next, more specialized guide (Stage 1.5).
•
Stage 1.5: This “professional guide” carries the drivers to recognize the file system, allowing us to search for core resources in the directory.
•
Stage 2: Finally, the complete GRUB core is loaded. It presents us with a boot menu and loads two key files – the compressed kernel image and the initial RAM disk – into specified memory locations.
GRUB also fills a small structure called the “setup header,” which contains useful information such as the location of the kernel, the location of command line parameters, and whether an initrd (initial RAM disk) exists and its location.
With preparations complete, the real adventure is about to begin.
Third Stop: Crossing the Time Gate – From Real Mode to Protected Mode
Linux on modern PCs runs in long mode, which is the 64-bit mode of the x86_64 architecture. However, it cannot directly jump from real mode to long mode; it must first transition from real mode to protected mode, and then from protected mode to long mode.
Protected mode was introduced to overcome the limitations of the 1980s, providing a 32-bit runtime environment that brought two core concepts:
•
Global Descriptor Table (GDT): A brief list of segment descriptors. Each descriptor specifies “where this segment starts, how big it is, and what operations are allowed.” Linux simplifies this by adopting a flat model, with a base address of zero, covering the entire 32-bit space.
•
Interrupt Descriptor Table (IDT): Like a “phone book” for emergency calls. When an interrupt occurs, the CPU consults the IDT and jumps to the corresponding handler listed there. During the system switch, we first load a temporary placeholder IDT, as we are preparing to mask interrupts. The complete IDT will only be loaded after the real kernel takes over.
Now, the CPU is about to bid farewell to the 16-bit “old world.” This critical transition is accomplished by the kernel’s built-in assembly code, which acts as a skilled “architect.”
•
Surveying the Terrain: By calling BIOS interrupts, it obtains a map of the system’s memory layout.
•
Breaking the Shackles: Opening the A20 address line, a historical legacy issue: early PCs would experience address wrapping at 1MB, and enabling A20 eliminates this wrapping, allowing access to higher addresses to work as expected.
•
Establishing a New Order: Loading a streamlined Global Descriptor Table (GDT) and a simplified Interrupt Descriptor Table (IDT), containing only the currently necessary information. Finally, it sets a bit named PE in the control register called CR0 and performs a far jump. This jump reloads the code segment from the GDT, locking it into protected mode.
Note: The CPU has special registers called control registers used to control switches, such as:
•
CR0 is used to enable protected mode.
•
CR3 stores the address of the top of the page table.
•
CR4 is used to enable a series of extended features, such as larger page table entries.
Fourth Stop: Moving Towards Modernity – From Protected Mode to Long Mode
After entering the 32-bit world, we do not stop; the goal is to reach the 64-bit “long mode.” This task is completed by the decompression code.
•
Setting the Stage: Initializing a temporary page table and enabling the memory paging mechanism – the core of modern operating system memory management.
•
Checking the Pass: Confirming that the CPU supports 64-bit long mode.
•
Changing the Appearance: The code enables PAE in CR4, allowing for larger page table entries. Additionally, it writes the address of the top-level page table into the CR3 register. At this point, the paging mechanism is ready.
•
Final Evolution: Finally, it sets the LME bit in the EFER register and executes a far return instruction, jumping to a segment of 64-bit code. At this point, long mode is activated.
Final Stop: The Birth of a New World – Kernel Initialization
Now, the 64-bit Linux kernel can finally stretch its limbs and begin creating a new world. The entry function acts like the “creator god” of this new world.
It methodically:
1.
Initializes the memory management subsystem, planning every inch of “land.”
2.
Starts the process scheduler, establishing rules for the future “multitasking” society.
3.
Initializes interrupts and device drivers, bringing hardware to “life.”
4.
Mounts the root file system, establishing a complete “file archive.”
5.
Finally, creates the system’s first user process (or ).
At this point, the kernel’s mission is complete, and a complete operating system environment is ready, quietly waiting for your login.
Summary: A Carefully Designed Evolution
Looking back at this journey, the booting of Linux is not a one-time event, but a meticulously designed, interlocking mode evolution:
16-bit real mode → 32-bit protected mode → 64-bit long mode
Why is such caution necessary? Switching modes during system operation is like changing tires while the car is moving. The code first disables interrupts, prepares the most basic tables, then flips the corresponding bits, and finally re-enables interrupts. This gradual approach avoids strange, half-switched states.
Next time you boot Linux, take a moment to recall this kernel’s fantastic journey. Behind the screen, a great evolution from ancient to modern, from bondage to freedom is unfolding.
For details, refer to:https://www.0xkato.xyz/linux-boot/