How to build and install your own Linux kernel

From LQWiki
Jump to navigation Jump to search


Introduction

This guide to building and installing your own kernel is intended for those who:

  • want to use a distribution that expects users to build their own kernel
  • want to make their kernel smaller and faster to load
  • want to avoid having to use an initrd image for booting
  • want to test or fix a kernel configuration issue
  • need the newest kernel to run their hardware
  • are simply curious.

There was a time when Linux users in general were expected to build their own kernels. Nowadays most users use the stock kernel that came with their distribution. Modern computer processors (CPUs) run fast, so it is no longer necessary to shrink the kernel simply to save on boot time. However if you do need or want to "roll your own", this article will guide you through the process.

Prerequisites for the build

Prerequisites for your system

To build any software, you need a set of tools for the purpose such as

  • a compiler to create the binary code
  • tools for linking, indexing and otherwise handling the resultant binaries,
  • informative headers for the various libraries that you wish to link to; the compiler needs these to ensure that the program is handling library functions correctly
  • a way of selecting and building in the many optional configuration variables that the developer has provided for you

and so forth. GNU provides a standard set of such tools for this purpose which is known as the GNU build system.

A full list of the build tools required might be rather offputting. Fortunately most Linux distributions either include these tools in a standard install, or provide them in a single installable package. For example, all distributions in the Debian family (such as Ubuntu) have a package called build-essential, which contains everything you need for most builds. Other distribution families have similar packages such as Arch's base-devel. Some distributions also have something called "package groups" that can install all of the required development tools for you, if your distribution has such an option, you can look for something called "development" or similar. A quick search of what your distribution provides should tell you the name of any package(s) you need to install separately.

In addition to the basic build tools, the kernel configuration dialogue requires the development package (headers) for the ncurses library, and modern kernels require the following build dependencies;

  • xz-utils
  • libssl (both the library itself and its development package as well)
  • bc
  • flex
  • libelf (both the library itself and its development package as well)
  • bison

Note: Some of the above packages may already be installed on your system, therefore you should check with your distribution's package manager to ensure all of the packages listed above are in fact installed before continuing on. You should also note that the exact names of the packages listed above may vary slightly from distribution to distribution, so check with your package manager before continuing.

Prerequisites for the user

Users who wish to build their own software (and enjoy the process) need a few basic skills. You need to feel fairly confident working at the command line, which means typing instructions into a terminal rather than using your mouse to click on buttons. You need some basic knowledge of how directories (aka folders) and files are organised in Linux, how to switch directories, how to move or copy files and so on. This wiki provides quite a lot of instruction materials on such elementary matters.

To make your new kernel bootable, you will need a basic knowledge of how your bootloader works and how to add a new kernel to its menu.

Getting the kernel source

The first thing you need to do once you have prepared your system for building the kernel is to get the kernel source. Make sure that you are working as an unprivileged user and not as root. There are three ways we can get the kernel source, which are described below.

From kernel.org

Open http://www.kernel.org in your web browser and download the relevant kernel source. The source downloads as a "tarball", a compressed archive which must be decompressed using the tar command. This should be done in your home directory/folder, where you have full rights to read, write and create files. It will create a toplevel directory called linux-x.y.z, where x.y.z is the version number. Change to this directory by using the cd command.

You can extract the downloaded "tarball" with something like the following:

tar -zxvf linux-x.x.x.tar.xz

Replace x.x.x with the actual kernel version you've downloaded, and if need be, replace .tar.xz with the relevant filename extension.

From your Linux distribution

Most Linux distributions offer a package called something similar to "kernel-source", use your package manager to install this package.

When installed, it usually resides in a /usr/src/linux-x.x.x subdirectory, where x.x.x is the version of the kernel source.

The safest way to build the kernel from your distribution is to copy the source to your unprivileged user account's "home" directory. The reason for copying the kernel source to your unprivileged user account's "home" directory is because unprivileged users do not have write permission in the /usr directory tree, therefore the build will fail. Run the command below to copy your distribution's kernel source to your unprivileged user's "home" directory:

cp -r /usr/src/linux-x.x.x /home/$USER/

Replace x.x.x with the actual version of the kernel source.

If you plan on packaging your new kernel build, then you should consult your distribution's own documentation instead of following this guide.

From git

git clone git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git

This will create a subdirectory called "linux" in your "home" directory with the downloaded kernel source in it.

