# LFX Mentorship Task - Build & boot kernel
[TOC]
## Requirements
1. Build and boot Linus's latest tree and show proof.
2. Upload proof and send email to Shuah Khan <skhan@linuxfoundation.org>
## Outputs
### Summary
This report describes detail on how to compile kernel on Ubuntu.
This report can also be read online via: https://hackmd.io/@0xff07/rJaQvcGW0
### `uname -a` output

### First few lines from `dmesg`

## Prerequisites
### Step 0: Clone the source code
Clone Linus' tree (`kernel/git/torvalds/linux.git`). In kernel.org there are 3 remotes listed in the *Clone* section. I chose the one from Google source (https://kernel.googlesource.com/pub/scm/linux/kernel/git/torvalds/linux.git), as I think less people would use it and may be faster to clone.
```
$ git clone 'https://kernel.googlesource.com/pub/scm/linux/kernel/git/torvalds/linux.git'
```
### Step 1: Install Build Dependencies
Install the build dependencies. I'm using Ubuntu 22.04. On Ubuntu, the `apt` tool has ability to resolve the build dependencies from source package. This however requires enabling source packages channels from the source list. To do this, edit the `/etc/apt/source.list`:
```
$ vim /etc/apt/sources.list
```
Uncomment (by removing the `#` in the beginning) the `deb-src` lines and run `apt update`. Note that proper privilege may be needed for editing the file.
### Step 2: Build Dependencies
After the `apt update`, install the build dependencies:
```
$ sudo apt build-dep linux
```
According to [*BuildYourOwnKernel*](https://wiki.ubuntu.com/Kernel/BuildYourOwnKernel) in Ubuntu community WiKi this may not be enough. There are other package that may be needed:
```
$ sudo apt install libncurses-dev gawk flex bison openssl libssl-dev dkms libelf-dev libudev-dev libpci-dev libiberty-dev autoconf llvm
```
## Configuration
The `make menuconfig` could be used for building kernel. But for Ubuntu configuration, there may need some tweaks.
### Step 1: The `/boot` directory
The `/boot` directory contains configuration for the current kernel. I used as a starting point:
```
$ cat /boot/config-$(uname -r) > .config
```
Now there's a basic configuration. Run the `menuconfig`:
```
$ make menuconfig
```
### Step 2: Remove Debian-specific configs
Some options in Ubuntu kernel configuration are configured specifically for Debian packaging the kernel binary. Those options may lead to error during mainline kernel compilation, as the mainline kernel tree is no Debian source package. Those options needs to be removed.
First, scroll down to the `Cryptographic API`, then `Certificates for signature checking`. There should be a line that looks like this in the menuconfig:
```
(debian/canonical-certs.pem) Additional X.509 keys for default system keyring
```
This is the path of the key file used by Canoncial. The `debian` directory in the path is specific for Debian packaging and doesn't exist in the mainline kernel.
Press enter on this option, and remove the line. It should looks like this:
```
() Additional X.509 keys for default system keyring
```
Another file that needs to be removed is:
```
(debian/canonical-revoked-certs.pem) X.509 certificates to be preloaded into the system blacklist keyring
```
Remove the path as well. It should now looks like this:
```
() X.509 certificates to be preloaded into the system blacklist keyring
```
Save the configuration by navigating bottom tabs to `< Save > `, and then select `< Exit >` in the bottom.
## Build and install
### Step 1: make
This is a very standard `make`. I `tee` the build log into another file:
```
$ make -j$(nproc) 2>&1 | tee build.log
```
### Step 2: modules_install
The next step would be installing the modules. This however comes with a catch. If I install all modules without stripping them, the size of `initrd.image` would explode and is unable to boot. So I stripped the module while installing:
```
$ sudo make INSTALL_MOD_STRIP=1 modules_install
```
Finally, install the kernel:
```
$ sudo make install
```
## Boot the kernel
### Step 1: Change GRUB next boot order with grub-reboot
Instead of modifying the `/etc/default/grub`, I use `grub-reboot` the set the next boot entry. Pass what menu entry should be selected in the next boot:
```
$ sudo grub-reboot "Advanced options for Ubuntu>Ubuntu, with Linux 6.9.0-rc5"
```
And the reboot:
```
$ sudo reboot
```
### Step 2: Confirm the kernel version
After reboot, confirm kernel version using `uname`:
```
$ uname -a
```
It shows the following
```
Linux 0xff07 6.9.0-rc5 #1 SMP PREEMPT_DYNAMIC Mon Apr 22 12:38:59 CST 2024 x86_64 x86_64 x86_64 GNU/Linux
```
Or using `dmesg`
```
$ sudo dmesg
```
In the beginning, it shows:
```
[ 0.000000] Linux version 6.9.0-rc5 (f@0xff07) (gcc (Ubuntu 11.4.0-1ubuntu1~22.04) 11.4.0, GNU ld (GNU Binutils for Ubuntu) 2.38) #1 SMP PREEMPT_DYNAMIC Mon Apr 22 12:38:59 CST 2024
```