| | {{infobox |
| | | title = LFS: Kernel, Bootloader & First Boot |
| | | chapter = Linux Handbook, chapter 6 — the system becomes a machine |
| | | stage | LFS book chapters 9–10 — the payoff |
| | | milestone | boot: the machine you built from source, running itself |
| | | hardest_idea = The kernel must know your hardware before it exists as a system |
| | | needs | The complete chroot userspace from chapter 5 |
| | | next | BLFS — building beyond the base system |
| | }} |
| | |
| | **This is the chapter where it boots.** The fifty-package marathon leaves a complete userspace sitting on a partition — but a filesystem is not a machine. Chapter 6 installs the last load-bearing pieces (the boot scripts, the fstab, the network config, the kernel itself, the bootloader), and then commits the ultimate act: **rebooting into the system you built**. If it comes up, you own a Linux assembled entirely from source — every binary a product of your own compiler. |
| | |
| | ## First: the configuration files |
| | |
| | Before kernel, before GRUB — the system's identity files. Inside the chroot: |
| | |
| | ```sh |
| | # /etc/fstab — what mounts where at boot |
| | cat > /etc/fstab << "EOF" |
| | # file system mount-point type options dump fsck order |
| | /dev/sda3 / ext4 defaults 1 1 |
| | /dev/sda2 swap swap pri=1 0 0 |
| | proc /proc proc nosuid,noexec,nodev 0 0 |
| | sysfs /sys sysfs nosuid,noexec,nodev 0 0 |
| | devpts /dev/pts devpts gid=5,mode=620 0 0 |
| | tmpfs /run tmpfs defaults 0 0 |
| | devtmpfs /dev devtmpfs mode=0755,nosuid 0 0 |
| | tmpfs /dev/shm tmpfs nosuid,nodev 0 0 |
| | cgroup2 /sys/fs/cgroup cgroup2 nosuid,noexec,nodev 0 0 |
| | EOF |
| | # UEFI builders add: /dev/sda1 /boot/efi vfat ... |
| | ``` |
| | |
| | And the network — `iproute2` + a static or dhcpcd config in `/etc/sysconfig/`, plus `/etc/resolv.conf` if DNS is static: |
| | |
| | ```sh |
| | cat > /etc/sysconfig/ifconfig.eth0 << "EOF" |
| | ONBOOT=yes |
| | IFACE=eth0 |
| | SERVICE=ipv4-static |
| | IP=192.168.1.20 |
| | GATEWAY=192.168.1.1 |
| | PREFIX=24 |
| | BROADCAST=192.168.1.255 |
| | EOF |
| | cat > /etc/resolv.conf << "EOF" |
| | nameserver 192.168.1.1 |
| | EOF |
| | hostname > /etc/hostname |
| | ``` |
| | |
| | Plus `/etc/inittab` (for SysVinit — defining the runlevels and the gettys), `/etc/sysconfig/clock`, `/etc/inputrc`, `/etc/shells`, and the sysklogd config. The book walks each; every one is a file you've been meaning to understand — now you write them from nothing. |
| | |
| | ## The kernel — configuration as authorship |
| | |
| | ```sh |
| | cd /sources/linux-*/ |
| | make mrproper |
| | make defconfig # a sane generic starting point |
| | make menuconfig # YOUR hardware, YOUR choices — the real work |
| | ``` |
| | |
| | `menuconfig` is the chapter's soul: an ncurses tree of every kernel option — CPU family, filesystems, device drivers, security modules. The rules of thumb: |
| | |
| | - **Built-in `[*]`** vs **module `[M]`**: disk controllers and root filesystem must be **built-in** (a module can't load before the filesystem it lives on mounts — unless you carry an initramfs; classic LFS builds them in) |
| | - **Your disk controller** — SATA/AHCI (`CONFIG_ATA`, `SATA_AHCI`), NVMe (`CONFIG_BLK_DEV_NVME`), or virtio (`CONFIG_VIRTIO_*`) for QEMU — must be in |
| | - **Your filesystem** — `CONFIG_EXT4_FS` built-in |
| | - **Your network card** — e1000e, virtio-net, whatever the machine has |
| | - **Devtmpfs automount** — `CONFIG_DEVTMPFS_MOUNT=y` so `/dev` populates itself at boot |
| | - **UEFI** — `CONFIG_EFI` + `EFI_VARS` if you're on it |
| | |
| | Then compile — the longest single build of the project: |
| | |
| | ```sh |
| | make -j$(nproc) |
| | make modules_install |
| | cp -iv arch/x86_64/boot/bzImage /boot/vmlinuz-<ver>-lfs-12.x |
| | cp -iv System.map /boot/System.map-<ver> |
| | cp -iv .config /boot/config-<ver> |
| | install -d /usr/share/doc/linux-<ver> |
| | cp -r Documentation/* /usr/share/doc/linux-<ver> |
| | ``` |
| | |
| | The three files in `/boot` are the kernel (`bzImage`), its symbol map (`System.map`), and the recipe it was built from (`.config` — keep it; every future kernel starts from it). |
| | |
| | ## GRUB — the door |
| | |
| | On BIOS/MBR: |
| | |
| | ```sh |
| | grub-install /dev/sda |
| | cat > /boot/grub/grub.cfg << "EOF" |
| | set default=0 |
| | set timeout=5 |
| | insmod part_gpt |
| | insmod ext2 |
| | set root=(hd0,3) |
| | menuentry "GNU/Linux, Linux <ver>-lfs" { |
| | linux /vmlinuz-<ver>-lfs-12.x root=/dev/sda3 ro |
| | } |
| | EOF |
| | ``` |
| | |
| | On UEFI/GPT: `grub-install --target=x86_64-efi --efi-directory=/boot/efi --bootloader-id=LFS` and the ESP mounted at `/boot/efi` — `root=/dev/sda3` unchanged. GRUB's `(hd0,3)` partition numbering starts at 1; `root=` is the kernel's view. Getting these two right — and matching them — is the chapter's most classic mistake. |
| | |
| + | ## The kernel config — the critical set |
| + | |
| + | The options that decide whether it boots: |
| + | |
| + | ```sh |
| + | # make menuconfig — the load-bearing options: |
| + | CONFIG_EXT4_FS=y # root filesystem — BUILT-IN not module |
| + | CONFIG_ATA + SATA_AHCI=y # SATA disks — or: |
| + | CONFIG_BLK_DEV_NVME=y # NVMe — or: |
| + | CONFIG_VIRTIO_BLK/PCI=y # QEMU virtio — VM builds |
| + | CONFIG_DEVTMPFS=y + DEVTMPFS_MOUNT=y # /dev populates itself at boot |
| + | CONFIG_VT=y + VT_CONSOLE=y # the virtual console — or nothing displays |
| + | CONFIG_EFI=y + EFI_VARS=y # UEFI builds |
| + | CONFIG_NET + your NIC driver=y # networking |
| + | CONFIG_TMPFS=y # /run, /dev/shm |
| + | CONFIG_PROC_FS + SYSFS=y # /proc /sys — the kernel interfaces |
| + | CONFIG_UNIX=y # unix sockets — EVERYTHING needs this |
| + | CONFIG_BINFMT_ELF=y # run ELF binaries — or nothing runs |
| + | ``` |
| + | |
| + | The pattern: **boot-critical = built-in `[*]`**, everything else = module `[M]` or off `[ ]`. A module can't load from a filesystem that isn't mounted — disk + rootfs + console must be built-in, or you carry an initramfs to load them early. LFS's classic path: build them in, no initramfs — simpler. |
| + | |
| + | ## The fstab in full |
| + | |
| + | ```sh |
| + | cat > /etc/fstab << "EOF" |
| + | # device mount type options dump pass |
| + | /dev/sda3 / ext4 defaults 1 1 |
| + | /dev/sda2 swap swap pri=1 0 0 |
| + | proc /proc proc nosuid,noexec,nodev 0 0 |
| + | sysfs /sys sysfs nosuid,noexec,nodev 0 0 |
| + | devpts /dev/pts devpts gid=5,mode=620 0 0 |
| + | tmpfs /run tmpfs defaults 0 0 |
| + | devtmpfs /dev devtmpfs mode=0755,nosuid 0 0 |
| + | tmpfs /dev/shm tmpfs nosuid,nodev 0 0 |
| + | cgroup2 /sys/fs/cgroup cgroup2 nosuid,noexec,nodev 0 0 |
| + | EOF |
| + | # UEFI adds: /dev/sda1 /boot/efi vfat defaults 0 2 |
| + | ``` |
| + | |
| + | The `dump`/`pass` columns: `pass 1` = fsck checks root first, `2` = after, `0` = never. The virtual filesystems mount `nosuid,nodev,noexec` — kernel interfaces shouldn't run code. |
| + | |
| + | ## The network's files |
| + | |
| + | ```sh |
| + | cat > /etc/sysconfig/ifconfig.eth0 << "EOF" |
| + | ONBOOT=yes |
| + | IFACE=eth0 |
| + | SERVICE=ipv4-static |
| + | IP=192.168.1.20 |
| + | GATEWAY=192.168.1.1 |
| + | PREFIX=24 |
| + | BROADCAST=192.168.1.255 |
| + | EOF |
| + | cat > /etc/resolv.conf << "EOF" |
| + | nameserver 192.168.1.1 |
| + | EOF |
| + | echo "lfs" > /etc/hostname |
| + | cat > /etc/hosts << "EOF" |
| + | 127.0.0.1 localhost lfs |
| + | ::1 localhost |
| + | EOF |
| + | ``` |
| + | |
| + | ## GRUB — both paths |
| + | |
| + | **BIOS/MBR:** |
| + | |
| + | ```sh |
| + | grub-install /dev/sda # writes to the boot sector — the disk, not a partition |
| + | cat > /boot/grub/grub.cfg << "EOF" |
| + | set default=0 |
| + | set timeout=5 |
| + | insmod part_msdos # or part_gpt for GPT |
| + | insmod ext2 |
| + | set root=(hd0,3) # GRUB numbering: disks 0-based, partitions 1-based |
| + | menuentry "GNU/Linux, Linux 6.x-lfs" { |
| + | linux /vmlinuz-6.x-lfs root=/dev/sda3 ro |
| + | } |
| + | EOF |
| + | ``` |
| + | |
| + | **UEFI/GPT:** |
| + | |
| + | ```sh |
| + | mkfs.vfat /dev/sda1 # the ESP — if not already |
| + | mount /dev/sda1 /boot/efi # mount the ESP |
| + | grub-install --target=x86_64-efi --efi-directory=/boot/efi --bootloader-id=LFS |
| + | # grub.cfg identical — GRUB-EFI reads it the same |
| + | ``` |
| + | |
| + | The two numbering traps: GRUB's `(hd0,3)` is *disk 0, partition 3* (0-indexed disks, 1-indexed partitions); the kernel's `root=/dev/sda3` is Linux naming. They must match — same partition, two languages. |
| + | |
| + | ## The boot's transcript — reading it |
| + | |
| + | A successful first boot scrolls: GRUB's menu → `Loading Linux 6.x` → `Loading initial ramdisk` (or none — LFS classic has none) → kernel decompress → the device-detection flood → `Freeing unused kernel memory` → `Run /sbin/init as init process` → the init scripts' `[ OK ]`-style output → `login:`. Each stage's failure signature is the troubleshooting table's input. |
| + | |
| | ## The moment of truth |
| | |
| | ```sh |
| | # exit the chroot, unmount the virtual filesystems |
| | exit |
| | umount -v $LFS/dev/pts |
| | umount -v $LFS/{sys,proc,run,dev} |
| | umount -v $LFS |
| | reboot |
| | ``` |
| | |
| | Boot. GRUB's menu appears; the kernel decompresses; init starts; login prompts on a console. `login: root` — into a system where *every single file* is something you compiled. `uname -a`, `cat /etc/lfs-release`, `ls /` — a filesystem of your own making. |
| | |
| | ## What almost always goes wrong — and what to do |
| | |
| | | Symptom | Cause | |
| | | --- | --- | |
| | | Kernel panic: "unable to mount root fs" | Disk controller or ext4 built as *module* not built-in — rebuild kernel with `[*]` | |
| | | GRUB can't find the kernel | `set root=(hd0,N)` numbering vs actual partition — enumerate with `ls` at GRUB's command line | |
| | | Boots but no network | NIC driver missing — `make menuconfig`, add it built-in | |
| | | Boots but no console/keyboard | `CONFIG_VT`, keyboard driver missing | |
| | | `/dev` empty at boot | `DEVTMPFS_MOUNT` off — rebuild | |
| | | GRUB error: no such partition | GPT vs MBR mismatch — `insmod part_gpt` or wrong root | |
| | | Boots into GRUB rescue only | `grub-install` targeted the wrong disk | |
| | | Everything works except the hostname | `/etc/hostname` or hosts file | |
| | |
| | ## The recovery move you'll need |
| | |
| | If it won't boot: boot the host/live system again, `mount /dev/sda3 /mnt/lfs`, re-mount the virtual filesystems, `chroot` back in — the whole chapter-4 pivot — fix the kernel config or grub.cfg, and reboot again. LFS's greatest lesson: **nothing is unrecoverable while the host still boots.** The chroot door works both directions. |
| | |
| | ## What you now own |
| | |
| | A Linux where `ls /usr/bin` is a list of things *you* built — where `gcc --version` reports a compiler you compiled, where the kernel's `.config` is your hardware autographed. The system is minimal — no X, no package manager, no convenience — but it's **complete**: it boots, logs in, runs jobs, and can compile more of itself. |
| | |
| | ## Exercises |
| | |
| | 1. Boot it. (The only exercise that matters.) |
| | 2. Read your kernel's `.config` — find the five options that would have prevented boot had they been modules. |
| | 3. Rebuild the kernel with one deliberate break (e.g. ext4 as `M`) — watch the panic, then chroot-rescue it back. |
| | 4. Write the fstab from memory; compare to the book's. |
| | 5. `df -h /` — how big is the system you built? |
| | |
| | ## Timeline |
| | |
| | | Step | Result | |
| | | --- | --- | |
| | | Config files | fstab, inittab, network, hostname | |
| | | Kernel config | Your hardware, autographed into .config | |
| | | Kernel build | bzImage + System.map + .config in /boot | |
| | | GRUB | The bootloader installed and written | |
| | | Reboot | The machine runs itself | |
| | | next | BLFS — X, tools, the usable system beyond the base | |
| | |
| | ## References |
| | |
| | - linuxfromscratch.org — chapters 9–10: system configuration, kernel, bootloader |
| | - The kernel's own Kconfig documentation — `make menuconfig`'s reference |
| | - GRUB manual — boot-time partition/device naming |
| | |
| | ## See also |
| | |
| | - [[LFS Preparation]] · [[LFS Cross-Toolchain]] · [[LFS Temporary System]] · [[LFS System Packages]] · [[Linux]] |
| | |
| | [[Category:Linux]] |
| | [[Category:LFS]] |
| | [[Category:Handbook]] |
| | |