Configuring the kernel for building

Arguably this is probably the most important part of the process in building your new kernel, because the way you configure the kernel will determine which drivers and other features your kernel is built with, and whether they are built in or built separately as loadable modules. There are several ways you can configure the kernel for building each with its own advantages and disadvantages. We will list each configuration method below, while listing some advantages and disadvantages of each method.

  • Answering all questions from the kernel build system for each and every kernel configuration option

This approach, not often used nowadays, allows you to specify exactly which features and modules you would like to build your new kernel with. The disadvantage is that it takes a long time to finish answering all of the questions asked by the kernel build system, and it may require a lot of understanding of which configuration options are most relevant to your machine. Also, if you accidentally send an answer you did not intend, you have to abort the process and start again. You can shorten the time by just pressing return (also called "Enter") where you have no strong preference instead of answering Yes or No. This will give you the default answer to the question, which is often a fairly safe one.

  • Copying the configuration file for your existing kernel

This approach has the advantage of being one of the quickest options. The disadvantage is that you may be building the kernel with modules that you simply don't need and features that you do not want. Also this may not be an option available to you. It depends on your system and whether or not you have an existing configuration file.

  • Using make allyesconfig

This method will set all kernel configuration options that can be, to "yes". The advantage with this is that you can quickly get a working configuration without going through each option by hand. The disadvantages to this are that your kernel will be quite big, and will include a lot of unnecessary drivers and kernel features.

  • Using make allnoconfig

This method will set all kernel configuration options that can be, to "no". The advantage with this is that you can "fine tune" your kernel to include only the drivers and kernel features you wish to have. The disadvantages to this method are that it will be quite tedious, and you will need to go through each option by hand to get a working kernel. Therefore, this method is not recommended for the novice.

  • Using make menuconfig or make nconfig

The advantage with make menuconfig is that it will provide a text-based menu where you can configure each kernel configuration option by hand, thus giving you complete control over which features and modules you build the kernel with. You can also use this approach starting from your current kernel's configuration file. The disadvantage is that it may still be quite tedious and time-consuming. Also the menuconfig interface, based on the ncurses library, is not particularly friendly for people accustomed to a graphical interface. make nconfig is essentially functionally equivalent to make menuconfig, however it is more user friendly than make menuconfig and allows you to create multiple kernel configurations without closing the configuration screen.

  • Using make xconfig or make gconfig

If you have a KDE desktop or at least the Qt libraries, you can use make xconfig for a graphical configuration window. If you have the gtk libraries (Gnome or xfce desktops), use make gconfig instead. The advantages and disadvantages of a graphical approach are much the same as for make menuconfig. However, the interface is easier to navigate, as you can use your mouse to click on options.

  • Using a "kernel seed"

This approach is essentially a pre-written kernel configuration file that includes options for a particular type of system. Basically a lot of the work has already been done for you. The disadvantage is that you would need to make sure the configuration is suitable for the target system.

  • Using make oldconfig

This is the method you use if you have already built a kernel and you simply want to upgrade it to a new version. Before using it, you must first copy the old configuration file to the linux-x.y.z build directory as .config. The script will ask you questions only about new configuration options that have no equivalent in the old file. This is usually a quick and easy way to build a kernel, but it becomes progressively more burdensome as the gap between the old kernel version and the new one grows wider. You should not use it to upgrade a very old kernel.

The kernel build system will look for a file called .config that will reside in the kernel source directory, so copy the configuration file you are going to use as a starter into this directory, naming it .config (note the initial dot in the filename which makes it a "hidden file"). This will be the file that is edited by the configuration process. It is also the file that the make command uses to know what kernel configuration to use when actually building the kernel. It is important to note that the process of configuration overwrites the existing .config file, so if you want to make any manual changes to this file, do not do so until after you've finished the configuration.

Notes

  • There are more kernel configuration options than are listed above, you can type make help at the command-line for a complete list of the configuration targets available.
  • If you do not have a starter configuration file to copy, you can create a .config file with sensible defaults by running the command make defconfig, before using one of the above configuration options.
  • If you are building the kernel using the LLVM/Clang toolchain, there maybe some configuration options and extra packages that you may need to change and/or install for the build to succeed at all. We will cover this in the "Tips and tricks" section of this wiki page below.
  • Some kernel configuration options need to be set if you plan booting the kernel directly from UEFI without using a bootloader - see the "Tips and tricks" section below for more details.
  • If you have already built a kernel and want to start with a clean slate, it's a good idea to run make mrproper Which will clean all object code, built binaries and configuration from the kernel source directory.
  • If you want to patch your kernel, this should be done before configuring the kernel. You can see the "See also" section at the end of this article below, where there are some links to further information about patching and configuring the kernel.

