Build and Install a Kernel Object

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 object 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 objects on Sierra Wireless Modules. It references toolchains for the WP Series Modules and has been tested on both the WPX5XX and WP76XX modules.

Pre-Requisites

This tutorial requires you to have:

  • Legato AF version 16.10.3 or newer installed on your dev machine and target device.
  • The toolchain associated with your Module and Linux Distribution installed on your dev machine.
  • The source driver files for the IoT expansion card (.c files) or the pre-built kernel object (.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.

First Time Setup

If this is your first time building .ko files, you have to run the kernel build scripts that are used to compile your module on your dev machine; the script to build the objects is included in a directory in the toolchain. If you have installed the toolchain with Developer Studio or legato-spm these steps are already done for you.

1. Verify that you have installed the toolchain for your specific target.

2. Add the following directory to your PATH: /opt/swi/y17-ext/sysroots/x86_64-pokysdk-linux/usr/bin/arm-poky-linux-gnueabi

$ export PATH=/opt/swi/y17-ext/sysroots/x86_64-pokysdk-linux/usr/bin/arm-poky-linux-gnueabi:$PATH

3. Change directory to: /opt/swi/y17-ext/sysroots/armv7a-vfp-neon-poky-linux-gnueabi/usr/src/kernel

$ cd /opt/swi/y17-ext/sysroots/armv7a-vfp-neon-poky-linux-gnueabi/usr/src/kernel

4. Take ownership of the files in the directory and run make scripts, when done return ownership to the root user.

Note
The root user does not know the path to the Legato compiler so file ownership must be temporarily transfered to yourself so that the scripts build properly and then given back when the script is completed.
$ sudo chown -R $USER .
$ ARCH=arm CROSS_COMPILE=arm-poky-linux-gnueabi- make scripts
$ sudo chown -R root .
Warning
The last step must be repeated every time that you install a new version of the toolchain or install a new toolchain for a different module/target.

Configuring Def Files

To load the kernel object into the Legato Runtime Environment you must configure your app's mdef file to include the source files for the driver; next configure your target's sdef to include the driver at build time.

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 object 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
}

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 make <target>.

Warning
make clean must be run before making a build with a new .ko file or the .ko file will not build.

Example of running make for a wp85:

$ make clean
$ make wp85

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.

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

$ 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.

As long your build is in the normal build location (e.g.; $LEGATO_ROOT/build) then only the target's platform and the target's IP needs to be specified with using instlegato. If it it built to a different location then the full path to the .update file must be provided.

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:

$ bin/legs
$ instlegato <target's platform> <target's IP>

Example command and output:

$ bin/legs
$ instlegato wp85 192.168.2.2
Installing Legato system update pack build/wp85/system.wp85.update
Applying update from file 'build/wp85/system.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 object 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:

$ instlegato wp85 192.168.2.2
Installing Legato system update pack build/wp85/system.wp85.update
Applying update from file 'build/wp85/system.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/object/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