Install Embedded Linux Built with Yocto Project

Summary of steps used to install and boot embedded Linux image on an SSD. Image was built with Yocto Project using mainline Linux kernel and custom image.

advertisement

Overview

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

These steps assume that our system can be booted with at least a minimal Linux image with NFS support. If you don't have this, then you'll need to boot with a RAM image or via NFS. Neither of these are currently covered in this article, but we'll try to add these steps at a later date (if requested).

Partition the SSD

We're using a 120 G SandDisk SSD ( model SDSSDA-120). We divide our development disks into 4 partitions using a running Linux system ( not necessarily the target) as shown below.

# fdisk -l /dev/sda
Disk /dev/sda: 111.8 GiB, 120034123776 bytes, 234441648 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0xfb036974

Device     Boot     Start       End  Sectors  Size Id Type
/dev/sda1            2048  52430847 52428800   25G 83 Linux
/dev/sda2        52430848 104859647 52428800   25G 83 Linux
/dev/sda3       104859648 157288447 52428800   25G 83 Linux
/dev/sda4       157288448 234441647 77153200 36.8G 83 Linux

We alternate between /dev/sda2 and /dev/sda3 as our current root filesystem. We mount /dev/sda4 as /build for building applications and storing databases that need to be persistent between updates of our root filesystem. We keep /dev/sda1 reserved for other images x(i.e., NXP's SDK-built image) or swap. /build is mounted automatically each time in 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

Make the disk

Determine which partitions are already mounted:

# mount

/dev/sda3 on / type ext3 (rw,relatime,data=ordered)
devtmpfs on /dev type devtmpfs (rw,relatime,size=482104k,nr_inodes=120526,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)
devpts on /dev/pts type devpts (rw,relatime,gid=5,mode=620,ptmxmode=000)
/dev/sda2 on /run/media/sda2 type ext2 (rw,relatime,errors=continue)
/dev/sda1 on /run/media/sda1 type ext2 (rw,relatime,errors=continue)
/dev/sda4 on /run/media/sda4 type ext2 (rw,relatime,errors=continue)
/dev/sda4 on /build type ext2 (rw,relatime,errors=continue)
...

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

mke2fs 1.43.4 (31-Jan-2017)
/dev/sda2 contains a ext2 file system
	last mounted on / on Wed Dec 31 19:00:01 1969
Proceed anyway? (y,N) y
Discarding device blocks: done                            
Creating filesystem with 6553600 4k blocks and 1638400 inodes
Filesystem UUID: 0d8f85f9-ce9c-4a83-9b71-85d999d2e036
Superblock backups stored on blocks: 
	32768, 98304, 163840, 229376, 294912, 819200, 884736, 1605632, 2654208, 
	4096000

Allocating group tables: done                            
Writing inode tables: done                            
Creating journal (32768 blocks): done
Writing superblocks and filesystem accounting information: done  

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

# mkdir -p /mnt/disk

# mount /dev/sda2 /mnt/disk

EXT4-fs (sda2): mounting ext3 file system using the ext4 subsystem
EXT4-fs (sda2): mounted filesystem with ordered data mode. Opts: (null)


# ls -l /mnt/disk

total 16
drwx------ 2 root root 16384 Apr  6 09:46 lost+found

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

We use NFS from our currently running embedded Linux system to mount our build machine's drive / 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 embedded Linux shell, change directory 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 p1010rdb-ml-<date>

rootfs# cp -r * /mnt/disk/

rootfs# cd /mnt/disk

disk# ls

bin  boot  dev  etc  home  lib  lost+found  media  mnt  p1010rdb-ml-060117  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/deploy/images/p1010rdb-ml/uImage /build/tftp/p1010rdb-ml/
$ cp /build/<path>/tmp/deploy/images/p1010rdb-ml/uImage-p1010rdb-ml.dtb /build/tftp/p1010rdb-ml/

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

setenv bootargs root=/dev/sda2 rw console=ttyS0,115200 loglevel=8
tftp 0x1000000 p1010rdb-ml/uImage
tftp 0xc00000 p1010rdb-ml/uImage-p1010rdb-ml.dtb
bootm 0x1000000 - 0xc00000

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. BTW, this particular system has the hostname eraser.

# reboot
....

=> tftp p1010rdb-ml/boot.img
eTSEC3 Waiting for PHY auto negotiation to complete...... done
Speed: 1000, full duplex
Using eTSEC3 device
TFTP from server 192.168.3.36; our IP address is 192.168.3.200
Filename 'p1010rdb-ml/jr/jrd.img'.
Load address: 0x1000000
Loading: #
	 1000 Bytes/s
done
Bytes transferred = 278 (116 hex)
=> source 0x1000000

....

Poky (Yocto Project Reference Distro) 2.2+snapshot eraser /dev/ttyS0

eraser login: root
root@:~# uname -a
Linux eraser 4.9.0-yocto-standard #1 Thu Apr 6 10:16:10 EDT 2017 ppc ppc ppc GNU/Linux

Help us improve this article by adding your comment or question:

email addresses are neither displayed nor shared