The build step by step

Now that we have configured our kernel build, it's time to start building it. Be aware that this step can take quite some time to complete depending on how you've configured the kernel in the previous steps. There are some arguments you can use with make to speed up the build quite dramatically described in the "Tips and tricks" section of this wiki page below.

You only need to choose one of the following build options, not both.

Using the GNU toolchain for the build

Making sure you are still sitting in the kernel source directory, issue the following command as a normal user;

make

Using the LLVM/Clang toolchain for the build

If you are using the LLVM/Clang toolchain instead of the GNU build system, just running make as described above may not succeed and the kernel build may fail. This is because, at the time of this writing, there seem to be issues with using the built-in LLVM linker for linking the kernel code and modules. You need to direct make to use the GNU linker with the associated BFD libraries to link the compiled code.

Making sure you are still sitting in the kernel source directory, issue the following command as a normal user;

make CC=clang LD=ld.bfd

Installing the new kernel and its modules

If you've reached this step, congratulations! You are now ready to install your new kernel.

The first step is to install the drivers and other modules that the previous step built to their new home on the root filesystem of your system. But we need to do this as the root user. In some distributions (such as Ubuntu), this is done by preceding each command with the word sudo, entering your password if requested. In others, you can simply switch to the root user account. Make sure you are still in your kernel source directory where you previously issued the make command, or the following commands will fail.

To install newly built drivers, run the following command;

make modules_install

Installing the kernel itself

There are a couple of ways you can install your newly built kernel. The easiest way just involves executing a make command and all the work is done for you. You can also install it manually, which is described afterwards.

Choose one of the following methods.

  • To use make to install your new kernel and its associated files, run the make install command. The kernel will be installed under the filename /boot/vmlinuz and any previous file or link of that name will be renamed with a .old suffix. This may not be what you want.
  • Alternatively, simply copy the bzImage file and the system map file by hand to the /boot directory of your system, using:
cp arch/x86/boot/bzImage  /boot/your_chosen_kernel_name (replace x86 if necessary by your actual CPU architecture)
cp System.map /boot/your_chosen_system_map_name

The advantage of installing this way is that you can choose what to call your new kernel image to distinguish it from any existing ones.

Notes

  • If you use make to install the kernel, it will attempt to add the new kernel to the LILO configuration file. If you are using a different bootloader, you will get a warning message that LILO was not found, which can be safely ignored. Please refer to the following section of this wiki page for details about making your new kernel bootable.
  • Whichever installation method you use, it is a good idea to also copy over to /boot (for storage and future reference) the final .config file:
cp .config /boot/your_chosen_config_name
  • If you plan on booting the kernel directly from UEFI firmware and without using a bootloader, you need to choose the second method of installing the kernel above - see the "Tips and tricks" section below for more details.

Making your new kernel bootable

The final stage is to make your bootloader aware of your new kernel, so that it can load and run it. You may also need to create an initrd image for this kernel, depending on how you have configured it. If you have UEFI firmware, you can also directly boot the kernel from your UEFI firmware instead of using a bootloader - see the "Tips and tricks" section below for more details.

Making an initrd image

You may or may not need this. One advantage of using a handmade kernel is that you can configure it to include all the disk drivers you need, rather than building them as dynamic modules to be loaded at boot time. If you do this, your new kernel will be able to boot directly from the hard drive.

For this to work, you will need to include the basic block device layer, the libata disk driver and the driver for your root filesystem (usually ext4). If you have a SATA or NVME drive, you will need the drivers for the appropriate controller. Make sure that you have said "YES" to all of these so that they compile as static internal code and not as modules.

A kernel which does not have all these drivers built in can still boot successfully, but it will need an initrd (sometimes also called an initramfs image). This is simply a very basic root filesystem stored as a compressed image and subsequently loaded onto a ramdisk by the bootloader. The kernel uses this as an initial root device, loads any driver modules it needs from it and then switches to the real root device on the hard drive.

