Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

Note

Note – Take your time while identifying where your designated SD-Card is mapped on your linux system. Failure to do so can result in overwriting an arbitrary disk on your system!

Booting from USB (OTG)

An unfused i.MX6 SoM will fall back to booting from USB when it has not found any bootable code on the attached storage. Therefore it can be used to deploy software to a new system. Since the HummingBoard 2 there are also boot select jumpers that allow explicitly selecting USB as the boot source. The particulars can be found HummingBoard Edge/Gate Boot Jumpers .

Identify the OTG port

To quote our developer Jon: “it is the top port next to the Ethernet jack” More formally it is the top port on the U5 header. This holds true of all our i.MX6 based boards.

Build an OTG cable

Essentially a straight Male to Male USB-A cable would accomplish the task. However it is highly recommended to build a custom cable with a large resistor on the VCC line to protect both your PC and your board from destruction. For this task some skills in electrical engineering are required! Hint: Both the voltage, and the maximum allowed current are defined by the USB standard.

imx_usb_loader

This application implements the Serial Download Protocol that the i.MX6 Boot-ROM uses to communicate. It is available on the github account of boundarydevices. Download and compile:

The final binary is called imx_usb and can be executed in place.

load SPL

sudo ./imx_usb ../u-boot_imx6/SPL

On success, SPL should announce itself on the serial console:

Code Block
U-Boot SPL 2018.01-00024-g457cdd60c3 (Aug 07 2018 - 21:16:13)
Trying to boot from USB SDP
SDP: initialize...
SDP: handle requests...

load U-Boot

Code Block
sudo ./imx_usb ../u-boot_imx6/u-boot.img

...

SATA

This section assumes that you have a device running linux, and the target sata drive attached to it. This can be any device! Optionally create an MBR partition table, and any partitions you may want.

The Boot-ROM searches for the SPL after the first 1024 bytes. The SPL then looks for the full u-boot binary at 69k. The dd command can be used for writing SPL and u-boot to these locations on your sata drive. Substitute sdX by the device node of your sata drive.

Code Block
dd if=SPL of=/dev/sdX bs=1k seek=1 conv=sync
dd if=u-boot.img of=/dev/sdX bs=1k seek=69 conv=sync
Note

Note – Take your time while identifying where your designated SD-Card is mapped on your linux system. Failure to do so can result in overwriting an arbitrary disk on your system!

Booting from USB (OTG)

An unfused i.MX6 SoM will fall back to booting from USB when it has not found any bootable code on the attached storage. Therefore it can be used to deploy software to a new system. Since the HummingBoard 2 there are also boot select jumpers that allow explicitly selecting USB as the boot source. The particulars can be found HummingBoard Edge/Gate Boot Jumpers .

Identify the OTG port

To quote our developer Jon: “it is the top port next to the Ethernet jack” More formally it is the top port on the U5 header. This holds true of all our i.MX6 based boards.

Build an OTG cable

Essentially a straight Male to Male USB-A cable would accomplish the task. However it is highly recommended to build a custom cable with a large resistor on the VCC line to protect both your PC and your board from destruction. For this task some skills in electrical engineering are required! Hint: Both the voltage, and the maximum allowed current are defined by the USB standard.

imx_usb_loader

This application implements the Serial Download Protocol that the i.MX6 Boot-ROM uses to communicate. It is available on the github account of boundarydevices. Download and compile:

The final binary is called imx_usb and can be executed in place.

load SPL

sudo ./imx_usb ../u-boot_imx6/SPL

On success, SPL should announce itself on the serial console:

Code Block
DownloadingU-Boot file of size 329312 to 0x177fffc0... done
Jumping to header at 0x177fffc0
Header Tag is not an IMX image


U-Boot 2018.01-00024-g457cdd60c3 (Aug 07 2018 - 21:16:13 +0200)

CPU:   Freescale i.MX6Q rev1.5 996 MHz (running at 792 MHz)
CPU:   Extended Commercial temperature grade (-20C to 105C) at 41C
Reset cause: POR
Board: MX6 HummingBoard2 (som rev 1.5)
       SPL 2018.01-00024-g457cdd60c3 (Aug 07 2018 - 21:16:13)
Trying to boot from USB SDP
SDP: initialize...
SDP: handle requests...

load U-Boot

Code Block
sudo ./imx_usb ../u-boot_imx6/u-boot.img

On success, U-Boot should announce itself on the serial console:

Code Block
Downloading file of size 329312 to 0x177fffc0... done
Jumping to header at 0x177fffc0
Header Tag is not an IMX image


