Kernel Modules

Loadable kernel modules (.ko files) are object files that are used to extend the kernel of the Linux Distribution. They are used to provide drivers for new hardware like IoT expansion cards that have not been included in the Linux Distribution.

This tutorial walks you through building a .ko file, bundling the kernel module with your Legato System and updating the Legato Runtime Environment. The benefit of this is that you can provide any drivers needed for your hardware with your applications and easily install the drivers on your target device without having to rebuild the Linux Distribution.

The files that are used in this tutorial are located in $LEGATO_ROOT/drivers/example

This tutorial is specific to building kernel modules on Sierra Wireless Targets. It references toolchains for the WP Series Targets and has been tested on both the WPX5XX and WP76XX targets.

Pre-Requisites

This tutorial requires you to have:

  • Legato Application Framework version 18.06.0 or newer installed on your dev machine and target device.
  • Legato Application Framework dev environment is installed with Leaf workspace manager.
  • The source driver files for the IoT expansion card (.c files) or the pre-built kernel module (.ko file)
Warning
This tutorial is designed to teach the software aspects of building, installing and loading drivers into the kernel using the Legato Application Framework. It does not focus on setting up or interfacing with specific hardware. It also does not cover writing or compiling source driver files for specific kernels. The source driver files must be compatible with the kernel on your target device.

Toolchain Setup

If you have manually installed the toolchain (not installed through Leaf or Developer Studio) and are using a WP module then you will have to run through an extra set-up script before you can build your kernel module against the toolchain. See Run Kernel Build Scripts.

Configuring Def Files

To load the kernel module into the Legato Runtime Environment you must configure a mdef file to include the source files for the driver and then configure your target's sdef to include the driver at build time.

Note
When the mdef is built the source files are built against Linux header files (which are included with the toolchain), if the toolchain does not match the Linux version that is installed on your target then the module won't run, you need to make sure that you are using the toolchain that matches the Linux version on your target.

If you have the source code driver files then your mdef must include the sources section of the mdef.

Copy the source files into the directory that you will reference in your mdef.

sources:
{
example.c //the example.c file is in the same location as the example.mdef
}
Note
If your kernel module sources needs any parameters or flags use the params or flags sections of the Kernel Module Definition .mdef.

If you have a compiled binary kernel module that matches your kernel, then your mdef must include the preBuilt section of the mdef.

Example of a preBuilt section in the mdef:

preBuilt:
{
~/drivers/example/example.ko
}
Note
You are able to add multiple prebuilt .ko files into the same mdef if needed.

The kernelModules: section in the declares the kernel modules to be bundled and installed into the Runtime Environment.

Example kernelModules section in the defFilesSdef:

kernelModules:
{
~/drivers/example/example.mdef
}

Building your System

Once you've set up your system to include the source driver files or binary .ko the next step is to build your update system by running toolsBuild_mksys.

Example of running mksys for a wp85:

$ mksys -t wp85 mySystem.sdef

This will build the system update file and place it in the build directory under $LEGATO_ROOT. For example, if you make wp85 then the update file will be called system.wp85.update and will be located in the $LEGATO_ROOT/build/wp85 directory.

Note
If you are building your files from source you need to make sure that they are supported by the Linux Kernel that is installed on your target. Drivers from a 3rd party may need to be verified that they can be build against the kernel version on the target. To check the Linux version on your target run # fwupdate query.
Warning
When the mdef is built the source files are built against Linux header files (which are included with the toolchain), if the toolchain does not match the Linux version that is installed on your target then the module won't run, you need to make sure that you are using the toolchain that matches the Linux version on your target.

You can also do a search for the .ko file to view the kernel module.

$ cd $LEGATO_ROOT/build/wp85
$ find -name \*.ko

Example output:

$ find -name \*.ko
./system/staging/modules/example.ko
./system/modules/example/example.ko
./_staging_system.wp85.update/system/modules/example.ko
Warning
The .ko file that is built is built for the specific Linux kernel that exists on your target machine. If the .ko is needed for other targets with a different models of module then the .ko file must be built using that target's toolchain.

Installing the System

Now that you have your .update file you can use tools included in the Legato AF to install the update on your target. update and instlegato will both update the Legato system on your target.

Note
If you wish to Verify the Update with logread, you must set up the logread before installing the Legato system update.

To access the Legato target management tools bin/legs or source bin/configlegatoenv must be run first. This step is not necessary if bin/configlegatoenv has been added to your bash profile.

From the $LEGATO_ROOT directory:

$ update <target's platform> <target's IP>

Example command and output:

$ bin/legs
$ update $LEGATO_ROOT/build/mySystem.wp85.update 192.168.2.2
Installing Legato system update pack build/wp85/mySystem.wp85.update
Applying update from file 'build/wp85/mySystem.wp85.update' to device at address '192.168.2.2'.
Unpacking package: 100% ++++++++++++++++++++++++++++++++++++++++++++++++++
Applying update: 100% ++++++++++++++++++++++++++++++++++++++++++++++++++
SUCCESS
Done

Verify the Update

Depending on what your kernel module does there are a couple of ways to verify that it was successfully installed.

legato status

To verify that your system was updated, from your target:

# legato status

legato status should show that the systems installed has been incremented and that you have a good system and are currently running the new system. (As long as the markKnownGood threshold has not been reached)

# legato status
Systems installed:
  19 [good]
  20 [tried 1] <-- current
Legato framework is running.
Warning
If there is a kernel mismatch (the .ko was built against a different kernel then what is installed on your target) then a rollback may be initiated and your Legato system will revert to the previous known good system. If this happens then you must rebuild the .ko files with the same kernel version as what is on your target. This should not happen if you are building your system with the source code driver files as long as the source code driver files are compatible with the target's kernel.

lsmod

lsmod (a Linux command) will display what kernel modules have been installed into the target's kernel.

Example output of lsmod:

# lsmod
    Tainted: G
example 755 0 - Live 0xbf133000 (O)
...
Note
lsmod might report your kernel as "Tainted" if you are using an out-of-tree driver such as example.ko. The kernel is labeled "Tainted" if it is not in a state that is supported by the Linux Community, but can be safely ignored in this case.

logread

Following the log files as the system update is installed will display the modules being loaded into the system.

Example of greping for the example.ko being loaded on the system; this needs to be setup before you install the system update with instlegato. SSH to the target and run logread (a Linux tool):

# logread -f | grep "example"      # example should be replaced with what your .ko file is called

On your dev machine install the updated Legato system:

Example command and output:

$ update mySystem.wp85.update 192.168.2.2
Installing Legato system update pack build/wp85/mySystem.wp85.update
Applying update from file 'build/wp85/mySystem.wp85.update' to device at address '192.168.2.2'.
Unpacking package: 100% ++++++++++++++++++++++++++++++++++++++++++++++++++
Applying update: 100% ++++++++++++++++++++++++++++++++++++++++++++++++++
SUCCESS
Done

On the target you should be able to see something like the following message in the logs:

Legato:  INFO | supervisor[1956]/supervisor T=main | kernelModules.c ModuleInsert() 285 | New kernel module 'example'

Verifying the Kernel Version

If the kernel module does not show in the list of lsmod it means that it was not successfully loaded onto your target. The most common cause of this is that your toolchain version and firmware version are using different kernels. It is very important to make sure you are building your kernel modules with the same version of toolchain that matches the firmware on your device.

The following command will grep for the kernel version of the kernel module:

# strings /path/to/kernel/module/example.ko |grep vermagic

Example of using grep on example.ko:

# strings /legato/systems/current/modules/example.ko |grep vermagic
vermagic=3.14.29ltsi-961ca71325_ab5094eade preempt mod_unload ARMv7
__UNIQUE_ID_vermagic0
__UNIQUE_ID_vermagic0

To find the kernel version that your target is using:

# uname -a

Example of finding the kernel on a target:

# uname -a
Linux swi-mdm9x15 3.14.29ltsi-961ca71325_ab5094eade #2 PREEMPT Thu Apr 27 02:17:10 PDT 2017 armv7l GNU/Linux

In this example both kernels are version 3.14.29ltsi-961ca71325_ab5094eade, if they are different at all the kernel module or system will fail to load and the system may rollback to the previous known good system.

Note
Connecting to the console port of your target and using logread will let you view the logs as your target loads. This is helpful to view errors in real time or check if the target is rolling back to the previous system.

To resolve this download and install the toolchain that matches the version of your target or update your firmware to match the version of the toolchain that you are using.

Running fwupdate query on your target will display the current firmware version:

Example of running fwupdate:

# fwupdate query
Connecting to service ...
Firmware Version: SWI9X15Y_07.12.09.00 r34123 CARMD-EV-FRMWR1 2017/04/26 23:34:19
Bootloader Version: SWI9X15Y_07.12.09.00 r34123 CARMD-EV-FRMWR1 2017/04/26 23:34:19
Linux Version: 3.14.29ltsi-961ca71325_ab5094eade #2 PREEMPT Thu Apr 27 02:17:10 PDT 2017