All distributions include a script for making such a device. It is usually called mkinitrd or mkinitramfs. Use the command's man page to find out how to use it, as these scripts are completely unstandardized. Make sure your initrd image is in the /boot directory alongside the kernel.

Note: If you have an encrypted root partition on your hard drive, you will definitely need an initrd containing the software to decrypt it, no matter how your kernel is configured. But that is beyond the scope of this article.

Adding the kernel to the boot menu

Most Linux systems nowadays boot with GRUB, which works with both traditional BIOS machines and the more modern computers that use UEFI. GRUB is quite a complex program which includes drivers for various filesystems and can therefore find kernels anywhere in your system. Most versions of GRUB come packaged with scripts for automating these processes. The update-grub command (given with root privileges as described above) will usually be sufficient to cause GRUB to find the new kernel and add it to its configuration file. When GRUB next runs, it will use this file to generate a boot menu for you.

Different GRUB installations may manage their menus differently, depending on how they have been scripted. Some produce a single menu containing all the kernels they have found. Others have only two entries in the top-level menu: the most recent kernel and a "Further options" which gives access to a sub-menu containing the other kernels. If you cannot find your new kernel anywhere, the automated scripts have failed to find it and you will need to modify one of the GRUB scripts to include it explicitly. GRUB scripts are kept in /etc/grub.d and should include at least one script named "custom". You can add the path to your kernel (and initrd if you are using one) to this file and then run update-grub.

LILO is an alternative (and older) bootloader which some distributions use with BIOS-booting computers. It has a configuration file called /etc/lilo.conf into which you need to edit the path to your kernel and optional initrd, using an existing entry as a model. Then you must run (as root) a program called lilo which will transfer the configuration details into the LILO map file. The LILO bootloader can then find these files by their actual physical addresses.

ELILO is the LILO equivalent for UEFI computers. It uses a configuration file called elilo.conf which is stored on the EFI system partition, a special vfat-formatted partition for storing boot files. Most distributions mount this partition at need on the /boot/efi directory. Unlike GRUB, ELILO cannot read filesystems other than vfat, so if you are using this bootloader, you will need to copy over your kernel (and initrd if you are using one) to the EFI partition. The syntax for elilo.conf is identical to that for lilo.conf, but there is no need to run an installer program after editing it as you do for LILO.

There is further information about configuring the bootloaders discussed above in the "Tips and tricks" section below.

Note: The update-grub script may not exist in some distributions, refer to the "Tips and tricks" section below for more details.

Tips and tricks

In this section we will provide some useful tips, as well as some solutions to common problems you may run into, both during, and post-build.

Copying your current kernel configuration over to your new kernel build

It may be desirable to copy your current kernel configuration over to your new kernel build for a number of reasons, if this option is available to you.

You can do this in a couple of ways, depending which option (if any) is available on your system. If your distribution installs the kernel configuration into the /boot directory, you can use the command below:

cp -v /boot/config-xxxx .config

You will need to change config-xxxx to the actual filename for your current kernel's configuration file that was used to build it with. The above command also assumes that you are currently sitting in your kernel source directory. If you are not, change to this directory, or the cp command will fail to copy your current kernel's configuration over to your new kernel build.

You can also get the kernel configuration used to build your current kernel from /proc with the command below:

zcat /proc/config.gz > ~/kernel_source_directory/.config

You need to change kernel_source_directory to the actual directory name of the directory where your kernel source has been decompressed to earlier on.

Note: The -v argument means "be verbose" as by default the cp command will only display what's happened if it encounters an error, but this argument is not explicitly required.

LLVM/Clang build issues

If you are using the LLVM/Clang toolchain to build your new kernel, you may run into the following error during the build process;

    BTF: .tmp_vmlinux.btf: pahole (pahole) is not available
    Failed to generate BTF for vmlinux
    Try to disable CONFIG_DEBUG_INFO_BTF
    make: *** [Makefile:1170: vmlinux] Error 1

Thankfully, there are a couple of simple solutions to this issue. You can either install the package containing pahole or you can disable that particular kernel configuration setting as described below.

If you cannot install the pahole tool, you need to change the following line (under the "Compile-time checks and compiler options" heading in your kernel configuration file) from;

CONFIG_DEBUG_INFO_BTF=y

to

CONFIG_DEBUG_INFO_BTF=n

