wiki:newport/firmware

Version 17 (modified by Cale Collins, 5 years ago) ( diff )

added section to flash from microSD to eMMC

Updating Newport Firmware / Software

This page is all about updating / flashing firmware / software onto a Newport SBC.

The various components of the 'firmware' on a Newport board which you may want to update from time to time are (lowest level components listed first):

  • GSC firmware
  • BDK components (boot.bin bootstub, board device-tree, init.bin app)
  • Linux device-tree
  • ATF
  • U-Boot bootloader
  • Linux kernel
  • root filesystem

Some of the above components are contained within the embedded FAT12 filesystem and others are placed at offsets within the boot device specified by the Newport 'boot firmware' flash map. Typically you do not want to update the entire boot firmware with a simple dd if=firmware-newport.bin of=/dev/mmcblk0 as this would have the undesired affect of overwriting your U-Boot env and the contents of the embedded FAT12 filesystem that you may not want to alter.

For components which are not contained in the embedded FAT12 fs such as the bootstub, the ATF, and the U-Boot FIP you can update them individually in Linux using dd or in U-Boot using mmc write taking care to place them at the right offset. Note that the BDK provided by Gateworks (modified from the Cavium SDK to support Newport) does not contain any support for redundancy or fallbacks although such features could be implemented in the BDK if you choose. The same can be said for the ARM Trusted Firmware provided by Gateworks (from the Cavium SDK) which loads/verifies/executes the bootloader. The only component that technically can not have a fallback is the bootstub unless you are using trusted boot with flash jump enabled and consider the non-trusted bootstub a backup.

To determine the versions of the various components of the firmware you can use the details stored in the 'version' file on the embedded FAT12 filesystem. These details are created by the Newport BSP Makefile (newport/Makefile) if you need to modify or add to them. The GSC firmware version details can be obtained via the Linux driver sysfs fw_ver and fw_crc properties in '/sys/bus/i2c/devices/0-0020/'.

Pre-Built Firmware

Newport Pre-Built Firmware / Software

Firmware Versioning

You can determine the firmware version of various portions of the firmware by looking for banners on the serial console. For example:

Gateworks Newport SPL (ea21abc Tue Dec 12 23:42:48 UTC 2017)

