[[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: * GW630x: - J9: PCIe - J10: PCIe or SATA - J11: PCIe or USB3.0 * GW640x: - J9: PCIe - J10: PCIe or SATA - J11: PCIe - J12: USB 3.0 / SIM (no hwconfig) Note that USB2.0 is routed to all three miniPCIe sockets always but as USB3.0 shares signals with PCIe you must choose between PCIe and USB3 on sockets that support USB3. 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: * GW630x: - J10 PCIe, J11 PCIe (default) {{{#!bash setenv hwconfig 'j10:pcie;j11:pcie'; saveenv }}} - J10 mSATA, J11 USB3.0 {{{#!bash setenv hwconfig 'j10:sata;j11:usb3'; saveenv }}} - J9/J10 disabled, J11 PCIe {{{#!bash setenv hwconfig 'j9:disabled;j10:disabled;j11:pcie'; saveenv }}} '''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: * enable RS485 half duplex no on-board termination {{{#!bash setenv hwconfig "serial:mode=rs485_hd,term=no"; saveenv }}} * enable RS485 full duplex with on-board termination {{{#!bash setenv hwconfig "serial:mode=rs485_fd,term=yes"; saveenv }}} * enable RS232 with hardware flow-control: {{{#!bash setenv hwconfig "serial:mode=rs232_dtr"; saveenv }}} '''Note that {{{hwconfig}}} is also used for serial 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: {{{#!bash tftpboot $loadaddr kernel.itb && setenv bootargs 'console=ttyAMA0,115200n8 earlycon=pl011,0x87e028000000 coherent_poll=64M root=/dev/mmcblk2 rootfstype=f2fs' && bootm $loadaddr - $fdtcontroladdr }}} 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