Loading Linux Images via Ethernet and TFTP Print


This note explains how to load images to the target via Ethernet. With an Ethernet connection available, U-Boot can load images from a TFTP host quickly and easily. This is the development and software manufacturing option that is preferable with U-Boot and Linux.

The download procedure is based on the tftpboot command provided by the U-Boot command interface. tftboot implements a download capability over Ethernet using the TFTP protocol and has the following synopsis:

tftpboot <file> [<load_addr>]

If you do not specify a load address, then the value will be taken from the loadaddr environment variable. On the STM32H753I-EVAL board, loadaddr is set as follows, placing the download buffer into the on-module SDRAM:

STM32H7-EVAL U-Boot > print loadaddr
loadaddr=0xD0C00000
STM32H7-EVAL U-Boot >

The MAC address of the Ethernet interface is defined by the ethaddr environment variable.The IP address of the board is defined by the ipaddr U-Boot environment variable. The TFTP server IP address is defined by the serverip U-Boot environment variable. Make sure you define these environment variables to values that make sense for your LAN and save them in the SD Card:

STM32H7-EVAL U-Boot > env default -a
## Resetting to default environment
STM32H7-EVAL U-Boot > setenv ethaddr 12:34:56:78:9a:bc
STM32H7-EVAL U-Boot > setenv ipaddr 172.17.0.166
STM32H7-EVAL U-Boot > setenv serverip 172.17.0.1
STM32H7-EVAL U-Boot > saveenv

Saving Environment to MMC... Writing to MMC(0)... OK
STM32H7-EVAL U-Boot >

Once the transmission using tftpboot finishes, the file will be in memory at the specified load address. The loadaddr environment variable will automatically be set to the
address the tftpboot command used. The filesize environment variable will automatically be set to the number of bytes transferred during the load operation.

Then you are free to do whatever you like with the loaded image. You can boot Linux from the image (assuming it is a Linux uImage file), display the memory, etc.

One typical command sequence involving tftpboot is defined in the netboot environment variable, which by default is set in U-Boot as follows:

STM32H7-EVAL U-Boot > pri netboot
netboot=tftp ${image} && run addip && bootm
STM32H7-EVAL U-Boot >

What netboot does is load from tftpdir in a TFTP host a file defined by image (the tftp command), then add the TCP/IP related parameters to the kernel command string (addip), and finally boot Linux from the just loaded image (bootm).

Let's use netboot to boot Linux via TFTP from the sample Linux image (rootfs.uImage) included in the Emcraft software distribution. Copy rootfs.uImage to the appropriate (tftpdir) TFTP directory on the host and then from U-Boot on the target set the image environment variable to point to the image:

