Version 18 (modified by 5 years ago) ( diff ) | ,
---|
Newport U-Boot Bootloader
Gateworks supports the U-Boot Bootloader for the Newport product family. We provide pre-built firmware images (see 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
Restoring defaults
To restore default bootloader environment variables:
- At the "Hit any key to stop autoboot:" prompt press any key.
- Execute the following command:
env default -f -a
- Because the bootloader queries the EEPROM for the contents of the variable "prompt" and defaults have been restored there will be no "GW6xxx-xx>" prompt until the EEPROM is queried again on reboot, this results in a blank line with no prompt. On the blank line type:
saveenv
- Reboot the board
reset
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)
hwconfig: miniPCIe Socket Configuration
Newport board model socket options:
- GW640x:
- J9: USB2/PCI (for build option for Mezzanine connector contact sales@…)
- J10: PCI or SATA and optional USB2 (USB2 option removes it from top front panel USB connector)
- J11: USB2/PCI
- J12: USB2 and USB3
- GW630x:
- J9: USB2 and PCI (for build option for Mezzanine connector contact sales@…)
- J10: USB2 and PCI or SATA
- J11: USB2 and PCI or USB3
- GW620x:
- J6: USB2 and PCI or USB3
- J8: USB2 and PCI or SATA
- GW610x:
- J6: USB2 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:
- GW620x:
- J6 USB3 (removes PCI)
setenv hwconfig 'j6:usb3'; saveenv
- J6 PCIe and USB2 (removes USB3)
setenv hwconfig ; saveenv
- J6 USB3 (removes PCI)
- GW640x:
- J10 SATA
setenv hwconfig 'j10:sata'; saveenv
- J10 PCIe and USB2 (removes USB2 from top front panel USB connector)
setenv hwconfig 'j10:pci,usb2'; saveenv
- J10 SATA
- GW630x:
- J10 PCIe, J11 PCIe (default)
setenv hwconfig 'j10:pci;j11:pci'; saveenv
- J10 mSATA, J11 USB3.0
setenv hwconfig 'j10:sata;j11:usb3'; saveenv
- J9/J10 disabled, J11 PCIe
setenv hwconfig 'j9:disabled;j10:disabled;j11:pci'; saveenv
- J10 PCIe, J11 PCIe (default)
You can see that the hwconfig
configuration took place by watching the output of the BDK during boot. For example:
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
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
setenv hwconfig "serial:mode=rs485_hd,term=no"; saveenv; saveenv
- Enable RS485 full duplex with on-board termination
setenv hwconfig "serial:mode=rs485_fd,term=yes"; saveenv; saveenv
- Enable RS232 with hardware flow-control:
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
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 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
Boot Scripts
When writing bootscripts compatible with 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 bootscript and 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 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:
mkimage -A arm64 -T script -C none -d ubuntu.txt newport.scr
The bootscript can be updated at runtime on the target. For example:
mkimage -A arm64 -T script -C none -d ubuntu.txt /boot/newport.scr
If storing the bootscript on the embedded FATFS partition (which would make sense if your root filesystem is something that is not supported by the Bootloader such as F2FS or BTRFS):
- You can update the bootscript uImage
newport.scr
in the boot firmware:fatfs-tool -i firmware-newport.img cp newport.scr /
- You can udpate the bootscript uImage
newport.scr
on a live target via:mount /dev/mmcblk0p1 /mnt mkimage -A arm64 -T script -C none -d ubuntu.txt /mnt/newport.scr umount
Boot Device Order (boot_targets)
While the Newport product family can only boot its 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 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:
setenv boot_targets sata0 saveenv
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 <addr>:<name>
# source a script by name from FIT image in memoryiminfo <fitaddress>
# print all the info contained in a FIT image in memory and verify (just not boot it)imextract <fitaddress> <item> <addr>
# extract item (ie kernel@1) to addrbootm <fitaddress>[#conf] - $fdtcontroladdr
# boot default or 'conf' configuration (ie #config@1)bootm start <fitaddress>[#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)
/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:
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:
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 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:
# 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 newport/newport.env bootscript to create its kernel parameters which may be useful to understand.
References:
- 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 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 Newport BSP and found in the newport/ folder.
To create this file:
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 here.