U-Boot 2018.01-00024-g457cdd60c3 (Aug 07 2018 - 21:16:13 +0200)

CPU:   Freescale i.MX6Q rev1.5 996 MHz (running at 792 MHz)
CPU:   Extended Commercial temperature grade (-20C to 105C) at 41C
Reset cause: POR
Board: MX6 HummingBoard2 (som rev 1.5)
       Watchdog enabled
DRAM:  2 GiB
MMC:   FSL_SDHC: 0, FSL_SDHC: 1
No panel detected: default to HDMI
Display: HDMI (1024x768)
In:    serial
Out:   serial
Err:   serial
Net:   FEC
Hit any key to stop autoboot:  0

...

There are actually three methods for installing the U-Boot binaries:

  1. usb mass storage mode: The board presents itself as a usb drive to the host PC

  2. DFU: The board listens for the DFU protocol on USB

  3. the hard way: load and write files by hand using u-boot commands

We highly recommend using methods 1 or 2 as they are much easier to understand than the third!

...

Code Block
Copying data from PC to DFU device
Download        [=========================] 100%        52224 bytes
Download done.
state(7) = dfuMANIFEST, status(0) = No error condition is present
state(2) = dfuIDLE, status(0) = No error condition is present
Done!The Hard Way:

...

Using U-Boot console and USB Flash Drive:

If Linux is already running on the device, the procedure is identical to microSD. In this case the previous section can be used, where sdX is replaced with mmcblk1.

However it is more likely that neither Linux nor even U-Boot are available at this point. Refer to section i.MX6 U-Boot  how to load u-boot to RAM.

...

Code Block
# select eMMC (mmc1)
mmc dev 1 0

usb start
# expected output: 1 Storage Device(s) found

load usb 0:1 ${kernel_addr_r} SPLspl-imx6-emmc
# expected output: 52224 bytes read in 24 ms (2.1 MiB/s)
mmc write ${kernel_addr_r} 0x2 0x66
# expected output: MMC write: dev # 1, block # 2, count 102 ... 102 blocks written: OK

load usb 0:1 ${kernel_addr_r} u-boot.img
# expected output: 329312 bytes read in 38 ms (8.3 MiB/s)
mmc write ${kernel_addr_r} 0x8A 0x284
# expected output: MMC write: dev # 1, block # 138, count 644 ... 644 blocks written: OK

There are many magic numbers in this short script that require attention!:

  • mmc dev 1: 0 is microSD, 1 is eMMC

  • mmc write ${kernel_addr_r} 0x2 0x66:

    • 0x2 = destination block number in hexadecimal. Here one block is 512 bytes –> SPL goes to block 2 (1024 bytes)

    • 0x66: The size of SPL in blocks in hexadecimal. This is the ceiling of filesize divided by 512, in this example 52224 / 512 = 102 = 0x66

  • mmc write ${kernel_addr_r} 0x8A 0x284

    • 0x8A: SPL is expected at 69kB –> 138 = 0x8A

    • 0x284: ceil(329312 / 512) = ceil(643,1875) = 644 = 0x284

Note

It is highly recommended to write U-Boot from either Linux, or over the USB OTG port with DFU, which are both easier to use!

Boot Process after U-Boot has loaded

The way U-Boot searches for an operating system to load has recently undergone substantial changes towards a standard behaviour across all devices. This new standard is called distro support, and fully supported by our 2018.01 release. It automatically searches all attached storage for bootable files such as boot scripts, extlinux configuration or EFI applications. For documentation please refer to the official U-Boot documentation.

Loading Linux By Hand:

The manual way for loading Linux from U-Boot is very straight forward:

Code Block
1. load the DeviceTree Binary
2. load the kernel image
3. load the initramfs (optional)
4. set boot commandline options
5. execute

Here is a sample for loading a kernel from microSD:

Code Block
load mmc 0:1 ${fdt_addr_r}
load mmc 0:1 ${kernel_addr_r}
 # 1, block # 2, count 102 ... 102 blocks written: OK

load usb 0:1 ${kernel_addr_r} u-boot-imx6-emmc.img
# expected output: 329312 bytes read in 38 ms (8.3 MiB/s)
mmc write ${kernel_addr_r} 0x8A 0x284
# expected output: MMC write: dev # 1, block # 138, count 644 ... 644 blocks written: OK

# select eMMC boot partition
mmc partconf 1 0 7 0

