Goal: Configure a target running u-boot to retrieve files
via TFTP and a laptop to serve them, both using static IP addresses
for convenience. The command output shown here comes from a Freescale
SabreSD board running U-boot 2013.04 and connected to a laptop running
Debian, but the instructions are far more general, although x86-based
boards and Linux kernels before 3.0 do not make use of
device-tree.

Hardware set-up

Connect an appropriate cable between the console port (often a DB9
or USB connector) of your target and a USB connector on your laptop.
On Linux, the USB connection should appear at /dev/ttyUSB0. By
default, this device is not accessible to non-root users. Fix this
problem with:

<user@localhost>$ sudo addgroup $USER dialout

Then connect a LAN cable between the laptop and the target, either
using a crossover
cable or by interposing a network switch. The
LED next to the Ethernet connector on the board should light up.

Note that xinetd and NFS are potentially security risks if configured
improperly. Do not expose your $HOME via xinetd! Do not
configure NFS to serve files from /!

Now create a /tftpboot directly and copy your root filesystem,
kernel and device-tree there. U-boot follows symbolic links, so a lot
of developers create a symlink to the device-tree and kernel files so
that the U-boot environment variables (see below) need not ever
change.

What you've done so far will enable the board to access files in
/tftpboot via tftp, but will not tell NFS to make the root filesystem
available for mounting. Edit the /etc/exports file to config NFS:

# /etc/exports: the access control list for filesystems which may be exported
# to NFS clients. See exports(5).
/tftpboot 172.17.0.1(rw,sync,no_subtree_check,no_root_squash)

Here /tftpboot is the default directory that xinetd
exposes to the target and 172.17.0.1 is the IPv4 address I've
selected for it. The parameter no_root_squash is optional
and permits root to login to the target without a password. Once
you've modified /etc/exports, type

<user@localhost>$ sudo systemctl restart nfs-kernel-server

if the server is already running so that it will re-read its configuration file.

NetworkManager's nmtui shows the new laptop static IP connection under
the "Wired" heading.

Now to set our desired static IP address on the host. The easiest
way is use NetworkManager's nmcli. Here "SabreSD" is the name of the connection and 172.17.0.5 is my elected IP address:

The second command shows the settings for the new connection, which
now can be selected from nmtui ncurses configurator (see figure) or
your favorite NetworkManager GUI. Alternatively, you can use a script
to put your other wired connection down and choose the new static IP
connection:

When finished with your session connected to the board, use ntmui or nmcli to restore the default 'Wired connection 1'.

Configuring the kernel

The following kernel options are necessary as of Linux 4.1 to make
mounting the root filesystem via NFS work. Note static
compilation (=y) since loading of modules will not work until the
filesystem is mounted.

Implementation-specific parameters: console, baudrate, ipaddr,
serverip, rootfs, fdt_addr, dtbfile, loadaddr and uimage. Pick values
appropriate for your architecture and filesystem layout. Console
generally matches "tty*", baudrate is typically 115200, and ipaddr and
serverip are static IPv4 addresses (i.e., ones that don't start with
192 or 127). Any well-formed address can be chosen for your devices
if neither is connected to an external network. The pathnames in
dtbfile and uimage variables are relative to /tftpboot, if that's
where the files are located.

Note that you start the socket, not "systemctl start
sshd@0.service". The way systemd's socket-based activation works, the
listener on the socket will start the service automagically when a
client tries to connect.

(Finally) Bringing the Board Up

With these parameters, 'run netboot' at the U-boot prompt should
bring the board up. The most common mistake is to omit 'ip_dyn=no'.
If you do, tftp will work fine, but then the board will get a dynamic
address when the Linux kernel starts. Note that failure to edit
/etc/exports or to restart nfs-kernel-server after editing
/etc/exports also mean that tftp will start, but NFS will fail.

'ping -I eth0' insures that the laptop tries to use the hard-cabled
interface. I've seen ping report 'Network is unreachable' when wlan0
is disabled and eth0 is plugged in. U-boot can send pings but does
not respond, so it's necessary to boot the board to ping the other way.