GSC     : v49 0x832c WDT:disabled board temp:61C
RTC     : 0
Model   : GW6304-B
...
NOTICE:  BL1: v1.3(release):OCTEONTX_SDK_6_2_0_build_26
NOTICE:  BL1: Built : 15:30:07, Dec  4 2017
...
U-Boot 2017.09-rc1-00023-g1fd1415 (Dec 12 2017 - 15:42:30 -0800) for Cavium OcteonTX CN81XX ARM V8 Core
...
[    0.000000] Linux version 4.14.4-00005-g9e5958b (tharvey@tharvey) (gcc version 5.3.0 (Cavium Inc. Version 0.99 build 440)) #141 SMP PREEMPT Fri Dec 15 10:18:19 PST 2017
...
Ubuntu 16.04 LTS xenial-newport ttyAMA0
...
  • The above output shows you:
    • Secondary Program Loader (SPL) is 'ea21abc' built on Tue Dec 12 23:42:48 2017. The git sha of 'ea21abc'.
    • GSC v49 0x832c
    • ATF (ARM Trusted Firmware) is v1.3 built on Dec 4 2017.
    • U-Boot is '2017.09-rc1-00023-g1fd1415' built on Dec 12 2017.
    • Linux version 4.14.4-00005-g9e5958b built on Fri Dec 15 10:18:19 PST 2017
    • Ubuntu 16.04 (aka xenial) OS (use dpkg -l | grep "^ii" to see what packages and versions are installed

If you want more detail on the versions of the various components of the Boot Firmware you can look at the version file created/placed by the Newport BSP Makefile in the FAT12 filesystem. See newport/boot/version for details.

Updating Firmware

This section provides instructions for updating both GSC firmware as well as boot device firmware.

There are two methods for updating firmware:

  • on a live board using Serial Console and Ethernet
  • on removable storage (ie recovery microSD)
  • using a GW16099 JTAG dongle (see below)

The various items that can be updated:

  • GSC Firmware - currently only JTAG updates are supported for Newport - see below
  • Boot Firmware (Everything up to and including the Bootloader)
  • Root Filesystem (Operating System)

JTAG Programming

The Gateworks JTAG adapter (GW16099) is available in the Newport Dev Kit as well as on the Gateworks web store here

All Newport boards have a 10-pin JTAG header which provides:

  • JTAG Programming for embedded emmc flash - see here for instructions
  • Serial Console access via UART0 (/dev/ttyAMA0)

Please Note:

  • Linux software is supported for programming Newport (jtag_usbv4 required). Windows is not supported. (serial console through Windows does work).
  • JTAG Programming of eMMC is available, although it is a slower process, see here
  • JTAG Programming of the GSC firmware is supported by the most recent version of jtag_usbv4 here

Update Firmware via Serial Console and Ethernet

The quickest and easiest way to update your firmware is via Serial Console and Ethernet. You can do this either in the U-Boot bootloader (recommended) or within a Linux OS. If your primary boot device is corrupt, then you can boot via an alternate boot device (ie microSD) - see newport/recovery for details.

Update Firmware via Serial Console and Ethernet from Bootloader

If updating firmware via Bootloader/Serial/Ethernet (recommended for speed) you need to setup a TFTP server to host the files for transfer. Alternatively you could load firmware files from removable storage (microSD, mSATA, or USB for example) however the transfer rate is typically very slow compared to Gigabit Ethernet. For details on setting up a TFTP server see here.

The following instructions assume your board target IP address is 192.168.1.1 and you have a TFTP server at 192.168.1.146. Adjust environment according to your network via 'setenv ipaddr <ipaddr>' and 'setenv serverip <serverip>'.

Note that the dev variable needs to be set to the MMC device you are updating:

  • setenv dev 0 # boot device
  • setenv dev 1 # secondary device
  • use mmc list to see how they are configured

The methods you use to update the firmware depends on what specifically you are trying to update.

Update entire firmware (recommended)

Update the entire device from a Compressed Disk Image. This image includes the ('boot firmware as well as entire OS and kernel):

Complete Compressed Disk Images are available for download here: http://dev.gateworks.com/newport/images/

Gateworks Update Script

This is the easiest.

setenv ipaddr 192.168.1.1 # sets device IP

setenv serverip 192.168.1.146 # sets TFTP LAN server IP

setenv dev 0 # sets MMC device to be flashed 

setenv image xenial-newport.img.gz # or whatever filename is used, with any directories in front of the filename

run update_all

This is what the update_all script does:

update_all=tftpboot ${loadaddr} ${image} && gzwrite mmc ${dev} ${loadaddr} ${filesize}

Troubleshooting:

If you're seeing T's while flashing this indicates a transmit error, check that there is not a firewall present between your TFTP server and the SBC.

GW6200-B> run update_all

lmac0 Waiting for PHY auto negotiation to complete...... done

BGX0:LMAC 0 link up

Using vnic0 device

TFTP from server 192.168.1.1; our IP address is 192.168.1.55

Filename 'bionic-newport.img'.

Load address: 0x2000000

Loading: ###T ###T #T ##T ########T #T ###T ####T ####"

Manual Method

setenv ipaddr 192.168.1.1 # sets device IP

setenv serverip 192.168.1.146 # sets TFTP server IP

setenv dev 0 # sets MMC device to be flashed 

tftpboot ${loadaddr} xenial-newport.img.gz && gzwrite mmc ${dev} ${loadaddr} ${filesize} # will flash xenial-newport.img.gz which resides in the top most directory of the TFTP server  
  • If the image was created using a minimally sized filesystem you will want to resize it after booting to take advantage of the full partition space. For an ext4 root filesystem on the primary MMC device run resize2fs /dev/mmcblk0p2.

Updating just the kernel

Updating the kernel requires you first have a U-Boot FIT Image kernel.itb which can be created from a non-compressed kernel image (arch/arm64/boot/Image) with the U-Boot mkimage application and a FIT Image template (.its) file:

# use the mkits.sh script from the Newport BSP to create an its file that points to your compressed kernel
cp linux/arch/arm64/boot/Image vmlinuz
gzip -f vmlinuz
./newport/mkits.sh -o kernel.its -k vmlinux.gz -C gzip -v "My Kernel"
mkimage -f kernel.its kernel.itb
  • more information can be found on FIT images here
  • Note that ARM64 Linux does not support self-extracting compressed kernels which is why we use a FIT image which allows U-Boot to do the decompression and data verification.

Updating just the kernel.itb (FIT Image) can be done with tftpboot and fatwrite:

# choose device (0 for boot device, 1 for alternate device)
setenv dev 0
# kernel
tftpboot $loadaddr kernel.itb && ext4write mmc $dev:2 $loadaddr /boot/kernel.itb $filesize
# bootscript
tftpboot $loadaddr newport.scr && ext4write mmc $dev:1 $loadaddr /boot/newport.scr $filesize

Updating just the boot firmware

Updating the Boot firmware (everything up to and including the Bootloader): On a Newport booted to the bootloader:

mmc dev 0 # use 'mmc list' to show which device to use for eMMC vs microSD
tftpboot ${loadaddr} firmware-newport.img && mmc write ${loadaddr} 0 8000 # update first 16MB
mmc rescan # re-scan the mmc devices in case the partition table changed

Incorrect or out of date Boot Firmware may result in the analogue to digital conversion or registers being misinterpreted, in example:

GSC     : v51 0x859f WDT:disabled board temp:3276C
RTC     : 0
Model   : GW6300-B
MFGDate : 12-13-2017
Serial  : 757565
DTB     : gw6300.dtb
SoC     : CN8020-850BG676-SCP-P12-G 1024KB 850/500MHz 0xa2 Pass 1.2 
MMC0    : eMMC
MMC1    : not detected
Boot    : eMMC non-trusted 
DRAM    : 1024 MB, 1333 MT/s, DDR4 UDIMM
J9      : PCI
J10     : PCI
J11     : PCI
QLM0    : PCIE_1X1@5000MHz
QLM1    : SGMII_1X1@1250MHz
QLM2    : PCIE_1X1@5000MHz
QLM3    : PCIE_1X1@5000MHz
Serial  : 2x RS232 without flow control
PEM0    : QLM0 Link Timeout
PEM1    : QLM2 Link Timeout
PEM2    : QLM3 Link Timeout
temp    : 32765 - Failed High: 9000
vin     : 7798784 - Failed High: 60000
3p3     : 137088 - Failed High: 3630
5p0     : 84481 - Failed High: 5500
0p9     : 107521 - Failed High: 990
core    : 8782184 - Failed High: 946
1p2     : invalid
2p5     : invalid
1p0     : invalid
1p5     : invalid
1p8     : invalid
anl     : invalid

Update Firmware via Serial Console and microSD from Bootloader

Adapting what we know from updating firmware via serial console and ethernet, if no TFTP server/ethernet is available we can use a similar method to write a compressed disk image from microSD or USB to the eMMC.

For example when booted from eMMC, to flash the eMMC with a compressed disk image stored on an ext4 formatted microSD:

ext4load mmc 1:1 ${loadaddr} bionic-newport.img.gz && gzwrite mmc 0 ${loadaddr} ${filesize} #mmc 1 is microSD, mmc 0 is eMMC

Update Firmware via Serial Console and Ethernet from Linux

If booted to Linux on a board you can also update the kernel and bootscript by updating the files in the boot directory of the root filesystem:

cp kernel.itb /boot
cp newport.scr /boot

You can also easily update the Boot Firmware. First prepare a boot image that contains your desired partition table, boot firmware, kernel, bootscript and U-Boot environment (see example above). Then on a booted Newport:

cd /tmp
wget http://dev.gateworks.com/newport/boot_firmware/firmware-newport.img
dd if=firmware-newport.img of=/dev/mmcblk0
  • Note above we are writing to /dev/mmcblk0 and not a partition
  • Use /dev/mmcblk1 for the secondary MMC device (ie microSD)
  • Note that Newport boards only supports MMC based boot devices
  • Note that this overwrites the partition-table, the U-Boot environment, and the FAT12 filesystem which are things you might have customizations in.

Note that if you want to update the root filesystem itself from within Linux you can only do this by either:

a) updating portions of the live filesystem that are not in use (ie package updates) b) booting to a kernel+ramdisk (ie [wiki:buildroot buildroot) and imaging the disk

Updating GSC firmware

The GSC firmware is updated via the gsc_update application running under Linux as described at on the gsc wiki. While it takes only a few seconds to update there is no recovery for a failed update. Gateworks has ensured that this update is robust but can not survive a power-cut or kernel crash in the middle of the update. Updates to the GSC firmware are expected to be rare.

Update GSC Firmware via JTAG

To update the GSC firmware via JTAG download the jtag_usbv4 application on a Linux x86 host from here and execute as follows:

./jtag_usbv4 -m gsc_630x_v49.txt

Note that the ftdi_sio kernel module must not be loaded (sudo rmmod ftdi_sio) and you may need to run this command as root by pre-pending a sudo depending on the configuration of your linux host.

For more details please see:

Updating BDK components

The BDK is the 'secondary program loader' that the CN80xx BOOT ROM loads/validates/executes. It consists of several components or stages:

  • bootstub: The first 192KB at the fixed FLASH offset of 0x20000 (non-trusted) and 0x50000 (trusted) is the contents of the 'boot.bin' bootstub (bdk/apps/boot/boot.bin). The bootstub is responsible for very early init including identifying the board, loading the board.dtb from the FAT12 filesystem and loading/verify/executing the 'init app' (bdk/apps/init/init.bin). Updating the bootstub can be done in Linux using dd or in U-Boot using mmc write but you will also need to update the CVM_CLIB flash headers at 0x10000. For example:
    • extract extract the CVM_CLIB headers, the non-trusted bootstub and the trusted bootstub from firmware-newport.img:
      dd if=firmware-newport.img of=bootstub.bin bs=64K skip=1 count=7 # extract 0x10000 to 0x80000
      
    • write it in Linux:
      dd if=bootstub.bin of=/dev/mmcblk0 bs=64K seek=1 count=7 # program 0x10000 to 0x80000
      
    • If you need to update one bootstub without the other you will need to modify the CVM_CLIB headers using the details specified in the CN80XX HRM and performed by the newport/make-bootfs.py script.
  • board.dtb: The 'board.dtb' file (ie gw6300.dtb*, gw6304.dtb*, etc) is loaded/verified by the bootstub and contains very low level board-specific CN80XX configuration details that are outside of the scope of the Linux kernel device-tree bindings such as QLM configuration and DRAM configuration. Updating the board.dtb can be done by mounting the FAT12 filesystem in Linux (/dev/mmcblk0p1) and replacing the file.
  • init.bin: The 'init app' (bdk/apps/init) is responsible for the majority of the low-level board configuration such as configuring the CN80XX DDR controller, QLM's, BGX's, phy's, and various board-specific GPIO's. When complete it will load/validate the Linux device tree from the FAT12 filesystem, then load/validate/execute the ATF from its fixed offset in FLASH at 0xe00000 (14MiB). Updating the init app can be done by mounting the FAT12 filesystem in Linux (/dev/mmcblk0p1) and replacing the init.bin file.

Updating Linux device-tree

The board specific Linux device-tree (ie gw*-linux.dtb*) is loaded by the BDK 'init app' from the embedded FAT12 fs therefor can be updated by mounting the filesystem in Linux (/dev/mmcblk0p1) and replacing the file.

Updating ARM Trusted Firmware (ATF)

The ARM Trusted Firmware exists from '0x0e00000 - 0x0f00000' (1Mib at 14MiB offset) specified by the 'boot firmware' flash map. It will load/verify/execute U-Boot from its FIP image. The ATF can be updated individually from Linux using dd or U-Boot using mmc write but there is a header around it so you must obtain it from the firmware-newport.img.

For example:

  • extract ATF from firmware-newport.img:
    dd if=firmware-newport.img of=atf.bin bs=1M skip=14 count=1 # extract 1MiB@14MiB)
    
  • write it in Linux:
    dd if=atf.bin of=/dev/mmcblk0 bs=1M seek=14 count=1 # program 1MiB@14MiB
    

Updating U-Boot bootloader

The U-Boot bootloader is wrapped in a ATF FIP package placed at '0x0f00000 - 0x0ff00000' (960KiB at 15MiB offset) and is loaded/verified/executed by the ATF. You can update this taking the 'fip.img' created by the Newport BSP Makefile uboot target and using Linux dd or U-Boot mmc-write.

Examples:

  • build u-boot and update the fip.img within the u-boot directory:
    cd /usr/src/newport/bsp
    . ./setup_environment
    cd u-boot
    make -j8 distclean thunderx_81xx_defconfig u-boot-nodtb.bin && \
     cp ../atf/build/t81/release/fip.bin fip.img && \
     fiptool update --nt-fw u-boot-nodtb.bin fip.img
    
  • write fip.img in Linux:
    dd if=fip.img of=/dev/mmcblk0 bs=1M seek=15 # program at 15MiB offset
    
  • write fip.img in U-Boot:
    tftpboot $loadaddr newport/fip.img && mmc write $loadaddr 0x7800 0x780 # update 960kb at 15mb offset
    

Updating Boot script

The U-Boot boot script exists in the root filesystem and is loaded by the U-Boot 'generic distro' config bootscripts.

Updating Linux kernel

The Linux kernel exists in the root filesystem and is loaded by the bootloader boot scripts. It can be updated by mounting /dev/mmcblk0p2 in Linux and replacing the file. How and from where the kernel is loaded can be changed to your liking in the U-Boot env however the Gateworks U-Boot env uses a bootscript which is scanned for by the U-Boot scripts (look over the U-Boot env to follow the 'distro config' bootscript setup). The Ubuntu bootscript in the Newport BSP (newport/ubuntu.scr) uses a compressed kernel in a FIT image (kernel.itb). If wanted your bootscripts can be altered to provide a redundant/alternate kernel based on some U-Boot env var flags and counters that could be modified in Linux with the fw_setenv/fw_printenv tools from the U-Boot package. These are packaged in the u-boot-tools Ubuntu package and you can see example usages in the Newport BSP newport/Makefile.

Updating root filesystem

Updates on the root filesystem are very use specific. You can use a package manager, or use multiple rootfs partitions on the FLASH selected by U-Boot when setting up the bootargs passed to the kernel. A common way to to this would be to use U-Boot variables as flags and counters that are altered within Linux via the fw_setenv/fw_printenv tools from the U-Boot u-boot-tools package. You can see example usages in the Newport BSP newport/Makefile.

Booting to a kernel/rootfs on the microSD

This assumes the bootloader will remain on the eMMC, but then we switch to the microSD for the kernel/rootfs.

Run the following commands in the uboot bootloader command prompt on the Newport SBC bootloader serial console:

#This sets the bootargs, make special note of the root = and adjust partition as necessary
setenv bootargs 'cma=64M coherent_pool=16M net.ifnames=0 root=/dev/mmcblk1p1 rw rootwait console=ttyAMA0,115200n8 earlycon=pl011,0x87e028000000'

#This loads the kernel file (Image) from folder boot (on microSD) into memory
ext4load mmc 1:1 ${kernel_addr_r} boot/Image

#This boots the board
booti ${kernel_addr_r} - ${fdtcontroladdr}

Troubleshooting:

  • Use the ext4ls to confirm you can read the microSD and see the kernel in the boot folder
    GW6304-B> ext4ls mmc 1:1 boot
    <DIR>       4096 .
    <DIR>       4096 ..
            12066824 Image
    

Creating a microSD recovery image

If your primary boot won't boot for some reason (ie, you corrupted it during development) you can boot from a microSD (see here).

To create a bootable microSD meant for recovery purposes only needing the Bootloader you can use firmware-newport.img:

  • On a Linux host:
    DEVICE=/dev/sdc # set to the microSD on your host
    sudo dd if=firmware-newport.img of=$DEVICE
    
    • Be careful to set the DEVICE above to the device the microSD appears as on your Linux host - you do not want to overwrite part of your hosts filesystem
  • On a Newport board booted from eMMC from U-Boot:
    mmc list # if booted from eMMC you should see microSD as dev 1
    mmc dev 1 # select microSD
    tftpboot ${loadaddr} firmware-newport.img && mmc write ${loadaddr} 0 8000
    
Note: See TracWiki for help on using the wiki.