GRUB & Multibooting
A Complete 10-Chapter Bootloader & Multi-Boot Course
Table of Contents
- What a Bootloader Actually Does
- GRUB2 Architecture & Boot Stages
- Configuring GRUB — /etc/default/grub and update-grub
- Kernel Parameters & the GRUB Command Line
- MBR vs. GPT and BIOS vs. UEFI
- Dual-Booting Linux and Windows
- Dual-Booting Two Linux Distributions
- Multi-Boot With More Than Two OSes & Advanced Partitioning
- Recovering From a Broken Bootloader
- Capstone: Building a Real Triple-Boot Test Environment
What a Bootloader Actually Does
GRUB & Multibooting
Chapter 1 · What a Bootloader Actually Does
linux1-5 walked through a real Debian install, including the moment the installer asks "Install the GRUB boot loader?" and offers to write it to a disk — then moved on, without ever explaining what that step actually does. This chapter is that explanation, from the ground up.
The Boot Sequence — From Power-On to a Running Kernel
- The machine's own firmware (BIOS or UEFI) runs first, initializing hardware
- Firmware locates and hands control to a bootloader
- The bootloader loads the kernel — and usually an initramfs, a small temporary filesystem — into memory
- The kernel takes over, mounts the real root filesystem, and starts the init system (
systemdon Debian and most modern distros)
The bootloader's own job is narrow and specific: it's the bridge between "firmware has no concept of an operating system" and "the kernel is now running and can take it from here." It does not run the operating system itself — it hands off, once.
BIOS vs. UEFI — Two Different Firmware Models
BIOS (legacy) reads the very first sector of a disk and blindly executes whatever code is there — no awareness of filesystems, no real structure. UEFI (modern) is a genuinely more capable environment: it can read an actual filesystem — specifically a FAT-formatted EFI System Partition — and directly execute a real, named .efi file from it. This distinction gets its own full chapter later (grub1-5); for now, just know the two models exist and behave in fundamentally different ways.
MBR vs. GPT — Previewed
MBR (Master Boot Record) is the legacy partition table format — a maximum of four primary partitions, a 2TB disk-size ceiling, and the natural pairing for BIOS. GPT (GUID Partition Table) is the modern replacement — far more partitions allowed, no meaningful size limit, and the natural pairing for UEFI. Full depth on both is grub1-5's own job; this preview exists purely so the chapters between here and there make sense as you go.
What GRUB's Actual Job Is
GRUB (the GRand Unified Bootloader) is one specific bootloader implementation — the one Debian, and most major Linux distributions, install by default. Its job: find the kernel, find the initramfs, load both into memory with the right parameters, and hand off control. Along the way it offers a menu — letting you choose between multiple installed kernels, or multiple operating systems entirely — and lets kernel parameters be edited live at boot time, previewed here and covered fully in grub1-4.
Resolving linux1-5's Own Installation Screen
That "Install the GRUB boot loader?" prompt is the exact moment GRUB gets written to disk — into the MBR's own boot sector on a BIOS system, or as a real file inside the EFI System Partition on a UEFI system. linux1-5 walked through this operationally, as one screen in an installer wizard, without explaining the mechanism underneath it. That mechanism is now on the table.
| Partition table used | Filesystem-aware? | Bootloader location | |
|---|---|---|---|
| BIOS | MBR | No — reads a raw disk sector | The MBR's own boot sector, not a normal file |
| UEFI | GPT | Yes — reads FAT on the EFI System Partition | A real, named .efi file, an ordinary file on disk |
/boot/efi) and you can ls it directly — the actual .efi bootloader files sit there as ordinary files on an ordinary FAT filesystem. A concrete, inspectable artifact, unlike BIOS's opaque, raw MBR boot sector.
Hands-On Exercises
List, in order, the four steps of the boot sequence from this chapter, and explain in one sentence what would go wrong if the bootloader step were skipped entirely.
📄 View solutionExplain why a UEFI system's bootloader can be inspected as an ordinary file, while a BIOS system's cannot, referencing the actual filesystem-awareness difference between the two.
📄 View solutionA USB installer was created in UEFI mode, but the target machine's firmware is set to boot in legacy BIOS mode. Predict what would happen, using this chapter's own warn-box.
📄 View solutionChapter 1 Quick Reference
- Boot sequence: firmware → bootloader → kernel + initramfs loaded → kernel mounts root, starts init
- A bootloader's job is narrow: bridge firmware (no OS concept) to a running kernel, then hand off, once
- BIOS reads a raw MBR sector, no filesystem awareness; UEFI reads a real FAT filesystem and runs a named .efi file
- MBR (legacy, 4 partitions, 2TB limit) pairs with BIOS; GPT (modern, no practical limits) pairs with UEFI — full depth in grub1-5
- GRUB is one specific bootloader: finds the kernel/initramfs, loads them, offers a menu, allows live parameter edits
- linux1-5's own "Install the GRUB boot loader?" prompt is exactly this — writing GRUB to the MBR or the EFI System Partition
- BIOS and UEFI are incompatible models — mixing them (wrong-mode USB, mismatched partition table) is a real, common failure source
GRUB2 Architecture & Boot Stages
GRUB & Multibooting
Chapter 2 · GRUB2 Architecture & Boot Stages
grub1-1 established what a bootloader's job is in general. This chapter goes inside GRUB specifically — why it bootstraps itself in stages, where its pieces actually live on disk, and the one rule the rest of this course depends on: grub.cfg is generated, never hand-edited.
GRUB's Own Multi-Stage Loading Process
A full-featured bootloader — one that understands filesystems, reads a config file, and draws a menu — is far too large to fit in the tiny space firmware actually hands control to (446 usable bytes in a classic MBR, per grub1-1). GRUB solves this by bootstrapping itself in stages, each one slightly more capable than the last:
- boot.img — tiny, fits directly in the MBR itself (or the equivalent UEFI boot stub). Knows almost nothing — just enough to find and load the next stage.
- core.img — larger, contains basic filesystem drivers. Lives in the small gap immediately after the MBR on a BIOS/MBR disk, or on a dedicated BIOS Boot Partition on a GPT disk. Knows enough to read a real filesystem.
- The full GRUB environment — loaded by core.img from
/boot/grub, now capable of readinggrub.cfg, loading additional modules, and presenting the menu you actually see.
Each stage exists purely because the one before it was too small to do the whole job — a tiny bootstrap loading a slightly bigger bootstrap loading the real thing.
Where GRUB Actually Lives on Disk
/boot/grub/ holds grub.cfg, GRUB's own kernel-style modules (.mod files), locale files, and themes. On a BIOS/MBR system, core.img sits in the small unused space right after the MBR (or a dedicated BIOS Boot Partition on GPT), since no real filesystem is available yet at that point in the boot process. On a UEFI/GPT system, the actual GRUB EFI binary (commonly grubx64.efi) lives directly inside the EFI System Partition, alongside its own copy of configuration and modules.
grub.cfg — Generated, Never Hand-Edited
That's the literal top of a real grub.cfg. It's auto-generated by a script (grub-mkconfig, wrapped as update-grub on Debian — grub1-3 covers this fully), built from a set of scripts in /etc/grub.d/ combined with settings in /etc/default/grub. A manual edit to grub.cfg itself is silently overwritten the next time that generator runs — often triggered automatically by a routine kernel package upgrade. This is exactly the "manual fix reverted by the next automated apply" pattern this site's own infrastructure-as-code material already warned about (tf1-9, ansible1-1's own "fix the config, not just the console"), here applied to a bootloader instead of cloud infrastructure. grub1-3 is where the actually-supported editing workflow lives.
/etc/grub.d/ — The Real Building Blocks
A set of numbered scripts, each contributing one piece of the final grub.cfg, run in numeric order: 00_header, 10_linux, 30_os-prober, 40_custom, and others. 10_linux scans /boot for every installed kernel and generates a menu entry for each one. 30_os-prober — previewed here, covered fully in grub1-6/grub1-7 — scans other partitions on the disk for other operating systems and adds entries for them. The numbering isn't cosmetic; it's the literal order these scripts run in, which matters later for menu ordering.
Kernel Modules — Why GRUB Needs Its Own Drivers
GRUB has to understand filesystems, partition schemes, even things like LVM, entirely on its own — independent of, and before, the operating system it's about to boot even exists as a running thing. This is why /boot/grub is full of .mod files like ext2.mod and part_gpt.mod: GRUB is, in effect, its own small, purpose-built environment, with its own drivers, existing solely to find and load a real kernel.
| Stage | Size | Capability |
|---|---|---|
| boot.img | Fits in the MBR itself | Almost none — just enough to find core.img |
| core.img | Small, but real | Basic filesystem drivers — enough to read /boot/grub |
| Full GRUB environment | As large as needed | Reads grub.cfg, loads modules, draws the menu |
ls /boot/grub/*.mod | wc -l counts the filesystem/feature modules GRUB actually ships with on a typical install — often dozens. A concrete way to see, directly, just how much this small pre-OS environment genuinely has to know on its own.
grub.cfg often appears to work immediately — the change is right there, and nothing complains. The problem surfaces later, sometimes days or weeks afterward, when a routine kernel update silently regenerates the file and the edit simply vanishes, with no obvious connection between the kernel update and the "missing" change. grub1-3's own editing workflow avoids this entirely.
Hands-On Exercises
Explain, in your own words, why GRUB can't just be one single piece of code loaded directly from the MBR, and name the two intermediate stages that solve this.
📄 View solutionA new kernel is installed via the package manager. Explain what happens to grub.cfg as a result, and which specific numbered script in /etc/grub.d/ is responsible for that change.
📄 View solutionSomeone hand-edits grub.cfg to change the default boot entry, and it works immediately. Three weeks later, after a routine kernel update, their change is gone. Explain exactly what happened.
📄 View solutionChapter 2 Quick Reference
- GRUB bootstraps itself: boot.img (fits in the MBR) → core.img (basic filesystem drivers) → the full GRUB environment (reads grub.cfg, draws the menu)
/boot/grub/holds grub.cfg, modules, locales, themes; core.img/the EFI binary live in the MBR gap, a BIOS Boot Partition, or the EFI System Partition depending on BIOS vs. UEFI- grub.cfg is generated, never hand-edited — a manual edit is silently overwritten the next time the generator runs, often triggered by a kernel update
- /etc/grub.d/'s numbered scripts (10_linux, 30_os-prober, ...) each contribute one piece of grub.cfg, run in that numeric order
- GRUB ships its own filesystem/feature .mod files — it's effectively a small, self-contained pre-OS environment
- grub1-3 covers the actual, supported way to change GRUB's behavior
Configuring GRUB — /etc/default/grub and update-grub
GRUB & Multibooting
Chapter 3 · Configuring GRUB — /etc/default/grub and update-grub
grub1-2 ended with a promise: this is the actual, supported way to change GRUB's behavior — the workflow that survives every future regeneration, instead of quietly vanishing after the next kernel update.
/etc/default/grub — The Real File You Edit
A plain, shell-variable-style config file, read by grub-mkconfig whenever it builds grub.cfg. Editing this file, then regenerating, is the correct workflow — the change survives every future regeneration precisely because it's now part of grub1-2's own named source of truth, not a one-off edit to generated output.
The Common Settings
- GRUB_DEFAULT — which menu entry boots automatically: a number (
0for the first entry), orsavedcombined withGRUB_SAVEDEFAULT=trueto remember whichever entry was last manually chosen - GRUB_TIMEOUT — seconds the menu is shown before auto-booting the default;
0skips the menu entirely, useful on a single-OS system; a real number matters once multiple entries genuinely need choosing between, directly relevant oncegrub1-6/grub1-7add real dual-boot entries - GRUB_TIMEOUT_STYLE —
menu/countdown/hidden, whether the menu itself is visibly shown during that countdown - GRUB_CMDLINE_LINUX_DEFAULT / GRUB_CMDLINE_LINUX — kernel parameters appended to boot entries (
_DEFAULTexcludes recovery-mode entries, the plain version applies to every entry) —grub1-4covers what these parameters actually do; this is where they're set permanently
Applying Changes — update-grub
After editing /etc/default/grub, nothing actually changes until this runs. update-grub is Debian's own wrapper around grub-mkconfig -o /boot/grub/grub.cfg — the exact regeneration step grub1-2 described, now run deliberately instead of triggered automatically by a package update. Its output lists every kernel and operating system it found along the way — the Found linux image... lines are literally 10_linux's own work from grub1-2, made visible.
A Worked Example — Reducing the Timeout and Setting a Default
- Edit
/etc/default/grub: setGRUB_TIMEOUT=3,GRUB_DEFAULT=saved, addGRUB_SAVEDEFAULT=true - Run
sudo update-grub— confirm it reports success and lists the expected kernel(s) - Reboot — the menu now shows for 3 seconds, and whichever entry was last chosen becomes the new default going forward
The whole workflow, end to end: edit the real source file, regenerate deliberately, verify by rebooting.
Custom Menu Entries — 40_custom
grub1-2 named /etc/grub.d/'s numbered scripts as auto-generating most of grub.cfg's content. 40_custom is the one deliberate exception — a script explicitly meant to hold hand-written content, run as-is by grub-mkconfig rather than generated by scanning anything. Anything placed there survives regeneration on purpose. This is the real answer to "I genuinely need a custom menu entry" — not editing grub.cfg directly, but adding it here instead.
| Approach | Survives update-grub? | Correct for |
|---|---|---|
| Editing grub.cfg directly | No — silently overwritten | Nothing — this is the grub1-2 mistake |
| Editing /etc/default/grub + update-grub | Yes | Timeouts, defaults, kernel parameters |
| Adding to 40_custom | Yes — run as-is, not overwritten | Genuinely custom, hand-written menu entries |
grub1-6/grub1-7 are relevant) that a second operating system was correctly detected.
/etc/default/grub and then not running update-grub leaves the change genuinely correct, sitting in the right place — it just hasn't been applied yet. This is a real, distinct source of "why isn't my change working" confusion from grub1-2's own "edited the wrong file entirely" mistake — here the fix is right, it's just one step short of taking effect.
Hands-On Exercises
Write the two lines you'd add to /etc/default/grub to make GRUB remember and default to whichever entry was last manually selected, and the command needed afterward to make the change take effect.
📄 View solutionExplain why a genuinely custom menu entry should be added to 40_custom rather than typed directly into grub.cfg, referencing how grub-mkconfig treats each of the two files differently.
📄 View solutionSomeone edits GRUB_TIMEOUT in /etc/default/grub, reboots, and sees no change in the menu's timing. They're confused because "I edited the right file this time." Explain the most likely cause.
📄 View solutionChapter 3 Quick Reference
- /etc/default/grub is the real, supported file to edit — changes here survive future regeneration
- GRUB_DEFAULT (which entry boots), GRUB_TIMEOUT/_STYLE (menu duration/visibility), GRUB_CMDLINE_LINUX[_DEFAULT] (kernel parameters)
sudo update-grubregenerates grub.cfg from the edited source — nothing takes effect until this runs- 40_custom is the sanctioned place for genuinely hand-written menu entries — run as-is, never overwritten
- Editing the right file but forgetting update-grub is a distinct, common mistake from grub1-2's own wrong-file mistake
- update-grub's own output lists every detected kernel/OS — a fast way to confirm a change actually took effect
Kernel Parameters & the GRUB Command Line
GRUB & Multibooting
Chapter 4 · Kernel Parameters & the GRUB Command Line
grub1-3 covered setting kernel parameters permanently. This chapter is the other half — editing them live, once, at the GRUB menu itself, for genuine troubleshooting, without touching any file at all.
The GRUB Menu — Editing an Entry Live
At the GRUB menu, highlighting an entry and pressing e opens a text editor showing that entry's actual boot commands — the same linux/initrd lines grub1-2 described GRUB reading from grub.cfg, now genuinely editable, live, for this one boot only. Ctrl+X (or F10) boots with the edits applied; Esc discards them. Nothing here is ever written to disk — reboot again, and the menu is back to its normal, unedited state. This is grub1-2's own "GRUB reads grub.cfg and presents a menu" material, made interactive.
What Kernel Parameters Actually Are
Words appended to the linux line, passed directly to the kernel the moment it starts — before any userspace or init system is even running. They configure kernel-level behavior: which device is root, which console to use, debugging/recovery flags, hardware quirk workarounds.
A Real Troubleshooting Scenario — Booting Into Recovery Mode
The classic real use case: a forgotten root password, a broken /etc/fstab, or a misconfigured service blocking a normal boot entirely. Live-editing the linux line to append systemd.unit=rescue.target boots straight into a minimal shell with root access, bypassing normal service startup — enough to fix the actual problem before rebooting normally.
- At the GRUB menu, press
eon the default entry - Find the
linux ...line, move to its end - Append
systemd.unit=rescue.target Ctrl+Xto boot with the edit- Land in a rescue shell — fix the actual problem (reset a password, correct
fstab) - Reboot normally
This is the light version of a rescue scenario — the system still successfully reaches a kernel and boots, just to a minimal shell instead of a full desktop. grub1-9 covers the heavier case: GRUB itself broken, never even reaching a kernel at all.
Other Common Parameters Worth Knowing
- ro / rw — mount root read-only or read-write at boot; recovery mode typically starts
rofor safety, and often needs manually remountingrwbefore a real fix (like editingfstab) can be saved - quiet / splash — suppress boot messages / show a graphical splash screen (
grub1-3's own default). Temporarily removing these during troubleshooting reveals the actual kernel boot messages — genuinely useful for diagnosing a hang - nomodeset — a real, common graphics-driver workaround for a system that hangs on a black screen during boot due to a broken or unsupported graphics driver
Making a Temporary Fix Permanent — Closing the Loop Back to Chapter 3
If a parameter discovered live via e turns out to be something needed on every boot — nomodeset because this specific hardware always needs it, say — the correct move is not to re-type it at every single boot. It's grub1-3's own workflow: add it to GRUB_CMDLINE_LINUX_DEFAULT in /etc/default/grub, then run update-grub. This chapter is for temporary, diagnostic edits; grub1-3 is for turning a genuine discovery into something permanent.
| Persistence | Right for | |
|---|---|---|
| Live edit via 'e' | This boot only — gone on reboot | Diagnosis, one-off recovery, testing a fix before committing to it |
| GRUB_CMDLINE_LINUX_DEFAULT + update-grub | Permanent, every boot | A confirmed, needed-every-time parameter |
e — a genuine GRUB shell, useful when even a normal menu entry doesn't help. Previewed here; grub1-9's own rescue chapter goes further into when this is genuinely needed.
e edit, confirming it works, then being confused when the exact same problem reappears on the very next reboot is a genuinely common beginner experience — the edit was never saved anywhere. This chapter's own "make it permanent" section, feeding back into grub1-3's workflow, is the actual fix for that confusion.
Hands-On Exercises
Write the exact key sequence (from the GRUB menu to a booted rescue shell) needed to boot into recovery mode using systemd.unit=rescue.target, matching this chapter's own numbered walkthrough.
📄 View solutionA system hangs on a black screen during every boot due to a broken graphics driver. Explain which parameter to add live via 'e' to diagnose/work around this, and what the correct permanent fix would be once confirmed.
📄 View solutionA user fixes a boot issue by appending nomodeset via 'e', confirms it works, reboots later, and the same black-screen problem is back. Explain exactly why, using this chapter's own warn-box.
📄 View solutionChapter 4 Quick Reference
- 'e' at the GRUB menu opens a live, temporary editor for one entry's boot commands;
Ctrl+Xboots,Escdiscards, nothing is ever saved to disk - Kernel parameters are words appended to the linux line, passed directly to the kernel before userspace even starts
- systemd.unit=rescue.target — the real recovery-mode workflow: minimal shell, root access, bypassing normal service startup
- ro/rw, quiet/splash, nomodeset — common, genuinely useful troubleshooting parameters
- A confirmed-useful live edit belongs in GRUB_CMDLINE_LINUX_DEFAULT (grub1-3) to make it permanent — not retyped at every boot
- A live edit that "worked" but reappears on the next reboot was never actually saved — expected behavior, not a bug
- 'c' drops into a full GRUB command-line shell — previewed here, covered further in grub1-9's own rescue chapter
MBR vs. GPT and BIOS vs. UEFI
GRUB & Multibooting
Chapter 5 · MBR vs. GPT and BIOS vs. UEFI
grub1-1 previewed this distinction just enough to make sense of everything since. This is the chapter every dual-boot scenario in this course actually depends on — the full structural difference between MBR and GPT, and between BIOS and UEFI, in enough depth to explain the real failures those combinations produce.
MBR — The Legacy Partition Table
The Master Boot Record lives in the disk's first 512-byte sector: 446 bytes for boot code (grub1-2's own boot.img), 64 bytes for the partition table itself — four 16-byte entries, no more — and 2 bytes for a boot signature. Exactly four primary partitions is a hard limit baked directly into that 64-byte structure, not a soft recommendation. The historical workaround — converting one primary slot into an "extended" partition that holds further logical partitions — exists purely to route around this. 32-bit sector addressing caps a usable disk at roughly 2TiB, a genuine ceiling MBR cannot exceed.
GPT — The Modern Partition Table
GPT stores partition information in a proper table structure rather than squeezing it into 64 bytes, using 64-bit addressing — no meaningful size limit for the foreseeable future — and supports up to 128 partitions by default, with no extended/logical workaround needed. Genuinely more resilient, too: GPT keeps a full backup copy of its own partition table at the end of the disk, plus checksums, rather than MBR's single, unprotected copy sitting at the very start. And every GPT disk carries a protective MBR at sector 0 — a deliberate dummy MBR entry, present specifically so older tools that only understand MBR don't mistake a GPT disk for empty space and overwrite it.
BIOS vs. UEFI — Revisited in Full
UEFI is, in real terms, its own small, standardized pre-OS operating environment. It can run programs — drivers, bootloaders — directly from a real FAT filesystem, and it maintains its own persistent, NVRAM-stored list of boot entries (viewable and editable with efibootmgr), independent of any disk's own partition table. BIOS has none of this: no persistent boot-entry storage of its own, no native filesystem reading — exactly why GRUB needs the staged bootstrap grub1-2 described, and exactly why that bootstrap only exists on BIOS systems in the first place.
Which Combinations Actually Work
| Combination | Status |
|---|---|
| BIOS + MBR | The traditional, natural pairing |
| UEFI + GPT | The modern, recommended pairing |
| BIOS + GPT | Possible via a hybrid/compatibility setup — real, but not the clean path |
| UEFI + MBR | Possible via CSM (Compatibility Support Module) — again real, but a frequent source of confusing edge cases |
This is the precise, technical version of grub1-1's own warn-box: those off-diagonal combinations are where mismatched-boot-mode confusion genuinely originates.
Secure Boot — Briefly
A UEFI-specific feature: firmware refuses to execute any bootloader that isn't cryptographically signed by a trusted key. Some Linux distributions ship a GRUB build signed via a small intermediary ("shim") layer specifically to work with Secure Boot out of the box; others require disabling Secure Boot, or manually enrolling a key, before their own bootloader will run at all. A genuinely practical concern for grub1-6/grub1-7's own dual-boot scenarios — named here deliberately briefly, not covered exhaustively.
Revisiting pc_build_11's Own Material
pc_build_11 covered BIOS/UEFI at the hardware level — how to enter your firmware's own settings screen while building a PC. This chapter goes deeper on a genuinely different question that chapter never addressed: not "how do I access these settings," but "what is the actual structural difference in how each firmware model finds and executes a bootloader in the first place."
sudo parted -l or lsblk -o NAME,PTTYPE reports whether a disk is currently MBR or GPT, right now — turning this chapter's conceptual material into something directly checkable on a real system.
gdisk's own conversion mode, for one) — but this remains a genuinely risky operation on the partition table itself, and backups matter before ever attempting it. Not something to experiment with on a disk holding data you actually care about.
Hands-On Exercises
Explain, using MBR's own 64-byte partition table structure, exactly why it can hold only four primary partitions, and what the historical extended/logical partition workaround actually does.
📄 View solutionExplain what a GPT disk's own "protective MBR" is actually protecting against, and why it's placed at sector 0 rather than somewhere else on the disk.
📄 View solutionA system is set to boot in UEFI mode, but its disk is partitioned as MBR. Using this chapter's own "which combinations actually work" table, explain what's technically happening here and why it's a real source of confusing edge cases rather than a clean setup.
📄 View solutionChapter 5 Quick Reference
- MBR — 512-byte first sector, 4 primary partitions max, ~2TiB size limit, single unprotected partition-table copy
- GPT — a real table structure, up to 128 partitions, no practical size limit, a backup copy plus checksums, and a protective MBR for compatibility
- UEFI is its own small pre-OS environment — reads a real filesystem, keeps persistent NVRAM boot entries; BIOS has none of this, which is exactly why GRUB needs its own staged bootstrap on BIOS systems
- BIOS+MBR and UEFI+GPT are the clean pairings; BIOS+GPT and UEFI+MBR are real but genuinely confusing edge cases
- Secure Boot (UEFI-only) requires a signed bootloader — a real, practical consideration for the dual-boot chapters ahead
parted -l/lsblk -o NAME,PTTYPE— check a real disk's own partition table type- Converting a disk between MBR and GPT is destructive to the partition table — never attempt without a backup
Dual-Booting Linux and Windows
GRUB & Multibooting
Chapter 6 · Dual-Booting Linux and Windows
The first of two genuinely different dual-boot scenarios this course covers. grub1-5's own BIOS/UEFI/MBR/GPT material — and its Secure Boot preview — both become directly relevant here, since Windows and Linux frequently disagree on defaults.
Windows's Own Bootloader — bootmgfw.efi
Windows uses its own bootloader — Windows Boot Manager, bootmgfw.efi on a UEFI system, or the older NTLDR/BOOTMGR pairing on legacy BIOS — Microsoft's direct parallel to GRUB. On a UEFI system, it lives inside the same EFI System Partition GRUB itself wants to use, exactly grub1-5's own material made concrete. The key insight: on UEFI, both bootloaders can coexist as separate .efi files in that same partition, each registered as its own entry in UEFI's persistent NVRAM boot list. On a legacy BIOS/MBR system, this isn't possible the same way — only one thing can ever occupy the MBR's own tiny boot-code region at a time.
The Recommended Installation Order — Windows First, Then Linux
Install Windows first, then Linux. Windows's own installer is not cooperative about detecting other operating systems, and will happily overwrite the boot sector or EFI boot entries without asking. Linux's installer — and GRUB's own os-prober, previewed in grub1-2 — is specifically built to detect an existing Windows installation and add a menu entry pointing at it. Installing in the reverse order means Windows clobbers GRUB outright, requiring a real repair (grub1-9).
Partitioning for Dual-Boot
Windows needs its own NTFS partition; Linux needs its own (an ext4 root, optionally a separate /home, and swap). Both operating systems share the same EFI System Partition on a UEFI system, rather than each getting its own — a genuinely important, sometimes-surprising point. Practical advice: shrink the Windows partition first, from Windows's own Disk Management tool, then let the Linux installer use the freed space — not the reverse.
os-prober — How GRUB Actually Finds Windows
os-prober scans other partitions on the system for other bootable operating systems it recognizes — including checking for Windows's own hidden system files. When found, it generates a menu entry pointing back at Windows's own bootloader:
GRUB doesn't understand Windows internals at all — it simply chainloads, handing control directly to Windows's own bootloader, which then takes it from there. This entry is generated automatically by 30_os-prober — never hand-write it, exactly grub1-2/grub1-3's own "generated, never hand-edited" rule, now seen concretely in the one case most likely to tempt someone into hand-editing.
The Classic Gotcha — Windows Update Breaks GRUB
A genuinely common real-world event: after a major Windows Update, Windows sometimes silently resets itself to the top of the UEFI boot order, or — on a legacy BIOS system — directly overwrites the MBR's own boot code. GRUB effectively vanishes from the boot process; the system boots straight into Windows with no menu at all.
The fix: from a live USB or rescue environment, reinstall GRUB (grub-install, previewed here, covered fully in grub1-9) and/or use efibootmgr to reset the UEFI boot order so GRUB's own entry is first again — grub1-5's own NVRAM boot-list material, put to practical use.
| Can both bootloaders coexist? | What Windows tends to overwrite | |
|---|---|---|
| BIOS + MBR | No — only one occupies the MBR's own boot code | The MBR's own boot sector directly |
| UEFI + GPT | Yes — separate .efi files, separate NVRAM entries | The boot order (which entry runs first), not the files themselves |
grub1-5's own preview) and the installed GRUB isn't properly signed/shimmed for it, GRUB's own entry can be rejected outright by firmware even while still correctly listed in the boot order — a different problem from a reordered boot list, needing a different fix (re-enrolling a shim/key), not just running efibootmgr again.
Hands-On Exercises
Explain why installing Linux before Windows on the same disk is more likely to require a repair afterward than installing Windows first.
📄 View solutionExplain what "chainloading" actually means in the context of the os-prober-generated Windows menu entry shown in this chapter, and why GRUB doesn't need to understand Windows internals to make it work.
📄 View solutionAfter a Windows Update, a dual-boot system boots straight into Windows with no GRUB menu. Running efibootmgr -v shows GRUB's own entry still present, just no longer first. Explain the correct fix, and how this scenario would differ if GRUB's entry were being outright rejected instead.
📄 View solutionChapter 6 Quick Reference
- Windows uses its own bootloader (bootmgfw.efi); on UEFI it coexists with GRUB as separate .efi files and separate NVRAM entries
- Install Windows first, then Linux — Linux's own installer/os-prober cooperatively detects Windows; Windows's installer does not detect Linux
- Windows and Linux each need their own partitions, but share one EFI System Partition on UEFI systems
- os-prober auto-generates a chainloading menu entry pointing at Windows's own bootloader — never hand-written
- Chainloading means handing off control entirely — GRUB never needs to understand Windows internals
- The classic gotcha: a Windows Update resets the UEFI boot order or overwrites the MBR, hiding GRUB — fixed via efibootmgr and/or grub-install
- Secure Boot re-enabling is a genuinely different failure (rejection, not reordering) needing a different fix
Dual-Booting Two Linux Distributions
GRUB & Multibooting
Chapter 7 · Dual-Booting Two Linux Distributions
A genuinely different problem from grub1-6, not just an easier version of it. Windows and GRUB are two entirely separate bootloaders with a clean handoff between them. Two Linux distros both install the same bootloader family, each with its own package manager convinced it alone is responsible for keeping the boot configuration current.
Why This Is a Genuinely Different Problem
With Windows, GRUB chainloads to a completely foreign bootloader it doesn't understand or manage — clean separation, no conflict of ownership. With two Linux distros, both typically install their own copy of GRUB, and each distro's own package manager — apt on a Debian-based system, dnf on a Fedora-based one, pacman on Arch — considers itself responsible for regenerating "the" grub.cfg every time its own kernel updates. A genuine conflict of ownership, not a clean handoff.
What Actually Happens When You Install a Second Distro
The second distro's installer typically detects that GRUB is already installed, and either offers to install its own alongside it or asks directly which distro's GRUB should actually control the boot process. This matters structurally: only one GRUB installation can actually be the one occupying the MBR's boot sector or holding the primary EFI boot entry (grub1-5's own material). That one installation's own os-prober is what scans for and lists every other distro's kernels as additional menu entries.
os-prober Finding Multiple Kernels — Not Just Multiple OSes
grub1-2 distinguished 10_linux (lists every kernel for the current distro) from 30_os-prober (finds other operating systems entirely). For a second Linux distro specifically, os-prober generates entries that chainload directly to that other distro's own kernel and initramfs — a different kind of chainload target than grub1-6's own bootloader-level handoff to Windows. This arrangement is more efficient, but genuinely more fragile: it can break if the other distro's own kernel file gets renamed or removed by its own package updates without the authoritative distro's grub.cfg ever being regenerated to notice.
Choosing an Authoritative GRUB
Practical guidance: settle on one distro's GRUB installation as authoritative — commonly whichever was installed last, since it's naturally the one left controlling the boot sector or EFI entry — and let its own os-prober manage the real, in-use grub.cfg, rather than fighting over which one "should" be in charge. The other distro's own GRUB installation, once superseded, becomes effectively redundant for actual booting — though its own package manager has no idea, and will keep dutifully regenerating its own grub.cfg on every kernel update: a file that firmware simply never reads. This is exactly the "competing package managers each wanting to own the boot process" tension this chapter opened with.
The os-prober Update Timing Problem
A genuine, real gotcha: the authoritative distro's own grub.cfg only picks up a new kernel from the other distro once the authoritative distro's own update-grub is manually re-run. The other distro's own package manager updating its own kernel does not automatically trigger the authoritative distro's own regeneration — they're two entirely separate systems, with no coordination between them at all. This can leave a stale, "phantom" menu entry pointing at a kernel that's since been replaced or removed, until update-grub is deliberately re-run on the authoritative side.
| What's being handed off to | The real conflict | |
|---|---|---|
| Linux + Windows (grub1-6) | A completely separate, foreign bootloader | None — a clean, one-directional handoff |
| Linux + Linux (this chapter) | The other distro's own kernel/initramfs directly | Two package managers each assuming ownership of the boot config |
update-grub (or the local equivalent) from the authoritative distro specifically — never assume it happens automatically. This closes the update-timing gotcha directly.
Hands-On Exercises
Explain, using this chapter's own compare-table, why a Linux/Linux dual-boot has a real ownership conflict that a Linux/Windows dual-boot structurally does not.
📄 View solutionDistro B (not the authoritative one) receives a kernel update. Explain exactly what does and doesn't happen to the boot menu as a result, and the specific command needed to fix it.
📄 View solutionA user notices their dual-boot menu occasionally changes ordering or loses an entry with no obvious cause. Using this chapter's own warn-box, propose the most likely root cause and how to confirm it.
📄 View solutionChapter 7 Quick Reference
- Linux/Linux is genuinely different from Linux/Windows: both distros install the same bootloader family, each package manager assuming ownership
- Only one GRUB installation can actually control the boot sector/EFI entry — that one is authoritative, usually whichever was installed last
- os-prober for a second Linux distro chainloads directly to that distro's own kernel/initramfs, not to a separate bootloader
- The non-authoritative distro's own GRUB keeps regenerating its own unused grub.cfg — never actually read by firmware
- The authoritative distro's grub.cfg only picks up the other distro's new kernel after its own update-grub is manually re-run
- A dual-boot menu that changes or loses entries with no obvious cause traces directly back to two package managers fighting over ownership
Multi-Boot With More Than Two OSes & Advanced Partitioning
GRUB & Multibooting
Chapter 8 · Multi-Boot With More Than Two OSes & Advanced Partitioning
grub1-6 and grub1-7 established two chainloading mechanisms for two different kinds of neighbor. This chapter shows they don't need reinventing for a third, fourth, or fifth operating system — they combine and scale directly — and goes deeper on partitioning strategy for a genuinely complex layout.
Generalizing to Three or More Operating Systems
The underlying mechanisms don't change with more operating systems on the disk: one authoritative GRUB installation (grub1-7's own principle), os-prober scanning every other partition (grub1-2/grub1-6/grub1-7), each additional OS adding one more menu entry via whichever mechanism actually fits it. What genuinely grows with more OSes: install order matters even more — grub1-6's own "Windows first" lesson generalizes into "install every uncooperative OS first, Linux/GRUB last," so GRUB ends up as the final, authoritative bootloader regardless of how many neighbors it has — and os-prober's own scan simply has more partitions to check, with correspondingly more opportunity for something to go wrong.
A Dedicated /boot Partition — Why and When
In a genuinely complex multi-OS layout, keeping /boot as its own small, separate partition — rather than folded into the root filesystem — has real advantages, building on grub1-5's own material: it guarantees GRUB is working with a filesystem it definitely understands (plain ext2/ext4), sidestepping any support gap with a more exotic root filesystem, and keeping it small and separate means it survives a root-filesystem reinstall or reformat completely untouched. This becomes genuinely more valuable specifically once three or more OSes share a disk, where "just reinstall this one distro" is a real, common temptation that gets riskier the more entangled /boot is with root.
Chainloading — the Generalized Mechanism
grub1-6's chainload-to-a-foreign-bootloader and grub1-7's chainload-to-a-kernel-directly are two flavors of exactly the same underlying idea: GRUB's own general-purpose "hand control to this other thing" mechanism. This is precisely what lets an arbitrary number of operating systems share one boot menu without GRUB ever needing to understand any of their internals beyond locating the right file to hand off to.
A Three-Way Example — Debian + Fedora + Windows
- Partition layout: one shared EFI System Partition, a Debian root partition, a Fedora root partition, a Windows NTFS partition
- Install order: Windows first, then Fedora, then Debian last — leaving Debian's own GRUB as the final, authoritative installation
- The resulting menu: native entries for every Debian kernel (via
10_linux), a chainload-to-kernel entry for Fedora (grub1-7's own mechanism), and a chainload-to-bootloader entry for Windows (grub1-6's own mechanism) — all generated automatically by Debian's ownos-prober, none hand-written
LVM Considerations — Deferred, Not Covered
Logical Volume Manager (LVM) is a genuinely common, flexible way to manage disk space across multiple partitions and operating systems, and GRUB does have real LVM support of its own (a module, the same kind of thing grub1-2 described GRUB carrying for filesystems and partition schemes generally). But LVM's own concepts — physical volumes, volume groups, logical volumes — are substantial enough to deserve their own dedicated treatment, exactly what this site's own still-outstanding "Linux filesystems" bucket-list topic exists for. Named honestly here as a real, acknowledged gap in this course's own scope, not silently skipped over.
| Chainload target | Used for | Chapter |
|---|---|---|
| Another bootloader entirely | Windows, or any genuinely foreign OS | grub1-6 |
| A kernel/initramfs directly | A second (or third) Linux distro | grub1-7 |
grub.cfg, or at minimum note down which distro is currently authoritative. A genuinely cheap insurance step, directly relevant given grub1-9's own upcoming rescue chapter.
os-prober can occasionally misdetect an operating system, generate a broken entry, or simply miss one entirely. Verify every generated entry against update-grub's own printed output (grub1-3's own tip) rather than assuming a clean run means every OS was correctly found — a clean exit code says the script ran without error, not that every entry it produced is actually correct.
Hands-On Exercises
For a four-OS layout (Windows, Fedora, Debian, and a Windows-adjacent recovery partition the user wants untouched), propose an install order and explain your reasoning using this chapter's own generalized "uncooperative OSes first" rule.
📄 View solutionExplain why a dedicated /boot partition becomes more valuable specifically as more operating systems share one disk, referencing the "reinstall temptation" this chapter names.
📄 View solutionupdate-grub finishes with no errors on a three-OS system, but the resulting menu is missing an entry for one of the operating systems. Explain why this is possible despite the clean exit, using this chapter's own warn-box.
📄 View solutionChapter 8 Quick Reference
- The mechanisms don't change with more OSes — one authoritative GRUB, os-prober scanning, chainloading to whichever target fits each OS
- Install order generalizes: every uncooperative OS first, Linux/GRUB last
- A dedicated /boot partition guarantees a filesystem GRUB understands and survives a root reinstall untouched — genuinely more valuable with 3+ OSes sharing a disk
- Chainloading is one general mechanism with two flavors: to a foreign bootloader (grub1-6) or directly to a kernel/initramfs (grub1-7)
- LVM is real, common, and GRUB does support it — but deliberately deferred here to the site's own still-outstanding Linux filesystems topic
- Back up a working grub.cfg (or note the authoritative distro) before adding another OS
- A clean update-grub exit doesn't guarantee every OS was correctly detected — verify against its own printed output
Recovering From a Broken Bootloader
GRUB & Multibooting
Chapter 9 · Recovering From a Broken Bootloader
grub1-4 covered the light rescue scenario — the system still boots, just to a minimal shell. This chapter is the heavy one: GRUB itself is broken, and the system never reaches a kernel at all. This assumes real comfort with the command line, the same prerequisite linux1-11's own Essential Terminal Skills chapter established — worth naming honestly up front.
Recognizing a Broken Bootloader
Three genuinely different symptoms: a grub rescue> prompt (a minimal fallback shell GRUB itself drops into when core.img ran successfully but couldn't find /boot/grub — distinct from grub1-4's own full menu editor); the system booting straight past GRUB into another OS with no menu at all (grub1-6's own gotcha); or a firmware-level "no bootable device" / "operating system not found" error, meaning firmware couldn't find any bootloader whatsoever. The first means GRUB partially loaded; the last means firmware never found GRUB in the first place — genuinely different failures.
Step 1 — Boot From a Live USB
The same installation media linux1-4 described creating doubles as the rescue tool here — boot it, but choose "Try" or live mode rather than "Install."
Step 2 — Identify and Mount the Broken System's Partitions
From the live environment, lsblk or fdisk -l identifies which partition holds the broken system's root filesystem, and — if kept separate per grub1-8's own advice — its dedicated /boot partition. Mount them under a temporary mountpoint.
Step 3 — chroot Into the Broken System
chroot temporarily makes the mounted broken system's own root filesystem be the root filesystem for a new shell — commands from this point on run against the broken system's own binaries, libraries, and configuration, as though it had actually booted normally. Bind-mounting /dev, /proc, and /sys first gives that chrooted environment working device and process access, without which most repair commands would fail outright.
Step 4 — Reinstall GRUB with grub-install
Now run from inside the chroot, using the broken system's own grub-install — as if executed from a normal boot. On BIOS, the target is the whole disk device, never a specific partition (grub1-5's own material on why boot code needs the MBR itself). On UEFI, the syntax is genuinely different, because the installation mechanism itself differs — writing an EFI binary into the EFI System Partition and registering a fresh NVRAM boot entry, rather than writing directly to an MBR.
Step 5 — Exit, Unmount, Reboot
exit leaves the chroot; unmount everything in reverse order; reboot; remove the live USB; confirm the menu is back.
A Real Walkthrough — Recovering From Chapter 6's Own Gotcha
Applied directly to grub1-6's own scenario — a Windows Update reset the boot order or overwrote the MBR: boot the live USB, mount the Linux root partition, chroot in, run grub-install (and update-grub, or efibootmgr to restore the boot order on UEFI), reboot. The same five-step procedure, resolving the exact problem named three chapters earlier.
| Symptom | What's actually broken | Repair |
|---|---|---|
| grub rescue> prompt | GRUB partially loaded, can't find /boot/grub | chroot + grub-install |
| No bootable device | Firmware never found any bootloader at all | chroot + grub-install (target/EFI entry likely missing entirely) |
grub1-7's own "wrong distro became authoritative" scenario specifically, running just os-prober plus update-grub inside the chroot is often enough on its own, without needing a full grub-install. Worth trying before reaching for the heavier repair.
lsblk or fdisk -l before running grub-install, especially on any system with more than one disk attached.
Hands-On Exercises
Write the full command sequence to mount a broken system's root partition at /mnt, bind-mount /dev, /proc, and /sys, and chroot into it, matching this chapter's own example.
📄 View solutionExplain why grub-install's own target argument differs between BIOS and UEFI systems, referencing the actual difference in what each one writes to disk.
📄 View solutionA dual-Linux system (grub1-7's own scenario) suddenly boots the wrong distro's menu after an update. Explain the lighter fix worth trying before a full grub-install, and why it's likely sufficient here.
📄 View solutionChapter 9 Quick Reference
- grub rescue> — GRUB partially loaded but lost grub.cfg; no bootable device — firmware never found GRUB at all
- Boot a live USB (linux1-4's own installation media) in "Try"/live mode, never "Install"
- Mount the broken system's root (+ /boot/efi if UEFI), bind-mount /dev /proc /sys, then chroot in
- grub-install /dev/sdX (BIOS, whole disk) vs. grub-install --target=x86_64-efi --efi-directory=... (UEFI) — genuinely different mechanisms
- update-grub inside the chroot, then exit, unmount, reboot
- For a wrong-authoritative-distro problem, try os-prober + update-grub alone before a full grub-install
- Always confirm the target device with lsblk/fdisk -l first — the wrong device makes things worse, not better
Capstone: Building a Real Triple-Boot Test Environment
GRUB & Multibooting
Chapter 10 · Capstone — Building a Real Triple-Boot Test Environment
The final chapter. One virtual machine, one virtual disk, three real operating systems — built in the correct order, configured properly, deliberately broken, and repaired using exactly the procedure grub1-9 taught. A disposable VM is exactly the right place to intentionally break something you already know how to fix.
The Environment — Three OSes, One Shared Disk
A single VM (VirtualBox or QEMU, tool-agnostic), UEFI firmware enabled in its settings, one virtual disk — this is how real triple-boot actually works: one machine, one disk, three operating systems sharing it, not three separate machines.
Step 1 — Partition Planning
GPT, matching grub1-5's own recommended UEFI pairing. Layout: one shared EFI System Partition (grub1-6's own material), a Windows NTFS partition, a Fedora root partition, and Debian's own root partition plus a dedicated /boot partition — grub1-8's own advanced-partitioning recommendation, applied for real this time rather than just described.
Step 2 — Install Order
Windows first, Fedora second, Debian last — grub1-8's own generalized rule applied directly: every uncooperative OS first, Linux/GRUB last, leaving Debian as the final, authoritative installation.
Step 3 — Confirming the Menu
Booting after Debian's install should show exactly this shape: native Debian kernel entries generated by 10_linux, a Fedora entry chainloading directly to its own kernel and initramfs (grub1-7), and a Windows entry chainloading to its own bootloader (grub1-6) — all produced automatically by Debian's own os-prober, none hand-written.
Step 4 — Applying Chapters 3 and 4's Own Configuration
grub1-3's own workflow, applied deliberately: a real triple-boot menu needs a genuinely usable timeout, not the single-OS GRUB_TIMEOUT=0 default. Run update-grub to apply it. Then, as a direct test of grub1-4's own live-edit workflow, press e on the Fedora entry, confirm it's genuinely editable exactly as it was for a single-OS menu, and back out with Esc — confirming the live-edit workflow still behaves correctly in this more complex environment.
Step 5 — Deliberately Breaking It
Boot into Windows and simulate grub1-6's own gotcha directly — reset the UEFI boot order, or use Windows's own boot-repair tooling, so Windows becomes the sole boot target. Reboot: the three-way menu is gone, the system boots straight into Windows. Exactly grub1-6's own scenario, now reproduced on purpose, in an environment safe to break.
Step 6 — The Rescue, Applied for Real
- Boot the Debian live USB image (the same media from Step 2's own install)
- Mount Debian's root partition and its EFI System Partition
- Bind-mount
/dev,/proc,/sys;chrootin grub-install --target=x86_64-efi --efi-directory=/boot/efi --bootloader-id=GRUBupdate-grub- Exit, unmount, reboot, remove the media
grub1-9's own five-step procedure, applied end to end for real — and the full three-way menu, Debian/Fedora/Windows entries and all, is back.
| Piece | Chapter |
|---|---|
| GPT + UEFI, shared EFI System Partition | grub1-5, grub1-6 |
| Dedicated /boot partition | grub1-8 |
| Install order (uncooperative OSes first) | grub1-6, grub1-8 |
| 10_linux / os-prober-generated menu | grub1-2, grub1-6, grub1-7 |
| Permanent GRUB_TIMEOUT/GRUB_DEFAULT config | grub1-3 |
| Live edit verification via 'e' | grub1-4 |
| The deliberate break (simulated Windows overwrite) | grub1-6 |
| The full chroot + grub-install rescue | grub1-9 |
grub1-8 to the site's own still-outstanding "Linux filesystems" topic, not covered here either. Secure Boot enrollment is likewise not tested end to end here — grub1-5's own light-touch preview stands as this course's full coverage of it. And this is a genuinely manual, hands-on lab exercise, not an automated, idempotent build — deliberately not what ansible1's own capstone did, since GRUB's own configuration isn't really automatable the same way service configuration is; a full VM rebuild means repeating these steps by hand, not re-running a playbook. Finally, this is VM-only — a real, stated limitation distinct from testing against actual physical hardware, where firmware quirks can behave differently than a hypervisor's own UEFI implementation.
Hands-On Exercises
Explain why the partition layout in Step 1 gives Debian and Fedora each their own root partition, but only one shared EFI System Partition between all three operating systems.
📄 View solutionExplain what would likely have gone wrong in Step 3's own confirmation step if the install order in Step 2 had instead been Debian, then Fedora, then Windows.
📄 View solutionA reader asks why this capstone doesn't just write an Ansible playbook (per the site's own ansible1 course) to automate the whole triple-boot build. Give an honest answer using this chapter's own scope note.
📄 View solutionChapter 10 Quick Reference — GRUB & Multibooting Complete
- One VM, one disk, GPT + UEFI, a shared EFI System Partition, a dedicated Debian /boot — the real-world shape of triple-boot
- Install order: Windows → Fedora → Debian, leaving Debian's own GRUB authoritative
- The resulting menu combines native entries, a chainload-to-kernel entry, and a chainload-to-bootloader entry — all auto-generated
- grub1-3's permanent config and grub1-4's live-edit workflow both verified working in the more complex environment
- The deliberate break (simulating grub1-6's own Windows-overwrite gotcha) and its repair (grub1-9's own five-step chroot rescue) close the loop for real
- Honest scope note: no LVM, no Secure Boot enrollment tested end to end, a manual (not automated) build, VM-only
- The full GRUB & Multibooting course — 10 chapters — is now complete.