Skip to content

Instantly share code, notes, and snippets.

@sr105
Created July 18, 2021 23:13
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save sr105/6ac4476af97623a20be6ae588c2c9a97 to your computer and use it in GitHub Desktop.
Save sr105/6ac4476af97623a20be6ae588c2c9a97 to your computer and use it in GitHub Desktop.
Embedded Server Installation - DHCP, TFTP, NFS
Network Booting

It saves time during development to boot the kernel and use a networked rootfs from the developer’s machine. It also allows for editing on the host files used live on the target

Two variants: with/without PXE

The device can be statically configured in the boot loader to know it’s IP address and what files to download and how to boot them. OR you can configure a DHCP server to tell the device those steps. The latter is preferred as it moves more of the configuration to the developer’s machine and requires less interaction with U-Boot on the device over the console.

TFTP
Install
sudo apt install tftpd-hpa
sudo chmod 1777 /srv/tftp
Check server optionsDefaults (after normal install)
tftpd-hpa.service
└─29319 /usr/sbin/in.tftpd --listen --user tftp --address :69 --secure /srv/tftp
Desired configuration options
  1. –listen
  2. –address DEVICE_NET_IP
    • limit to the one interface
    • it will use port 69 by default, no need to specify
  3. –create
    • allow new files to be created. makes it easy for devs to stash a file
  4. –secure
    • Uses chroot and makes all server paths referenced from /
  5. –user tftp
    • Default for systemd
  6. /srv/tftp
    • I used to use /tftpboot, but this is ok.
Overwrite /etc/default/tftpd-hpa Limit it to the one interface hooked up to development boards.
# /etc/default/tftpd-hpa

TFTP_USERNAME="tftp"
TFTP_DIRECTORY="/srv/tftp"
TFTP_ADDRESS="192.168.2.1:69"
TFTP_OPTIONS="--secure --create"

sudo systemctl restart tftpd-hpa

NFS
Build tar images Add tar.bz2 to IMAGE_FSTYPES in conf/local.conf
  • This already seems to be part of the dey image or machine configs.
Install
sudo apt install nfs-kernel-server
sudo mkdir /srv/tsproot
sudo chown root:$(id -u) /srv/tsproot
sudo chmod 775 /srv/tsproot
sudo bash -c "echo '/srv/tsproot/ *(rw,no_root_squash,async,no_subtree_check)' >> /etc/exports"
sudo systemctl restart nfs-kernel-server
Install Rootfs
# cd to tmp/deploy/images/tspv1rb
sudo tar --numeric-owner -C /srv/tsproot -xvjf dey-image-tsp-tspv1rb.tar.bz2
DHCP

Use ISC’s DHCP server as Busybox’s server doesn’t support device matching. sudo apt install isc-dhcp-server

The main thing to do is configure DHPCd to hand out addresses only on the interface connected to devices. Also, we only want it to hand out addresses to devices we specify with a MAC address.

/etc/dhcp/dhcpd.conf Configure a range of
subnet 192.168.2.0 netmask 255.255.255.0 {
 range 192.168.2.10 192.168.2.20;
 option routers 192.168.2.1;
 # boot-unknown-clients off;
 # ignore unknown-clients;
 # Only if your TFTP server is elsewhere
 # next-server 192.168.2.1;
}

group {
  filename "dey-imx6ul-boot.scr";
  # Use the host name for hostname
  use-host-decl-names on;
  # To turn this off without turning off DHCPd
  # deny booting;
  host harvey-dey { hardware ethernet 00:04:F3:18:07:88; }
}

# Don't listen or respond on these subnets (which are configured on this server)
subnet 192.168.170.0 netmask 255.255.255.0 {
}
subnet 10.73.111.0 netmask 255.255.255.0 {
}
subnet 172.17.0.0 netmask 255.255.0.0 {
}
subnet 10.47.61.0 netmask 255.255.255.0 {
}
subnet 10.0.2.0 netmask 255.255.255.0 {
}
/etc/default/isc-dhcp-server
# Only listen on this interface
INTERFACES="enx0050b60b7c3c"

sudo systemctl restart isc-dhcp-server

