Porting KubOS to a New OBC

The KubOS middleware and applications are intended to be able to run on any OBC which is running Kubos Linux. Unfortunately, while userland programs are completely portable between OBCs, the underlying operating system and bootloader are not.

This doc is intended as a high-level overview of the work which needs to be done in order to get KubOS up and running on a new OBC.

Note: The terms “board” and “OBC” are used interchangeably.

System Layout

Before any work can be done, the system’s partition layout should be decided.

The system should be composed of at least the following partitions:

  • Boot partition - Contains U-Boot, the kernel, and the device tree (may be broken into multiple partitions)
  • U-Boot envar partition - The environment variables which U-Boot uses in order to load and boot Kubos Linux. We recommend that this be placed in its own partition in order to help prevent corruption.
  • Root FS - The Kubos Linux root file system
  • Upgrade partition - This will hold the Kubos upgrade/rollback files
  • User data partition - This will hold all of the user data. It is placed in its own partition to prevent it from being affected by a system upgrade or rollback.

These partitions may be placed across multiple memory devices, if desired. For example, the partition containing U-Boot could be placed in a more secure memory device (ex. flash storage), while the root FS could be placed in a larger, but less secure location since it can be easily recovered.

Buildroot

Buildroot is responsible for building and assembling the OS components based on a given configuration file.

Kubos’ Buildroot configurations and files are kept in the KLB repo and follow Buildroot’s recommended external tree structure.

Clone the KLB repo repo to your local development environment. Almost all work done to port KubOS to a new OBC will be done here.

Board Config

The high-level configuration file for the new OBC should be placed in kubos-linux-build/configs and should have a name which ends in “*_defconfig”.

The kubos-linux-build/configs/generic-kubos_defconfig file gives a good starting place for your configuration. The “{target}” string should be replaced with your OBC’s name.

The Kubos core services are included by default, so do not need to be manually specified in this file.

Board Directory

All other files needed for your OBC should be placed in a new directory under the kubos-linux-build/board directory.

The normal convention is board/{company}/{obc}.

You may add your OBC under the kubos directory or you may create a new directory for your organization.

Files in this directory include:

  • U-Boot configuration
  • Linux configuration
  • Linux device tree
  • Image generation
  • Board-specific overlay
  • Board-specific patches

These files will be covered in more detail in later sections of this doc.

Overlay

Board-specific overlay files should be given in a subdirectory, board/{company}/{obc}/overlay.

These files should be located under the same directories as the file target file system.

There are a few overlay files which should be common to all boards.

etc/network/interfaces

This file defines the default ethernet connection (if one exists) as well as any other network connections. For example, a SLIP connection might also be defined.

etc/fstab

This file defines all of the partitions which should be mounted at system boot.

etc/fw_env.config

This file defines the location of the U-Boot envar partition so that the envars can be accessed from Linux with the fw_printenv and fw_setenv commands.

etc/inittab

This file is responsible for running some boot-time activities and kicking off all the init scripts.

Most importantly, it should be customized to run fsck on all system partitions and then to mount all relevant partitions.

etc/monitrc

This file controls the settings of Monit, the system’s process monitoring tool.

This file is customized for each board primarily due to the SET HTTPD command, which varies depending on whether or not the system has an ethernet connection available.

Image Creation

Once the build process has been completed, a final OS image will likely need to be created so it can be loaded onto your target memory device/s.

For the Beaglebone Black and Pumpkin MBM2 targets, this is controlled by the post-image.sh script, which calls genimage in order to create the image. It uses the genimage.cfg file in order to determine which partitions need to be created, what size the partitions need to be, and which files need to be placed inside of them.

genimage is our preferred tool used to create system images, however it might not be compatible with all board layouts.

U-Boot

U-Boot is the bootloader which is used for all boards. It is responsible for loading the operating system files into the appropriate storage locations and then kicking off the OS boot process.

U-Boot configuration is a very manual process. The easiest way to determine what settings need to be used is to find example boards which are as close to your desired architecture as possible (frequently things like a processor’s evaluation kit board are available).

Kubos has created a fork of U-Boot at https://github.com/kubos/uboot. When adding a new board, users may do one of three things:

  • Create a pull request which adds support for their board to Kubos’ U-Boot repo
  • Create a patch which adds support and store it in their board’s Buildroot directory
  • Create a custom fork of U-Boot

Buildroot Config

A good portion of the U-Boot configuration is done with a configuration file, located in the board’s Buildroot directory. This file defines the high-level capabilities and the behavior of the U-Boot prompt.

The following options should be enabled in order to build the Kubos OS recovery and upgrade system into the U-Boot binary:

  • CONFIG_UPDATE_KUBOS
  • CONFIG_DFU
  • CONFIG_DFU_TFTP
  • The CONFIG_DFU_* options which match the memory device type/s you are using (ex. CONFIG_DFU_MMC)

U-Boot Config

The remainder of a board’s configuration is done within U-Boot itself.

You’ll need to create a new configuration header file in uboot/include/configs.

This header file will define things like the location of the U-Boot envars, the default values for those envars, and the location and properties of various system resources.

The file should have #include "kubos-common.h" in order to build in the resources needed for OS upgrade and recovery.

U-Boot Board Package

Next, you’ll need to create a new directory under uboot/board. Boards currently supported by Kubos are located under uboot/board/kubos.

Within this directory should be at least two files:

  • Kconfig - Defines the new board-specific configuration options, including a pointer to the previously mentioned configuration header file (SYS_BOARD)
  • Makefile - Defines the board-specific drivers which need to be compiled into U-Boot

Installing U-Boot

Special care should be taken when determining where the final U-Boot binary should be installed.

Many boards’ initial bootloaders expect the starting executable (U-Boot, in this case) to be located in a particular memory location.

Note: This same care is not required for installing the rest of the system since you’ll be defining the location of the other major components (kernel, root FS, etc) within U-Boot.

Linux

Config

The Buildroot configuration supports having multiple “fragment” files for Linux configuration (BR2_LINUX_KERNEL_CONFIG_FRAGMENT_FILES). We take advantage of that by specifying common Linux options within the kubos-linux-build/common/linux-kubos.config file.

Board-specific options should be specified within a separate config file under the board’s Buildroot directory. These options include things like model-specific peripheral drivers and processor-specific definitions.

Device Tree

The board’s device tree defines the particular hardware characteristics of the board. This includes things like specifying the pins allocated to a SPI bus, and the address of a particular bank of memory.

Device tree development is one of the major pain points when bringing up a new OBC.

We recommend the following debug tactics:

  1. Turn your compiled device tree (*.dtb) back into the source tree to make sure that it’s getting assembled the way you want it to. dtc -I dtb -O dts {buildroot}/output/images/{board}.dtb
  2. Start up Linux with debug printing enabled (Note: this will generate a huge amount of data, so you’re going to want to have it automatically saved off somewhere for you to review later):
    • Power up your board and hold down a key to go into the U-Boot console
    • Enter editenv bootargs
    • Add debug to the end of the printed string and then press Enter
    • Enter run bootcmd
    • This will start up Linux and spew out all kinds of stuff. Once it’s done booting (probably a minute or so), you can review the startup data. You’ll be looking for any kinds of issues assigning the desired pins to a particular device or loading the needed driver for a peripheral.

Busybox

Currently, all OBCs supported by Kubos use a common Busybox configuration, located in kubos-linux-build/common/busybox-kubos.config. This config file specifies all the commands and utilities which are needed in order to run KubOS.

Additional config fragment files may be specified, if desired, with the BR2_PACKAGE_BUSYBOX_CONFIG_FRAGMENT_FILES option.