Firmware Upgrades

This page describe how to upgrade firmware on a board.

Getting Started

Why Git-Annex?

Plain git repositories are not appropriate for distributing binaries (e.g. FPGA bitstreams, parser binaries, et cetera).

A git checkout contains the tree’s entire history, including all revisions, even for files that have been deleted. So, a git tree containing even a small number of revisions of small binary files can become huge. For example, the DANFirmwareReleases wiki page (which we used to distribute DAN firmware) has a 3.5 GB total size.

Instead, we use git-annex to distribute and revision-control binaries. This tool checks in metadata associated with a large binary, and embeds a list of places the file can actually be found. In practice, we place these large files in an Amazon AWS bucket.

Initializing git-annex for the first time

To get started with git-annex in this repository, type the following:

$ export AWS_ACCESS_KEY_ID=AKIAJEZIY2BA3HPBJBWQ
$ export AWS_SECRET_ACCESS_KEY=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
$ git annex enableremote cloud

You will then be able to see binaries as broken symlinks.

If enableremote is not an option you may have an outdated version of git-annex installed.

If you see the following error:

$ git annex enableremote cloud
Enter passphrase for key '/home/dfmuxuser/.ssh/id_rsa':
Failed to get annex.uuid configuration of repository origin
Instead, got: "logged in as dfmuxuser\n\nYou can use git or hg to connect to Bitbucket. Shell access is disabled\n"
This is unexpected; please check the network transport!
enableremote cloud (checking bucket...) ok
(Recording state in git...)

It doesn’t actually prevent you from successfully git-annex getting files, but can be solved in the following way:

$ git config remote.origin.annex-ignore true

