My Linux From Scratch notes for x86_64 EFI system

The goal of this guide is to provide a simplified version of the Linux From Scratch project, with steps organized in short sections that give you the satisfaction of testing each progress.

One key difference of this approach is that instead of building all the packages and tools that are part of a regular Linux OS, we start with a basic system based on the kernel and BusyBox, a simple binary that provides all the required commands.

Later we will continue adding packages and configurations until we get a system similar to the original LFS project.

Reference Links:

Disk configuration

For the guide we are going to use a disk image, but you can do this with real hardware.

Create raw disk image

30GiB example:

$ dd if=/dev/zero of=disk.img bs=1G count=30 status=progress

Create disk partitions

$ fdisk disk.img
  1. Create a new GPT partition table
  2. Add a new 512MiB EFI partition
  3. Add a new partition for the root filesystem with the remaining space
  4. Write the partition table

Format the partitions:

Take note of the name assigned to the loop device (in this case /dev/loop0), as it might vary depending on the system and already used loop names, so you might need to adjust some of the later commands.

$ losetup -P -f disk.img
$ losetup -a
  /dev/loop0: [2065]:26214403 (/mnt/1TB/LFS/disk.img)
$ lsblk /dev/loop0
loop0       7:0    0   30G  0 loop 
├─loop0p1 259:4    0  512M  0 part 
└─loop0p2 259:5    0 29,5G  0 part 
$ mkfs.vfat -F32 /dev/loop0p1
$ mkfs.ext4 /dev/loop0p2

Check the new partitions:

$ fdisk -l /dev/loop0
  Disk /dev/loop0: 30 GiB, 32212254720 bytes, 62914560 sectors
  Units: sectors of 1 * 512 = 512 bytes
  Sector size (logical/physical): 512 bytes / 512 bytes
  I/O size (minimum/optimal): 512 bytes / 512 bytes
  Disklabel type: gpt
  Disk identifier: 41907C5B-56E5-A64C-A89B-688589A53CC9

  Device         Start      End  Sectors  Size Type
  /dev/loop0p1    2048  1050623  1048576  512M EFI System
  /dev/loop0p2 1050624 62914526 61863903 29.5G Linux filesystem

Mount the root partition:

$ sudo mkdir -v /mnt/lfs
$ sudo mount -v /dev/loop0p2 /mnt/lfs
$ sudo chown -v $(whoami) /mnt/lfs

Building the initial root filesystem

Creating the directory layout

$ cd /mnt/lfs
$ mkdir -pv dev etc proc run sys var usr/{bin,lib,src}
$ ln -sv usr/lib lib
$ ln -sv usr/lib lib64
$ ln -sv usr/lib usr/lib64
$ ln -sv usr/bin bin
$ ln -sv usr/bin sbin
$ ln -sv usr/bin usr/sbin

Installing shared libraries (glibc)

$ cd /mnt/lfs/usr/src
$ wget -O- | xz -dc | tar -x
$ cd glibc-2.34
$ mkdir build
$ cd build
$ ../configure --prefix=/usr --enable-kernel=4.4
$ make
$ make DESTDIR=/mnt/lfs install

Getting BusyBox

BusyBox is a software suite that provides several Unix utilities in a single executable file. It was specifically created for embedded operating systems with very limited resources, as the single executable replaces basic functions of more than 300 common commands.

This makes it perfect for this project, as it allows us to have a functional system much earlier, without needing to compile all the packages for each tool.

$ cd /mnt/lfs/usr/src
$ wget -O- | bzip2 -dc | tar -x
$ cd busybox-1.34.0
$ make defconfig
$ make -j

In case you want to configure the build of BusyBox, instead of make defconfig you can use make menuconfig, which shows a menu with all the settings.

Once compiled, we can now move the generated binary to the system's /bin directory and create all the links for each command it provides.

$ cp -v busybox /mnt/lfs/bin/
$ cd /mnt/lfs/bin/
$ for t in $(./busybox --list); do
    ln -sv busybox $t

Configure busybox as the init program:

$ cd /mnt/lfs/
$ ln -sv bin/busybox /mnt/lfs/init

Try it with chroot

$ sudo chroot /mnt/lfs /bin/sh

Getting the Kernel

Compile the Kernel

$ cd /mnt/lfs/usr/src
$ wget -O- | xz -dc | tar -x
$ cd linux-5.14.8
$ make -j x86_64_defconfig

Same as for BusyBox, if you want to customize your kernel build you can run make menuconfig.

To make the system even simpler we won't use a boot loader, for now, so one thing we do need to configure before compiling is the kernel parameters so that it knows where to find the root partition.

$ PARTUUID=$(blkid /dev/loop0p2 -s PARTUUID -o value)
$ echo "CONFIG_CMDLINE_BOOL=y" >> .config
$ echo "CONFIG_CMDLINE=\"root=PARTUUID=$PARTUUID rw rootwait\"" >> .config
$ echo "CONFIG_CMDLINE_OVERRIDE=n" >> .config
$ make -j$(nproc)

Try the kernel with Qemu

Only running the kernel in Qemu would give us a 'Kernel Panic' error, as it wouldn't find the root filesystem. But as we already have the root partition built, we can specify it to Qemu as the main disk:

$ cd /mnt/lfs/usr/src/linux-5.14.8
$ qemu-system-x86_64 -hda /dev/loop0 -kernel arch/x86/boot/bzImage

You can also use the path to the raw disk image instead of the loop device.

Making the disk image bootable

Configure the EFI boot

Mount the EFI partition:

$ mkdir -pv /mnt/lfs/boot/efi/
$ sudo mount -v /dev/loop0p1 /mnt/lfs/boot/efi/