There are many magic numbers in this short script that require attention!:

  • mmc dev x y:

    • x = 0 is microSD, x = 1 is eMMC

    • y = 0 is eMMC main (data) partition

    • y = 1 is eMMC hardware boot0 partition, y = 2 is eMMC hardware boot1 partition

  • mmc write ${kernel_addr_r} 0x2 0x66:

    • 0x2 = destination block number in hexadecimal. Here one block is 512 bytes –> SPL goes to block 2 (1024 bytes)

    • 0x66: The size of SPL in blocks in hexadecimal. This is the ceiling of filesize divided by 512, in this example 52224 / 512 = 102 = 0x66

  • mmc write ${kernel_addr_r} 0x8A 0x284

    • 0x8A: SPL is expected at 69kB –> 138 = 0x8A

    • 0x284: ceil(329312 / 512) = ceil(643,1875) = 644 = 0x284

  • mmc partconf x a y b:

    • x = 0 is microSD, x = 1 is eMMC

    • a = 0 is disable acknowledge to boot-rom

    • y = 7 is eMMC main (data) partition

    • y = 1 is eMMC hardware boot0 partition, y = 2 is eMMC hardware boot1 partition

    • y = 0 is disable eMMC boot

    • b is partition access enable, values same as y: 0, 1, 2, 7

Note

It is highly recommended to write U-Boot from either Linux, or over the USB OTG port with DFU, which are both easier to use!

Boot Process after U-Boot has loaded

The way U-Boot searches for an operating system to load has recently undergone substantial changes towards a standard behaviour across all devices. This new standard is called distro support, and fully supported by our 2018.01 release. It automatically searches all attached storage for bootable files such as boot scripts, extlinux configuration or EFI applications. For documentation please refer to the official U-Boot documentation.

Loading Linux By Hand:

The manual way for loading Linux from U-Boot is very straight forward:

Code Block
1. load the DeviceTree Binary
2. load the kernel image
3. load the initramfs (optional)
4. set boot commandline options
5. execute

Here is a sample for loading a kernel from microSD:

Code Block
load mmc 0:1 ${fdt_addr_r}
load mmc 0:1 ${kernel_addr_r}
load mmc 0:1 ${ramdisk_addr_r}
setenv bootargs console=ttymxc0,115200n8 root=/dev/mmcblk0p1 rootfstype=auto rootwait
bootz ${kernel_addr_r} ${ramdisk_addr_r}:${filesize} ${fdt_addr_r}

Transitioning from 2013.04 and earlier

We have developed a transitional boot-script that simulates the old behaviour to allow booting old system images that have not adopted support for distro boot: i.MX6 Legacy Boot-Script


Download:

Code Block
wget https://github.com/SolidRun/u-boot/releases/download/v2013.01-imx6-sr-transition/legacyboot.scr

This boot-script should be placed at a well-defined location that u-boot can read from, under a name that does *not* equal boot.scr. We suggest calling it legacyboot.scr. Then the bootcmd environment variable has to be configured to force always running this script unconditionally. Here is a sample for when legacyboot.scr lives on the first partition on microSD:

Code Block
setenv bootcmd 'load mmc 0:1 ${ramdisk_addr_r}
setenv bootargs console=ttymxc0,115200n8 root=/dev/mmcblk0p1 rootfstype=auto rootwait
bootz ${kernel_addr_r} ${ramdisk_addr_r}:${filesize} ${fdt_addr_r}

Transitioning from 2013.04 and earlier

We have developed a transitional boot-script that simulates the old behaviour to allow booting old system images that have not adopted support for distro boot: i.MX6 Legacy Boot-Script

...

Code Block
wgetscriptaddr} legacyboot.scr; source ${scriptaddr}'
saveenv

Note

This legacy script hasn’t been thoroughly tested. There may be bugs and unexpected behaviour!

Compiling from source

This section assumes that you have git, make and a cross-compiler targeting 32-bit arm available on your system!

These are the instructions to fetch the code, and build a binary:

Code Block
git clone --branch v2018.01-solidrun-imx6 https://github.com/SolidRun/u-boot/releases/download/v2013.01-imx6-sr-transition/legacyboot.scr

This boot-script should be placed at a well-defined location that u-boot can read from, under a name that does *not* equal boot.scr. We suggest calling it legacyboot.scr. Then the bootcmd environment variable has to be configured to force always running this script unconditionally. Here is a sample for when legacyboot.scr lives on the first partition on microSD:

Code Block
setenv bootcmd 'load mmc 0:1 ${scriptaddr} legacyboot.scr; source ${scriptaddr}'
saveenv

