Mar 172020
 
Picture of Raspberry Pi 4 box and Raspberry Pi 4 board below box

So you’ve got a shiny new Raspberry Pi 4 and you need to compile a fresh and custom Linux kernel on Raspbian. You might need some features, some kernel modules, or you just want to compile the latest version from source.

I’m doing various projects (and blog posts) and with one of the projects, I found I needed to compile and enable a kernel module that wasn’t built in to the latest Raspbian image for the Pi 4.

This guide is also great if you just want to learn how to compile the kernel yourself!

Instructions

You may find that this guide is slightly different that the guide on the Raspberry Pi website and other sites. I like to append a unique name to the kernel version so I don’t have to touch the existing kernels. This allows me to revert or run multiple different custom kernels and switch back and forth.

Please note: You must be using a 32-bit kernel (or the default Raspbian kernel) to compile a new 32-bit kernel. You will not be able to compile a new kernel (32-bit or 64-bit) if you have booted in to the 64-bit kernel using the “arm_64bit=1” switch in “config.txt”. I’ve tried to compile a 64-bit kernel on Raspbian, but have not yet been able to do so. I’ll update with a new post once I figure it out.

And don’t forget, this can take some time and is CPU intensive. I installed a fan to help cool the temperatures while compilling!

This guide will compile a 32-bit kernel.

  1. Install some packages required to building and compiling.
    apt install raspberrypi-kernel-headers build-essential bc git wget bison flex libssl-dev make libncurses-dev
  2. Create a directory for us to work in.
    mkdir kernel
    cd kernel
  3. Clone the latest kernel sources using GIT.
    git clone --depth=1 https://github.com/raspberrypi/linux
  4. Setup the kernel configuration for compiling.
    cd linux
    KERNEL=kernel7l
    make bcm2711_defconfig
  5. Make any changes you want to the kernel configuration and append a friendly local version name by using make menuconfig.
    make menuconfig

    To change the friendly name, navigate to “General Setup” and select/modify “Local Version – append to kernel release”.
    (-v7lstephen) Local version - append to kernel release
  6. Compile the kernel, modules, and device tree blobs.
    make -j4 zImage modules dtbs
  7. Install compiled modules.
    make modules_install
  8. Copy the kernel, modules, and other files to the boot filesystem.
    cp arch/arm/boot/dts/*.dtb /boot/
    cp arch/arm/boot/dts/overlays/*.dtb* /boot/overlays/
    cp arch/arm/boot/dts/overlays/README /boot/overlays/
    cp arch/arm/boot/zImage /boot/kernel-stephen.img
  9. Configure the PI to boot using the new kernel by modifying and adding the below line to “/boot/config.txt”.
    kernel=kernel-stephen.img
  10. Reboot!

Bam! You’re now using your shiny new Linux kernel on the Raspberry Pi 4!

To rescue a failed build or if the Pi won’t boot

If for some reason the Pi won’t boot, you can recover the previous kernel since we used a new name with the new kernel.

To rescue the image you’ll need another Linux computer that can read the Micro-SD card.

  1. Insert the Micro-SD Card in the computer.
  2. Mount the /boot/ filesystem on the Micro SD card to a local directory.
  3. Edit the “config.txt” file and remove the “kernel=kernel-name.img” line we made above, or alternatively comment it out by inserting a “#” before the line.
    #kernel=kernel-stephen.img
  4. Save the file.
  5. Unmount the partition.
  6. Insert in the Raspberry Pi and boot!

You should now be back up and running and should be able to try again!

Leave some feedback and let me know if it worked for you. In the future I’ll be doing another post on compiling a 64-bit kernel for the Raspberry Pi 4 on Raspbian.

  13 Responses to “How to compile a Linux kernel for the Raspberry Pi 4 on Raspbian”

  1. […] running Raspbian, you need to compile a custom kernel and build the iSCSI Target Core Modules. Please follow my instructions (click here) to compile a custom kernel on Raspbian or Raspberry Pi. When you’re following my custom kernel build guide, in addition after running “make […]

  2. Thanks for the instructions. I has to compile my own kernel to add a line to the hid-ids.h and hid-quirks.c files to get a Mayflash Sega Saturn adaptor to work on my RetroPie. For some reason following the instructions on the Raspberry Pi website didn’t work for me, but following your instructions worked great!

  3. Hello
    i am trying to disable r8152 built-in driver and compile kernel again, and following your guide step-by-step.
    can you please tell me how long does it take to compile the kernel after this command ?

    make -j4 zImage modules dtbs

  4. Hi Batu,

    All parts of the kernel can take an extremely long time to build. It could be many hours.

    Stephen

  5. Hey Stephen,

    What sort of problems did you run into with trying to compile the 64bit kernel? I am trying to add iSCSI support to Volumio distro (based on Raspian) for my RiP4. Did you ever find a way forward and finish compiling a 64bit kernel?

    Steve

  6. Thank you for the great guide! Needed to recompile only media-tree for my USB Sat-Tv Tuner Card (to apply a patch), but messed up all sorts of things while trying to use linuxtv.org ‘s tutorial.
    With your tutorial I realized that it is smarter, easier and way easier to recompile the whole Linux kernel with my patch attached, now everything is working great!

  7. Glad the post helped!

  8. Worked great 🙂
    Now, I’m on to the iscsi target tutorial that you made.
    Thanks a bunch.

    Regards,
    Jim

  9. Jim! I’m glad to hear it’s working and thanks for leaving a comment! 🙂

  10. Hi. Question for you.
    We make a Kernel Pack (as we call it) which is for our products, which supports all of the Raspberry Pi’s, So Pi1, Pi2/Pi3, Pi4 and the 64bit one. After building the kernels all to the same folders, we tar.gz them up and distribute, and then our customers untar over top of their install (provided kernel versions match etc) and they are off and away.
    Is there a way to do the above process (we actually do cross compile – but same difference) where you don’t have to do menuconfig each time?
    We enable a few of our own modules, and disable 1 default module in menuconfig. Have to do this each time for each kernel before rebuild the kernel, so we have to do the same things in menuconfig 4 times.
    Is there a way this can be done only a single time?
    Would save a bunch of manual work, as the changes in Menuconfig are identical for each one.
    Thanks

  11. Hi James,

    When “make manuconfig” is ran, it generates a “.config” file for the kernel source.

    If you were to save and copy this, and the copy it back on other systems, you wouldn’t need to run the “make menuconfig”, and it would use that file.

    Hope that helps!

    Cheers,
    Stephen

  12. Thanks Stephen, but not exactly what I was asking. Saving the Config is all fine and good, its not about doing it on multiple machines, its about doing it for the 4 different Pi kernels, and then doing the same again when an update happens to the OS or the Kernels. The first part is having to do Menuconfig for Pi1, then Pi2/3 and then Pi4 and then the 64bit one. That is 4 times. Then in a few weeks or so when an update happens, we have to repeat the process. Simply copying the config I dont think will be good enough, as if the update added something new, then our config would exclude that.
    I was trying to find a way if we can do the menuconfig once, which covers all Pi1/Pi2/Pi3/Pi4/64bit in one hit, and then each time there is an update, do something which only modifies the default settings in menuconfig to suit the changes we want (enabling 2 new things, making modules of 3 new things, and disabling one default thing).

  13. Thank you for your helpful & detail document. I successfully built my own kernel.

 Leave a Reply

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

(required)

(required)