[[PageOutline]] [=#bootloader] = Newport U-Boot Bootloader = Gateworks supports the U-Boot Bootloader for the Newport product family. We provide pre-built firmware images (see [wiki:newport#firmware here]) as well as source for building and/or modifying it yourself. One of the primary features of the Bootloader is to provide access to the {{{hwconfig}}} environment variable that the firmware uses for initial board configuration on power-up. == Pre-Built U-Boot Firmware == Pre-Built U-Boot is contained inside of the Gateworks Newport boot firmware artifact here: [http://dev.gateworks.com/newport/boot_firmware/] == Version == As of Q3, 2018, the U-Boot version used on the Newport boards is v2017.09-rc1 Source code is located here: [https://github.com/Gateworks/uboot-newport] [=#hwconfig] == hwconfig The U-Boot Bootloader by convention provides a {{{hwconfig}}} environment variable which is used by the boot firmware (before U-Boot is loaded and executed) to configure board options at power-up. These options can include things such as: * miniPCIe socket functions (ie PCIe vs mSATA vs USB3.0) * serial configuration (ie RS232 vs RS485) [=#socketconfig] === hwconfig: miniPCIe Socket Configuration Newport board model socket options: * GW640x: - J9: USB2/PCI (for build option for Mezzanine connector contact sales@gateworks.com) - J10: PCI or SATA and optional USB2 **(USB2 option removes it from top front panel USB connector)** - J11: USB2/PCI - J12: USB2/SIM and USB3 * GW630x: - J9: USB2 and PCI (for build option for Mezzanine connector contact sales@gateworks.com) - J10: USB2 and PCI or SATA - J11: USB2 and PCI or USB3 * GW620x: - J6: USB2/SIM and PCI or USB3 - J8: USB2 and PCI or SATA * GW610x: - J6: USB2/SIM and PCI or SATA Note that as PCIe, USB3.0 SS, and SATA share signals so if multiple options exist you must choose between them on those sockets using the {{{hwconfig}}} bootloader env variable. If a socket is not specified in {{{hwconfig}}} then the PCI option will be the default. You can get/set the {{{hwconfig}}} variable within the U-Boot bootloader but you must reboot the board for it to take effect as the variable is acted upon in the Secondary Program Loader (SPL). Examples: * '''Note that setting {{{hwconfig}}} currently requires saveenv to be ran twice''' * GW640x: - J10 SATA {{{#!bash setenv hwconfig 'j10:sata'; saveenv; saveenv }}} - J10 PCIe and USB2 (this removes USB2 from top front panel USB connector) {{{#!bash setenv hwconfig 'j10:pci,usb2'; saveenv; saveenv }}} * GW630x: - J10 PCIe, J11 PCIe (default) {{{#!bash setenv hwconfig 'j10:pci;j11:pci'; saveenv; saveenv }}} - J10 mSATA, J11 USB3.0 {{{#!bash setenv hwconfig 'j10:sata;j11:usb3'; saveenv; saveenv }}} - J9/J10 disabled, J11 PCIe {{{#!bash setenv hwconfig 'j9:disabled;j10:disabled;j11:pci'; saveenv; saveenv }}} You can see that the {{{hwconfig}}} configuration took place by watching the output of the BDK during boot. For example: {{{#!bash Gateworks Newport SPL (3442703 Wed Jun 6 20:26:30 UTC 2018) GSC : v52 0xbf2d WDT:disabled board temp:38C RTC : 506646 Model : GW6304-C MFGDate : 03-28-2018 Serial : 776375 DTB : gw6304.dtb SoC : CN8030-1500BG676-SCP-P12-G 1024KB 1500/550MHz 0xa2 Pass 1.2 MMC0 : eMMC MMC1 : not detected Boot : eMMC non-trusted DRAM : 2048 MB, 1333 MT/s, DDR4 UDIMM J9 : PCI J10 : SATA J11 : USB3 QLM0 : PCIE_1X1@5000MHz QLM1 : SGMII_1X1@1250MHz QLM2 : DISABLED@5000MHz QLM3 : SATA_2X1@6000MHz Serial : 2x RS232 without flow control ... Hit any key to stop autoboot: 0 GW6304-C> print hwconfig hwconfig=j10:sata;j11:usb3 }}} * The above shows that J9 is configured for PCI, J10 for SATA, and J11 for USB3 '''Note that {{{hwconfig}}} is also used for serial configuration so care should be taken to preserve that configuration if used''' [=#serialconfig] === hwconfig: serial Configuration Many boards in the Newport product family provide a 5-pin off-board serial connector that provides the following options: - 1x RS485 FD (UART2) - 1x RS485 HD (UART2) - 1x RS232 w/ hardware flow control (UART2) - 2x RS232 w/o hardware flow control (UART2/UART3) By default 2x RS232 with no flow control is enabled. To configure a different option use the {{{hwconfig}}} U-Boot env variable. The {{{mode}}} property of the {{{serial}}} option defines the initial configuration of the serial port(s). If RS485 is selected by the {{{mode}}} property the {{{term}}} property will select whether or not on-board termination is enabled. The {{{mode}}} property can have the following values: * rs232 - 2x RS232 (UART2/UART3) without hardware flow control (default if not specified) * rs232_dtr - RS232 (UART2) with hardware flow control * rs485_hd - RS485 half-duplex * rs485_fd - RS485 full-duplex Examples: * '''Note that setting {{{hwconfig}}} currently requires saveenv to be ran twice''' * Enable RS485 half duplex no on-board termination {{{#!bash setenv hwconfig "serial:mode=rs485_hd,term=no"; saveenv; saveenv }}} * Enable RS485 full duplex with on-board termination {{{#!bash setenv hwconfig "serial:mode=rs485_fd,term=yes"; saveenv; saveenv }}} * Enable RS232 with hardware flow-control: {{{#!bash setenv hwconfig "serial:mode=rs232_dtr"; saveenv; saveenv }}} '''Note that {{{hwconfig}}} is also used for pcie configuration so care should be taken to preserve that configuration if used''' [=#distro-config] == Distro Config The Newport Bootloader uses U-Boot's 'Distro Config' which is a well defined U-Boot env intended to make it easier for distro maintainers to develop compatible bootscripts. This primarily entails a set of 'boot scripts' and variables that control them. Ultimately this U-Boot environment is looking for a U-Boot [#bootscript boot script] on a 'bootable' partition (partitions with the 'boot' flag enabled). It searches in this order with these rules: - **boot_targets** - list of target device type/nums to search: defaults to mmc0 mmc1 usb0 sata0 - **devplist** - ''dynamically created'' list of all partitions flagged as 'bootable' - **boot_prefixes** - list of directories within a partition searched for bootscripts - **boot_scripts** - list of boot script names searched for [=#bootscript] == Boot Scripts When writing bootscripts compatible with [#distro-config Distro Config] you can assume the following env variables: - **devtype** - the device type the script was loaded from (mmc|usb|sata) - **devnum** - the device number the script was loaded from (ie 0 for mmc0, 1 for mmc1, etc) - **distro_bootpart** - the partition number the script was loaded from (ie 0, 1, etc) - **fdtcontroladdr** - the address the device-tree is at (Note that the Newport bootloader does not load/manipulate the device-tree itself - this is done by the SPL which loads/manipulates the device-tree and passes it to the bootloader) - **kernel_addr_r** - address where kernel can be loaded - **bootargs** - default bootargs to pass to the kernel - you probably want to add to this and not overwrite it - **console** - the serial console device to pass to the kernel Additionally you should note the following: - use load/ls/save commands which support FAT/ext filesystem types automatically instead of the fs specific commands - if using a root filesystem that is not supported by the bootloader (ie F2FS or BTRFS) you can place your kernel image in the FAT12 filesystem on partition 1 of the boot device. This filesystem is part of the 16MB 'Boot Firmware' image. If doing so you will need to compress the kernel and package it into a [#fit FIT image] in order to fit it in the available space. The Distro-Config environment supports legacy uImage scripts (it does not support FIT images with scripts). You can create these with the {{{mkimage}}} tool from U-Boot as such: {{{#!bash mkimage -A arm64 -T script -C none -d ubuntu.txt newport.scr }}} You can then place the uImage {{{newport.scr}}} on a bootable partition such as the embedded FAT12 filesystem within the Newport boot firmware as such: {{{#!bash fatfs-tool -i firmware-newport.img cp newport.scr / }}} Alternatively this can be done at runtime on the target within Linux by mounting the FAT12 partition. For example: {{{#!bash mount /dev/mmcblk0p1 /mnt mkimage -A arm64 -T script -C none -d ubuntu.txt /mnt/newport.scr umount }}} [=#boot_targets] === Boot Device Order (boot_targets) === While the Newport product family can only boot its [wiki:newport/boot Boot Firmware] from an MMC device (ie eMMC or microSD), once you are booted to the bootloader you can choose from a wider variety of devices to boot the OS from. This OS boot device order is specified by the [#distro-config Distro Config] environment. Specifically it is controlled by the {{{boot_targets}}} env variable which defaults to {{{mmc0 mmc1 usb0 sata0}}}. For example, to limit OS booting to only SATA: {{{#!bash setenv boot_targets sata0 saveenv }}} [=#fit] == Flattened Image Tree (FIT) images == The U-Boot bootloader supports Flattened Image Tree (FIT) images which expand greatly on the legacy U-Boot image (uImage) format by allowing multiple binary blobs within an image. These blobs can be kernel images, ramdisk images, device-tree blobs, and bootloader scripts. Each image can also be optionally compressed (meaning U-Boot will decompress it) and check-sumed with a variety of hash mechanisms (meaning U-Boot will verify the image before using it). Quick summary of FIT Images: * introduced to resolve limitations with original single-image formats and follow-on multi-image format supported by UBoot bootm (boot memory) * uses power of the Device-Tree-Compiler (DTC) * FIT .itb files can be created with mkimage by passing in a .its file which in device-tree notation describes the images * U-Boot supports FIT with several commands: - {{{source :}}} # source a script by name from FIT image in memory - {{{iminfo }}} # print all the info contained in a FIT image in memory and verify (just not boot it) - {{{imextract }}} # extract item (ie kernel@1) to addr - {{{bootm [#conf] - $fdtcontroladdr}}} # boot default or 'conf' configuration (ie #config@1) - {{{bootm start [#conf] - $fdtcontroladdr}}} # boot from memory a specific configuration (or default configuration) from FIT image Example: * kernel.its with a single compressed kernel for ARM64 (used by Newport) {{{#!bash /dts-v1/; / { description = "Simple image with single Linux kernel"; #address-cells = <1>; images { kernel@1 { description = "ThunderX kernel"; data = /incbin/("./Image.gz"); type = "kernel"; arch = "arm64"; os = "linux"; compression = "gzip"; load = <0x40080000>; entry = <0x40080000>; hash@1 { algo = "sha256"; }; }; }; configurations { default = "conf@1"; conf@1 { description = "Boot Linux kernel"; kernel = "kernel@1"; }; }; }; }}} * create image: {{{#!bash cp arch/arm64/boot/Image . gzip Image mkimage -f kernel.its /tftpboot/kernel.itb }}} * boot the default configuration from U-Boot. For example if your using an ext4 fs on the first MMC device, 2nd partition use: {{{#!bash tftpboot $loadaddr kernel.itb && setenv bootargs 'console=ttyAMA0,115200n8 earlycon=pl011,0x87e028000000 coherent_poll=64M root=/dev/mmcblk0p2 rootfstype=ext4 rootwait rw' && bootm $loadaddr - $fdtcontroladdr }}} Note that the Newport BSP does these steps in its 'ubuntu-image' make target uses the [https://github.com/Gateworks/bsp-newport/blob/master/mkits.sh newport/mkits.sh] script to create an its file then uses this to kernel a kernel.itb. You can follow along with the [https://github.com/Gateworks/bsp-newport/blob/master/Makefile] and do these by hand in your Newport BSP directory: {{{#!bash # create kernel.itb with compressed kernel image tar xvf linux-newport.tar.xz ./boot/Image --strip-components=2 mv Image vmlinux gzip -f vmlinux ./newport/mkits.sh -o kernel.its -k vmlinux.gz -C gzip -v "Ubuntu" mkimage -f kernel.its kernel.itb }}} The Newport BSP also uses the [https://github.com/Gateworks/bsp-newport/blob/master/newport.env newport/newport.env] bootscript to create its kernel parameters which may be useful to understand. References: * [http://git.denx.de/?p=u-boot.git;a=tree;f=doc/uImage.FIT doc/uImage.FIT] * http://www.denx.de/wiki/pub/U-Boot/Documentation/multi_image_booting_scenarios.pdf * http://elinux.org/images/f/f4/Elc2013_Fernandes.pdf = U-boot tools A detailed description of u-boot-tools usage can be found [wiki:/ventana/bootloader#U-Bootenvtoolsfw_printenvfw_setenv here]. In order to configure u-boot-tools to work correctly for Newport you will need a fw_env.config file the appropriate values. This file will be downloaded as part of the [http://trac.gateworks.com/wiki/newport/bsp#BuildingtheBSPfromsource Newport BSP]. To create this file: {{{#!bash cat << EOF > /env/fw_env.config # Device offset Env. size /dev/mmcblk0 0xff0000 0x8000 /dev/mmcblk0 0xff8000 0x8000 EOF }}} Further information on these offsets and the adjcent data can be found [wiki:/newport/boot#BootFirmareImage here].