(from https://git-annex.branchable.com/forum/git-annex-sync_with_bitbucket/)

The pydfmux/firmware/ directory

The firmware directory contains tools to obtain firmware release files and build flash images from them.

In this directory, you will find:

  • date directories, each containing portions of a firmware release. This approach has been phased out in favour of
  • release directories (with names like r10.0 or r10.0_128x), containing the necessary ingredients for a complete and named release,
  • the “image.sh” script, which transforms the contents of an experiment directory into a full flash image, and
  • the “netboot_image.sh” script, which creates a .tar.bz2 archive suitable for use in an NFS-root (netboot) environment.

Note that the binaries themselves are versioned using git-annex, so you may have to use ‘git annex get [...]’ to actually retrieve materials.

Note that some of the steps below (specifically, Building a Flash Image) are Linux-only.

Downloading Files

To retrieve a firmware release, you can run:

pydfmux/firmware$ ./fetch.sh r10.0

The files pointed to by symlinks in latest will be downloaded from cloud storage.

Upgrading Firmware

The following flowchart shows how to upgrade firmware.

digraph { node [ shape=box,style=filled,fillcolor=gray90 ]; start -> boot_method; start[shape=box, style="rounded,filled", label="Start"]; boot_method[shape=diamond, label="How will your\nboard(s) boot?"]; flash[shape=box, label="Image a Flash Card"]; done[shape=box, style="rounded,filled", label="Done"]; boot_method -> flash [label="SD Card"]; flash -> done; spi_flash_upgrade[shape=box, label="Upgrade SPI flash\n(if required; unlikely)"]; u_boot_upgrade[shape=box, label="Upgrade U-Boot &\nKernel Image"]; nfs_root_upgrade[shape=box, label="Upgrade NFS Filesystem"]; boot_method -> spi_flash_upgrade [label="Netboot"]; spi_flash_upgrade -> u_boot_upgrade; u_boot_upgrade -> nfs_root_upgrade; nfs_root_upgrade -> done; {rank=same; flash u_boot_upgrade} }

Firmware Upgrade Flowchart

Netboot Instructions

This section describes how to upgrade a netboot installation. For details on netbooting (and information on setting it up for the first time), please see Netbooting.

Upgrade the SPI Flash

Important

This step is rarely required. While it’s hard to “brick” an IceBoard following these steps, the SPI flash has a limited number of write cycles and failures are harder to debug. Please only do this if you’re sure it’s needed.

For netboot installations, the first-stage bootloader (a stripped-down version of u-boot) is present in soldered-on SPI flash. This section describes how to upgrade this flash image.

  1. If your boards are accessible, verify that their DIP switches are set as follows:

    SW1.M0:on
    SW1.M1:on
    SW1.M2:on
    SW1.M3:off
    SW1.M4:on

    These settings prioritize MMC first (if a card is present), SPI flash second, and other methods (all irrelevant) after that.

  2. Boot your board into Linux. Since this is generally the first step in a firmware upgrade, you will be running your “old” firmware. Copy the SPI flash image to the board you wish to upgrade:

$ scp /path/to/u-boot.min.spieth.spi root@iceboard0309.local:/tmp
  1. Using md5sum, ensure the image is valid and complete. This md5sum should match the version you retrieved from git-annex (if you are unsure, you can always ask Graeme Smecher to confirm.)

    $ ssh root@iceboard0309.local md5sum /tmp/u-boot.min.spieth.spi
    
  2. Overwrite the SPI flash with the new image.

    $ ssh root@iceboard0309.local /usr/sbin/flashcp /tmp/u-boot.min.spieth.spi /dev/mtd0
    

You may now reboot the board. Because this stage is generally independent of the rest of the firmware upgrade, you may wish to ensure it reboots successfully before proceeding with the rest of your upgrade. (If something does not work, an early reboot will give us a better idea of where to start debugging.)

Upgrade U-Boot & Kernel Image

Copy the u-boot.bin and uImage files to /srv, or wherever your TFTP server is configured to serve files. (See Netbooting for hints on where to look.)

Upgrade NFS Filesystem

  1. Generate a tarball that combines the root filesystem and specified OPK packages. (This step does not require sudo access.)

    $ cd /path/to/pydfmux/firmware
    $ ./netboot_image.sh -o r10.0_128x.tar.bz2 -d r10.0_128x
    
  2. Unpack this image into your NFS root directory.

    $ cd /srv/iceboard
    $ sudo tar xjvf /path/to/pydfmux/firmware/r10.0_128x.tar.bz2
    

Image a Flash Card

Caution

Run this step with care. Re-imaging an SD card is dangerously close to re-imaging your hard drive, and Linux will happily do the latter if you are not very careful about device files.

Beginning with release r10.0, we have been shipping complete filesystem images rather than just the ingredients needed to make them. As a result, it is simpler to re-flash a SD card than it used to be.

You can directly image a flash card as follows:

  1. Identify (AND VERIFY) the device file associated with your SD slot. In this example, we’ll use /dev/mmcblk0. Often, the device file is named “/dev/sdb” or similar (PROBABLY JUST LIKE YOUR HARD DRIVE)

  2. Insert the victim SD card into your reader. Give it a few seconds to be recognized, and ensure the device is unmounted (but not ejected). For example:

    $ sudo umount /dev/mmcblk0p*
    
  3. Ensure you have retrieved the entire release using the fetch.sh script.

    $ cd /path/to/pydfmux/firmware
    $ ./fetch.sh r10.0_128x
    
  1. Clobber the entire SD card. You will lose everything on it (or whatever device you pointed to instead, by accident!):

    $ bzcat r10.0_128x/dfmux_release_10.0.img.bz2 | sudo dd bs=10M of=/dev/mmcblk0
    
  2. Eject the device. (This may or may not work, but important for some drivers!):

    $ sudo eject /dev/mmcblk0
    

Building an Image File

Note

These steps are only required if you want to create a flash image file from the other ingredients distributed with the bitstream. You probably don’t need to do this.

The script only works on a Linux host. Begin by installing the following Debian/Ubuntu packages:

$ sudo apt-get install libssl-dev libgpgme11-dev u-boot-tools libarchive-dev
$ sudo apt-get install git-annex realpath autoconf libtool libtool-bin libcurl4-openssl-dev
$ sudo apt-get install util-linux pkg-config

Now, we install opkg:

$ git clone git://git.yoctoproject.org/opkg
$ cd opkg
$ ./autogen.sh
$ ./configure --enable-shared=no --disable-gpg
$ make
$ sudo make install

Now, you may use the ‘image.sh’ script to build a flash image that can be written to a flash card. again, using the ‘mcgill’ experiment directory as an example, run:

pydfmux/firmware$ ./image.sh -d latest -o my_new_firmware.img