Intro
In my previous posts I have shared
my first experience with debos
and
how to run debos in a container.
In today’s post, I’d like to present how can we use all of that to generate base
Debian image for an ARM board. My board of choice for this particular example
will be the
HummingBoard Edge.
The post is inspired by the feedback from the new users (such as
this one) that there are no
end-to-end examples how to quickly start using this tool.
HummingBoard Edge upstream support
The Hummingboard Edge
is described in the Linux by the
hummingboard2 devicetree.
It is supported
since the 4.16 Linux release.
I have decided to use the sid
flavor of Debian
in order to get quite recent
kernel version
(4.18+98
at the moment of writing).
debos recipe
The full recipe and all other files are available in the
3mdeb/debos-recipes repository on github.
I wanted to create a really base system image, just to try out that it boots
properly. I took the
existing RPI3 recipe
as a starting point.
As stated in the previous paragraph, the sid
flavor of Debian will be used,
hence following action in the recipe file appears:
1
2
3
4
5
6
|
- action: debootstrap
suite: "sid"
components:
- main
mirror: https://deb.debian.org/debian
variant: minbase
|
Some of the following actions are:
- setting the hostname with a
run
action:
1
2
3
4
|
- action: run
description: Set hostname
chroot: true
command: echo HummingBoard2 > /etc/hostname
|
note that we can decide with the
chroot flag
whether the command shall be executed on the host or in the chrooted
environment
- copying over
extlinux
config files with an overlay
action:
1
2
3
|
- action: overlay
description: Install U-boot extlinux menu file
source: u-boot
|
The
extlinux config I came up with
could have been definitely improved (e.g. to be autogenerated, to use UUID
for root partition etc.), but is perfectly enough for the purpose of this
demonstration.
- installation of the
Linux
and U-Boot
packages:
1
2
3
4
5
6
|
- action: apt
description: Install Linux and U-Boot packages
recommends: false
packages:
- linux-image-armmp
- u-boot-imx
|
Another important action is the image-partition
. We can specify there the
final image size, partitions to be created as well as their mount points. Note
that the /etc/fstab
entries will be automatically added for created
partitions.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
# leave 4MB offset at the image start for U-Boot installation
- action: image-partition
description: Create partitioned image
imagename: {{ $image }}
imagesize: 1GB
partitiontype: msdos
mountpoints:
- mountpoint: /
partition: root
partitions:
- name: root
fs: ext4
start: 4MB
end: 100%
flags: [ boot ]
|
The substantial difference from the RPI3
recipe is the bootloader. Unlike many
other ARM
boards, RPI3
does not use the U-Boot
installed directly (into
not partitioned area) at the start of the image file (or block device).
As shown in the
mx6cuboxi README,
SPL U-Boot
shall be installed into the device as follows:
1
2
|
sudo dd if=SPL of=/dev/mmcblk0 bs=1k seek=1; sync
sudo dd if=u-boot.img of=/dev/mmcblk0 bs=1k seek=69; sync
|
In debos
, we can use the raw
action and use built-in sector
keyword to
install binaries at required offsets:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
# 'filesystem' origin points to the target root filesystem
# 2 sectors = 1K
# bs=1K seek=1
- action: raw
description: Install SPL to the image
origin: filesystem
source: /usr/lib/u-boot/mx6cuboxi/SPL
offset: {{ sector 2 }}
# bs=1K seek=69
- action: raw
description: Install U-Boot to the image
origin: filesystem
source: /usr/lib/u-boot/mx6cuboxi/u-boot.img
offset: {{ sector 138 }}
|
Note that we can use filesystem
as an argument for the origin
in order to
gain access to files located in the filesystem we have generated in the previous
steps. This feature does not seem to be documented somewhere, but I found such
map
in the code.
Other useful arguments might be: artifacts
or recipe
.
The final actions include deploying filesystem to image and compressing the
final image. Optionally, the
bmap file
can be generated.
1
2
3
4
5
6
7
8
9
10
11
12
|
- action: filesystem-deploy
description: Deploy filesystem to the image
- action: run
description: Create bmap file
postprocess: true
command: bmaptool create {{ $image }} > {{ $image }}.img.bmap
- action: run
description: Compress image
postprocess: true
command: gzip -f9 {{ $image }}
|
Image building
I’ve used our debos docker container to
perform debos
build. I chose to save the
run script in my
PATH
for easy execution:
1
|
debos-docker debimage-hb2.yaml
|
The end result looks like:
1
2
3
4
5
6
7
8
9
10
|
< truncated >
2018/09/19 19:07:19 ==== Install SPL to the image ====
2018/09/19 19:07:19 ==== Install U-Boot to the image ====
2018/09/19 19:07:19 ==== Deploy filesystem to the image ====
2018/09/19 19:07:20 Setting up fstab
2018/09/19 19:07:20 Setting up /etc/kernel/cmdline
Powering off.
2018/09/19 19:07:21 ==== Create bmap file ====
2018/09/19 19:07:26 ==== Compress image ====
2018/09/19 19:08:35 ==== Recipe done ====
|
And we should have a final image file:
1
|
-rw-r--r-- 1 maciej root 143M wrz 21 11:51 debian-hb2.img.gz
|
Image flashing
The usual way
No explanation needed for the dd
command:
1
|
gzip -cdk debian-hb2.img.gz | sudo dd of=/dev/mmcblk0 bs=16M status=progress
|
The fancy way
Thanks to the bmap
file we created, we can use bmaptools
to flash the image.
Explanation of this tool could be itself a story for another post. More details
can be found in the
bmaptool documentation.
We might need to install the tool first:
1
|
sudo apt install bmap-tools
|
Image can be flashed with following command:
1
|
bmaptool copy --bmap debian-hb2.img.img.bmap debian-hb2.img.gz /dev/mmcblk0
|
Comparison
It is a good opportunity to show a quick comparison between those two:
1
2
3
4
5
6
|
time sh -c 'gzip -cdk debian-hb2.img.gz | sudo dd of=/dev/mmcblk0 bs=16M status=progress && sync'
1000000000 bytes (1,0 GB, 954 MiB) copied, 32 s, 31,2 MB/s
0+27202 records in
0+27202 records out
1000000000 bytes (1,0 GB, 954 MiB) copied, 78,7137 s, 12,7 MB/s
sh -c 6,62s user 1,27s system 10% cpu 1:18,73 total
|
1
2
3
4
5
6
7
8
|
time sudo sh -c 'bmaptool copy --bmap debian-hb2.img.img.bmap debian-hb2.img.gz /dev/mmcblk0 && sync'
bmaptool: info: block map format version 2.0
bmaptool: info: 244141 blocks of size 4096 (953.7 MiB), mapped 110274 blocks (430.8 MiB or 45.2%)
bmaptool: info: copying image 'debian-hb2.img.gz' to block device '/dev/mmcblk0' using bmap file 'debian-hb2.img.img.bmap'
bmaptool: info: 100% copied
bmaptool: info: synchronizing '/dev/mmcblk0'
bmaptool: info: copying time: 38.0s, copying speed 11.3 MiB/sec
sudo sh -c 8,48s user 1,26s system 25% cpu 38,209 total
|
Image running
The boot log:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
|
U-Boot SPL 2018.05+dfsg-1 (May 10 2018 - 20:24:57 +0000)
Trying to boot from MMC1
U-Boot 2018.05+dfsg-1 (May 10 2018 - 20:24:57 +0000)
CPU: Freescale i.MX6DL rev1.3 996 MHz (running at 792 MHz)
CPU: Commercial temperature grade (0C to 95C) at 38C
Reset cause: POR
Board: MX6 Hummingboard2
DRAM: 1 GiB
MMC: FSL_SDHC: 0
Loading Environment from MMC... *** Warning - bad CRC, using default environment
Failed (-5)
No panel detected: default to HDMI
Display: HDMI (1024x768)
In: serial
Out: serial
Err: serial
Net: FEC
Hit any key to stop autoboot: 2 1 0
switch to partitions #0, OK
mmc0 is current device
Scanning mmc 0:1...
Found /boot/extlinux/extlinux.conf
Retrieving file: /boot/extlinux/extlinux.conf
498 bytes read in 110 ms (3.9 KiB/s)
U-Boot menu
1: Debian GNU/Linux kernel
2: Debian GNU/Linux kernel (rescue target)
Enter choice: 1: Debian GNU/Linux kernel
Retrieving file: /initrd.img
17499178 bytes read in 1028 ms (16.2 MiB/s)
Retrieving file: /vmlinuz
4174336 bytes read in 395 ms (10.1 MiB/s)
append: root=/dev/mmcblk1p1 ro rootwait console=ttymxc0,115200
Retrieving file: /boot/dtbs/imx6dl-hummingboard2.dtb
39570 bytes read in 120 ms (321.3 KiB/s)
## Flattened Device Tree blob at 18000000
Booting using the fdt blob at 0x18000000
Using Device Tree in place at 18000000, end 1800ca91
Starting kernel ...
[ 0.000000] Booting Linux on physical CPU 0x0
[ 0.000000] Linux version 4.18.0-1-armmp (debian-kernel@lists.debian.org) (gcc version 7.3.0 (Debian 7.3.0-29)) #1 SMP Debian 4.18.6-1 (2018-09-06)
[ 0.000000] CPU: ARMv7 Processor [412fc09a] revision 10 (ARMv7), cr=10c5387d
< truncated >
Starting Update UTMP about System Runlevel Changes...
[ OK ] Started Update UTMP about System Runlevel Changes.
Debian GNU/Linux buster/sid HummingBoard2 ttymxc0
HummingBoard2 login: user
Password:
Linux HummingBoard2 4.18.0-1-armmp #1 SMP Debian 4.18.6-1 (2018-09-06) armv7l
|
Conclusion
As I have shown in this post, debos
can be quite easily used for building
Debian
image for an ARM
platform. This is especially true if such board has
good mainline support and the Linux
and U-Boot
packages for it are already
available in the Debian
package feed. I hope that my post can be helpful for
new debos
users and that my recipe gets merged into the
debos-recipes, so it can be easily
accessible.
Maciej Pijanowski
Engineering Manager at 3mdeb with years of experience in engineering and management. Open-source software enthusiast and contributor. Interested in embedded systems in general, build systems, security.