Difference between revisions of "TFTP Boot and NFS Root Filesystems"

From eLinux.org
Jump to: navigation, search
(minor text updates and typo correction)
(rework of text to simplify)
Line 2: Line 2:
 
<br />
 
<br />
 
= How To Set Up TFTP Boot And NFS Root Filesystems On Parallella =
 
= How To Set Up TFTP Boot And NFS Root Filesystems On Parallella =
 
+
This Guide describes how to set up the Parallella U-Boot to netwok boot using TFTP. <br />
 +
Also, it describes how to set up mounting a root filesystem (''rootfs'') via NFS. <br />
 +
See the Manual for [http://www.denx.de/wiki/DULG/Manual Das U-Boot]<br />
 +
The following is based on the original blog post by [https://plus.google.com/+shogunx/posts/K5taMhPKurp Scott Johnson] describing how to set up a Parallella cluster to use TFTP/NFS, but has been tweaked - mainly to minimise the need to edit/update the U-Boot variables via the Serial/UART cable, and provide more flexibility by using PC-based editors and storage.<br />
 +
By editing a ''bootscript'' on the TFTP server (and re-booting), a Parallella can be re-configured to a different boot mode (headless,HDMI) and/or different root filesystem (Ubuntu, Debian, nano) - all without having to 'burn' another Parallella SD card (perhaps ever..?).<br />
 +
Tweak the example below to suit your  needs.
 
== Requirements ==
 
== Requirements ==
 
+
Linux PC, Parallella board(s), USB to Serial (TTL/UART) adapter, DHCP server.
Linux PC, Parallella board(s), USB to TTL/UART adapter, DHCP server
 
 
 
 
== Summary ==
 
== Summary ==
 
This is an approach to booting the Parallella using TFTP, and mounting the root filesystem via NFS. It should be useful to the owner of a Parallella cluster, or even the owner of a single Parallella.<br />
 
Each Parallella is modified to fetch a ''bootfile'' script via TFTP, which points at a ''bootmode'' TFTP directory containing the loadable images. <br />
 
The ''bootfile'' also sets up the NFS boot parameters. <br />
 
By editing the ''bootfile'' on the TFTP server, the Parallella can quickly and easily be re-configured to a different ''bootmode'', and/or change the NFS Filesystem - all without having to 'burn' another micro-SD card (ever..??). <br />
 
Although it requires a bit of preparation, the approach involves minimal changes to each Parallella U-Boot environment using the USB to UART cable, and then all the loading and re-configuration is controlled on the TFTP/NFS host - in this case, a Debian PC.
 
 
 
This Guide describes:
 
This Guide describes:
* An addressing and naming scheme to support the choice of ''bootmode'' (headless, HDMI) and NFS root filesystems.
+
* An IP addressing and naming scheme to support different boot modes (headless, HDMI) and NFS root filesystems.
* A directory layout for TFTP ''bootfiles'' and ''bootmode'' image files
+
* Setting up TFTP and a directory layout for TFTP ''bootscripts'' and boot mode image files.
* Changing the way the boot command arguments are passed to the kernel, i.e. in a U-Boot script rather than devicetree
+
* Changing the way the boot arguments are passed to the kernel, i.e. in the U-Boot 'bootargs' rather than devicetree "chosen {}" branch.
* A directory layout for NFS root filesystems, allowing a choice of filesystems for each Parallella
+
* A directory layout for NFS root filesystems, allowing a choice of root filesystems for each Parallella.
* The minimum changes to the U-Boot variables on each board to trigger a network TFTP boot instead of micro-SD card boot
+
* Changing the U-Boot boot command to fetch a small script file using TFTP.
* An example script for TFTP boot and NFS root filesystems.
+
* An example ''bootscript'' for TFTP boot and NFS root filesystem.
* Use of mkimage to convert the ''bootfile'' text file into a U-Boot script image file.
+
* Use of mkimage to convert the ''bootscript'' text file into a U-Boot script image file.
 
+
* A breakdown of the ''bootscript'' to show how it might be altered to suit different environments.
There are many examples and reference material to illustrate the flexibility of U-Boot, and TFTP booting for ARM-based and embedded systems - you only need to search for them. TFTP booting appears to be normal for small embedded systems. See [http://www.denx.de/wiki/DULG/Manual the Manual for Das U-Boot]<br />
+
IMPORTANT NOTE:  
The following is originally based on the blog post by [https://plus.google.com/+shogunx/posts/K5taMhPKurp Scott Johnson] describing how to set up a Parallella cluster to use TFTP/NFS, but along the line it has been tweaked - mainly to minimise the need to edit/update the U-Boot variables via the UART cable, and make more use of the PC-based editors, etc.<br />
+
* {Sept 2014} There is a problem in Parallella U-Boot w.r.t. the Ethernet interface after any network activity in U-Boot (e.g. TFTP). (See the post on the Parallella forum post by [http://forums.parallella.org/viewtopic.php?f=48&t=1667#p10409 tajama]). The ethernet interface is left in an unuseable state.  A workaround is included in the script example below; but before attempting to apply it - you MUST check the U-Boot version. (Revisit)
Tweak the example below to suit your local needs ...  
+
* {Sept 2014} the Parallella U-Boot is being updated which just might affect the script below. (Revisit).  
 
+
= Prepare File Service Environments =
IMPORTANT CAVEATS:  
+
== Set up IP Addresses ==
* There appears to be a problem in Parallella U-Boot w.r.t. the Ethernet interface after any network activity in U-Boot (e.g. TFTP). (See the post on the Parallella forum post by [http://forums.parallella.org/viewtopic.php?f=48&t=1667#p10409 tajama]). In effect, the network interface is left in an unuseable state.  A workround is included in the script example below; but before attempting to apply it - you MUST check the U-Boot version. (To be revisited)
+
Allocate IP addresses for the Parallella(s) and the TFTP/NFS servers in your DHCP server based on MAC address. The Parallella MAC address is printed on the board, and is also a U-Boot variable (see later).<br />
* As of early Sept 2014, the Parallella U-Boot is to being updated, which may affect the script below. (To be revisited).  
+
Refer to the documentation of your DHCP server, or discuss with your network admin. <br />
 
+
The IP addresses are used as follows:
== IP Addressing and Naming ==
+
* U-Boot tftpboot command requests a ''bootscript'' file, and needs the TFTP server IP address <serverip>, and its own IP address <ipaddr>.
The approach relies on consistent IP address allocation and naming:
+
* U-Boot tells Linux to use DHCP.  
* On the Parallella, the U-Boot tftpboot command uses the IP address of the TFTP server <serverip>, its own IP address <ipaddr>.
+
* NFS uses IP addresses to control access to the rootfs directories.
* The tftpbooot command will request a file based on a unique hostname.
+
This is an example IP address allocation and naming convention (your network may vary):
* On booting, U-Boot will tell Linux to use DHCP.
 
* The NFS service uses the IP address of the Parallella to control access to the exported NFS directories.
 
 
 
The IP addresses for the Parallella(s) and the TFTP/NFS servers are pre-allocated in the DHCP server - based on MAC address.<br />
 
The MAC address of each Parallella is printed on a label on the board, but is also held as a U-Boot variable (see later).<br />
 
Refer to the documentation of your DHCP server, or discuss with your network admin. In my case, the DHCP server runs in the ISP-supplied home router.
 
 
 
Note: the TFTP and NFS services do not need to be on the same physical server, or even the same operating system. Here, a Debian (Wheezy) PC provides both services.
 
 
 
The Parallella naming convention and IP allocation (for this example) is as follows:
 
 
<blockquote>
 
<blockquote>
 
<pre>
 
<pre>
192.168.1.201 para1
+
192.168.1.201 para1 // <ipaddr> IP address of Parallella "para"<n>
 
192.168.1.202 para2
 
192.168.1.202 para2
192.168.1.203 para3
 
192.168.1.204 para4
 
 
...
 
...
 
192.168.1.208  para8    // ... I wish
 
192.168.1.208  para8    // ... I wish
 
+
192.168.1.50 TFTP server // IP address of TFTP server "serverip"
192.168.1.50 TFTP server // IP address of PC TFTP server
+
192.168.1.50 NFS server // IP address of NFS server "nfs_ip"
192.168.1.50 NFS server // in this case, both services are on the same Debian PC
 
 
</pre>
 
</pre>
 
</blockquote>
 
</blockquote>
 
+
Note: The TFTP and NFS services do not need to be on the same physical server, or even the same operating system. Here, a Debian (Wheezy) PC provides both services.<br />
== Set up the TFTP and NFS services ==
+
== Prepare the TFTP Service ==
On Debian, get the required packages, if not already set up.
+
Get the required software if not already set up. On Debian:
 +
<pre>
 +
apt-get install tftpd-hpa
 +
</pre>
 +
The TFTP service does not start automatically. <br />
 +
Start the tftpd-hpa service automatically by adding a command to ''/etc/rc.local'' (just before the exit 0 line).
 +
<pre>
 +
sudo nano /etc/rc.local
 +
</pre>
 +
(Edit and save)
 +
<pre>
 +
service tftpd-hpa start
 +
</pre>
 +
To control the TFTP service use:
 
<pre>
 
<pre>
apt-get install tftpd-hpa nfs-kernel-server
+
sudo service tftpd-hpa restart // or 'stop', or 'start' as needed.
 
</pre>
 
</pre>
By default, the NFS service is configured to start automatically, but the tftpd_hpa service is not. (There are a few ways to start the tftpd-hpa service automatically - not covered here)
+
=== Set up the TFTP Directories ===
To control the tftp and NFS services use:
+
By default, the tftpd-hpa service looks for requested files under ''/srv/tftp/''. Each Parallella has its own ''bootscript'', e.g. ''para1''. This is a U-Boot script image file, created using ''mkimage'' from a text file (see below).  The ''bootscript'' points U-Boot to a boot mode directory. The ''bootscript'' also provides U-Boot with the Linux boot parameters to mount the NFS root filesystem, and finally to boot the kernel. <br />
 +
Each boot mode (headless, HDMI, etc) has a separate directory containing the equivalent of the BOOT partition on a SD card, containing the kernel, parallella.bit.bin and devicetree image files. <br />
 +
Different sets of image files can be held in different directories, e.g. ''hdmi_7010_new_kernel/'', ''test_usb_fix/''. <br />
 +
Note: that is one directory per boot mode - not one per Parallella.<br />
 +
Create a boot mode directory:
 
<pre>
 
<pre>
sudo service tftpd-hpa start          // or 'stop', or 'restart' as needed.
+
sudo mkdir -p /srv/tftp/<name> // replace <name> with boot mode, e.g. hdmi_7010
sudo service nfs-kernel-server restart // or 'stop', or 'start' as needed.
 
 
</pre>
 
</pre>
 
+
== Prepare the Image Files ==
== The Bootfile Directories ==
+
Follow the instructions for creating the SD card (that is, download, extract and rename the kernel uImage, parallella.bit.bin and devicetree.dtb files), but instead of 'burning' to a SD card simply copy the image files to the boot mode directory (as root).<br />
By default, the tftpd-hpa service looks for requested files in the ''/srv/tftp/'' directory. The directory is owned by root, so use sudo for file commands here (or run as root). <br />
+
The TFTP service directory layout (for this example) will look something like:
 
 
The Parallella boot files are prepared under ''/srv/tftp/'' as follows.<br />
 
Each ''bootmode'' (e.g. headless_7010 or HDMI_7010) has a separate directory under ''/srv/tftp''. Note: that is one directory per ''bootmode'' - not one per Parallella.
 
Different types or generations of image files can be held in different ''bootmode'' directories, e.g. ''hdmi_7010_new_kernel/'', ''test_usb_fix/''. <br />
 
Each directory contains the equivalent of a BOOT partition on a micro-SD card, containing the kernel, parallella.bit.bin and devicetree images. To create the contents, follow the instructions for creating a micro-SD card, that is, download, extract and rename the kernel uImage, parallella.bit.bin and devicetree.dtb files.  Instead of 'burning' to a micro-SD card, simply copy the image files to the ''bootmode'' directory (as root or using sudo).
 
 
 
Each Parallella has its own ''bootfile'' image, e.g. ''para1''. This file is a U-Boot script, which is created using mkimage from a text file, e.g. ''para1'' (see below).  The ''bootfile'' points U-Boot to the ''bootmode'' directory. The ''bootfile'' also tells U-Boot to set up the Linux boot parameters to point to the NFS root filesystem, and finally to boot the kernel (see below).
 
 
 
The directory layout (for this example) looks like:
 
 
<blockquote>
 
<blockquote>
 
<pre>
 
<pre>
 
/svr/tftp/ // TFTP service directory
 
/svr/tftp/ // TFTP service directory
hdmi_7010/ // bootmode: Zynq 7010 with HDMI support
+
hdmi_7010/ // boot mode = Zynq 7010 with HDMI support
 
paralella.bit.bin
 
paralella.bit.bin
 
devicetree.dtb
 
devicetree.dtb
 
uImage
 
uImage
headless_7010/ // bootmode: Zynq 7010 Parallella configured as headless
+
headless_7010/ // boot mode = Zynq 7010 Parallella configured as headless
 
paralella.bit.bin
 
paralella.bit.bin
 
devicetree.dtb
 
devicetree.dtb
 
uImage
 
uImage
hdmi_7010_new_kernel/ // bootmode: example testing variation
+
hdmi_7010_new_kernel/ // boot mode = temp testing variation
 
paralella.bit.bin
 
paralella.bit.bin
 
devicetree.dtb
 
devicetree.dtb
 
uImage
 
uImage
para1         // initial bootfile for para1
+
para1         // bootscript for para1
para2         // initial bootfile for para2
+
para2         // bootscript for para2
para3         // initial bootfile for para3
 
para4         // initial bootfile for para4
 
 
...
 
...
para8         // etc, etc
+
para8         // bootscript for para8, etc
 
</pre>
 
</pre>
 
</blockquote>
 
</blockquote>
 
+
Note: The image files follow the same naming convention as for SD card booting.
== Edit the Devicetree ==
+
== Remove Bootargs from Devicetree ==
In this approach, the kernel boot command parameters are created in the ''bootfile'' script and passed to the kernel by U-Boot rather than in the devicetree.dtb file. To change the devicetree, install the devicetree compiler if not already installed, and edit the supplied devicetree.dtb in each ''bootmode'' directory to remove the parameters which boot from the micro-SD card.
+
The devicetree as supplied by Adapteva passes the boot arguments to support booting from the SD card. Instead, the boot arguments are passed to the kernel by U-Boot, as defined in the ''bootscript''. <br />
 +
Install the devicetree compiler if not already installed. On Debian:
 
<pre>
 
<pre>
 
sudo apt-get install device-tree-compiler
 
sudo apt-get install device-tree-compiler
 
</pre>
 
</pre>
Produce a .dts text file from the existing devicetree.dtb file.
+
Extract/edit/rebuild the devicetree.dtb file to remove the parameters from the ''chosen {}'' branch.
 +
{Check.. do we need the linux console line in chosen ..? Revisit}
 
<pre>
 
<pre>
cd /srv/tftp/hdmi_7010     // for example
+
cd /srv/tftp/hdmi_7010
 
 
 
sudo dtc -I dtb -o dev.dts -O dts devicetree.dtb
 
sudo dtc -I dtb -o dev.dts -O dts devicetree.dtb
</pre>
 
Edit the devicetree text file to remove the mmc boot parameters from the 'chosen' branch, leaving the UART console line (if required).
 
<pre>
 
 
sudo nano dev.dts
 
sudo nano dev.dts
 
</pre>
 
</pre>
(Edit and save.)
+
Look for ''chosen {'' branch, remove the arguments, and save.
 
<blockquote>
 
<blockquote>
 
<pre>
 
<pre>
chosen {
+
chosen {  
linux,stdout-path = "/amba@0/uart@E0001000";
 
 
}
 
}
 
</pre>
 
</pre>
 
</blockquote>
 
</blockquote>
Recompile the devicetree.dtb in the ''bootmode'' directory, and delete the dev.dts file.
+
Recompile the devicetree.dtb and delete the dev.dts text file.
 
<pre>
 
<pre>
 
sudo dtc -I dts -O dtb -o devicetree.dtb dev.dts
 
sudo dtc -I dts -O dtb -o devicetree.dtb dev.dts
 
sudo rm dev.dts
 
sudo rm dev.dts
 
</pre>
 
</pre>
 
+
Repeat for all supplied devicetree.dtb files in each boot mode directory.
== Prepare the NFS Root Filesystems ==
+
== Prepare the NFS Service ==
Each Parallella is provided with a separate NFS directory containing its root filesystem. In this example, the NFS directories are placed under ''/srv/nfs''.<br />
+
Get the required software if not already set up. On Debian:
Just as with preparing and swapping different micro-SD cards, each Parallella could have different versions of root filesystem, (e.g. standard Ubuntu, development and experimentation, alternative builds). A Parallella can be re-purposed by rebooting after editing its ''bootfile''. Here is an example layout of NFS Filesystem directories showing separate filesystems for each Parallella, and variations.
+
<pre>
 +
apt-get install nfs-kernel-server
 +
</pre>
 +
The NFS service starts automatically.<br />
 +
To control NFS services use:
 +
<pre>
 +
sudo service nfs-kernel-server restart // or 'stop', or 'start' as needed.
 +
</pre>
 +
=== Set up the NFS Directories ===
 +
Each Parallella has at least one NFS directory containing a root filesystem. Each Parallella may have alternative root filesystems (e.g.  Ubuntu, Linaro Nano) - just like preparing and swapping alternative SD cards. <br />
 +
In this example, the directories are organised under ''/srv/nfs'', which need to be created. <br />
 +
<pre>
 +
sudo mkdir -p /srv/nfs
 +
sudo mkdir -p /srv/nfs/para1_ubuntu
 +
sudo mkdir -p /srv.nfs/para1_nano
 +
</pre>
 +
Here is an example layout of NFS filesystem directories showing separate branches for each Parallella.
 
<blockquote>
 
<blockquote>
 
<pre>
 
<pre>
 
/srv/nfs/
 
/srv/nfs/
para1/ // root filesystem for para1, based on, say, standard Parallella Ubuntu
+
para1_ubuntu/ // rootfs for para1, based on, say, Parallella Ubuntu
 
bin/
 
bin/
 
boot/
 
boot/
 
                 etc/
 
                 etc/
... // etc, etc
+
...
para1_deb/ // root filesystem for para1, with 9600's Debian and ESDK
+
para1_deb/ // rootfs for para1, with 9600's Debian and ESDK
 
bin/
 
bin/
 
boot/
 
boot/
 
                 etc/
 
                 etc/
... // etc, etc
+
...
para1_nano/ // root filesystem for para1 based on linaro_nano
+
para1_nano/ // rootfs for para1 based on linaro_nano
 
bin/
 
bin/
 
boot/
 
boot/
 
                 etc/
 
                 etc/
... // etc, etc
+
...
para2/ // root filesystem for para2
+
para2_ubuntu/ // rootfs for para2, based on, say, Parallella Ubuntu
 
bin/
 
bin/
 
boot/
 
boot/
 
                 etc/
 
                 etc/
... // etc, etc
+
...
        ...
 
 
         ...
 
         ...
para8/       // root filesystem for para8
+
para8_ubuntu/       // rootfs for para8, based on, say, Parallella Ubuntu
...       // etc, etc
+
...       // etc, etc
 
</pre>
 
</pre>
 
</blockquote>
 
</blockquote>
 
+
=== Update NFS Exports File ===
It is possible to share the same root filesystem between two or more Parallellas, but different temporary filestore, etc. needs to be set up, (not covered here).  Since there's loads of space(?) on the server disk(s), duplication is not costly in terms of storage. Care needs to be taken to manage version control (but it's much quicker and easier to manage/fix than re-burning a stack of micro-SD cards).
+
The NFS server requires ''/etc/exports'' to be configured correctly, to control access to each NFS filesystem directory to specific hosts.<br />
 
+
For each Paralella root filesystem that is created, add the export control line to ''/etc/exports'', adjusting (as you should for all examples herein) for your local IP address and directory naming scheme. The following is an example based on the layout described above.
Place the payload root filesystem in the target directory e.g. ''/srv/nfs/para1/'' <br />
 
This can be the default Parallella Ubuntu build, or, say, 9600's Debian images, or follow shodrucky's nano build from here [[http://elinux.org/Parallella_Linaro_Nano|Linaro-nano]], with some mods as below. <br />
 
For example, download the linaro-saucy-nano image.
 
<pre>
 
wget http://releases.linaro.org/14.04/ubuntu/saucy-images/nano/linaro-saucy-nano-20140410-652.tar.gz
 
</pre>
 
Extract the filesystem image to the NFS directory for the target Parallella.
 
<pre>
 
sudo tar --strip-components=1 -C /srv/nfs/para1_nano -xzpf ~/Downloads/linaro-saucy-nano-20140410-652.tar.gz
 
</pre>
 
Edit some configuration files as per shodrucky's notes.
 
Important note: To avoid the mistake of editing the host PC's configuration, '''make sure you are in the correct NFS subdirectory!!!'''.
 
<pre>
 
cd /srv/nfs/para1_nano // for example; Note the lack of '/' before etc/ !!
 
</pre>
 
=== Prevent installation of unnecessary packages ===
 
<pre>
 
sudo nano etc/apt/apt.conf.d/00InstallRecommends
 
</pre>
 
(Edit and save.)
 
<pre>
 
    APT::Install-Recommends "false";
 
</pre>
 
 
 
=== Network configuration ===
 
The assumption is that DHCP will be used. Edit the interfaces file.
 
I DONT THINK YOU NEED TO DO THIS BECAUSE WE'VE ALREADY TOLD LINUX TO USE DHCP -  TO BE REVISITED
 
<pre>
 
sudo nano /srv/nfs/para1/etc/network/interfaces
 
</pre>
 
(Edit and save.)
 
<pre>
 
    source-directory /etc/network/interfaces.d
 
    auto lo
 
    iface lo inet loopback
 
    auto eth0
 
    # If you prefer DHCP, comment out the above 5 lines, uncomment the below.
 
    iface eth0 inet dhcp
 
      up sleep 3; mii-tool -F 1000baseT-FD
 
</pre>
 
<pre>
 
sudo nano etc/resolv.conf  //// ???? is this needed
 
(Edit and save.)
 
<pre>
 
    nameserver 192.168.1.1
 
</pre>
 
 
 
== Set Up The NFS Filesystem Exports ==
 
The NFS server will require ''/etc/exports'' to be configured correctly, and export each NFS Filessystem directory to specific hosts only.
 
 
<pre>
 
<pre>
 
sudo nano /etc/exports
 
sudo nano /etc/exports
 
</pre>
 
</pre>
For each Paralella and for root each filesystem  add the following line to ''/etc/exports'', adjusting (as you should for all examples herein) for your local IP addressing scheme. Note that the ''bootfile'' ensures that only one of the optional filesystems can be accessed by a Parallella on a re-boot.
+
(Edit and save)
This is based on the example layout shown above.
 
<blockquote>
 
 
<pre>
 
<pre>
/srv/nfs/para1 192.168.1.201(rw,sync,no_root_squash,no_subtree_check)
+
/srv/nfs/para1_ubuntu 192.168.1.201(rw,sync,no_root_squash,no_subtree_check)
 
/srv/nfs/para1_deb 192.168.1.201(rw,sync,no_root_squash,no_subtree_check)
 
/srv/nfs/para1_deb 192.168.1.201(rw,sync,no_root_squash,no_subtree_check)
 
/srv/nfs/para1_nano 192.168.1.201(rw,sync,no_root_squash,no_subtree_check)
 
/srv/nfs/para1_nano 192.168.1.201(rw,sync,no_root_squash,no_subtree_check)
/srv/nfs/para2 192.168.1.202(rw,sync,no_root_squash,no_subtree_check)
+
/srv/nfs/para2_ubuntu 192.168.1.202(rw,sync,no_root_squash,no_subtree_check)
...
+
/srv/nfs/para8_ubuntu 192.168.1.208(rw,sync,no_root_squash,no_subtree_check)
...
 
/srv/nfs/para8 192.168.1.208(rw,sync,no_root_squash,no_subtree_check)
 
 
</pre>
 
</pre>
</blockquote>
+
Note: The ''bootscript'' ensures that only one of the optional filesystems will be accessed/mounted by a Parallella on a re-boot.<br />
 
+
=== Export the NFS Directories ===
Ensure that these directories are exported either by using the following command, or by restarting the NFS service, as follows:
+
Ensure that these directories are made visible by the NFS service. Either:
 
<pre>
 
<pre>
 
sudo exportfs -a
 
sudo exportfs -a
Line 245: Line 192:
 
sudo service nfs-kernel-server restart
 
sudo service nfs-kernel-server restart
 
</pre>
 
</pre>
 +
== Set up the Pallella NFS Root Filesystems ==
 +
Instead of 'burning' a filesystem image to a partition on the SD card, place the payload root filesystem in the NFS directory, e.g. ''/srv/nfs/para1/''. <br />
 +
Each source of root filesystem may need different preparation to enable the NFS access to work smoothly. Some examples below.<br />
 +
=== Default Parallella Ubuntu Build ===
 +
{under construction - as of Sept 2014: NFS mounts OK, but doesn't complete boot, two penguins ..??}
 +
=== 9600's Debian Build ===
 +
{under construction - as of Sept 2014: can't extract tar file ..??}
 +
=== Linaro Nano Build ===
 +
See [[Parallella Linaro Nano tftpboot NFS rootfs|how-to for network booting a Linaro Nano NFS rootfs]]
  
== Change The Parallella to Boot Using TFTP ==
+
= Set Up the Parallella to TFTP Boot =
This is the only change required on the Parallella itself. <br />
+
Repeat the following for each Parallella, changing the values of ''hostname'' and ''ipaddr'' as necessary.<br />
Remove any Ethernet, USB and HDMI cables and micro-SD card. <br />
+
Power off the Parallella and remove the ethernet, USB peripheral and HDMI cables and SD card. <br />
Connect a USB serial cable to the 3-pin header on the Parallella. (Example device http://www.adafruit.com/products/954 from Adafruit). <br />
+
Connect a USB serial cable to the 3-pin UART header on the Parallella. (Example device http://www.adafruit.com/products/954 from Adafruit). <br />
Use a terminal program (e.g. screen,minicom) to connect to the USB device.  On minicom, set hardware flow control to off, and point the logfile to, say, ~/minicomlog for diagnostics.  <br />
+
Use a terminal program (e.g. screen, minicom) to connect to the UART Serial device.  On minicom, set hardware flow control to off, and point the logfile to, say, ~/minicomlog for diagnostics.  <br />
 
Power up the Parallella.  <br />
 
Power up the Parallella.  <br />
After the boot failure messages, you should get the zynq-uboot> prompt in the terminal window. <br />
+
After the boot failure messages, you should get the ''zynq-uboot>'' prompt in the terminal window.  
This command displays a sorted list of the current state of the U-Boot environment variables.
+
Display a list of the current state of the U-Boot environment variables using the ''printenv'' command. <br />
<pre>
+
Check the value of the ''ethaddr=xx:xx:xx:xx:xx:xx'' variable; this should be the same as the label on the board, and the MAC address you are using for this Parallella in your DHCP server.<br />
printenv
+
Enter the following commands at the ''zynq-uboot>'' prompt in order to:
</pre>
+
* set the ''hostname'' variable which will be used as the ''bootscript'' name.
Note the value of the 'ethaddr=xx:xx:xx:xx:xx:xx' variable and check that this is the MAC address you are using for this Parallella in your DHCP server. It should be the same as the label on the board. It cannot be changed at the prompt.  <br />
+
* set the IP address of the Parallella and the TFTP server.
Enter the following commands at the zynq-uboot> prompt, adjusting the hostname and IP addresses. These commands will:
+
* create a variable ''tboot'' which contains the commands to fetch and execute the ''bootscript''.  
* Set the hostname and IP address <ipaddr> of this Parallella, and the IP Address of the TFTP server <serverip>, based on the example above.
+
* change the U-Boot bootcmd so that it will run the ''tboot'' TFTP boot sequence.  
* Set up a variable containing the TFTP boot sequence <t-boot>. This fetches the ''bootfile'' (based on <hostname>) for this Parallella into a memory address and executes it as a script. The ''bootfile'' is described below.
 
* Change the U-Boot boot command so that it will run the <t-boot> TFTP boot sequence.  
 
* Alternatively, change the U-Boot command to try the SD card first, before trying TFTP boot
 
<blockquote>
 
 
<pre>
 
<pre>
 
setenv hostname para1
 
setenv hostname para1
 
setenv ipaddr 192.168.1.201
 
setenv ipaddr 192.168.1.201
 
setenv serverip 192.168.1.50
 
setenv serverip 192.168.1.50
set t-boot 'tftpboot 0x100000 ${hostname} ; source 0x100000'
+
setenv taddr 0x100000
 +
setenv tboot 'tftpboot ${taddr} ${hostname} ; source ${taddr}'
 +
setenv bootcmd 'run tboot'
 
</pre>
 
</pre>
</blockquote>
+
Alternatively, if preferred as a fall-back, replace the U-Boot bootcmd in the above sequence so that the boot sequence tries to boot from the SD card first. If no SD card is present, then run the TFTP boot sequence.
EITHER (much preferred) replace the current bootcmd to run the t-boot sequence:
 
<blockquote>
 
 
<pre>
 
<pre>
setenv bootcmd 'run t-boot'
+
setenv bootcmd 'run modeboot ; run tboot'
 
</pre>
 
</pre>
</blockquote>
+
Check that the variables have been set correctly and, if OK, save to flash memory.
OR (as a fall-back) replace the U-Boot bootcmd to try to boot from a micro-SD card first; if no micro-SD card is present, then run the TFTP boot sequence.  
 
<blockquote>
 
 
<pre>
 
<pre>
setenv bootcmd 'run modeboot ; run t-boot'
+
printenv
</pre>
 
</blockquote>
 
Check (!!) that the variables have been set correctly and, if OK, save to flash memory.
 
<pre>
 
printenv   // Check. Check.
 
 
saveenv
 
saveenv
 
</pre>
 
</pre>
 +
Power off. <br />
 +
Reconnect the ethernet cable. <br />
 +
Reconnect any USB peripherals or HDMI you intend to use on the Parallella. <br />
 +
Ready to TFTP boot. <br />
 
Notes:  
 
Notes:  
* It's worthwhile checking (again) after a power recycle that the variables have been set correctly
+
* It's worthwhile checking (again) after a power recycle that the U-Boot variables have been set correctly
* To correct/change a variable, use the setenv command with new/correct value.
+
* To correct/change a variable, use the ''setenv'' command with new/correct value.
* To remove a variable e.g. 'badvarible',  use the setenv command with no value, e.g. setenv badvarible
+
* To remove a variable e.g. 'badvarible',  use the ''setenv'' command with no value, e.g. ''setenv badvarible''
* U-Boot autocompletes commands so 'print', 'set', 'save' will also work.
+
* U-Boot autocompletes commands so ''print'', ''set'', ''save'' will also work.
 
+
= Write a Parallella Bootscript =
Reconnect Ethernet cable and any peripherals you intend to use on the Parallella. Ready to TFTP boot.
+
On the PC host, the ''bootscript'' image file is created and edited as a text file, and compiled into a U-Boot executable image using mkimage.<br />
 
+
Create a working directory to hold the ''bootscript'' text file(s).
== Example Bootfiles ==
 
 
 
On the host, the ''bootfiles'' are created and edited as text files, and compiled into images using mkimage for loading/executing by U-Boot.
 
 
 
Create a working directory to hold the ''bootfile'' text files.
 
 
<pre>
 
<pre>
 
mkdir ~/Documents/bootscr
 
mkdir ~/Documents/bootscr
 
</pre>
 
</pre>
In summary, the directory structure on the Debian PC looks like this example:
+
Create a text file and copy/paste the text below as a template. The following is an example ''bootscript''. This loads the headless image files.<br />
<blockquote>
 
<pre>
 
/home/<user>/Documents/bootscr/ 
 
para1
 
para2
 
para3
 
para4
 
...
 
para8
 
</pre>
 
</blockquote>
 
 
 
== Example Bootfile ==
 
The following shows an example ''bootfile''. (A breakdown and explanation of the components follows).
 
 
 
Create a text file and copy/paste the text below. Edit/copy the file to create a ''bootfile'' script for each Parallella, adjusting the values of the <tftp_dir> and <nfs_rootfs> variables for each ''bootfile'' as necessary.
 
 
<pre>
 
<pre>
 
cd ~/Documents/bootscr
 
cd ~/Documents/bootscr
nano para1   // or para2, etc., etc.
+
nano para1.txt
 
</pre>
 
</pre>
(edit and save)
+
(Edit and save)
<blockquote>
 
 
<pre>
 
<pre>
setenv tftp_dir hdmi_7010
+
setenv tftp_dir headless_7010
setenv nfs_rootfs /srv/tftp/para1
+
setenv nfs_rfs /srv/tftp/para1_ubuntu
 
+
setenv bootargs ip=dhcp
setenv nfs_ip 192.168.1.52
+
setenv bootargs ${bootargs} console=ttyPS0,115200
setenv bootargs root=/dev/nfs rw nfsroot=${nfs_ip}:${nfs_rootfs}
+
setenv nfs_ip 192.168.1.50
setenv bootargs ${bootargs} ip=dhcp console=ttyPS0,115200
+
setenv bootargs ${bootargs} root=/dev/nfs rw nfsroot=${nfs_ip}:${nfs_rfs}
 
+
setenv bootargs ${bootargs} nfsrootdebug earlyprintk
 
setenv fpga_image parallella.bit.bin
 
setenv fpga_image parallella.bit.bin
 
setenv fpga_addr 0x4000000
 
setenv fpga_addr 0x4000000
Line 340: Line 267:
 
setenv fpga_tftp 'tftpboot ${fpga_addr} ${tftp_dir}/${fpga_image}'
 
setenv fpga_tftp 'tftpboot ${fpga_addr} ${tftp_dir}/${fpga_image}'
 
setenv fpga_load 'fpga load 0 ${fpga_addr} ${fpga_size}'
 
setenv fpga_load 'fpga load 0 ${fpga_addr} ${fpga_size}'
 
 
setenv fdt_image devicetree.dtb
 
setenv fdt_image devicetree.dtb
 
setenv fdt_addr 0x2A00000
 
setenv fdt_addr 0x2A00000
 
setenv fdt_tftp 'tftpboot ${fdt_addr} ${tftp_dir}/${fdt_image}'
 
setenv fdt_tftp 'tftpboot ${fdt_addr} ${tftp_dir}/${fdt_image}'
 
 
setenv kernel_image uImage
 
setenv kernel_image uImage
 
setenv kernel_addr 0x3000000
 
setenv kernel_addr 0x3000000
 
setenv kernel_tftp 'tftpboot ${kernel_addr} ${tftp_dir}/${kernel_image}'
 
setenv kernel_tftp 'tftpboot ${kernel_addr} ${tftp_dir}/${kernel_image}'
 
 
setenv phy_rst 'mw.w f8000008 df0d ; mw.w f8000140 00100801 ; mw.w f8000004 767b'
 
setenv phy_rst 'mw.w f8000008 df0d ; mw.w f8000140 00100801 ; mw.w f8000004 767b'
 
setenv rset_phy 'run phy_rst'
 
setenv rset_phy 'run phy_rst'
 
 
setenv boot_now 'bootm ${kernel_addr} - ${fdt_addr}'
 
setenv boot_now 'bootm ${kernel_addr} - ${fdt_addr}'
 
 
run fpga_tftp fpga_load kernel_tftp fdt_tftp rset_phy boot_now
 
run fpga_tftp fpga_load kernel_tftp fdt_tftp rset_phy boot_now
 +
</pre>
 +
Copy the file to create a ''bootscript'' for each Parallella, changing the filename. <br />
 +
Edit the values of the ''tftp_dir'' and ''nfs_rfs'' variables in each file as required.<br />
 +
The directory structure on the Debian PC will then look something like this:
 +
<blockquote>
 +
<pre>
 +
/home/{username}/Documents/bootscr/ 
 +
para1.txt
 +
para2.txt
 +
...
 +
para8.txt
 
</pre>
 
</pre>
 
</blockquote>
 
</blockquote>
 +
== Make the Bootscript Image ==
 +
Install the mkimage package if not already installed. On Debian:
 +
<pre>
 +
sudo apt-get install u-boot-tools
 +
</pre>
 +
Convert each ''bootscript'' text file into a loadable image by mkimage, and place the image in the TFTP server directory.
 +
<pre>
 +
sudo mkimage -A arm -O u-boot -T script -C none -a 0 -e 0 -n "t-Boot Script" -d ~/Documents/bootscr/para1 /srv/tftp/para1
 +
</pre>
 +
 +
== Reboot the Parallella ==
 +
Reboot by power off, wait a few seconds, power on. <br />
 +
The output to the UART Serial terminal screen shows initialisation of the board and network, and then the boot sequence looking for the TFTP server.
 +
If the TFTP 'Loading:' line puts out a few 'T T T's, then it's retrying. Give it a few moments but if there's a line of 'T's then check that the TFTP service is actually running, and that the IP addresses and filename of the ''bootscript'' are valid. <br />
 +
Once the small (~1kb) ''bootscript'' has been loaded and is executed by U-Boot, further TFTP requests will be seen as the image files are downloaded before U-Boot hands over to the kernel.
  
== Breakdown of the Bootfile ==
+
== Breakdown of the Bootscript ==
This section takes the ''bootfile'' example above and breaks it down to illustrate what may be changed where needed to support your local environment.<br />
+
This section takes the ''bootscript'' example and breaks it down to illustrate what may be changed to support your local environment.<br />
* Set the ''bootfile'' to point to the required ''bootmode'' (i.e. TFTP sub-directory) and the NFS filesystem directory chosen for this Paralella, for '''this boot'''. By editing only these first two lines, a Parallella can be re-booted using a different FPGA, kernel and/or a different NFS root filesystem.  
+
Set the ''bootscript'' to point to the required boot mode (i.e. TFTP sub-directory) and the NFS filesystem directory chosen for this Paralella. By editing these first two lines, a Parallella can be re-booted using a different FPGA, kernel and/or a different NFS root filesystem.  
<blockquote>
+
<pre>
 +
setenv tftp_dir headless_7010   // or, hdmi_7010, etc
 +
setenv nfs_rootfs /srv/nfs/para1_ubuntu // or, para1_deb, etc
 +
</pre>
 +
Set the initial ''bootargs'' string to tell the kernel to use DHCP when loaded.
 +
<pre>
 +
setenv bootargs ip=dhcp
 +
</pre>
 +
Add the console argument to the ''bootargs'' string. If the console is not required, delete this line.
 
<pre>
 
<pre>
setenv tftp_dir hdmi_7010   // or, headless_7010, etc
+
setenv bootargs ${bootargs} console=ttyPS0,115200
setenv nfs_rootfs /srv/nfs/para1  // or, para1_deb, etc
 
 
</pre>
 
</pre>
</blockquote>
+
Add the NFS boot parameters to the ''bootargs'' string. The NFS server IP variable is not the same as the TFTP ''serverip'' variable, although they may have the same value.  
* Set the NFS boot parameters to be passed to the kernel by U-Boot in the <bootargs> variable. The NFS server IP is not the same variable as the <serverip> variable, the latter is used by U-Boot as the TFTP server. Note that the kernel is told to use DHCP when loaded.
 
<blockquote>
 
 
<pre>
 
<pre>
setenv nfs_ip 192.168.1.52    // your NFS server IP, usually the same for all your Parallellas
+
setenv nfs_ip 192.168.1.50
setenv bootargs root=/dev/nfs rw nfsroot=${nfs_ip}:${nfs_rootfs}
+
setenv bootargs ${bootargs} root=/dev/nfs rw nfsroot=${nfs_ip}:${nfs_rfs}
setenv bootargs ${bootargs} ip=dhcp console=ttyPS0,115200
 
 
</pre>
 
</pre>
</blockquote>
+
Add additional kernel boot diagnostic flags to the ''bootargs'' string. If not required, delete this line.
** To add diagnostic output to the console, add (or remove) the following line to the end of the bootargs block; this will append additional parameters to the existing string.
 
<blockquote>
 
 
<pre>  
 
<pre>  
 
setenv bootargs ${bootargs} nfsrootdebug earlyprintk
 
setenv bootargs ${bootargs} nfsrootdebug earlyprintk
 
</pre>
 
</pre>
</blockquote>
+
Set up the variables to download the fpga image, and to load the image into the fpga.  
* Set the tftpboot variables to request the fpga, devicetree and kernel images. This is exactly equivalent to the sequence of commands that load from the micro SD card.
 
<blockquote>
 
 
<pre>
 
<pre>
 
setenv fpga_image parallella.bit.bin
 
setenv fpga_image parallella.bit.bin
Line 389: Line 337:
 
setenv fpga_tftp 'tftpboot ${fpga_addr} ${tftp_dir}/${fpga_image}'
 
setenv fpga_tftp 'tftpboot ${fpga_addr} ${tftp_dir}/${fpga_image}'
 
setenv fpga_load 'fpga load 0 ${fpga_addr} ${fpga_size}'
 
setenv fpga_load 'fpga load 0 ${fpga_addr} ${fpga_size}'
 
+
</pre>
 +
Set up the variables to download the devicetree image.
 +
<pre>
 
setenv fdt_image devicetree.dtb
 
setenv fdt_image devicetree.dtb
 
setenv fdt_addr 0x2A00000
 
setenv fdt_addr 0x2A00000
setenv t_fdt 'tftpboot ${fdt_addr} ${tftp_dir}/${fdt_image}'
+
setenv fdt_tftp 'tftpboot ${fdt_addr} ${tftp_dir}/${fdt_image}'
 
+
</pre>
 +
Set up the variables to dowlnload the kernel image.
 +
<pre>
 
setenv kernel_image uImage
 
setenv kernel_image uImage
 
setenv kernel_addr 0x3000000
 
setenv kernel_addr 0x3000000
 
setenv kernel_tftp 'tftpboot ${kernel_addr} ${tftp_dir}/${kernel_image}'
 
setenv kernel_tftp 'tftpboot ${kernel_addr} ${tftp_dir}/${kernel_image}'
 
</pre>
 
</pre>
</blockquote>
+
Patch U-Boot network handling.<br />
* '''NB:''' The following is a workround for the problem identified by tajama, and referred to above.  
+
'''Note:''' This is a workround for the problem identified by ''tajama'', and referred to above. <br />
    IMPORTANT: this is a patch to U-Boot space and applies to the following version:
+
This is a patch to U-Boot space and applies to the following version, which is output initially by U-Boot:
 
<blockquote>
 
<blockquote>
 
<pre>
 
<pre>
Line 406: Line 358:
 
</pre>
 
</pre>
 
</blockquote>
 
</blockquote>
It MAY apply to your version but YOU MUST CHECK!! To be revisited if/when a new version of Parallella U-Boot build is provided.
+
It MAY apply to your version but YOU MUST CHECK!! (Revisit)
<blockquote>
 
 
<pre>
 
<pre>
 
setenv phy_rst 'mw.w f8000008 df0d ; mw.w f8000140 00100801 ; mw.w f8000004 767b'
 
setenv phy_rst 'mw.w f8000008 df0d ; mw.w f8000140 00100801 ; mw.w f8000004 767b'
 
setenv rset_phy 'run phy_rst'
 
setenv rset_phy 'run phy_rst'
 
</pre>
 
</pre>
</blockquote>
+
Set up the command to boot into the kernel, passing the kernel and devicetree image addresses.
* Set up the command to boot into the kernel, passing the kernel and devicetree image addresses.
 
<blockquote>
 
 
<pre>
 
<pre>
 
setenv boot_now 'bootm ${kernel_addr} - ${fdt_addr}'
 
setenv boot_now 'bootm ${kernel_addr} - ${fdt_addr}'
 
</pre>
 
</pre>
</blockquote>
+
Finally, run the sequence of tftp requests, and boot. <br />
* Run the sequence of tftp requests, and boot. If any of the commands passed to 'run' fails, then the 'run' command will halt (note - there are no ';' separators).
+
If any of the command sequence fails, then the 'run' command will halt (Note there are no ';' separators).
<blockquote>
 
 
<pre>
 
<pre>
 
run fpga_tftp fpga_load kernel_tftp fdt_tftp rset_phy boot_now
 
run fpga_tftp fpga_load kernel_tftp fdt_tftp rset_phy boot_now
 
</pre>
 
</pre>
</blockquote>
 
 
== Make the boot script image ==
 
Install the mkimage package if not already installed. On Debian, this is as follows:
 
<pre>
 
sudo apt-get install u-boot-tools
 
</pre>
 
 
After each ''bootfile'' script has been created/edited, it must be made into a loadable image by mkimage, and the image placed in the TFTP server directory. Based on the example above, the source text file is in a user working directory, and the TFTP service will expect to find the ''bootfile'' image in the TFTP server directory.
 
<pre>
 
sudo mkimage -A arm -O u-boot -T script -C none -a 0 -e 0 -n "t-Boot Script" -d ~/Documents/bootscr/para1 /srv/tftp/para1
 
</pre>
 
 
== Reboot the Parallella ==
 
Either recycle power or press the reset button. Given the reported problems with USB and HDMI initialisation, most success seems to be after full power recycle.
 
 
The output to the USB/UART terminal screen should show initialisation of the board and network, and then show the boot sequence looking for the TFTP server.
 
If the TFTP 'Loading:' line puts out a few 'T T T's, then it's retrying. Give it a few moments but if there's a line of 'T's then check that the TFTP service is actually running, and that the IP addresses and filename of the ''bootfile'' are valid. <br />
 
Once the small (~1kb) ''bootfile'' has been loaded and is executed by U-Boot, further TFTP requests will be seen as the image files are downloaded before U-Boot hands over to the kernel.
 
  
 
{{Template:Parallella Navbox}}
 
{{Template:Parallella Navbox}}

Revision as of 13:06, 20 September 2014


How To Set Up TFTP Boot And NFS Root Filesystems On Parallella

This Guide describes how to set up the Parallella U-Boot to netwok boot using TFTP.
Also, it describes how to set up mounting a root filesystem (rootfs) via NFS.
See the Manual for Das U-Boot
The following is based on the original blog post by Scott Johnson describing how to set up a Parallella cluster to use TFTP/NFS, but has been tweaked - mainly to minimise the need to edit/update the U-Boot variables via the Serial/UART cable, and provide more flexibility by using PC-based editors and storage.
By editing a bootscript on the TFTP server (and re-booting), a Parallella can be re-configured to a different boot mode (headless,HDMI) and/or different root filesystem (Ubuntu, Debian, nano) - all without having to 'burn' another Parallella SD card (perhaps ever..?).
Tweak the example below to suit your needs.

Requirements

Linux PC, Parallella board(s), USB to Serial (TTL/UART) adapter, DHCP server.

Summary

This Guide describes:

  • An IP addressing and naming scheme to support different boot modes (headless, HDMI) and NFS root filesystems.
  • Setting up TFTP and a directory layout for TFTP bootscripts and boot mode image files.
  • Changing the way the boot arguments are passed to the kernel, i.e. in the U-Boot 'bootargs' rather than devicetree "chosen {}" branch.
  • A directory layout for NFS root filesystems, allowing a choice of root filesystems for each Parallella.
  • Changing the U-Boot boot command to fetch a small script file using TFTP.
  • An example bootscript for TFTP boot and NFS root filesystem.
  • Use of mkimage to convert the bootscript text file into a U-Boot script image file.
  • A breakdown of the bootscript to show how it might be altered to suit different environments.

IMPORTANT NOTE:

  • {Sept 2014} There is a problem in Parallella U-Boot w.r.t. the Ethernet interface after any network activity in U-Boot (e.g. TFTP). (See the post on the Parallella forum post by tajama). The ethernet interface is left in an unuseable state. A workaround is included in the script example below; but before attempting to apply it - you MUST check the U-Boot version. (Revisit)
  • {Sept 2014} the Parallella U-Boot is being updated which just might affect the script below. (Revisit).

Prepare File Service Environments

Set up IP Addresses

Allocate IP addresses for the Parallella(s) and the TFTP/NFS servers in your DHCP server based on MAC address. The Parallella MAC address is printed on the board, and is also a U-Boot variable (see later).
Refer to the documentation of your DHCP server, or discuss with your network admin.
The IP addresses are used as follows:

  • U-Boot tftpboot command requests a bootscript file, and needs the TFTP server IP address <serverip>, and its own IP address <ipaddr>.
  • U-Boot tells Linux to use DHCP.
  • NFS uses IP addresses to control access to the rootfs directories.

This is an example IP address allocation and naming convention (your network may vary):

192.168.1.201	para1		// <ipaddr> IP address of Parallella "para"<n>
192.168.1.202	para2
...
192.168.1.208   para8     	// ... I wish
192.168.1.50	TFTP server	// IP address of TFTP server "serverip"
192.168.1.50	NFS server	// IP address of NFS server "nfs_ip"

Note: The TFTP and NFS services do not need to be on the same physical server, or even the same operating system. Here, a Debian (Wheezy) PC provides both services.

Prepare the TFTP Service

Get the required software if not already set up. On Debian:

apt-get install tftpd-hpa

The TFTP service does not start automatically.
Start the tftpd-hpa service automatically by adding a command to /etc/rc.local (just before the exit 0 line).

sudo nano /etc/rc.local

(Edit and save)

service tftpd-hpa start

To control the TFTP service use:

sudo service tftpd-hpa restart	// or 'stop', or 'start' as needed.

Set up the TFTP Directories

By default, the tftpd-hpa service looks for requested files under /srv/tftp/. Each Parallella has its own bootscript, e.g. para1. This is a U-Boot script image file, created using mkimage from a text file (see below). The bootscript points U-Boot to a boot mode directory. The bootscript also provides U-Boot with the Linux boot parameters to mount the NFS root filesystem, and finally to boot the kernel.
Each boot mode (headless, HDMI, etc) has a separate directory containing the equivalent of the BOOT partition on a SD card, containing the kernel, parallella.bit.bin and devicetree image files.
Different sets of image files can be held in different directories, e.g. hdmi_7010_new_kernel/, test_usb_fix/.
Note: that is one directory per boot mode - not one per Parallella.
Create a boot mode directory:

sudo mkdir -p /srv/tftp/<name>		// replace <name> with boot mode, e.g. hdmi_7010

Prepare the Image Files

Follow the instructions for creating the SD card (that is, download, extract and rename the kernel uImage, parallella.bit.bin and devicetree.dtb files), but instead of 'burning' to a SD card simply copy the image files to the boot mode directory (as root).
The TFTP service directory layout (for this example) will look something like:

/svr/tftp/				// TFTP service directory
	hdmi_7010/			// boot mode = Zynq 7010 with HDMI support
		paralella.bit.bin
		devicetree.dtb
		uImage
	headless_7010/			// boot mode = Zynq 7010 Parallella configured as headless
		paralella.bit.bin
		devicetree.dtb
		uImage
	hdmi_7010_new_kernel/		// boot mode = temp testing variation
		paralella.bit.bin
		devicetree.dtb
		uImage
	para1			        // bootscript for para1
	para2			        // bootscript for para2
	...
	para8			        // bootscript for para8, etc

Note: The image files follow the same naming convention as for SD card booting.

Remove Bootargs from Devicetree

The devicetree as supplied by Adapteva passes the boot arguments to support booting from the SD card. Instead, the boot arguments are passed to the kernel by U-Boot, as defined in the bootscript.
Install the devicetree compiler if not already installed. On Debian:

sudo apt-get install device-tree-compiler

Extract/edit/rebuild the devicetree.dtb file to remove the parameters from the chosen {} branch. {Check.. do we need the linux console line in chosen ..? Revisit}

cd /srv/tftp/hdmi_7010
sudo dtc -I dtb -o dev.dts -O dts devicetree.dtb
sudo nano dev.dts

Look for chosen { branch, remove the arguments, and save.

	chosen { 
	}

Recompile the devicetree.dtb and delete the dev.dts text file.

sudo dtc -I dts -O dtb -o devicetree.dtb dev.dts
sudo rm dev.dts

Repeat for all supplied devicetree.dtb files in each boot mode directory.

Prepare the NFS Service

Get the required software if not already set up. On Debian:

apt-get install nfs-kernel-server

The NFS service starts automatically.
To control NFS services use:

sudo service nfs-kernel-server restart		// or 'stop', or 'start' as needed.

Set up the NFS Directories

Each Parallella has at least one NFS directory containing a root filesystem. Each Parallella may have alternative root filesystems (e.g. Ubuntu, Linaro Nano) - just like preparing and swapping alternative SD cards.
In this example, the directories are organised under /srv/nfs, which need to be created.

sudo mkdir -p /srv/nfs
sudo mkdir -p /srv/nfs/para1_ubuntu
sudo mkdir -p /srv.nfs/para1_nano

Here is an example layout of NFS filesystem directories showing separate branches for each Parallella.

/srv/nfs/
	para1_ubuntu/		// rootfs for para1, based on, say, Parallella Ubuntu
		bin/
		boot/
                etc/	
		...
	para1_deb/		// rootfs for para1, with 9600's Debian and ESDK
		bin/
		boot/
                etc/	
		...
	para1_nano/		// rootfs for para1 based on linaro_nano
		bin/
		boot/
                etc/	
		 ...	
	para2_ubuntu/		// rootfs for para2, based on, say, Parallella Ubuntu
		bin/
		boot/
                etc/	
		...
        ...
	para8_ubuntu/	       	// rootfs for para8, based on, say, Parallella Ubuntu
	...	       		// etc, etc

Update NFS Exports File

The NFS server requires /etc/exports to be configured correctly, to control access to each NFS filesystem directory to specific hosts.
For each Paralella root filesystem that is created, add the export control line to /etc/exports, adjusting (as you should for all examples herein) for your local IP address and directory naming scheme. The following is an example based on the layout described above.

sudo nano /etc/exports

(Edit and save)

/srv/nfs/para1_ubuntu 192.168.1.201(rw,sync,no_root_squash,no_subtree_check)
/srv/nfs/para1_deb 192.168.1.201(rw,sync,no_root_squash,no_subtree_check)
/srv/nfs/para1_nano 192.168.1.201(rw,sync,no_root_squash,no_subtree_check)
/srv/nfs/para2_ubuntu 192.168.1.202(rw,sync,no_root_squash,no_subtree_check)
/srv/nfs/para8_ubuntu 192.168.1.208(rw,sync,no_root_squash,no_subtree_check)

Note: The bootscript ensures that only one of the optional filesystems will be accessed/mounted by a Parallella on a re-boot.

Export the NFS Directories

Ensure that these directories are made visible by the NFS service. Either:

sudo exportfs -a

or

sudo service nfs-kernel-server restart

Set up the Pallella NFS Root Filesystems

Instead of 'burning' a filesystem image to a partition on the SD card, place the payload root filesystem in the NFS directory, e.g. /srv/nfs/para1/.
Each source of root filesystem may need different preparation to enable the NFS access to work smoothly. Some examples below.

Default Parallella Ubuntu Build

{under construction - as of Sept 2014: NFS mounts OK, but doesn't complete boot, two penguins ..??}

9600's Debian Build

{under construction - as of Sept 2014: can't extract tar file ..??}

Linaro Nano Build

See how-to for network booting a Linaro Nano NFS rootfs

Set Up the Parallella to TFTP Boot

Repeat the following for each Parallella, changing the values of hostname and ipaddr as necessary.
Power off the Parallella and remove the ethernet, USB peripheral and HDMI cables and SD card.
Connect a USB serial cable to the 3-pin UART header on the Parallella. (Example device http://www.adafruit.com/products/954 from Adafruit).
Use a terminal program (e.g. screen, minicom) to connect to the UART Serial device. On minicom, set hardware flow control to off, and point the logfile to, say, ~/minicomlog for diagnostics.
Power up the Parallella.
After the boot failure messages, you should get the zynq-uboot> prompt in the terminal window. Display a list of the current state of the U-Boot environment variables using the printenv command.
Check the value of the ethaddr=xx:xx:xx:xx:xx:xx variable; this should be the same as the label on the board, and the MAC address you are using for this Parallella in your DHCP server.
Enter the following commands at the zynq-uboot> prompt in order to:

  • set the hostname variable which will be used as the bootscript name.
  • set the IP address of the Parallella and the TFTP server.
  • create a variable tboot which contains the commands to fetch and execute the bootscript.
  • change the U-Boot bootcmd so that it will run the tboot TFTP boot sequence.
setenv hostname para1
setenv ipaddr 192.168.1.201
setenv serverip 192.168.1.50
setenv taddr 0x100000
setenv tboot 'tftpboot ${taddr} ${hostname} ; source ${taddr}'
setenv bootcmd 'run tboot'

Alternatively, if preferred as a fall-back, replace the U-Boot bootcmd in the above sequence so that the boot sequence tries to boot from the SD card first. If no SD card is present, then run the TFTP boot sequence.

setenv bootcmd 'run modeboot ; run tboot'

Check that the variables have been set correctly and, if OK, save to flash memory.

printenv
saveenv

Power off.
Reconnect the ethernet cable.
Reconnect any USB peripherals or HDMI you intend to use on the Parallella.
Ready to TFTP boot.
Notes:

  • It's worthwhile checking (again) after a power recycle that the U-Boot variables have been set correctly
  • To correct/change a variable, use the setenv command with new/correct value.
  • To remove a variable e.g. 'badvarible', use the setenv command with no value, e.g. setenv badvarible
  • U-Boot autocompletes commands so print, set, save will also work.

Write a Parallella Bootscript

On the PC host, the bootscript image file is created and edited as a text file, and compiled into a U-Boot executable image using mkimage.
Create a working directory to hold the bootscript text file(s).

mkdir ~/Documents/bootscr

Create a text file and copy/paste the text below as a template. The following is an example bootscript. This loads the headless image files.

cd ~/Documents/bootscr
nano para1.txt

(Edit and save)

setenv tftp_dir headless_7010
setenv nfs_rfs /srv/tftp/para1_ubuntu
setenv bootargs ip=dhcp
setenv bootargs ${bootargs} console=ttyPS0,115200
setenv nfs_ip 192.168.1.50
setenv bootargs ${bootargs} root=/dev/nfs rw nfsroot=${nfs_ip}:${nfs_rfs}
setenv bootargs ${bootargs} nfsrootdebug earlyprintk
setenv fpga_image parallella.bit.bin
setenv fpga_addr 0x4000000
setenv fpga_size 0x3dbafc
setenv fpga_tftp 'tftpboot ${fpga_addr} ${tftp_dir}/${fpga_image}'
setenv fpga_load 'fpga load 0 ${fpga_addr} ${fpga_size}'
setenv fdt_image devicetree.dtb
setenv fdt_addr 0x2A00000
setenv fdt_tftp 'tftpboot ${fdt_addr} ${tftp_dir}/${fdt_image}'
setenv kernel_image uImage
setenv kernel_addr 0x3000000
setenv kernel_tftp 'tftpboot ${kernel_addr} ${tftp_dir}/${kernel_image}'
setenv phy_rst 'mw.w f8000008 df0d ; mw.w f8000140 00100801 ; mw.w f8000004 767b'
setenv rset_phy 'run phy_rst'
setenv boot_now 'bootm ${kernel_addr} - ${fdt_addr}'
run fpga_tftp fpga_load kernel_tftp fdt_tftp rset_phy boot_now

Copy the file to create a bootscript for each Parallella, changing the filename.
Edit the values of the tftp_dir and nfs_rfs variables in each file as required.
The directory structure on the Debian PC will then look something like this:

/home/{username}/Documents/bootscr/   	
	para1.txt	
	para2.txt
	...
	para8.txt

Make the Bootscript Image

Install the mkimage package if not already installed. On Debian:

sudo apt-get install u-boot-tools

Convert each bootscript text file into a loadable image by mkimage, and place the image in the TFTP server directory.

sudo mkimage -A arm -O u-boot -T script -C none -a 0 -e 0 -n "t-Boot Script" -d ~/Documents/bootscr/para1 /srv/tftp/para1

Reboot the Parallella

Reboot by power off, wait a few seconds, power on.
The output to the UART Serial terminal screen shows initialisation of the board and network, and then the boot sequence looking for the TFTP server. If the TFTP 'Loading:' line puts out a few 'T T T's, then it's retrying. Give it a few moments but if there's a line of 'T's then check that the TFTP service is actually running, and that the IP addresses and filename of the bootscript are valid.
Once the small (~1kb) bootscript has been loaded and is executed by U-Boot, further TFTP requests will be seen as the image files are downloaded before U-Boot hands over to the kernel.

Breakdown of the Bootscript

This section takes the bootscript example and breaks it down to illustrate what may be changed to support your local environment.
Set the bootscript to point to the required boot mode (i.e. TFTP sub-directory) and the NFS filesystem directory chosen for this Paralella. By editing these first two lines, a Parallella can be re-booted using a different FPGA, kernel and/or a different NFS root filesystem.

setenv tftp_dir headless_7010	   	// or, hdmi_7010, etc
setenv nfs_rootfs /srv/nfs/para1_ubuntu	// or, para1_deb, etc

Set the initial bootargs string to tell the kernel to use DHCP when loaded.

setenv bootargs ip=dhcp

Add the console argument to the bootargs string. If the console is not required, delete this line.

setenv bootargs ${bootargs} console=ttyPS0,115200

Add the NFS boot parameters to the bootargs string. The NFS server IP variable is not the same as the TFTP serverip variable, although they may have the same value.

setenv nfs_ip 192.168.1.50
setenv bootargs ${bootargs} root=/dev/nfs rw nfsroot=${nfs_ip}:${nfs_rfs}

Add additional kernel boot diagnostic flags to the bootargs string. If not required, delete this line.

 
setenv bootargs ${bootargs} nfsrootdebug earlyprintk

Set up the variables to download the fpga image, and to load the image into the fpga.

setenv fpga_image parallella.bit.bin
setenv fpga_addr 0x4000000
setenv fpga_size 0x3dbafc
setenv fpga_tftp 'tftpboot ${fpga_addr} ${tftp_dir}/${fpga_image}'
setenv fpga_load 'fpga load 0 ${fpga_addr} ${fpga_size}'

Set up the variables to download the devicetree image.

setenv fdt_image devicetree.dtb
setenv fdt_addr 0x2A00000
setenv fdt_tftp 'tftpboot ${fdt_addr} ${tftp_dir}/${fdt_image}'

Set up the variables to dowlnload the kernel image.

setenv kernel_image uImage
setenv kernel_addr 0x3000000
setenv kernel_tftp 'tftpboot ${kernel_addr} ${tftp_dir}/${kernel_image}'

Patch U-Boot network handling.
Note: This is a workround for the problem identified by tajama, and referred to above.
This is a patch to U-Boot space and applies to the following version, which is output initially by U-Boot:

U-Boot 2012.10-00003-g792c31c (Jan 03 2014 - 12:24:08)

It MAY apply to your version but YOU MUST CHECK!! (Revisit)

setenv phy_rst 'mw.w f8000008 df0d ; mw.w f8000140 00100801 ; mw.w f8000004 767b'
setenv rset_phy 'run phy_rst'

Set up the command to boot into the kernel, passing the kernel and devicetree image addresses.

setenv boot_now 'bootm ${kernel_addr} - ${fdt_addr}'

Finally, run the sequence of tftp requests, and boot.
If any of the command sequence fails, then the 'run' command will halt (Note there are no ';' separators).

run fpga_tftp fpga_load kernel_tftp fdt_tftp rset_phy boot_now