Summary of steps used to install and boot an embedded Linux image on a T1040RDB. Image was built with Yocto Project 2.7 using mainline Linux 5.0 kernel and our custom layer.

Overview

Provided below are the steps we use to install / update a Yocto-built image on an embedded Linux system. This particular system is a Freescale / NXP T1040RDB that we use with an SSD to run & test the Linux mainline kernel with the latest Yocto / Poky master branch. We also use our own custom layer & image that includes our miscellaneous daemons, scripts, and customized packages targeted at securing & monitoring a local network.

This is an older system, but it has great network performance and several Gigabit Ethernet ports since it's one of NXP's PowerPC-based network processors (QorIQ family). Also, we have a hardware debugger for it and can use NXP's Codewarrior debugger on it, so we love having it in our lab.

We typically build and test the latest release candidate (rc) of the Linux kernel independently before updating our Yocto recipe for the kernel. We're fortunate that this system and the T1040's PowerPC64 E5500 processor are supported without patching in the 5.0 Linux kernel. This is a big plus and a good reason to use older hardware for development and testing since all the drivers have already been reviewed and upstreamed.

Note that the Poky meta-freescale repo no longer carries a machine conf file for the T1040RDB, but it's easy enough to create one from a similar system, and we maintain t1040rdb-64b.conf and defconfig files in our own custom layer. Also, corenet64_fmanv3l_smp_defconfig provided our starting point for our defconfig.

The steps shown below assume that the embedded system can be booted with at least a minimal Linux image with NFS support to mount a drive from the build machine that produced the Yocto rootfs image.

Partitioning our SSD

We're using a 64G Micron M550 SSD on the T1040RDB. We divide our development disk into 4 partitions as shown below.

# fdisk -l /dev/sda ... Device Boot Start End Sectors Size Id Type /dev/sda1 2048 4196351 4194304 2G 83 Linux /dev/sda2 4196352 41945087 37748736 18G 83 Linux /dev/sda3 41945088 79693823 37748736 18G 83 Linux /dev/sda4 79693824 125045423 45351600 21.6G 83 Linux

We alternate between /dev/sda2 and /dev/sda3 as our current root filesystem, so we always have a known good backup. We mount /dev/sda4 as /build for building applications natively and storing databases that need to be persistent between updates of our root filesystem. We keep /dev/sda1 reserved for other images (i.e., NXP's SDK-built image). /build is mounted automatically each time by a custom init script that we add to our rootfs by appending the initscripts recipe:

initscripts_1.%.bbappend:

FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:" SRC_URI += "file://mntbuild.sh" do_install_append() { install -m 0755 ${WORKDIR}/mntbuild.sh ${D}${sysconfdir}/init.d update-rc.d -r ${D} mntbuild.sh start 70 2 3 4 5 . }

mntbuild.sh:

#!/bin/sh mkdir -p /build mount /dev/sda4 /build

Yes, we're still using sysvinit for this system / image. Yocto supports both sysvinit and systemd.

Make the disk

Determine which partitions are already mounted:

# mount /dev/sda3 on / type ext3 (rw,relatime) devtmpfs on /dev type devtmpfs (rw,relatime,size=1998340k,nr_inodes=499585,mode=755) proc on /proc type proc (rw,relatime) sysfs on /sys type sysfs (rw,relatime) debugfs on /sys/kernel/debug type debugfs (rw,relatime) tmpfs on /run type tmpfs (rw,nosuid,nodev,mode=755) tmpfs on /var/volatile type tmpfs (rw,relatime) /dev/sda4 on /run/media/sda4 type ext2 (rw,relatime,errors=continue) /dev/sda1 on /run/media/sda1 type ext2 (rw,relatime,errors=continue) /dev/sda2 on /run/media/sda2 type ext3 (rw,relatime) ...

We can see that our rootfs is currently located on /dev/sda3, so we'll use /dev/sda2 for our new rootfs. Unmount the /dev/sda2 partition and create a new file system (with journalling) on the partition.

# umount /dev/sda2 # mke2fs -j /dev/sda2

Mount the new partition to /mnt/disk so we can copy our rootfs onto it.

# mkdir -p /mnt/disk # mount /dev/sda2 /mnt/disk # ls -l /mnt/disk total 16 drwx------ 2 root root 16384 Mar 9 13:00 lost+found

Copy Yocto-built file system (rootfs) to drive:

We utilize NFS from our T1040RDB Linux system to mount our build machine's folder where our Yocto-built rootfs resides. Provided below is an excerpt of our mount script that mounts the /build directory to our embedded system's /mnt/build path. In the script, $1 is the build machine's (PC) host name

mnt_build_machine.sh

#!/bin/sh ... if ! echo `mount` | grep "/mnt/build" >> /dev/null; then mkdir -p /mnt/build mount -o vers=3 -o nolock $1:/build /mnt/build fi

From the T1040RDB's shell, cd to the PC image's rootfs folder and copy the rootfs. BTW, we configure our embedded system's prompt as export PS1='\u@:\W\$ '. Also note below that we leave a token using touch in our rootfs to help us later match up the target disk with where and when it was built.

# cd /mnt/build/<bsp location/image/release/>rootfs rootfs# ls bin boot dev etc home lib media mnt proc run sbin sys tmp usr var rootfs# touch t1040rdb_<date> rootfs# cp -r * /mnt/disk/ rootfs# cd /mnt/disk disk# ls bin boot dev etc home lib lost+found media mnt t1040_030919 proc run sbin sys tmp usr var

Create u-boot boot script and launch system

Returning to our build machine, we create / update our u-boot script that is used to boot our system from the u-boot shell. Copy both the generated Linux uImage file and dtb file to our tftp server location:

$ cp /build/<path>/tmp-glibc/deploy/images/t1040rdb-64b/uImage /build/tftp/t1040/ $ cp /build/<path>/tmp-glibc/deploy/images/t1040rdb-64b/t1040rdb.dtb /build/tftp/t1040/

Create the u-boot script: "boot.txt"

setenv bootargs root=/dev/sda2 rw console=ttyS0,115200 loglevel=8 tftp 0x2000000 t1040/uImage-5.0 tftp 0x1000000 t1040/t1040rdb.dtb bootm 0x2000000 - 0x1000000

Make the u-boot image:

$ mkimage -T script -C none -n "uboot script" -d boot.txt boot.img

The last steps are to reboot our embedded system, download the u-boot script, and then source it.

# reboot .... => tftp t1040/boot.img Load address: 0x1000000 Loading: # 38.1 KiB/s done Bytes transferred = 239 (ef hex) => source 0x1000000 .... OpenEmbedded nodistro.0 t1040rdb-64b ttyS0 t1040rdb-64b login: root root@:~# uname -a Linux t1040rdb-64b 5.0.0-yocto-standard #21 SMP Sat Mar 9 12:05:54 EST 2019 ppc64 ppc64 ppc64 GNU/Linux # python3 --version Python 3.7.2 # nft -v nftables v0.9.0 (Fearless Fosdick)