Note

This legacy script hasn’t been thoroughly tested. There may be bugs and unexpected behaviour!

Compiling from source

This section assumes that you have git, make and a cross-compiler targeting 32-bit arm available on your system!

These are the instructions to fetch the code, and build a binary:

Code Block
git clone --branch v2018.01-solidrun-imx6 https://github.com/SolidRun/u-boot.git u-boot-imx6
cd u-boot-imx6
export CROSS_COMPILE=<Set toolchain prefix to your toolchain>
# optionally add options to configs/mx6cuboxi_defconfig
make mx6cuboxi_defconfig
# optionally configure u-boot graphically
# make menuconfig
make

This will generate SPL and u-boot.img to be used when booting from eMMC. To target other boot media, set one of the following options in configs/mx6cuboxi_defconfig or through menuconfig:

  • eMMC (default)

Code Block
CONFIG_SPL_BOOT_DEVICE_MMC=y
  • SD-Card

Code Block
CONFIG_SPL_BOOT_DEVICE_SDHC=y
  • mSATA SSD

Code Block
CONFIG_SPL_BOOT_DEVICE_SATAboot.git u-boot-imx6
cd u-boot-imx6
export CROSS_COMPILE=<Set toolchain prefix to your toolchain>
# optionally add options to configs/mx6cuboxi_defconfig
make mx6cuboxi_defconfig
# optionally configure u-boot graphically
# make menuconfig
make

This will generate SPL and u-boot.img to be used when booting from eMMC. To target other boot media, set one of the following options in configs/mx6cuboxi_defconfig or through menuconfig:

  • eMMC data partition (default)

    Code Block
    CONFIG_SPL_BOOT_DEVICE_MMC=y
  • eMMC boot0 partition

    Code Block
    CONFIG_SYS_MMC_ENV_PART=1
  • eMMC boot1 partition

    Code Block
    CONFIG_SYS_MMC_ENV_PART=2
  • SD-Card

    Code Block
    CONFIG_SPL_BOOT_DEVICE_SDHC=y
  • mSATA SSD

    Code Block
    CONFIG_SPL_BOOT_DEVICE_SATA=y
    CONFIG_SCSI_AHCI=y
    CONFIG_SPL_SATA_RAW_U_BOOT_USE_SECTOR=y
    CONFIG_SPL_SATA_RAW_U_BOOT_SECTOR=0x8a
    CONFIG_ENV_IS_NOWHERE=y
  • SPI

    Code Block
    CONFIG_SPL_BOOT_DEVICE_SPI_FLASH=y

Note: The resulting binaries are SPL and u-boot.img.

eMMC Tips

Size matters: The production line burns the image to emmc. the process runs at 5.6 MB/sec, which means that burning 8GB image of which 80% is free space is very wasteful. The best way to optimize for production is to create a single partition (as small as possible to contain all the data), and a “firstboot” script that will complete the image creation.

...

  • resize the rootfs partition

  • resize the rootfs filesystem

  • create and format the 2nd and 3rd partitions

  • extract the archives from /boot into the relevant partitions

  • delete the archives from /boot

  • disable itself from systemd

...

  • calculate the smallest image size that will contain your data

    • run

    “du
    • du -s -B M /path/to/your/

    rootfs”
    • rootfs to get the size of your data in megabytes

    • add 10%

    • partition size is at least 1MB smaller than the drive.

...

    • create an image file with a single ext4 partition: and with the bootloader

    • dd if=/dev/zero of=/path/to/vivi.img bs=1M count=$SIZE_MB

    • losetup /dev/loop0 /path/to/vivi.img

    • dd if=path/to/u-boot-imx6/SPL of=/dev/loop0 bs=1k seek=1 oflag=sync

    • dd if=path/to/u-boot-imx6/u-boot.img of=/dev/loop0 bs=1k seek=42 oflag=sync

    • Code Block
      sfdisk -f -uB /dev/loop0 «EOF
    • 
      1024,${PARTSIZE}
    • 
      EOF
    • sync

    • losetup -d /dev/loop0

...

  • populate the single partition with the rootfs, the archives of the other partitions, and the firstboot script

    • losetup -o 1048576 /dev/loop0 /path/to/vivi.img # load the partition and not the entire disk image

    • mkfs -t ext4 /dev/loop0

    • mount /dev/loop0 /mnt

    • do populate

    • add the firstboot script: systemd firstboot script - Google Search

    • umount /dev/loop0

    • losetup -d /dev/loop0

Further reading

  • Booting from network/PXE