Creating a new DKMS from an out-of-tree driver

This tutorial will describe how to create Debian-packaged Dynamic Kernel Module Support (DKMS) from an out-of-tree driver. This is just one way to provide DKMS and is by no means the only or most correct way do so.

Complete documentation on DKMS can be found on the dkms - Linux man page.

More information on Debian packaging can be found in the Guide for Debian Maintainers - Basic

Prerequisites

  1. You should be running on the same release of Ubuntu that the DKMS is destined for. For example, if you are going to load the driver on a Xilinx KR260 running Jammy, your x86 computer needs to be on Jammy as well. You can use a container to achieve this.

  2. You’ll need an out-of-tree kernel module, including a Makefile, that compiles and loads on the target.

    For this tutorial, we will use the example mv-camera-sensor-module intended for Xilinx hardware.

  3. Determine the values of the following fields:

    • source : The name of the source-code project for the driver, usually the name of the git repository

    • package : The name of the Debian package, this can be the same name as the source

    • module : The name of the kernel module - there may be multiple kernel modules in a single package

  4. Install required tools:

    $ sudo apt install dh-make dkms
    

Creating the Debian package

  1. Check out the out-of-tree driver into a directory named with <source>-<version>, where <version> is the Debian package version:

    $ mkdir <source>-<version>
    $ git clone <out-of-tree kernel driver repo> <source>-<version>
    $ cd <source>-<version>
    
  2. Create src directory and move driver source code into it, including Makefile:

    $ mkdir src
    $ mv <driver source files> src
    
  3. In a new location, check out the dkms-template repository:

    $ git clone https://git.launchpad.net/~portias/+git/dkms-template -b main
    
  4. Return to the out-of-tree driver and run dh_make which will create the template files under the debian/ directory.

    Use the dkms-template repository from the previous step as a template. These files are explained in detail in Required files under the debian directory . This step will also create the original tarball which will be needed when buliding the first release of the package.

    Finally, delete unused files generating in debian/ directory. Depending on your use case, you may choose to use files that are being deleted below.

    $ dh_make --createorig --single --yes --template <path/to>/dkms-template/debian
    $ rm debian/README.* debian/*.ex debian/*.docs
    

    The remaining template files will need to be updated for our DKMS package.

debian/changelog

Update this file with the release and your name/email address. See debian policy - changelog for more details.

Example debian/changelog

mv-camera-sensor-module (0.1-1) focal; urgency=medium

  * Initial release

   -- Portia Stephens <[email protected]>  Thu, 2 Nov 2023 13:55:08 +1030

debian/control

For a complete description of all fields in the control file, see debian policy - control.

Change the following lines in the control file for your DKMS package.

Change the Section field to kernel, since this is a kernel driver:

Section: kernel

Update the maintainer field to the person or mailing list who is responsible for maintaining this DKMS.

Add dkms to the Build-Depends field. Your dependency version may be different:

Build-Depends: debhelper-compat (= 12), dkms

Add the URL for the upstream project in the Homepage field, if applicable.

Change Rules-Requires-Root to binary-targets, since DKMS will require root to build and install. If this line does not exist, it does not need to be added:

Rules-Requires-Root: binary-targets

Change the Architecture field to all, to allow you to build the DKMS on a different architecture than it is installed on:

Architecture: all

Update the Description field to a concise description of your driver.

Example debian/control

Source: mv-camera-sensor-module
Section: kernel
Priority: optional
Maintainer: Portia Stephens <[email protected]>
Build-Depends: debhelper-compat (= 12), dkms
Standards-Version: 4.4.1
Homepage: https://github.com/Xilinx/mv-camera-sensor-module
Rules-Requires-Root: binary-targets

Package: mv-camera-sensor-module
Architecture: all
Depends: ${shlibs:Depends}, ${misc:Depends}
Description: IMX547 sensor device driver
 This package contains the driver for imx547 sensor and uses DKMS to
 automatically build the kernel module.

debian/<package>.dkms

Complete documentation on all the fields can be found on the dkms - Linux man page.

Update the following fields.

  • BUILT_MODULE_NAME[0] : the name of the kernel module; it should be the same name as the ko file.

  • BUILT_MODULE_LOCATION[0] : the path to the source code for that kernel module from the src directory. For example, if the source code of the kernel module is in src/<module name>/ , BUILT_MODULE_LOCATION[0]=<module name>

  • DEST_MODULE_LOCATION[0] : the relative path to where the module will be installed on the system. By adding the updates/ directory we ensure that the DKMS driver will override any in-tree driver with the same name:

Multiple kernel modules can be included in the same package by indexing the fields below.

Example mv-camera-sensor-module.dkms

A package called mv-camera-sensor-module with a single kernel module, imx547 and the following directory structure:

mv-camera-sensor-module
└── src
    ├── Makefile
    ├── imx547.c
└── debian

Could have the following <package>.dkms, mv-camera-sensor-module.dkms

PACKAGE_NAME="mv-camera-sensor-module"
PACKAGE_VERSION="0.1"
AUTOINSTALL="yes"
BUILT_MODULE_NAME[0]="imx547"
BUILT_MODULE_LOCATION[0]="."
DEST_MODULE_LOCATION[0]="/updates/imx547/"

Building and testing

First build the source and the debian package:

$ dpkg-buildpackage -us -uc -rfakeroot -sa -F

Copy the generated .deb file onto the device.

NOTE The built outputs will be generated a level above where you ran the build command.

Next on the device, install the Debian package and load the kernel module.

ubuntu@kria $ sudo dpkg -i <package>_*.deb
ubuntu@kria $ insmod <path/to/module>.ko

Now on the device check dmesg and modinfo to see that the module was correctly loaded. modinfo will show the install path, which should be updates/dkms/:

ubuntu@kria $ modinfo <module>
ubuntu@kria $ sudo dmesg | tail

Example installing and loading mv-camera-sensor-module

ubuntu@kria $ sudo dpkg -i mv-camera-sensor-module_0.1-1_all.deb
Selecting previously unselected package mv-camera-sensor-module.
(Reading database ... 119099 files and directories currently installed.)
Preparing to unpack mv-camera-sensor-module_0.1-1_all.deb ...
Unpacking mv-camera-sensor-module (0.1-1) ...
Setting up mv-camera-sensor-module (0.1-1) ...
Loading new mv-camera-sensor-module-0.1 DKMS files...
Building for 5.15.0-1023-xilinx-zynqmp
Building initial module for 5.15.0-1023-xilinx-zynqmp
Done.

imx547.ko:
Running module version sanity check.
 - Original module
 - Installation
        - Installing to /lib/modules/5.15.0-1023-xilinx-zynqmp/updates/dkms/

depmod........

ubuntu@kria $ sudo insmod /lib/modules/5.15.0-1023-xilinx-zynqmp/updates/dkms/imx547.ko

ubuntu@kria $ ubuntu@versal:~$ sudo dmesg | tail
[  905.204512] imx547: loading out-of-tree module taints kernel.
[  905.204643] imx547: module verification failed: signature and/or required key missing - tainting kernel

ubuntu@kria $ modinfo imx547
filename:       /lib/modules/5.15.0-1023-xilinx-zynqmp/updates/dkms/imx547.ko
license:        GPL v2
description:    IMX547 CMOS Image Sensor driver
author:         FRAMOS GmbH
srcversion:     2B54A31AC37E2DC74AEA8CD
alias:          of:N*T*Cframos,imx547C*
alias:          of:N*T*Cframos,imx547
alias:          i2c:imx547
depends:
name:           imx547
vermagic:       5.15.0-1023-xilinx-zynqmp SMP mod_unload modversions aarch64