Board enablement overview
Board enablement is the process of constructing a complete Ubuntu Core image for an unsupported device. This process typically involves the following steps, each of which is outlined in greater detail below:
This process has been tested and performed on a Roseapple Pi. You can find the complete example source in this repository, but the same process should be applicable to other hardware.
The kernel snap
The kernel snap contains the Linux kernel for the device.
Ubuntu Core kernels are based on the multiv7_defconfig
Linux kernel build target plus some mandatory Ubuntu configs (see the snapcraft.yaml
example below).
You can find reference kernels here: https://github.com/snapcore/sample-kernels
Once you have a kernel ready for Ubuntu Core, the recommended way to build a kernel is with snapcraft. Preferably host the snapcraft.yaml
for the kernel in your device build tree, independent of the kernel tree.
Kernel `snapcraft.yaml` example
name: roseapple-pi-kernel
version: 3.10.37-1
summary: A roseapple kernel built from source
description: This is the reference kernel from xapp-le branch Ubuntu-Snappy-Core
type: kernel
architectures: [ armhf ]
parts:
kernel:
plugin: kernel
source: https://github.com/kubiko/kernel-roseapple-pi.git
source-branch: Ubuntu-Snappy-Core
source-type: git
kdefconfig: [snappy-actduino_bubble_gum_linux_defconfig]
kconfigs:
- CONFIG_LOCALVERSION="-roseapple"
- CONFIG_DEBUG_INFO=n
- CONFIG_SQUASHFS=m
- CONFIG_DEVPTS_MULTIPLE_INSTANCES=y
- CONFIG_RTL8192U=m
- CONFIG_BT_BCM=m
- CONFIG_MAC80211_LEDS=y
- CONFIG_RFKILL_LEDS=y
- CONFIG_ATH_COMMON=y
- CONFIG_ATH_CARDS=y
- CONFIG_ATH9K_HW=y
- CONFIG_ATH9K_COMMON=y
- CONFIG_ATH9K_BTCOEX_SUPPORT=y
- CONFIG_ATH9K_HTC=y
- CONFIG_ATH9K_HTC_DEBUGFS=y
- CONFIG_LEDS_TRIGGERS=y
kernel-initrd-modules:
- squashfs
kernel-image-target: zImage
kernel-device-trees:
- actduino_bubble_gum_sdboot_linux
build-packages: [bc, kmod, cpio]
The gadget snap
The gadget snap is an essential part of Ubuntu Core. It’s responsible for defining and manipulating device-specific system properties and configuration, as well as the boot and file system layout which is used for image building.
You will need to create two files in the meta
directory of this snap:
-
meta/snap.yaml
containing the basic device description, together with device specific interfaces if needed -
meta/gadget.yaml
describing the device boot mode and its filesystem layout.
`meta/snap.yaml` example
name: roseapple-pi
version: 16.04-1
summary: Roseapple Pi support package
description: |
Support files for booting Roseapple Pi
type: gadget
architectures:
- armhf
`meta/gadget.yaml` example
device-tree: actduino_bubble_gum_sdboot_linux.dtb
volumes:
roseapplepi:
schema: mbr
bootloader: u-boot
structure:
- offset: 2097152 #4096*512
size: 2097152 #2M
type: mbr
content:
- image: boot-assets/bootloader.bin
offset: 512 #(4097-4096)*512
- image: boot-assets/u-boot.bin
offset: 1048576 #(6144-4096)*512
- type: 0C
filesystem: vfat
filesystem-label: system-boot
size: 128M
content:
- source: boot-assets/
target: /
See Building a gadget snap for details on how to build the gadget snap.
The model assertion
Before you can build an image to flash on the board, you need to prepare a model assertion and sign it.
First, prepare a JSON file describing the model assertion:
Example model assertion for a Roseapple Pi
{
"type": "model",
"authority-id": "<your store account id>",
"brand-id": "<your store account id>",
"series": "16",
"model": "roseapple",
"architecture": "armhf",
"gadget": "roseapple-pi",
"kernel": "roseapple-pi-kernel",
"timestamp": "<timestamp>"
}
Keys description
-
type
: the assertion type you are creating -
authority-id
,brand-id
refer to your store account id. You will find it on your account page, in theAccount-Id
field. -
series
: the Ubuntu Core series in use -
model
: a free form lower-case name for your target device -
architecture
: the architecture of the device you are building the image for - The
gadget
andkernel
values refer to the name of your kernel and gadget snaps -
timestamp
is a valid timestamp you need to generate using thedate -Iseconds --utc
command
Additional supported keywords for model assertion are:
-
required-snaps
: list of strings describing the list of additional snaps to be preinstalled -
core
: define a custom core snap that needs to be used
See Model assertion for more details on what a model assertion can contain.
Sign the model assertion
Before signing the model, you need to have a valid key registered with your store account. Make sure the snapcraft
and snap
commands know about you by logging in using the email address attached to your account.
$ snapcraft login
$ snap login you@yourdomain.com
Note that logout
commands are available as well.
To check for keys on your machine, run
$ snap keys
For backup purposes, snap keys are stored under ~/.snap/gnupg
Key creation
If you do not have a key, create a new one. You can pass an optional name for the key. If you don’t, the key name will be default
.
$ snap create-key my-key
Then, register the key with your store account:
$ snapcraft register-key my-key
Signature step
Now you have to sign the model assertion with your key, by piping your JSON model through the snap sign -k <key name>
command and outputting a model file you will use to build your image.
$ cat roseapple-model.json | snap sign -k my-key | tee roseapple.model
You can find a more detailed example of this process on the Custom image building page.
Canonical signed assertions
Alternatively, if you just want to build an image using kernel and gadget snaps signed by Canonical, you can use Canonical signed model assertions. Assertions for Canonical supported boards can be fetched directly from the Ubuntu Store, for example:
$ curl -H "Accept: application/x.ubuntu.assertion" "https://assertions.ubuntu.com/v1/assertions/model/16/canonical/pc-amd64"
Or
$ curl -H "Accept: application/x.ubuntu.assertion" "https://assertions.ubuntu.com/v1/assertions/model/16/canonical/pi3"
You can also use the snap command:
$ snap known --remote model series=16 brand-id=canonical model=pc-amd64
Or
$ snap known --remote model series=16 brand-id=canonical model=pi3
Image building
Images are built from a model assertion using ubuntu-image, a tool to generate a bootable image. It can be installed on a snap-supporting Linux system as follows:
$ snap install ubuntu-image --classic
You can now build your image using the following command:
$ sudo ubuntu-image \
-c stable \ # available channels are: edge/beta/candidate/stable
--image-size 4G \
--extra-snaps <gadget snap file name, e.g. roseapple-pi_16.04-1_armhf.snap> \
--extra-snaps <kernel snap file name, e.g. roseapple-pi-kernel_3.10.37-1_armhf.snap> \
--extra-snaps <add more preinstalled snaps here, names from the store or local paths> \
-o <image output file name, e.g. roseapple-pi-20161107-0.img> \
<model file name, e.g. roseapple.model>
Note: The --extra-snaps
argument takes either a snap name accessible from the store or a local path to a built snap.
Your image is ready, you can use a tool like dd
to write the image to an SD Card and boot your board.
Build a custom image for a reference board
To build a custom image for one of the Canonical supported boards, use a Canonical signed model assertion, as described above and use a gadget and kernel snaps from the store.
Example for a custom Raspberry Pi3 image
$ curl -H "Accept: application/x.ubuntu.assertion" "https://assertions.ubuntu.com/v1/assertions/model/16/canonical/pi3" > pi3.model
$ sudo ubuntu-image \
-c stable \
--image-size 4G \
--extra-snaps pi2-kernel \
--extra-snaps pi3 \
--extra-snaps nextcloud \
-o pi3-20161107-0.img \
pi3.model