[[PageOutline]] = Provisioning boards = We refer to the act of duplicating a firmware image across multiple boards as **Provisioning**. The easiest way to provision boards or removable storage devices is to build the particular BSP you are interested in, and use its tools to create a JTAG image suitable for programming with the Gateworks JTAG dongle (for NAND flash boards) or to create removable storage devices (for NAND-less boards). See [wiki:linux/ubi linux/ubi]. * For Ventana click [wiki:/ventana/bootloader#BuildingfromSource here] for instructions on building custom a U-boot environment. If however you wish to customize a board's configuration in some way that you have not configured into the build system you will want to boot a board, make your customizations, then pull those customizations off and use them to provision further boards. This is what is presented in detail on this page. == SPI / NOR FLASH based boards (Laguna) == Products that use NOR and/or SPI flash have the ability to be uploaded to a host PC via the Gateworks GW16042 JTAG dongle and jtag_usb application. For these products simply configuring a board the way you want it at runtime then uploading the flash to a file provides you with a firmware image that can then be programmed onto other boards. Please read more about JTAG upload here: [wiki:jtag_instructions JTAG Instructions] == Ventana NAND flash based boards == Products that use NAND flash present an issue in that they can contain bad blocks. As a result the raw flash devices can differ in size making it difficult to implement a JTAG flash upload/download scenario. There are several ways of provisioning NAND bootable boards: * using JTAG (this is what Gateworks uses on our production line) * using U-Boot (more complex, much faster than JTAG, but does not allow provisioning the SPL) * using Linux (even more complex, much faster than JTAG, but allows provisioning the SPL) * a combination of the above Regardless of the method used for provisioning there are several artifacts that you need in order to provision NAND: * SPL (secondary program loader) * u-boot.img (bootloader) * env (bootloader env) * ubi (unsorted block image containing ubifs filesystem) === Pulling Software off of an Existing Board === ==== SPL and Bootloader ==== The SPL and u-boot.img are built artifacts (which can be downloaded from ​http://dev.gateworks.com/ventana/images). ==== Bootloader Environment ==== The env can be blank, which will use built-in defaults, or can be customized and extracted from the flash. To create and extract a bootloader env: 1. Create the env on a board: {{{#!bash # blank per-board vars (which are set from eeprom by default, yet overridable via env) setenv fdt_file setenv ethaddr setenv eth1addr # perform any other desired changes # save saveenv }}} 2. Extract the env from the board and save to removable storage: - from Linux {{{#!bash dd if=/dev/mtd1 of=env bs=1M }}} - from U-Boot: {{{#!bash # read the env (environment) partition into temporary memory, note the size reported below as 0x100000 Ventana > nand read ${loadaddr} env NAND read: device 0 offset 0x1000000, size 0x100000 1048576 bytes read: OK Ventana > # store it to file on micro-SD with an ext4 fs (size re-used from above) mmc dev 0 && ext4write mmc 0:1 ${loadaddr} /env 0x100000 # or store it to file on USB mass storage with an ext4 fs usb start && usb dev 0 && ext4write usb 0:1 ${loadaddr} /env 0x100000 }}} - Note that you may find it easier to build yourself a custom bootloader with defaults that match your needs rather than deal with extracting and imaging an env flash partition - Note that your ext4 filesystem must not have checksums enabled (metadata_csum, a feature added to newer e2fsprogs) as U-Boot does not support this in ext4write. ==== Root Filesystem ==== The ubi root filesystem is originally built by the the build system of the specific BSP your using, however if you end up imaging this onto a board, and customizing it, you may be able to pull it back off as long as your flash size is far less than your memory: * From Linux assuming /tmp is a tmpfs (ram based) and that you are booted into the filesystem you are copying and you have more ram available than the size of /dev/mtd2 (such as a 256MB flash on a 512MB system) {{{#!bash dd if=/dev/mtd2 of=/tmp/ubi bs=4M }}} * From U-Boot {{{#!bash # read the rootfs (filesystem) partition into temporary memory, note the size reported below as 0xef00000 Ventana > nand read ${loadaddr} rootfs NAND read: device 0 offset 0x1100000, size 0xef00000 250609664 bytes read: OK # store it to file on micro-SD with an ext4 fs (size re-used from above) Ventana > mmc dev 0 && ext4write mmc 0:1 ${loadaddr} /rootfs 0xef00000 switch to partitions #0, OK mmc0 is current device File System is consistent update journal finished 250609664 bytes written in 57489 ms (4.2 MiB/s) Ventana > # or store it to file on USB mass storage with an ext4 fs usb start && usb dev 0 && ext4write usb 0:1 ${loadaddr} /rootfs 0xef00000 }}} - Note that your ext4 filesystem must not have checksums enabled (metadata_csum, a feature added to newer e2fsprogs) as U-Boot does not support this in ext4write. === Flashing Boards with Pulled Software === Once you have all the artifacts you can re-assemble them into a JTAG image suitable for the Gateworks JTAG adapter and software. The following usage of mkimage_jtag will create a jtagable image matching the partitioning described by 'mtdparts=nand:16m(uboot),1m(env),-(rootfs)' {{{#!bash mkimage_jtag -e SPL@0 u-boot.img@14M env@16M ubi@17M > image.bin }}} Or, for a faster two-step method of imaging using U-Boot with serial and ethernet (to a tftp server with the ubi): 1. create a JTAG image of the SPL + bootloader + env: {{{#!bash mkimage_jtag SPL u-boot.img env > image.bin }}} 2. once the above is flashed with the Gateworks JTAG adapter and software you can flash the ubi (much more quickly than via JTAG) within U-Boot 3. break out into the bootloader, transfer the ubi image from a tftp server into SDRAM, and flash it: {{{#!bash setenv ipaddr 192.168.1.1 # local ip setenv serverip 192.168.1.146 # server ip tftp ${loadaddr} image.ubi # tftp ubi image nand erase.part rootfs # erase the nand partition named rootfs from the mdtparts variable nand write ${loadaddr} rootfs ${filesize} # write the downloaded ubi to rootfs }}} Notes: * you can always elect to build your own bootloader with a custom config rather than pulling the env data off a board [=#microsd] == micro-SD provisioning == === Directly Cloning SD Cards === See [wiki:linux/blockdev#Creatingadiskimage linux/blockdev] === U-Boot MicroSD Provisioning === The main difference between provisioning removable storage devices such as micro-SD compared to non-removable storage devices (such as NAND flash) is that the removable devices can be potentially booted on a board with a different model, CPU, or memory configuration. This causes us to treat the U-Boot environment differently when we extract it from a configured board. If you do not want a blank env (which uses built-in defaults) you must provision one board, boot it to the bootloader, customize your env, then extract that env to use when provisioning additional boards. The Ventana bootloader stores its microSD env on raw block sectors from offset 709K and is 256K in size. The env can be blank, which will use built-in defaults, or can be customized and extracted. To create and extract a bootloader env: (only if this is being used, otherwise skip this step) 1. Create the env on a board: {{{#!bash # blank per-board vars (which are set from eeprom by default, yet overridable via env) setenv fdt_file setenv ethaddr setenv eth1addr # perform any other desired changes # save saveenv }}} 2. extract the env from a board that boots to micro-SD: * from Linux: {{{#!bash # copy 256KB from offset 709KB to 'env' file dd if=/dev/sdc of=env bs=1K skip=709 count=256 oflag=sync }}} * from U-Boot: {{{#!bash mmc read ${loadaddr} 0x58a 0x200 # read 512x 512byte blocks (256K) from block 0x1418 # store it to file on micro-SD with an ext4 fs ext4write mmc 0:1 ${loadaddr} /mmc.env 0x40000 # store it to file on USB mass storage with an ext4 fs usb start && usb dev 0 && ext4write usb 0:1 ${loadaddr} /mmc.env 0x40000 }}} - Note that your ext4 filesystem must not have checksums enabled (metadata_csum, a feature added to newer e2fsprogs) as U-Boot does not support this in ext4write. To place an extracted env onto a micro-SD: * from Linux: {{{#!bash # copy 256KB from file env to offset 709KB: dd if=env of=/dev/sdc bs=1K seek=709 count=256 oflag=sync }}} = Provisioning root file system from live Newport board It's always best to create your rootfs from scratch using the Newport [wiki:/newport/bsp BSP] when this option is available. If you're prevented from doing so it is possible to provision the root file system from some Newport boards without too much difficulty. Newport SBC's are capable of booting from both eMMC and MMC. The boot device can be selected by the GSC performing a 5x press on the power button. To provision the root filesystem of located on the eMMC boot from MMC, create an image of the eMMC partition 2 on the MMC, then compress so it can be loaded on other boards. == Requirements * A Newport board with MMC card slot and push button (GSC must be configured to accept push button input—this is default) * A MMC with capacity enough to accommodate full size of eMMC (8GB) along with BSP for performing recovery. Recommended would be a minimum 16GB or 32GB card. * A desktop computer with Linux natively installed. This workstation must have a drive capable of accepting an MMC and have packages for DD and Mount. == On your workstation Download a Gateworks pre-built image. All of our images include the tools necessary to perform this operation, though Ubuntu will likely be the easiest to work with. {{{ wget -N http://dev.gateworks.com/newport/images/focal-newport.img.gz }}} Insert a micro SD card into your workstation and identify the device name it's been assigned. This can be done using a variety of methods, for example the "dmesg" output. In this example the MMC is "/dev/sdb" Image the MMC. {{{ zcat focal-newport.img.gz | sudo dd of=/dev/sdb bs=4M }}} Remove the SD card from your workstation. == On your Newport SBC Insert the SD card into the SD card reader, then apply power to the SBC (or otherwise turn it on). 5x press the power button, you will see the status LED turn off and back on. The BDK will display microSD as MMC0. Example output: {{{ Gateworks Newport SPL (12.7.0-96865d0 Tue Jul 7 21:19:32 UTC 2020) GSC : v55 0xe7e2 RST:BOOT_WDT2 Thermal Protection Enabled Temp : Board:34C/86C CPU:42C/100C Model : GW6400-B1 MFGDate : 09-23-2019 Serial : 802864 RTC : 8 SoC : CN8020-800BG676-SCP-P12-G 1024KB 800/550MHz 0xa2 Pass 1.2 MMC0 : microSD MMC1 : eMMC }}} Proceed to boot to Linux user-space. Once there if you would like to check the rootfs you're about to image the rootfs of the eMMC is located at /dev/mmcblk1p2. ** Optional: ** {{{ mount /dev/mmcblk1p2 /mnt ls /mnt #this will display the eMMC's rootfs umount /mnt }}} Image the partition to a file. {{{ dd if=/dev/mmcblk1p2 of=myrootfs.img }}} "sync" the filesystem and power board off {{{ sync #remove power }}} Remove MMC from the SBC. == Create an image Navigate to the "/tmp" directory on your workstation. In actuality this can be any directory that you have read and write permissions, "/tmp" should only be used if you don't care what happens to these files later. {{{ cd /tmp }}} Insert the MMC into the SD card reader on your workstation, as before note the the name the device is assigned. Because we created our image in within the rootfs we will need to mount the second partition, for example "/dev/sdb2": {{{ sudo mount /dev/sdb2 /mnt/ ls /mnt/ }}} Copy the image you created of mmcblk1p2 into "/tmp" {{{ cp /mnt/myrootfs.img . }}} Executing the command "file" on this file will return that it is ext4 filesystem data and the volume name is "rootfs". Example: {{{ user@workstation:/tmp$ file myrootfs.img myrootfs.img: Linux rev 1.0 ext4 filesystem data, UUID=951f19a1-cc54-4a07-9b7f-41a54ea8acb4, volume name "rootfs" (needs journal recovery) (extents) (64bit) (large files) (huge files) }}} Add boot firmware and create a gzipped image. * Download boot firmware {{{ wget http://dev.gateworks.com/newport/boot_firmware/firmware-newport.img }}} * name it however you please {{{ cp firmware-newport.img myimg-newport.img }}} * Create a disk image containing the root filesystem and boot firmware. The boot firmware is 16M so we will "dd" the rootfs using this offset. {{{ dd if=myrootfs.img of=myimg-newport.img bs=16M seek=1 }}} * gzip the image so it can be installed using standard methods on other Newport boards. {{{ gzip -k -f myimg-newport.img }}} Be mindful that the image size can't exceed the total DRAM of the board you plan to install it on if you're using the bootloader command "tftpboot". The "update_all", and "update_rootfs" scripts both use this command {{{ ls -lh myimg-newport.img.gz #size must be less than total DRAM of board }}} == Flash this image to a Newport SBC: In the bootloader: {{{ GW6400-B1> setenv ipaddr 192.168.1.52 GW6400-B1> setenv serverip 192.168.1.56 GW6400-B1> setenv image myimg-newport.img.gz GW6400-B1> setenv dev 0 GW6400-B1> run update_all }}}