or simply comment out the above line altogether with the hash symbol (#) appended to the very beginning of the above line. Thankfully, you should not need to start over, and therefore you can use any text editor to edit your kernel configuration file. Then simply issue the same make command you used prior to that error message appearing, to continue building your new kernel. The build should continue on from the point at which it stopped.

Note: If you plan on using the LLVM/Clang toolchain, you can avoid this issue by changing the kernel configuration option described above when you configure your new kernel prior to building.

Speeding up your new kernel build

Building your own kernel can take quite some time to finish, but its possible to reduce this time even where you have included a lot of modules. The make command has an argument that can dramatically reduce the time it takes to finish building the kernel and its modules. This argument is the -jX argument make provides, where X is the number of "jobs" make should execute concurrently.

In its basic form you can use the following example;

make -j5

You can change -j5 to some other number instead. A good rule of thumb is to use the number of cores in your CPU.

A word of warning though: using this argument can put even the most powerful system under a lot of strain. It is therefore strongly recommended that you do not perform any other tasks while the kernel build is taking place, particularly those that are highly intensive. You may overload your system, triggering the running kernel's "out of memory" response and crashing your kernel build in the process.

It is beyond the scope of this article to list all arguments make has to offer. You can look at the make command's man page for further details. You can also use make help to get a list of all the specific targets for kernel make beyond those described here.

Manually adding your new kernel to your GRUB boot menu

If you are using GRUB and the GRUB scripts fail to autodetect your new kernel, you can still manually add the relevant information to /etc/grub.d/40_custom. As the root user, open this file in a text editor and add something like:

       menuentry 'kernel x.y.z' {
       echo 'Loading Linux x.y.z ...'
       linux /boot/vmlinuz root=PARTUUID=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx <kernel parameters>
       echo 'Loading initial ramdisk ...'
       initrd /boot/initrd
       }

You need to change xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx to the actual PARTUUID of your root partition, and replace <kernel parameters> with valid kernel parameters appropriate to your setup. The kernel cannot read UUIDs or filesystem labels without a working root partition, therefore you cannot use them without an initrd.

The most important lines in the example above are the lines beginning with menuentry, linux and if you are using one, initrd. So let's give a quick explanation of what they do; The line beginning with menuentry signals the start of a menu entry and gives the name that will appear in the menu itself. The line beginning with linux tells GRUB where your kernel executable is located on the filesystem, where your root filesystem is located, along with any kernel parameters you may want to boot the kernel with. The line beginning with initrd tells GRUB where to find your initrd image (this line can be omitted if you are not using an initrd). If you're not using an initrd you need to use either root=PARTUUID= (as shown above) or a device node (such as /dev/sda2) in the line beginning with linux above.

Once you have added the relevant information, you then need to update your GRUB configuration so the changes take effect. We will discuss how you do that in the "Updating GRUB" sub-section below.

Further GRUB boot options may sometimes be desirable, but that is beyond the scope of this article. Please refer to the GRUB documentation if you have any questions about any of GRUB's boot options.

Note: The curly braces are required, otherwise the entry will not be added to your GRUB boot menu.

Manually adding your new kernel to a LILO or ELILO boot menu

These two bootloaders use the same configuration syntax. The main difference is that lilo.conf (used for MBR boots) is stored in the /etc directory on the root partition and elilo.conf (used for UEFI boots) on the EFI system partition. You may need to mount this partition by hand, depending on your distribution. In either case, you must edit the configuration file as root.

   image= /path/to/linux/kernel/  
   label = 'My new kernel' 
   initrd= /path/to/initrd/image 
   read_only  
   append "root=PARTUUID=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx <kernel parameters>"

For lilo.conf, all paths should start from /, the toplevel directory of your root partition. For elilo.conf, they must start from the root directory of the EFI system partition, and both the kernel and the initrd (if you are using one) must be present on this partition. The read_only option causes the root partition to be mounted initially read-only, which is good practice. The name of the root partition and other kernel command line parameters are passed in the append statement. The label is simply what will appear in the menu.

If you are not using an initrd, omit the initrd line in the above example. Since the kernel cannot read UUIDs or filesystem labels without an initrd, you will need to use either PARTUUID as shown above, or a device node (such as /dev/sda2).

For ELILO, nothing further is required. For LILO, complete the operation by running (as root) /sbin/lilo.

Updating GRUB

On some systems, the update-grub script may be called update-grub2. If neither of these is available, you can run the grub-mkconfig (or grub2-mkconfig as it may be called) executable directly with the relevant arguments as shown below.

grub-mkconfig -o /boot/grub/grub.cfg

Note: You should never edit /boot/grub/grub.cfg directly, as this file will be overwritten by any software update that involves updating GRUB.

Using contextual help in kernel configuration

Like many programs, the kernel configuration script provides contextual help. In fact kernel help is an unusually complete and informative system and you should get used to using it intensively.

If you are using menuconfig, you can get contextual help at any time by pressing the H key. In xconfig, click on the Help button with your mouse. The help you get will always be appropriate to the currently selected option.

Most contextual help systems simply tell you what an option does. Kernel help often tells you whether you need that option or not. It may tell you, for example, "If in doubt, say Yes" or "You will only need this option if you are using (such-and-such a device)", or even in some cases, "If you don't know what this is, you don't need it."

Sometimes a piece of software needs to be run with a kernel that has certain configuration options set. This is indeed one reason why people sometimes need to rebuild their kernel. The relevant documentation will always give the form the option takes in the actual configuration file. It is easy enough to find out if your current running kernel has this option set by using grep to search the saved file, which is why .config is normally saved in the boot directory for future reference. But if the option has not been set, how do you find it in the large and complex kernel configuration menu?

Fortunately another kind of help has been provided by the kernel development team. Simply type a / character and a text box will appear into which you can type the name of the option. Press return (also called "Enter"), and you will be taken at once to the part of the menu system which allows you to configure that option.

Booting a kernel directly from UEFI firmware

It's possible to boot the kernel without using a bootloader on UEFI based systems. If you don't have a sound understanding of the following prerequisites listed below, you should not proceed with the following instructions and use your distribution's bootloader instead. The following is intended for the advanced user, and not the novice user. In order to boot a kernel directly from UEFI firmware, the following prerequisites must be met.

Prerequisites

  • UEFI-based firmware
  • an understanding of how UEFI booting works
  • an understanding what the EFI System Partition (ESP) is
  • how to access your UEFI firmware boot menu
  • how to build an initrd if required
  • how to copy files and mount your ESP if required

The following kernel configuration options need to be set to "yes" (listed under "Processor type and Features");

CONFIG_EFI=y
CONFIG_EFI_STUB=y

Once you have built the kernel with the above kernel configuration options set as shown above, you then need to copy the kernel and if you're using one, your initrd to your EFI system partition (ESP). It's assumed in the examples below that you are copying the kernel and if using one, the initrd to the "EFI" directory that is in the root directory of the ESP itself - not the /boot/efi directory - notice the capital letters between the previous double quotes. This is very important. The following example also assumes that you're sitting in the appropriate part of your kernel source directory as your "current working directory". You also must append "64.efi" to the end of the kernel's executable filename. You will need to be running as the root user in the following example.

For example:

cp bzImage /boot/efi/EFI/kernel_5.10.13_64.efi
cp System.map /boot/efi/EFI/
mkinitrd /boot/efi/EFI/initrd 5.10.13

Using efibootmgr

Once you have copied the relevant files to your ESP, you then need to set a boot entry in your UEFI firmware's boot menu. The following uses efibootmgr to do just that - which needs to be run as the root user.

Running efibootmgr with the --verbose argument will print the current boot entries in NVRAM to the screen as the following example will show;

BootCurrent: 0001
Timeout: 1 seconds
BootOrder: 0001,0003,0000
Boot0000  openmandriva  HD(1,GPT,79bb7c24-066e-e345-8429-de074ae43cfa,0x800,0x32800)/File(\EFI\OPENMANDRIVA\GRUBX64.EFI)
Boot0001* openmandriva kernel 5.10.13   HD(1,GPT,79bb7c24-066e-e345-8429-de074ae43cfa,0x800,0x32800)/File(\EFI\KERNEL_5.10.13_64.EFI)r.o.o.t.=.U.U.I.D.=.2.1.0.9.a.2.5.b.-.c.f.6.0.-.4.1.f.1.-.9.6.5.c.-.1.b.0.8.d.d.9.c.f.9.b.5. .r.o. .i.n.i.t.r.d.=.\.E.F.I.\.i.n.i.t.r.d. .p.c.i.=.n.o.a.e.r.
Boot0003  UEFI OS       HD(1,GPT,79bb7c24-066e-e345-8429-de074ae43cfa,0x800,0x32800)/File(\EFI\BOOT\BOOTX64.EFI)..BO

The above output deserves some explanation; BootCurrent: 0001 is the "active" boot entry, in other words, that's the boot entry that will be booted by the UEFI firmware. In this example it's actually the second boot entry that is selected as the "active" boot entry. Timeout is how long the UEFI firmware will wait before booting the "active" boot entry. BootOrder is pretty self explanatory - it's the order that each boot entry will be booted in. The number assigned to each boot entry starts at zero, and all numbers are in hexadecimal notation. The next three lines are the boot entries themselves in the above example.

The following example sets a boot entry in the UEFI boot manager;

efibootmgr --disk /dev/nvme0n1 --part 1 --create --label "openmandriva kernel 5.10.13" --loader '\EFI\kernel_5.10.13_64.efi' --unicode 'root=UUID=2109a25b-cf60-41f1-965c-1b08dd9cf9b5 ro initrd=\EFI\initrd pci=noaer' --verbose

The --disk argument specifies the device node for the drive itself that the ESP is located on. The --part 1 argument specifies the ESP is "partition 1". The --create argument tells efibootmgr to create a "bootnum", with the --label argument giving our new boot entry a human-friendly name which is enclosed between double quotes. In this example that name would be "openmandriva kernel 5.10.13", this is the name that will appear in your UEFI boot menu. The --loader argument tells the UEFI firmware which executable to execute/boot at boot time, this is the executable that contains the kernel itself. The --unicode argument followed by what is enclosed in the single quotes are the kernel parameters you want the UEFI firmware to pass to the kernel being booted. The --verbose argument means "tell me what is going on", in other words, that tells efibootmgr to print what it's doing to the screen. It's very important that you use backslashes following the --loader and --unicode arguments, not forward slashes when using efibootmgr to set a boot entry, or it will not work and the boot entry will not be bootable.

To delete a boot entry, you can use the following example;

efibootmgr -b 0001 -B

But note that you may need to change 0001 to the correct boot entry - see above for printing out the current boot entries and order.

WARNING: Incorrectly deleting a boot entry can result in an unbootable system, therefore if in doubt don't do it!

Checking if your new boot entry works

One way you can check to see if your new boot entry was actually booted, is to have a look at the first line of your kernel log where it shows who built the kernel.

For example:

[    0.000000] Linux version 5.10.13 (james@jamespc) (OpenMandriva 11.0.1-0.20201127.1 clang version 11.0.1 (/builddir/build/BUILD/llvm-project-release-11.x/clang 9e3c7e6e46bee5eff7a631cdee2f6e8c084ad3b2), GNU ld (GNU Binutils) 2.35.1) #2 SMP PREEMPT Fri Feb 5 22:50:25 ACDT 2021

The above tells me that I'm using kernel version 5.10.13, the user that built it was "james" on a machine with a hostname of "jamespc", it was built by Clang version 11.0.1, it was linked by the GNU LD linker 2.35.1, and it was built on Friday February 5th at 10:50pm ACDT 2021. Therefore if you have built your kernel under your normal unprivileged user account (as you should have), then "james" will be replaced by your username, and your machine's hostname (sometimes called a "computer name") will replace "jamespc" in the above example.

Notes

  • You can run efibootmgr --help to display further information about efibootmgr's arguments.
  • You may have problems booting 64-bit EFI executables with 32-bit UEFI firmware.

Installing the proprietary NVIDIA kernel module

If your machine has NVIDIA graphics hardware, you may need to install the proprietary NVIDIA kernel module. This can be done after booting, see NVIDIA graphics drivers, or directly from the kernel directory after installation of the kernel if you're upgrading to a newer kernel version, by running as root:

/path/to/NVIDIA-Linux-<arch>-xxx.xx.run -a --kernel-name="`grep -o "2\..\.[0-9]*.*$" .config`" \
--no-x-check --kernel-module-only -s;

You'll need to replace <arch> and xxx.xx with the correct architecture and driver version respectively. The above command will need to be run as the root user. It will install only the NVIDIA kernel module from the downloaded .run installer and will require a system restart for the changes to take effect. You will need to rebuild the NVIDIA driver each time you update and/or build a new kernel.

See also