-
U-Boot Bootloader
- Features and Peripheral support
- Product Family specific notes
- Environment variables and scripts
- Boot Flow
- Flattened Image Tree (FIT) images
- General Purpose I/O (GPIO)
- LED support
- GSC support
- Network
- Generic File System and File Management support for Block storage devices
- MMC (eMMC and microSD)
- USB
- PCI
- NetConsole (access U-Boot console from network)
- Installing Large Disk Images on Systems with Limited RAM
U-Boot Bootloader
Gateworks uses U-Boot (the Universal Boot Loader) as a primary bootloader for all current product families. In some cases U-Boot is used as the 'secondary program loader' as well as the 'primary program loader'.
The purpose of a bootloader is to load the Operating System (OS) and execute it. In terms of a Linux based OS this means loading the kernel image, device-tree blobs (optional), and initial ramdisk images (optional) into DRAM and executing the kernel with any necessary kernel arguments. Often this is done in an OS specific fashion via a U-Boot bootscript stored along-side the kernel Image.
Features and Peripheral support
U-Boot has many features and peripheral support but it is not intended to be a full OS so some features do not work as well as they would on a Linux based OS for example. The intention of U-Boot is to provide enough support to load and execute the kernel therefore support for things like USB peripherals and high performance networking and I/O is not a priority and should not be expected.
Many features can be enabled by re-building and re-installing U-Boot. For more information on building U-Boot see the product specific BSP pages.
Product Family specific notes
Malibu
The Marvell CN913x based Malibu product family boots via a BOOT ROM internal to the CN913x which loads ARM Trusted Firmware (ATF) which contains a U-Boot payload image. In this case initial SoC chip and DRAM configuration is done by components in the ARM Trusted firmware
see also malibu/boot
Venice
The NXP i.MX 8M Mini/Nano/Plus based Venice product family boots via a BOOT ROM internal to the i.MX8M which loads U-Boot SPL (Secondary Program Loader) which then loads U-Boot proper. In this case initial SoC chip and DRAM configuration is done by U-Boot SPL.
see also venice/boot
Newport
The Marvell CN803x based Newport product family boots via a BOOT ROM internal to the CN803 which loads Marvell's 'Board Disagnostics Kit' (BDK) (which we call the SPL) which in turn loads the ATF and U-Boot from a payload inside the ATF. In this case initial SoC chip and DRAM configuration is done by the Marvell BDK software.
see also newport/boot
Ventana
The NXP i.MX 6Q/DL based Ventana product family boots via a BOOT ROM internal to the i.MX6 which loads U-Boot SPL (Secondary Program Loader) which then loads U-Boot proper. In this case initial SoC chip and DRAM configuration is done by U-Boot SPL.
Ventana U-Boot enables and supports PCI and the PCI based i210 NIC found on several of the Ventana boards. see also ventana/bootloader
Environment variables and scripts
U-Boot uses environment variables to configure much of its functionality. U-Boot environment variables can also be treated as scripts and therefore the environment dictates how U-Boot achieves its goal of loading and executing the OS.
You can use env
commands to get or set env vars. For example:
- Get a var:
env print model
- Set a var:
env set quiet 1
- Load default values (does not save):
env default -f -a
- Save current env:
env save
If you want to erase the env:
env erase
Some notable env variables used in U-Boot:
Category | Name | Purpose |
---|---|---|
boot | preboot | script executed before 'Hit any key to abort' if CONFIG_USE_PREBOOT=y |
boot | bootcmd | script executed at boot |
boot | bootdelay | number of seconds to wait for a key to abort automatic boot (if 0 will not wait) |
console | baudrate | baudrate of serial console |
console | device of serial console | |
network | ethprime | primary ethernet device (used at boot) |
network | ethaddr | mac addr of first eth interface |
network | eth1addr | mac addr of second eth interface |
network | ethact | active ethernet device (current) |
network | ipaddr | local ip address |
network | serverip | ip address of server for tftp commands |
network | netmask | netmask address (optional) |
network | gatewayip | ip address of gateway (optional) |
network | ethrotate | if set to 'no' will not automatically rotate through network devices on network operations |
network | dhcp | issue a DHCP request for network configuration (set 'autoload=no' to disable attempting to load an image) |
distro config | boot_targets | ordered list of boot targets (ie 'mmc1 mmc2 usb0 usb1') |
distro config | boot_prefixes | ordered list of prefixes of boot scripts (ie '/ /boot') |
distro config | boot_scripts | ordered list of boot script names (ie 'boot.scr') |
automatic | board | board model (automatically set during boot) |
automatic | serial# | board serial number (automatically set during boot) |
U-Boot env location, format, and accessing outside of U-Boot
There are several U-Boot config items (CONFIG_ENV_*) that specify where and how the U-Boot env is stored. Typically Gateworks configures 32KiB redundant env located at the end of the boot firmware. This means that U-Boot flips back and forth between the two env areas so that if a power-cut occurs during a 'saveenv' command it will default to the previous env saved.
There are several applications built by U-Boot that facilitate accessing U-Boot env outside of U-Boot:
- fw_printenv / fw_setenv - uses a config file to allow env get/set from Linux
- mkenvimage - creates a binary image from a source file in the format of name=value
The Ubuntu u-boot-tools package provides fw_printenv
and fw_setenv
but a config file must exist in /etc/fw_env.config
(or specified via the -c parameter) which describe the env location and size:
- Venice: (U-Boot env is at the top of 4MB on emmc boot0)
# Device offset Env. size /dev/mmcblk2boot0 0x3f0000 0x8000 /dev/mmcblk2boot0 0x3f8000 0x8000
- Note that at one point Venice stored its boot firmware on the emmc user hardware partition and its env at the top of 16M on emmc user). If you are using v2023.04 or above its at the device and offset above
- Malibu: (U-Boot env is at the top of 4MB on emmc boot0)
# Device offset Env. size /dev/mmcblk0boot0 0x3f0000 0x8000 /dev/mmcblk0boot0 0x3f8000 0x8000
- Note that at one point in time Venice stored its boot firmware on the emmc user hardware partition and its env at the top of 16M on emmc user).
- Newport:
# Device offset Env. size /dev/mmcblk0 0xff0000 0x8000 /dev/mmcblk0 0xff8000 0x8000
- Ventana (NAND boot device):
- cat /proc/mtd
dev: size erasesize name mtd0: 01000000 00040000 "uboot" mtd1: 00100000 00040000 "env" mtd2: 7ef00000 00040000 "rootfs"
- cat /etc/fw_env.config
# device offset size erasesize /dev/mtd1 0x0 0x20000 0x40000 /dev/mtd1 0x80000 0x20000 0x40000
- make sure /dev/mtd1 is your env partition
- cat /proc/mtd
- Ventana (MMC boot device)
# device offset size erasesize /dev/mmcblk0 0xb1400 0x20000 0x20000 /dev/mmcblk0 0xd1400 0x20000 0x20000
This will define the device being used, offset according to flash layout, size from flash map, and size of erase block (unless the device is a file). Ventana U-boot environment is redundant hence two entries, both locations need their variables updated.
Note that in certain circumstances the Linux representation of the boot device can change - please ensure that the devices specified do indeed point to your boot device.
It is important to understand the meaning of the Warning: Bad CRC, using default environment message. This means that the non-volatile env area specified by the config file is empty or corrupt and that the built-in env within U-Boot will be used which is not appropriate. Note that Gateworks Ventana boards ship with an empty env area and use built-in defaults so if you wish to use the u-boot-tools to access the env from Linux first do a 'saveenv' from U-Boot to provide a valid default env.
If you use fw_setenv
on an environment in this state it will properly set the variable you specify and all other variables will continue to use their built-in default values within U-Boot. Essentially you are 'overriding' the defaults as you would expect.
Example usage:
# display environment fw_printenv -c fw_env.config # set environment variable fw_setenv -c fw_env.config foo bar #foo being variable name bar being value variable will be set to #second example fw_setenv -c fw_env.config ipaddr 192.168.1.10 #print single environment variable fw_printenv -c fw_env.config foo #second example fw_printenv ipaddr
Boot Flow
Boot flow in U-Boot refers to how specifically U-Boot loads and passed control to the OS.
After U-Boot initializes it does the following
- executes contents of 'preboot' env variable (if configured with CONFIG_USE_PREBOOT)
- based on the contents of 'bootdelay' env variable it prints 'Hit any key to stop autoboot:' and counts down the number of seconds specified (if set to 0 it will skip this and not allow you to stop execution manually)
- executes contents of 'bootcmd' env variable
Distro Config
A set of scripts referred to as 'distro config' can be used to scan bootable partitions on a set of specified devices for boot scripts and execute the first one it finds.
This configuration is used on Newport, Venice, and Malibu product families (not Ventana which pre-dated this concept)
This feature provides 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 mmc1 mmc0 usb0 usb1 pxe dhcp
- 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
The boot device order is specified by the boot_targets
env variable which typically defaults to something like mmc1 mmc0 usb0 usb1 pxe dhcp
. For example, to limit OS booting to only mmc device 2 you would 'setenv boot_targets mmc 2; saveenv'.
The Distro-Config environment supports legacy uImage scripts (it does not support FIT images with scripts).
Boot script
A boot script is a U-Boot specific set of commands wrapped inside a U-Boot binary header which can be loaded from a device or filesystem and executed via the 'source <address>' command.
You can create these with the mkimage
tool from U-Boot as such:
mkimage -A arm64 -T script -C none -d boot.txt boot.scr
The bootscript can be updated at runtime on the Linux target. For example:
mkimage -A arm64 -T script -C none -d boot.txt /boot/boot.scr
When writing bootscripts compatible with Generic 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 Malibu bootloader contains a static version of the board device-tree)
- 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.
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
/dts-v1/; / { description = "Simple image with single Linux kernel"; #address-cells = <1>; images { kernel@1 { description = "Linux kernel"; data = /incbin/("./Image.gz"); type = "kernel"; arch = "arm64"; os = "linux"; compression = "gzip"; load = <0x40200000>; entry = <0x40200000>; 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:
tftpboot $loadaddr kernel.itb && bootm $loadaddr - $fdtcontroladdr
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
General Purpose I/O (GPIO)
The gpio
command provides the ability to list and configure board-specific GPIO's.
Examples:
- List GPIO's:
u-boot=> gpio status Bank GPIO1_: GPIO1_0: output: 0 [x] rs485_term.gpio-hog GPIO1_1: input: 0 [x] mipi_gpio4.gpio-hog GPIO1_5: output: 0 [x] regulator-wifi-en.gpio GPIO1_6: output: 0 [x] pci_usb_sel.gpio-hog GPIO1_7: input: 1 [x] dio0.gpio-hog GPIO1_8: output: 0 [x] regulator-usb-otg2.gpio GPIO1_9: input: 1 [x] dio1.gpio-hog GPIO1_12: output: 0 [x] regulator-usb-otg1.gpio Bank GPIO2_: GPIO2_12: input: 1 [x] mmc@30b50000.cd-gpios Bank GPIO3_: GPIO3_0: output: 0 [x] ethernet@30be0000.phy-reset-gpios Bank GPIO4_: GPIO4_0: output: 0 [x] rs485_en.gpio-hog GPIO4_1: input: 0 [x] mipi_gpio3.gpio-hog GPIO4_2: output: 0 [x] rs485_hd.gpio-hog GPIO4_3: input: 0 [x] mipi_gpio2.gpio-hog GPIO4_4: input: 0 [x] mipi_gpio1.gpio-hog GPIO4_7: output: 1 [x] pci_wdis#.gpio-hog Bank GPIO5_: GPIO5_4: output: 0 [x] led-1.gpios GPIO5_5: output: 0 [x] led-0.gpios
- set GPIO named DIO1 to logic 1:
u-boot=> gpio set dio1 gpio: pin dio1 (gpio 9) value is 1
- set GPIO named DIO1 to logic 0:
u-boot=> gpio clr dio1 gpio: pin dio1 (gpio 9) value is 0
- read GPIO DIO1 logic level:
u-boot=> gpio input dio1 gpio: pin dio1 (gpio 9) value is 0
LED support
If LED support is enabled you can configure board LED's via U-Boot:
- List LED's:
u-boot=> led list led-0 off led-1 off
- turn an LED on:
u-boot=> led led-0 on
- turn an LED off:
u-boot=> led led-0 off
Note that many Gateworks boards have a front-panel bi-color LED which is supported by two distinct LED's for 'red' and 'green'. In this case you must enable one and disable the other (setting both 'on' is the same as setting both 'off').
GSC support
The gsc
command that will let you interact with the Gateworks System controller on Gateworks boards.
Examples:
- see basic info
u-boot=> gsc GSCv3 : v61 0x1d6f RST:VIN Thermal protection:enabled at 96C RTC : 1970-01-05 22:36:56 UTC Model : GW7301-01-CF Serial : 928012 MFGDate : 01-09-2023 SOM : GW7001-F 928012 01-09-2023 BASE : GW7301-C 878707 05-04-2022
- disable primary power supply for 5 seconds
u-boot=> gsc sleep 5 GSC Sleeping for 5 seconds
- Show hardware monitor values:
u-boot=> gsc hwmon temp : 47.9C vdd_bat : 3.216V vdd_vin : 16.724V vdd_adc1: 0.000V vdd_adc2: 0.000V vdd_dram: 1.119V vdd_1p2 : 1.192V vdd_1p0 : 0.000V vdd_2p5 : 0.000V vdd_3p3 : 3.272V vdd_0p95: 0.938V vdd_1p8 : 1.793V vdd_gsc : 2.950V
- Note that the voltage rails connected to the GSC hardware monitor vary per board
Network
U-Boot network support exists for the network controllers found within the SoC of the board. If PCI is supported by the product family there are a few PCI based network controller drivers as well.
Because U-Boot is not a full OS and does not support background drivers network operations occur based on various network commands such as 'tftpboot', 'dhcp'. The network interface used for these commands is specified by the 'ethact' env variable. The 'net list' command available in newer versions of U-Boot can help identify the names of the network interface that can be used.
To see a table showing the physical network interface mapping to U-Boot devices refer to:
The following U-Boot environment variables are used with networking:
ipaddr
- local IP addressserverip
- TFTP server IPnetmask
- Netmaskgatewayip
- Gateway IP if neededethact
- controls which interface is currently activeethprime
- controls which interface is used firstethrotate
- when set to 'no' uboot does not go through all available network interfaces and instead just stays at the currently selected interface (ethact)filesize
- gets set to the size of data transferrednetretry
- when set to 'no' each network operation will either success or fail without retrying. When set to 'once' the operation will fail only when all available network interfaces have been tried once without success.
DHCP
The dhcp
command (if enabled) can use the DHCP protocol to configure networking.
Examples:
- use DHCP to configure networking:
u-boot=> dhcp BOOTP broadcast 1 BOOTP broadcast 2 BOOTP broadcast 3 DHCP client bound to address 172.24.20.160 (1047 ms)
A successful bind will set the following:
- ipaddr
- netmask
- gatewayip
- serverip
The following variables affect dhcp:
- autoload - if set will attempt to transfer a file from the server
DNS
The dns
command (if enabled) can use the DNS protocol to perform a name to IP lookup. You must setn the 'dnsip' env variable to an accessible DNS server.
Examples:
- use DNS to lookup dev.gateworks.com
u-boot=> dhcp BOOTP broadcast 1 DHCP client bound to address 172.24.20.160 (1046 ms) u-boot=> setenv dnsip 8.8.8.8 u-boot=> dns dev.gateworks.com 108.161.129.64
TFTP
The tftpboot
command has been the primary method for transferring files from a server for many years.
The following U-Boot environment variables (as well as the general network variables above) are used with tftp:
tftpsrcport
- UDP source port (if not set uses default)tftpdstport
- UDP dest port (if not set uses well known port 69)tftpblocksize
- if not set will use TFTP server's default block sizetftptimeout
- retransmission timeout for TFTP packets in ms (min value is 1000, default is 5000)
Examples:
- fetch a file via TFTP to a memory address specified by loadaddr:
u-boot=> tftpboot $loadaddr 192.168.1.146:file
The filesize
variable will be set to the number of bytes transferred
NFS
The NFS command (if enabled) can transfer a file from an NFS server to a memory address.
Examples:
- fetch a file via NFS to a memory address specified by loadaddr:
u-boot=> nfs $loadaddr 172.24.21.238:/venice/firmware-venice-imx8mp.bin
The filesize
variable will be set to the number of bytes transferred
WGET
The TCP protocol and wget
command (if enabled) were added to U-Boot v2023.01 to support fetching files via HTTP however until very recently it was plagued with a couple of issues. These issues have been resolved and support has been enabled for venice U-Boot
Examples:
- fetch a file via HTTP to a memory address specified by loadaddr:
u-boot=> wget $loadaddr 172.24.21.238:/venice/firmware-venice-imx8mp.bin HTTP/1.0 200 OK| | | | | | | | | | | | | | | | | | | | | | Packets received 2900, Transfer Successful Bytes transferred = 4194336 (400020 hex)
The filesize
variable will be set to the number of bytes transferred
Note that only HTTP is supported.
Generic File System and File Management support for Block storage devices
For modern versions of U-Boot there are several commands that work with files which support multiple file systems and device interfaces eliminating the need for you to know what filesystem is used and avoid using the deprecated filesystem specific commands. For these commands you specify the interface name (ie mmc,usb,sata) , a device number and optionally a partition.
- load <interface> [<dev[:part]> [<addr> [<filename> [bytes [pos]]]]] - load a file to memory
- save <interface> [<dev[:part]> <addr> <filename> bytes [pos] - save a file from memory
- ls <interface> [<dev[:part]> [directory]] - list files on a device/directory
- ln <interface> <dev[:part]> target linkname - create a symlink
- size <interface> <dev[:part] <filename> - determine size of a file (saved in 'filesize' env variable)
The 'part' command can be used to work with partition tables (both GPT and MBR if enabled):
- part uuid <interface> <dev>:<part> - print partition UUID
- part uuid <interface> <dev>:<part> <varname> - set varname to partition UUID
- part list <interface> <dev> - print partition table
- help part - see more options
Note that for the usb interface you must start the interface first with a 'usb start' operation. USB bus enumeration does not happen in the background.
MMC (eMMC and microSD)
The 'mmc' command supports various low level operations on MultiMediaCard bus devices such as eMMC and microSD when not working at the fileystem layer. When working at this level you must set the current mmc device manually. Examples:
- mmc list - list available device numbers
u-boot=> mmc list FSL_SDHC: 0 FSL_SDHC: 1 FSL_SDHC: 2 (eMMC)
- mmc dev [dev] [part] [mode] - show or set the current mmc device
u-boot=> mmc dev 2 switch to partitions #0, OK mmc2(part 0) is current device u-boot=> mmc dev switch to partitions #0, OK mmc2(part 0) is current device
- mmc info - show info for currently selected device:
u-boot=> mmc info Device: FSL_SDHC Manufacturer ID: 70 OEM: 0 Name: IB2964 Bus Speed: 200000000 Mode: HS400 (200MHz) Rd Block Len: 512 MMC version 5.1 High Capacity: Yes Capacity: 58.4 GiB Bus Width: 8-bit DDR Erase Group Size: 512 KiB HC WP Group Size: 8 MiB User Capacity: 58.4 GiB Boot Capacity: 4 MiB ENH RPMB Capacity: 4 MiB ENH Boot area 0 is not write protected Boot area 1 is not write protected
- mmc help - show more options
USB
The 'usb' command supports various low level operations on Universal Serial Bus hosts and devices when not working at the fileystem layer. When working at this level you must set the current usb device manually. Additionally you must use the 'usb start' command to initialize the USB subsystem and enumerate the bus. USB bus enumeration does not happen in the background. Examples:
- usb start - start and scan the USB controllers
- usb tree - show a tree view of USB enumerated devices
- help usb - more USB commands and options
Example Usage:
u-boot=> usb start && usb tree starting USB... Bus usb@32e40000: Bus usb@32e50000: USB EHCI 1.00 scanning bus usb@32e40000 for devices... 1 USB Device(s) found scanning bus usb@32e50000 for devices... 4 USB Device(s) found scanning usb for storage devices... 1 Storage Device(s) found USB device tree: 1 Hub (480 Mb/s, 0mA) u-boot EHCI Host Controller 1 Hub (480 Mb/s, 0mA) | u-boot EHCI Host Controller | +-2 Hub (480 Mb/s, 0mA) | Microchip Tech USB2744 | +-3 Mass Storage (480 Mb/s, 100mA) | CENTON USB 52D0CE92 | +-4 Vendor specific (480 Mb/s, 0mA) Microchip Tech Hub Controller
USB Device support (via USB Host mode)
A very small set of USB devices are supported in U-Boot depending on the version and configuration. Typically the following devices are used during development:
- USB Network Adapters
- USB Mass Storage
USB Network Adapters
A very small set of USB network adapters are supported in U-Boot depending on the version and configuration:
- ASIX AX8817X - (ie [http://plugable.com/products/usb2-e100 Plugable USB2-E100 10/100mbps)
- network device: asx0
- SMSC LAN95xx
- network device: sms0
Depending on the version of U-Boot more devices may be available
To use these use the following U-Boot configuration:
- scan USB bus for supported devices:
usb start
- If you have a supported USB device attached you will see a message to that effect
- set active ethernet device (use 'net list' to see a list of device names)
setenv ethact asx0
- Use networking as needed:
ping 192.168.1.254 tftp ${loadaddr} ${file}
USB Mass Storage (UMS) Device
USB Mass Storage (UMS) device support is not as robust as it is on Linux. Specifically some older devices that have support for various quirks in Linux may not work in U-Boot.
Older UMS devices sometimes fail to enumerate on the bus. If you encounter this you can try the following:
- see if it enumerates on a different port (sometimes enumerating through an on-board USB HUB can be problematic). If your board has a USB OTG or Type-C connector those interfaces do not go through a USB HUB so try your UMS device there
- try setting the 'usb_pgood_delay' env variable to something like 2000 before you do your 'usb start'. This represents a millisecond delay between enabling the VBUS regulator and enumerating the bus
Example:
u-boot=> usb start && usb tree starting USB... Bus usb@32e40000: Bus usb@32e50000: USB EHCI 1.00 scanning bus usb@32e40000 for devices... 1 USB Device(s) found scanning bus usb@32e50000 for devices... 4 USB Device(s) found scanning usb for storage devices... 1 Storage Device(s) found USB device tree: 1 Hub (480 Mb/s, 0mA) u-boot EHCI Host Controller 1 Hub (480 Mb/s, 0mA) | u-boot EHCI Host Controller | +-2 Hub (480 Mb/s, 0mA) | Microchip Tech USB2744 | +-3 Mass Storage (480 Mb/s, 100mA) | CENTON USB 52D0CE92 | +-4 Vendor specific (480 Mb/s, 0mA) Microchip Tech Hub Controller u-boot=> usb storage Device 0: Vendor: CENTON Rev: 8.07 Prod: Type: Removable Hard Disk Capacity: 61500.0 MB = 60.0 GB (125952000 x 512) u-boot=> ls usb 0:1 boot <DIR> 4096 . <DIR> 4096 .. 860 boot.scr 10407524 Image
USB Device Gadget support
Very limited support for USB device/gadget mode exists
USB Mass Storage (UMS) Gadget
The 'ums' command can be used to allow a host PC to access (slowly!) a block storage device on your target board.
On boards that support this with a USB OTG or Type-C connector cabled to a PC USB host you can use:
- ums <usb_controller> [<devtype>] <dev[:part]> - usb controller is the number of the usb controller (ie 0 or 1) to present the interface on while devtype, dev, and part specify the interface (devtype), device number (dev), and optional partition to expose via the USB Mass Storage device class
Examples:
- expose mmc device 0 on USB host controller 0 as a USB Mass Storage device:
usb start && ums 0 mmc 0
This requires CONFIG_USB_FUNCTION_MASS_STORAGE to be enabled and a USB host controller that can operate in gadget mode
USB CDC ACM (Serial) Gadget
You can use USB in device mode for console input/output to a host PC which supports the standard CDC ACM USB driver:
- Examples:
- use only ACM for console
setenv stderr usbacm && setenv stdout usbacm && setenv stdin usbacm
- use both ACM as well as original env based UART serial console (requires CONFIG_CONSOLE_MUX=y):
setenv stderr ${stderr},usbacm && setenv stdout ${stdout},usbacm && setenv stdin ${stdin},usbacm
- use only ACM for console
After doing this on your host PC the device is connected to with a USB-C to Host cable you should see a USB ACM device enumerate and can use it:
- example on a Linux PC you will see the following in syslog (dmesg):
usb 3-10.5.5: new high-speed USB device number 21 using xhci_hcd usb 3-10.5.5: New USB device found, idVendor=0525, idProduct=a4a5, bcdDevice= 2.21 usb 3-10.5.5: New USB device strings: Mfr=1, Product=2, SerialNumber=3 usb 3-10.5.5: Product: USB download gadget usb 3-10.5.5: Manufacturer: Gateworks usb 3-10.5.5: SerialNumber: 445096 usb-storage 3-10.5.5:1.0: USB Mass Storage device detected usb-storage 3-10.5.5:1.0: Quirks match for vid 0525 pid a4a5: 10000 cdc_acm 3-10.5.5:1.0: ttyACM0: USB ACM device # connect to ttyACM0 with a terminal program such as screen/minicom/picocom screen /dev/ttyACM0
This requires CONFIG_USB_FUNCTION_ACM to be enabled and a USB host controller that can operate in gadget mode
PCI
PCI bus support is enabled on the Ventana family due to the fact that at least one Ventana board model has only PCI based network interfaces.
NetConsole (access U-Boot console from network)
U-Boot does not contain any TCP implementation and as such there is no 'telnet server' or 'telnetd' support. There is however something similar called 'NetConsole' which will allow stdin/stdout/stderr to be directed to a UDP network port. If you set this up you can use the Linux 'nc' or 'netcat' tool or use the the 'netconsole' shell script provided in tools/netconsole (which uses these tools) to talk to U-Boot's interpreter from a Linux host.
Using NetConsole, the paradigm is reversed from the telnet/ssh perspective a bit such that you need to configure U-Boot to listen to a specifc IP address of a server.
To enable NetConsole you must do the following:
- U-Boot:
- configure networking: For example have a network interface supported by U-boot, set
ipaddr
env variable andserverip
env variable (make sure you canping $serverip
):setenv ipaddr 192.168.1.1 # local ip setenv serverip 192.168.1.146 # host ip running netcat/netconsole
- set the
ncip
address to your server:setenv ncip ${serverip}
- set stdin/stdout/stderr as desired to
nc
:setenv stdin nc; setenv stdout nc; setenv stderr nc
- (optional) if you want these changed persistent, do a
saveenv
:saveenv
- configure networking: For example have a network interface supported by U-boot, set
- Linux host:
- make sure you have netcat (either
nc
ornetcat
applications) - grab the
netconsole
shell script from U-Boot's tools directory:wget https://raw.githubusercontent.com/Gateworks/u-boot-imx6/gateworks_v2015.04/tools/netconsole chmod +x netconsole
- use
netconsole
to listen to your target IP address for input/output:netconsole 192.168.1.1
- Note that netconsole remaps the interrupt from Cntl-C to Cntl-T so that you can use Cntl-C over the network console
- make sure you have netcat (either
For a bootloader configuration that sits waiting for network commands from a specific host but with a timeout you can use the preboot env variable to execute a script prior to bootcmd such as:
setenv serverip 192.168.1.146 # your server ip setenv ipaddr 192.168.1.1 # your local ip setenv netretry no setenv preboot 'echo "Looking for server at $serverip..."; \ if ping $serverip; then setenv ncip ${serverip}; setenv bootdelay 10; \ echo "Starting NetConsole to ${ncip} and waiting for ${bootdelay} seconds..."; \ setenv stdin nc; setenv stdout nc; setenv stderr nc; \ fi' saveenv
- Note that we set
netretry
to 'no' which causes network operations to not retry (otherwise the ping will go forever). This could also be set to 'once' if you wish to cycle through all available network interfaces (such as on-board NIC's as well as USB nics) instead of just 'ethprime'.
This only pertains to input/output of the U-Boot environment. Once the bootloader jumps to the kernel, the kernel is in charge of what to do about its input/output, which is controlled via the 'console' kernel cmdline. Note that there is a CONFIG_NETCONSOLE option in the kernel that uses a 'netconsole' kernel cmdline however that option is not enabled in the Gateworks kernels by default
References:
Installing Large Disk Images on Systems with Limited RAM
In certain scenarios, devices with limited RAM face challenges when updating firmware or system images stored on MMC flash storage. Attempting to install large disk images directly may fail due to memory constraints. To address this limitation, a practical approach involves splitting the disk image into smaller chunks and updating the device incrementally. This wiki section documents a solution for how to install these larger than RAM disk images inside of u-boot; on Gateworks SBCs.
Spliting the Disk Image Into Segments
Before proceeding with the update process, the disk image needs to be split into smaller parts. This can be achieved using the Linux split
command, making sure to decompress the image if it's compressed. The key requirement for the process outlined here is that the file must be divided into segments that are evenly divisible by 512-byte blocks (so any multiple of KB or MB is fine). This ensures that the subsequent calculation of block count, as demonstrated in the script in the following section. Here are the steps to split our BSP disk image as an example:
# If the image is compressed, extract it first gunzip jammy-venice.img.gz # Split the image into parts of 500MB each named 'jammy-venice.img.part<x>' split -d -b 500M jammy-venice.img jammy-venice.img.part
Downloading and Installing the Segments
To handle the segmented installation of the disk image, we will utilize a U-Boot script specifically designed for devices with limited RAM. This script orchestrates the sequential installation of each segmented portion of the disk image. Here's how to create and use the U-Boot script:
cat <<\EOF> storage_split_update setenv storage_split_update 'if itest.s x == "x${splitfile}"; then # Check if the ${splitfile} environment variable is set echo "The following environment variables need to be set in order for this script to run:" echo " splitfile - full path file name prefix of the splitted files (eg file.img for file.img.part00)" exit 1 fi # Attempt to fetch the ${splitfile} to update storage echo "Attempting to fetch ${splitfile} to update storage" setenv 0 0 setexpr i 0 setexpr offset 0 # Iterate over segments to write to Storage while itest $i -le 99; do # Add leading zero to $i if necessary itest $i -gt 9 && setenv 0 if tftpboot $loadaddr ${splitfile}.part${0}${i}; then # Calculate block count setexpr blkcnt $filesize + 0x1ff setexpr blkcnt $blkcnt / 0x200 # Write segment to Storage if ${iface} write ${loadaddr} ${offset} ${blkcnt}; then echo "Successfully wrote segment ${i} of ${filesize} bytes" setexpr offset ${offset} + ${blkcnt} setexpr i ${i} + 1 # setexpr results in a hex number so convert to dec setexpr rem ${i} % 0x10; itest ${rem} -eq 0x0a && setexpr i ${i} + 6 else echo "Error writing segment ${i} of ${filesize} bytes" exit 1 fi elif itest ${i} -eq 0; then echo "ERROR: image file ${splitfile}.part${0}${i} not found or it is too big to fit in memory" exit 1 else echo "SUCCESS: ${splitfile} was successfully written to ${iface} storage device" exit 0 fi done' EOF
U-Boot requires scripts to be in a specific binary format for execution with the source
command. To compile the script into this format, we use the mkimage tool, which is provided as part of the U-Boot distribution.
mkimage -A arm64 -T script -C none -d storage_split_update ustorage_split_update
Once you have the u-boot source-able script and your split image segments saved to your tftp server; you can now install your large disk Image onto your target board.
cp storage_split_update your_tftp_server cp jammy-venice.img.part* your_tftp_server
Installing
Before running the update script, you need to download it from your tftp server to your target board, and you need to specify the name of the split image file that you want to use.
#Set your tftp server IP u-boot=> dhcp u-boot=> setenv serverip <YOUR_SERVER_IP> #Load the script, being sure to use full path name u-boot=> tftpboot /venice/ustorage_split_update u-boot=> source $loadaddr #Run the script & install the segments u-boot=> setenv splitfile /venice/jammy-venice.img
Depending on which storage device you want to write your Image to, you need to set the device accordingly then you can run the script. Here is the general use as well as a specific use case:
For MMC:
#mmc dev <device#> <hardware_partition#> # hardware partition: 0=user 1=boot0 2=boot1 u-boot=> mmc list # show mmc devs u-boot=> mmc dev 2 0 u-boot=> setenv iface mmc
For USB:
#usb dev <device#> <hardware_partition#> u-boot=> usb stop && usb start && usb storage # scan and show storage devs u-boot=> usb dev 0 0 u-boot=> setenv iface usb
For SATA:
#sata dev <device#> u-boot=> sata init && sata device # scan and show storage devs u-boot=> sata dev 0 u-boot=> setenv iface sata
For NVMe:
#nvme dev <device#> u-boot=> pci enum && nvme scan && nvme info # scan and show storage devs u-boot=> nvme dev 0 u-boot=> setenv iface nvme
To initiate the instillation after you have properly selected the storage device your want:
run storage_split_update
Once the image download and installation process is complete, you can proceed to use the board as usual.
u-boot=> boot