Even though it's pretty rare to boot the system without a boot loader, it is possible to use a kernel bzImage as an EFI executable. Now we only need to copy the bzImage kernel we previously compiled to the EFI partition.

The path \EFI\Boot\bootx64.efi is the only bootloader pathname that the UEFI firmware on 64-bit X86 systems will look for without any preexisting NVRAM boot settings, so this is what we are going to use.

$ sudo mkdir -pv /mnt/lfs/boot/efi/EFI/Boot/
$ sudo cp -v /mnt/lfs/usr/src/linux-5.14.8/arch/x86/boot/bzImage /mnt/lfs/boot/efi/EFI/linux/bootx64.efi

Try the bootable disk image

To boot Qemu in EFI mode, we need a bios file, for example OVMF, which is included with most package managers, and once installed you can find it with with locate OVMF.fd (make sure to use the 64bit file)

$ qemu-system-x86_64 -hda /dev/loop0 -bios OVMF.fd

As for the previous section where we ran the kernel with Qemu, you can use the path of the raw image disk instead of the loop device.

The number of Tuxes on display is set by the number of threads, which is cool to see 😄️ (add -smp and the threads you want)

Latest posts

Kali 2020.2 desktop and theme updates

kali 2020.2

Today Kali 2020.2 has been released and with it lots of new visual changes and desktop improvements.

Here's a quick summary of what's new:

  • KDE Plasma Makeover & Login
  • PowerShell by Default. Kind of.
  • Kali on ARM Improvements
  • Lessons From The Installer Changes
  • New Key Packages & Icons
  • Behind the Scenes, Infrastructure Improvements
Read more ↦

Pimp my terminal

pimp my term!

As a Linux user, I enjoy working with the terminal, and I find it an especially powerful tool. Therefore, I've spent quite a long time customizing it, and here is my definitive guide for terminal customizations.

First I thought I would only create a short post with some of the tweaks I like. But I had so many things I wanted to show that this started to become a considerably long post. So I've decided to publish it now, with as many tips as I can write, and I'll be updating it with new tips & tricks.

terminal preview Read more ↦

Kali 2020.1 visual updates

Today Kali 2020.1 has been released and with it lots of new visual changes for its desktop. The following is a brief feature summary for this release:

  • Non-Root by default
  • Kali single installer image
  • Kali NetHunter Rootless
  • Improvements to theme & kali-undercover
  • New tools

But here I'm not going to explain all the latest improvements that have been introduced in this version but to reveal all the different themes and visual modifications that come with it. By the way, an essential change that I do want to emphasize is the switch to a default non-root user, with the username "kali" and password "kali". For more of the reasons behind this switch, please see this blog post: Kali Default Non-Root User.

kali 2020.1 gnome desktop Read more ↦

Kali 2019.4 new themes 🐉

Today Kali Linux 2019.4 just launched, and I'm so excited to announce that, for the last two months, I've been working together with the Kali team developing all its new look. The first noticeable change is the move from Gnome to Xfce as the default desktop. This change was made to make default Kali more comfortable for low resource computers, as it is also commonly used on small ARM devices that don't have as high performance as an average desktop.

If you don't want to leave Gnome, don't worry. Kali now offers a Gnome build for you with some of the new desktop themes. As this release was focused on the Xfce DE change, most of the latest changes were intended for this desktop. For next releases, more changes will be available for all kali flavors to get them "close" to a similar user experience no matter the environment you run.

kali 2019.4 new desktop preview Read more ↦

Build a PHP minimal Blog

When I was about to create this new fancy blog for my website, I was wondering what would be the easiest way to implement it without losing much time programming. Moments later, I was doing the same thing I always do when something could be just straight forward. Using an existing framework? Would you say...
... 🤦‍♂️

Noup! I created my own ultra-minimal framework to handle it. But that is great because now I can blog in my blog about the blog! 🤯
If that makes any sense at all.

blog preview

Read more ↦

Swagger-js, tips and tricks

This article explains step-by-step how to set up and use the Swagger Client module for your JavaScript project. It also shows examples about how to properly use it and some useful tips and tricks that may help you in your development.

Swagger logo

About Swagger-js

Exactly as they define it in their github repository: Swagger Client is a JavaScript module that allows you to fetch, resolve, and interact with Swagger/OpenAPI documents. Thanks to these tools the developer is able to define the API to be used in a clean manner, and ensure all the code uses the latest API version.

Read more ↦

New Blog!


Finally! I've added a blog to my personal website 😎

Since I created this website I've been using it as a personal portfolio and a place to share my projects with the world. But many times I've felt I wanted to upload something less serious, not just projects. Something like tutorials, cool tech related posts, or just my thoughts... That's why I've just opened this blog and I hope I'll be adding lots of posts soon.

Read more ↦


Kali Linux Dragon logo

Kali Linux themes

Flat Remix cover

Flat Remix ICON theme

Flat Remix GNOME theme

Flat Remix GNOME theme

Flat Remix GTK theme

Flat Remix GTK theme



Skeuos GTK theme

Skeuos GTK theme

Flat Remix css library

Flat Remix CSS Library

Skeuos CSS Library

Skeuos CSS Library

Flat Remix KDE themes

Flat Remix KDE themes

Color Fixer logo

Color Fixer

Neural network with genetic algorithms in Unity3d

Neural network with genetic algorithms

Tetяis JS

Tetяis JS

Ethenis Framework logo

Ethenis Framework

Linux From Scratch

Linux From Scratch

Linux From Scratch

Mazda MX5 ND2 for Assetto Corsa

GNOME 4X themes

GNOME 4X themes

Consider supporting my work with a Donation 😉