Booting
Manually Apparently, the first network port becomes eth1 in Linux. Stupid Linux. I have my dedicated development machine interface set to 192.168.2.1/24.Manual commands on brand new dev board
setenv ipaddr 192.168.2.2
setenv netmask 255.255.255.0
setenv serverip 192.168.2.1
setenv gatewayip 192.168.2.1
setenv hostname harvey-dey
setenv rootpath /srv/tsproot
setenv fdt_file imx6ul-ccimx6ulsbc.dtb
setenv zimage zImage-ccimx6ulsbc.bin
setenv bootargs_ip "ip=${ipaddr}:${serverip}:${gatewayip}:${netmask}:${hostname}:eth1:off"
setenv bootargs "console=${console},${baudrate} ${bootargs_linux} root=/dev/nfs ${bootargs_ip} nfsroot=${serverip}:${rootpath},v3,tcp ${mtdparts} ${bootargs_once} ${extra_bootargs}"
tftpboot ${loadaddr} ${zimage}
tftpboot ${fdt_addr} ${fdt_file}
bootz ${loadaddr} - ${fdt_addr}
Set manual commands to auto-boot
env set ipaddr 192.168.2.2
env set netmask 255.255.255.0
env set serverip 192.168.2.1
env set gatewayip 192.168.2.1
env set hostname harvey-dey
env set rootpath /srv/tsproot
env set fdt_file imx6ul-ccimx6ulsbc.dtb
env set zimage zImage-ccimx6ulsbc.bin
env set bootargs_harvey 'setenv bootargs_ip "ip=${ipaddr}:${serverip}:${gatewayip}:${netmask}:${hostname}:eth1:off"; setenv bootargs "console=${console},${baudrate} ${bootargs_linux} root=/dev/nfs ${bootargs_ip} nfsroot=${serverip}:${rootpath},v3,tcp ${mtdparts} ${bootargs_once} ${extra_bootargs}"'
env set boot_harvey "run bootargs_harvey; tftpboot ${loadaddr} ${zimage}; tftpboot ${fdt_addr} ${fdt_file}; bootz ${loadaddr} - ${fdt_addr}"
env set bootcmd_orig "${bootcmd}"
env set bootcmd "run boot_harvey"
env save
Via DHCP Create a DHCP config that recognizes the board type somehow and returns a u-boot script file containing boot commands.Boot Script
  • /tftpboot/dey-imx6ul-boot.txt
setenv bootargs "console=${console},${baudrate} root=/dev/nfs ip=dhcp nfsroot=${serverip}:/srv/tsproot,v3,tcp";
tftpboot ${loadaddr} zImage-ccimx6ulsbc.bin;
tftpboot ${fdt_addr} imx6ul-ccimx6ulsbc.dtb;
bootz ${loadaddr} - ${fdt_addr};
ln -s /work/yocto/build/tmp/sysroots-components/x86_64/u-boot-tools-native/usr/bin/mkimage ~/.local/bin
mkimage -T script -C none -n 'Boot TSP via TFTP/NFS' -d boot-net.txt boot-net.scr
Boot Script 2
setenv bootargs_ip "ip=dhcp"
setenv rootpath /srv/tsproot
setenv bootargs console=${console},${baudrate} ${bootargs_linux} root=/dev/nfs ${bootargs_ip} nfsroot=${serverip}:${rootpath},v3,tcp ${mtdparts} ${bootargs_once} ${extra_bootargs}
tftpboot $loadaddr zImage-tspv1rb.bin
tftpboot $fdt_addr imx6ul-tspv1rb.dtb
bootz $loadaddr - $fdt_addr
  • Kick off via uuu

    We have to run our reset_ethernet command because the TSP is hard coded to 10 Mbps, but U-Boot expects the speed to be autonegotiated. It’s builtin to their tftp/dhcp code. Besides, that reseting gives us 100 Mbps.

    uuu u-boot-tspv1rb.imx
    uuu fb: acmd run reset_ethernet \&\& dhcp \&\& source
        
Set board to boot over DHCP
env set bootcmd_orig "${bootcmd}"
env set bootcmd "dhcp && source"
env save
Auto-restart dhcpd and tftpd when interface appears
udev rule detects a removable (USB) ethernet device and auto-restarts dhcpd and tftpd
  • Run after the system is fully started (don’t run while booting)
  • Run whenever a new ethernet device is added
  • Restart the dhcpd and tftpd services
  • Udev Rules Documentation
  • sudo systemctl restart isc-dhcp-server tftpd-hpa
  • systemctl list-units --type=service --state=failed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment