quick-docs/modules/ROOT/pages/kernel-build-custom.adoc
Brandon Nielsen 938bd22747 Improve documentation for building kernel from dist-git
Note how to checkout from dist-git, and how to retrieve the appropriate
kernel sources for a given dist-git version.

Add notes for different ways to customize the built kernel.

Remove section on using `make release`, make is only invoked directly when
building straight from kernel sources, not when building with fedpkg and
dist-git.

This is an attempt to clean up issues identified in quick-docs:666[0].

https://pagure.io/fedora-docs/quick-docs/issue/666
2023-12-18 15:07:20 -06:00

331 lines
9.2 KiB
Text

= Building a Custom Kernel
John Soros; Alessio; Brandon Nielsen
:revnumber: unspecified
:revdate: 2021-01-01
:category: Kernel
:tags: How-to, Kernel, Custom kernel
:page-aliases: kernel/build-custom-kernel.adoc
[abstract]
This document provides instructions for advanced users who want to rebuild the kernel from some source.
[NOTE]
====
When building or running a custom kernel, one should *not* expect support from
the Fedora kernel team.
====
Some common reasons to build a custom kernel are:
* To apply patches for testing that they either generated or obtained from
another source
* To reconfigure the existing kernel
* To learn more about the kernel and kernel development
== Get the Dependencies
The easiest way to install all the build dependencies for the kernel is to use
the Fedora kernel spec file:
[source,bash]
----
sudo dnf install fedpkg
fedpkg clone -a kernel
cd kernel
sudo dnf builddep kernel.spec
----
If you want to use `make xconfig`, you'll need some additional packages:
[source,bash]
----
sudo dnf install qt3-devel libXi-devel gcc-c++
----
=== Secure boot
Make sure you add the user doing the build to `/etc/pesign/users` and run the
authorize user script:
[source,bash]
----
sudo /usr/libexec/pesign/pesign-authorize
----
Create a new Machine Owner Key (MOK) to import to UEFI:
[source,bash]
----
openssl req -new -x509 -newkey rsa:2048 -keyout "key.pem" \
-outform DER -out "cert.der" -nodes -days 36500 \
-subj "/CN=<your name>/"
----
Import the new certificate into your UEFI database:
NOTE: You will be asked to authorize the import at next boot.
[source,bash]
----
mokutil --import "cert.der"
----
Create a PKCS #12 key file:
[source,bash]
----
openssl pkcs12 -export -out key.p12 -inkey key.pem -in cert.der
----
You can then import the certificate and key into the nss database:
[source,bash]
----
certutil -A -i cert.der -n "<MOK certificate nickname>" -d /etc/pki/pesign/ -t "Pu,Pu,Pu"
pk12util -i key.p12 -d /etc/pki/pesign
----
Once the certificate and key are imported into your nss database, you can build the kernel
with the selected key by adding `%define pe_signing_cert <MOK certificate nickname>` to the
kernel.spec file or calling rpmbuild directly with the
`--define "pe_signing_cert <MOK certificate nickname>"` flag.
NOTE: While https://bugzilla.redhat.com/show_bug.cgi?id=1651020[bugzilla bug #1651020] is open
you might need to edit the line that starts with `+%pesign+` in the kernel spec file and substitute
it with `+pesign -c %{pe_signing_cert} --certdir /etc/pki/pesign/ -s -i $KernelImage -o vmlinuz.signed+`.
It's also recommended that you install `ccache`, which can help speed up
rebuilds:
[source,bash]
----
sudo dnf install ccache
----
== Building a Kernel from the Fedora dist-git
First, a checkout from the https://src.fedoraproject.org/rpms/kernel[Fedora kernel dist-git] is required:
[source,bash]
----
git clone https://src.fedoraproject.org/rpms/kernel.git
----
The kernel, like any other Fedora package, has a branch per Fedora release.
`rawhide` corresponds to Rawhide and each version of Fedora has a branch called
`f<version>`.
. For example, to build a Fedora 28 kernel, you would first need
to switch to that branch with:
+
[source,bash]
----
git switch f28
----
. To avoid conflicts with existing kernels, you can set a custom buildid by
changing `# define buildid .local` to `%define buildid .<your_custom_id_here>`
in `kernel.spec`.
. Make whatever changes or customizations you need:
.. Kernel configuration options can be overriden by modifying the `kernel-local` file.
.. Existing patches can be added to `linux-kernel-test.patch`, they will be
picked up during the build automatically.
.. Patches can also be kept in seperate files and added to `kernel.spec` with
`Patch2: foo.patch`, `Patch3: bar.patch`, etc. They should be applied
automatically during the build process.
.. To make your own modifications to the kernel source, retrieve the kernel
sources for your current dist-git branch with `fedpkg sources`, then make
your desired changes to the kernel source and generate a patch, e.g. with
`diff -rupN kernel_src_folder kernel_src_folder_patched > mypatch.patch`.
The patch can then be added to `linux-kernel-test.patch` or the specfile.
. Build the RPMs:
+
[source,bash]
----
fedpkg local
----
. Install the new kernel:
+
[source,bash]
----
sudo dnf install --nogpgcheck ./x86_64/kernel-$version.rpm
----
== Building a vanilla upstream kernel
Sometimes a Fedora developer may ask you to try building and installing an
upstream kernel (possibly with a patch added) for testing. If there are
multiple iterations, it may be quicker for you to do this than for the
developer to turn around several RPMs.
[NOTE]
====
There is an effort underway for packaging vanilla kernels.
https://fedoraproject.org/wiki/Kernel_Vanilla_Repositories[See if this meets
your needs first]
====
=== Getting the Sources
Clone the kernel tree from kernel.org. If you don't know what tree you need,
you should get Linus' tree:
[source,bash]
----
git clone git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
cd linux
----
You may also want the stable tree (4.y.z releases), which you can add with:
[source,bash]
----
git remote add -f stable git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git
----
=== Applying patches
To apply patch files, you can use git-am:
[source,bash]
----
git am -3 <patch file>
----
=== Configuring the kernel
If the developer has pointed you at a specific config file to use, save it in
the linux directory with the filename `.config`
Otherwise, you'll need to pick a configuration file to start from. The Linux
kernel has thousands of configuration options, so you don't want to start from
scratch unless you know what you're doing.
==== Starting from an installed kernel configuration
If you want to tweak the configuration of a kernel you already have installed,
you can start with its configuration which is stored in /boot/. For example,
to start with the configuration of the currently running kernel:
[source,bash]
----
cp /boot/config-`uname -r`* .config
----
==== Starting from dist-git
If you want to use the configuration for a kernel you do not have installed,
you can get the configuration from the Fedora dist-git repository. For example,
to start with the latest Rawhide configuration:
[source,bash]
----
cd <dist-git directory>
git checkout rawhide
./generate_all_configs.sh # Ensure the latest configuration files are generated
cp kernel-<arch>.config <linux kernel directory>.config
----
The debug versions of the configuration files are in
`kernel-<arch>-debug.config` if you would like to build a kernel with debugging
options enabled.
=== Changing the configuration
There are several ways to change the configuration. You can run `make help` and
look at the `Configuration targets` for the full list, but `make menuconfig`
is a good place to start. You can also just edit the `.config` file directly.
[NOTE]
====
One configuration option you may want to set is CONFIG_MODULE_COMPRESS, which
compresses the modules (with gzip by default) when installing them. Without
this setting, the modules can be very large.
====
=== Building the kernel
Once you've configured the kernel, you're ready to build it. Before you do so,
you'll want to change the `EXTRAVERSION` in the `Makefile` to something you'll
recognize later. For example, if it reads `EXTRAVERSION = -rc5` change it to
`EXTRAVERSION = -rc5-dave`:
[source,bash]
----
$EDITOR Makefile
----
Now you're ready to build the kernel:
[source,bash]
----
make oldconfig
make bzImage
make modules
----
=== Installing the kernel
Installing the kernel is as simple as:
[source,bash]
----
sudo make modules_install
sudo make install
----
=== Rebuilding
If you have been asked to try several different things, the procedure once you
have already built the tree once is mostly the same. Running `make clean` is
recommended between builds. This will leave the `.config` in place, so you can
skip that step above and proceed straight to the `make bzImage` part of the steps
above. Because we installed `ccache` in the first step, subsequent builds may go
a lot faster as the compiler hits files that haven't changed since the last
time it built them.
=== Cleaning up
Once you have tested the kernel, and you've booted back to one of your kernels
installed from an RPM, you can clean up the files that the above procedure
installed.
[WARNING]
====
When running the following commands, be sure to get the kernel version correct!
====
Because you changed `EXTRAVERSION` in the `Makefile` to add a 'tag', all the
files it installed will have this as part of the filename. So you should be
able to use wildcards to delete them safely using commands similar to those
below (just replace 'dave' with whatever tag you chose):
[source,bash]
----
rm -f /boot/config-*dave* /boot/initramfs-*dave* /boot/vmlinuz-*dave* /boot/System.map-*dave*
rm -rf /lib/modules/*dave*
----
Finally, you will need to remove the kernel as an option in your bootloader.
Assuming your system is running grub2, this can be done by removing the
bootloader specification entries and rebuilding the grub config:
[source,bash]
----
rm -f /boot/loader/entries/*dave*
grub2-mkconfig -o /boot/grub2/grub.cfg
----