STM32H7-EVAL U-Boot > setenv image stm32h7-eval/rootfs.uImage STM32H7-EVAL U-Boot > saveenv Saving Environment to MMC... Writing to MMC(0)... OK STM32H7-EVAL U-Boot > run netboot ethernet@40028000 Waiting for PHY auto negotiation to complete. done Using ethernet@40028000 device TFTP from server 172.17.0.1; our IP address is 172.17.0.166 Filename 'stm32h7-eval/rootfs.uImage'. Load address: 0xd0c00000 Loading: ################################################################# ################################################################# ################################################################# ################################################################# ################################################################# ################################################################# ################################################################# ################################################################# ####################################### 1.1 MiB/s done Bytes transferred = 8192999 (7d03e7 hex) ## Booting kernel from Legacy Image at d0c00000 ... Image Name: Linux-6.1.28 Image Type: ARM Linux Multi-File Image (uncompressed) Data Size: 8192935 Bytes = 7.8 MiB Load Address: d0008000 Entry Point: d0008001 Contents: Image 0: 8176896 Bytes = 7.8 MiB Image 1: 16027 Bytes = 15.7 KiB Verifying Checksum ... OK ## Loading init Ramdisk from multi component Legacy Image at d0c00000 ... ## Flattened Device Tree from multi component Image at D0C00000 Booting using the fdt at 0xd13cc54c Loading Multi-File Image ... OK Loading Ramdisk to d1a7f000, end d1a82e9b ... OK ERROR: reserving fdt memory region failed (addr=d1c00000 size=300000) ERROR: reserving fdt memory region failed (addr=d1f00000 size=100000) Loading Device Tree to d1a78000, end d1a7ee9a ... OK Starting kernel ... [ 0.000000] Booting Linux on physical CPU 0x0 [ 0.000000] Linux version 6.1.28 (sasha@workbench.emcraft.com) (arm-none-eabi-gcc (GNU Arm Embedded Toolchain 10.3-2021.10) 10.3.1 20210824 (release), GNU ld (GNU Arm Embedded Toolchain 10.3-2021.10) 2.36.1.20210621) #14 PREEMPT Wed Aug 9 10:18:28 UTC 2023 [ 0.000000] CPU: ARMv7-M [411fc271] revision 1 (ARMv7M), cr=00000000 [ 0.000000] CPU: PIPT / VIPT nonaliasing data cache, PIPT instruction cache [ 0.000000] OF: fdt: Machine model: STMicroelectronics STM32H753i-EVAL board ..... [ 2.439510] ip=172.17.0.166:172.17.0.1::::eth0:off init started: BusyBox v1.24.2 (2023-08-08 13:33:53 UTC) [43] Jan 01 00:00:02 Running in background / # / # ps PID USER VSZ STAT COMMAND 1 root 732 S init 2 root 0 SW [kthreadd] 3 root 0 IW< [rcu_gp] 4 root 0 IW< [rcu_par_gp] 5 root 0 IW< [slub_flushwq] 7 root 0 IW< [kworker/0:0H-ev] 8 root 0 IW [kworker/u2:0-ev] 9 root 0 IW< [mm_percpu_wq] 10 root 0 SW [ksoftirqd/0] 11 root 0 IW [rcu_preempt] 12 root 0 SW [kdevtmpfs] 13 root 0 IW< [inet_frag_wq] 14 root 0 IW [kworker/0:1-eve] 15 root 0 IW< [writeback] 16 root 0 IW< [kblockd] 17 root 0 SW [watchdogd] 18 root 0 IW< [kworker/0:1H-kb] 19 root 0 IW< [rpciod] 20 root 0 IW< [xprtiod] 21 root 0 IW [kworker/u2:1-ev] 22 root 0 SW [kswapd0] 23 root 0 IW< [nfsiod] 24 root 0 IW< [stmmac_wq] 27 root 0 SW [irq/34-mmci-pl1] 30 root 0 IW< [mld] 31 root 0 IW< [ipv6_addrconf] 32 root 0 IW< [mmc_complete] 43 root 712 S dropbear -R 45 root 752 S -/bin/hush 65 root 0 SW [scsi_eh_0] 66 root 0 IW< [scsi_tmf_0] 67 root 0 SW [usb-storage] 68 root 0 IW [kworker/0:0-eve] 69 root 0 IW [kworker/0:2-pm] 70 root 740 R ps / #

Here are some troubleshooting tips, in case tftpboot does not work for you from U-Boot:

  1. As trivial as it sounds make sure that the board is connected to the LAN with an Ethernet cable.
  2. Suppose you are still not getting your file from the TFTP server. It is possible that the problem is on the host side - you must set up a TFTP server correctly. Just google for "how to set up a tftp server" and follow the advice from some top articles.
  3. Make sure you have copied a file you are trying to download to the TFTP server directory on the host.
  4. Disable the firewall on the host since get enabled, it will block TFTP requests from the target.
  5. On the target, make sure that you have set ipaddr and serverip correctly. Check ethaddr and make sure that you don't have another embedded board (eg. another board) configured for the same MAC address.