|
|
|
# Running a Debian distribution on the ZedBoard using tftp and NFS
|
|
|
|
|
|
|
|
This page explains how to run a regular Debian distribution on the ZedBord with:
|
|
|
|
|
|
|
|
* A minimal boot image on the SD card, containing only the First Stage Boot Loader (FSBL) and U-Boot
|
|
|
|
* Loading the kernel image and the device tree blob from a remote tftp server
|
|
|
|
* Mounting the root file system from a remote NFS server
|
|
|
|
|
|
|
|
This is not specific to SecBus and can be used for any development project on the ZedBoard.
|
|
|
|
|
|
|
|
This setup is extremely convenient as it almost completely avoids SD card manipulations. The Linux kernel and its device tree blob can be re-built any time, copied on the tftp server and re-loaded by the ZedBoard through its Ethernet link at the price of a single reboot. The Debian root file system can also be updated from the NFS server (thanks to Qemu and chroot) using the regular Debian tools. The changes are immediately reflected on the ZedBoard and, in most cases, without rebooting.
|
|
|
|
|
|
|
|
In the following we assume that:
|
|
|
|
|
|
|
|
* `<host>` is the hostname of the workstation we will use and to which the UART USB cable of the ZedBoard is attached
|
|
|
|
* The Xilinx tool chain is installed on `<host>` and it is on the PATH
|
|
|
|
* `<bistream>.bit` is the bistream file used to configure the Programmable Logic (PL), if any
|
|
|
|
* `<server>` is the hostname of the remote tftp and NFS server (can be the same as `<host>`)
|
|
|
|
* `<server_ip_address>` is the IP address of `<server>`
|
|
|
|
* `<zedboard_mac_address>` is the Ethernet MAC address of the ZedBoard
|
|
|
|
* `<zedboard_ip_address>` is the IP address of the ZedBoard
|
|
|
|
* `<gateway_ip_address>` is the IP address of the gateway through which the ZedBoard connects to `<server>` (if it connects directly `<gateway_ip_address>` = `<server_ip_address>`)
|
|
|
|
* `<tftproot>` is the absolute path on `<server>` of the root directory of the tftp server
|
|
|
|
* `<tftproot>/<tftpdir>` is the absolute path on `<server>` of the directory containing the tftp-served files
|
|
|
|
* `<nfsdir>` is the absolute path on `<server>` of the directory containing the NFS-served file systems
|
|
|
|
* We are root on `<server>` which runs a Debian variant, has access to Internet and has Qemu installed
|
|
|
|
|
|
|
|
Note: there are several ways to configure the Programmable Logic (PL). In the following we present three of them:
|
|
|
|
|
|
|
|
* Copy the bitstream somewhere in the NFS share on `<server>` and send it to the `/dev/xdevcfg` device after the Linux kernel booted. This method is very convenient because it allows to reconfigure the PL at run time without rebooting. On the other hand, it cannot be used when the PL must be configured before booting the Linux kernel.
|
|
|
|
* Let U-Boot download the bitstream from the tftp server and configure the PL. This method is less flexible because the system must be rebooted to change the PL configuration. However, it can be used when the PL must be configured prior booting the Linux kernel.
|
|
|
|
* Include the bitstream in the boot image on the SD card and let the First Stage Boot Loader (FSBL) do the job. This method is the less flexible of all because changing the PL configuration not only requires to reboot but also to regenerate the boot image and store it on the SD card. But it is the only one that can be used if U-Boot needs the PL to be already configured when it boots.
|
|
|
|
|
|
|
|
Please adapt the following instructions to your own settings.
|
|
|
|
|
|
|
|
## On `<server>`, the NFS server, prepare the root file system
|
|
|
|
|
|
|
|
### Create an empty image for the Debian root file system and mount it
|
|
|
|
|
|
|
|
```bash
|
|
|
|
server> cd <nfsdir>
|
|
|
|
server> dd if=/dev/zero of=debianrootfs4zynq.img bs=1024 count=1MB
|
|
|
|
server> sudo mkfs.ext3 -F debianrootfs4zynq.img
|
|
|
|
server> mkdir debianrootfs4zynq
|
|
|
|
server> sudo mount -o loop debianrootfs4zynq.img debianrootfs4zynq
|
|
|
|
```
|
|
|
|
|
|
|
|
### Install a minimal Debian distribution
|
|
|
|
|
|
|
|
```bash
|
|
|
|
server> sudo debootstrap --verbose --arch armhf --variant=minbase --foreign wheezy debianrootfs4zynq http://ftp.fr.debian.org/debian
|
|
|
|
server> sudo modprobe binfmt_misc
|
|
|
|
server> sudo cp /usr/bin/qemu-arm-static debianrootfs4zynq/usr/bin
|
|
|
|
server> sudo mkdir debianrootfs4zynq/dev/pts
|
|
|
|
server> sudo mount -t devpts devpts debianrootfs4zynq/dev/pts
|
|
|
|
server> sudo mount -t proc proc debianrootfs4zynq/proc
|
|
|
|
```
|
|
|
|
|
|
|
|
### Chroot into the file system and continue the Debian install
|
|
|
|
|
|
|
|
```bash
|
|
|
|
server> sudo chroot debianrootfs4zynq /bin/bash
|
|
|
|
server-chrooted> /debootstrap/debootstrap --second-stage
|
|
|
|
server-chrooted> cat <<! >> /etc/apt/sources.list
|
|
|
|
deb http://security.debian.org/ wheezy/updates main
|
|
|
|
deb-src http://security.debian.org/ wheezy/updates main
|
|
|
|
deb http://ftp.fr.debian.org/debian/ wheezy main
|
|
|
|
deb-src http://ftp.fr.debian.org/debian/ wheezy main
|
|
|
|
!
|
|
|
|
server-chrooted> apt-get update
|
|
|
|
server-chrooted> apt-get upgrade
|
|
|
|
server-chrooted> export LANG=C
|
|
|
|
server-chrooted> apt-get install apt-utils dialog locales
|
|
|
|
server-chrooted> dpkg-reconfigure locales
|
|
|
|
server-chrooted> export LANG=en_US.UTF-8
|
|
|
|
server-chrooted> apt-get install udev netbase ifupdown iproute openssh-server iputils-ping wget net-tools ntpdate nano less module-init-tools
|
|
|
|
```
|
|
|
|
|
|
|
|
### Configure file systems, hostname, root password and serial console
|
|
|
|
|
|
|
|
```bash
|
|
|
|
server-chrooted> cat <<! >> /etc/fstab
|
|
|
|
/dev/nfs / nfs defaults 0 1
|
|
|
|
tmpfs /tmp tmpfs defaults 0 0
|
|
|
|
!
|
|
|
|
server-chrooted> echo "MyZedBoard" > /etc/hostname
|
|
|
|
server-chrooted> passwd
|
|
|
|
...
|
|
|
|
```
|
|
|
|
|
|
|
|
Comment out the tty1 to tty6 specifications in `/etc/inittab` and add the serial console (use nano to edit the file):
|
|
|
|
|
|
|
|
```
|
|
|
|
#1:2345:respawn:/sbin/getty 38400 tty1
|
|
|
|
#2:23:respawn:/sbin/getty 38400 tty2
|
|
|
|
#3:23:respawn:/sbin/getty 38400 tty3
|
|
|
|
#4:23:respawn:/sbin/getty 38400 tty4
|
|
|
|
#5:23:respawn:/sbin/getty 38400 tty5
|
|
|
|
#6:23:respawn:/sbin/getty 38400 tty6
|
|
|
|
T0:23:respawn:/sbin/getty -L ttyPS0 115200 vt100
|
|
|
|
```
|
|
|
|
|
|
|
|
Allow the root user to log in through the serial console:
|
|
|
|
|
|
|
|
```bash
|
|
|
|
server-chrooted> cat <<! >> /etc/securetty
|
|
|
|
ttyPS0
|
|
|
|
!
|
|
|
|
```
|
|
|
|
|
|
|
|
### Escape from the chroot and export the NFS share
|
|
|
|
|
|
|
|
```bash
|
|
|
|
server-chrooted> exit
|
|
|
|
server> sudo mkdir <nfsdir>/debianrootfs4zynq/opt/bitstreams
|
|
|
|
server> sudo cat <<! >> /etc/exports
|
|
|
|
<nfsdir>/debianrootfs4zynq <zedboard_ip_address>/32(rw,sync,no_root_squash,no_subtree_check,insecure)
|
|
|
|
!
|
|
|
|
server> sudo exportfs -v <zedboard_ip_address>/32:<nfsdir>/debianrootfs4zynq
|
|
|
|
```
|
|
|
|
|
|
|
|
## On `<host>` build U-Boot, the Linux kernel, the device tree blob and generate the boot image
|
|
|
|
|
|
|
|
### Clone the U-Boot and Linux git repositories by Xilinx
|
|
|
|
|
|
|
|
```bash
|
|
|
|
host> export ROOTDIR=<some-path>
|
|
|
|
host> mkdir -p $ROOTDIR
|
|
|
|
host> cd $ROOTDIR
|
|
|
|
host> git clone http://github.com/Xilinx/u-boot-xlnx.git
|
|
|
|
host> git clone https://github.com/Xilinx/linux-xlnx.git
|
|
|
|
```
|
|
|
|
|
|
|
|
### Configure and build U-Boot
|
|
|
|
|
|
|
|
```bash
|
|
|
|
host> cd $ROOTDIR/u-boot-xlnx
|
|
|
|
host> export CROSS_COMPILE=arm-xilinx-linux-gnueabi-
|
|
|
|
host> make O=build zynq_zed_config
|
|
|
|
host> make O=build
|
|
|
|
host> cp build/u-boot build/u-boot.elf
|
|
|
|
host> export PATH=$PATH:$ROOTDIR/u-boot-xlnx/build/tools
|
|
|
|
```
|
|
|
|
|
|
|
|
### Configure and build the Linux kernel, compile the device tree blob, copy the image and the blob on the tftp server
|
|
|
|
|
|
|
|
Note: when configuring the Linux kernel do not forget to enable the NFS support if it is not already.
|
|
|
|
|
|
|
|
```bash
|
|
|
|
host> cd $ROOTDIR/linux-xlnx
|
|
|
|
host> make ARCH=arm xilinx_zynq_defconfig
|
|
|
|
host> make ARCH=arm menuconfig
|
|
|
|
host> make ARCH=arm UIMAGE_LOADADDR=0x8000 uImage
|
|
|
|
host> ./scripts/dtc/dtc -I dts -O dtb -o $ROOTDIR/devicetree.dtb arch/arm/boot/dts/zynq-zed.dts
|
|
|
|
host> scp arch/arm/boot/uImage $ROOTDIR/devicetree.dtb <server>:<tftproot>/<tftpdir>
|
|
|
|
host> ssh <server> chmod a+r <tftproot>/<tftpdir>/uImage <tftproot>/<tftpdir>/devicetree.dtb
|
|
|
|
```
|
|
|
|
|
|
|
|
### Compile the kernel modules and install them in the NFS share on `<server>`
|
|
|
|
|
|
|
|
```bash
|
|
|
|
host> cd $ROOTDIR/linux-xlnx
|
|
|
|
host> make ARCH=arm INSTALL_MOD_PATH=$ROOTDIR/debianrootfs4zynq modules modules_install
|
|
|
|
host> cd $ROOTDIR
|
|
|
|
host> tar -pzcvf - debianrootfs4zynq | ssh root@<server> 'cd <nfsdir>; tar -pzxvf -'
|
|
|
|
```
|
|
|
|
|
|
|
|
To configure the PL from a running Linux kernel, copy the bistream file on the NFS server:
|
|
|
|
|
|
|
|
```bash
|
|
|
|
host> scp <bitstream>.bit <server>:<nfsdir>/debianrootfs4zynq/opt/bitstreams
|
|
|
|
```
|
|
|
|
|
|
|
|
To configure the PL with U-Boot copy the bistream file on the tftp server:
|
|
|
|
|
|
|
|
```bash
|
|
|
|
host> scp <bitstream>.bit <server>:<tftproot>/<tftpdir>
|
|
|
|
host> ssh <server> chmod a+r <tftproot>/<tftpdir>/<bitstream>.bit
|
|
|
|
```
|
|
|
|
|
|
|
|
### Create and build the Board Support Package (BSP) and the FSBL, generate the boot image
|
|
|
|
|
|
|
|
Note: we use the `zed_hw_platform` template provided with the Xilinx SDK.
|
|
|
|
|
|
|
|
Note: delete the `<bitstream>.bit` line if the PL is not configured by the FSBL.
|
|
|
|
|
|
|
|
```bash
|
|
|
|
host> cd $ROOTDIR
|
|
|
|
host> cat <<! > fsbl.tcl
|
|
|
|
set_workspace ./fsbl
|
|
|
|
create_project -type app -name fsbl -app "Zynq FSBL" -proc ps7_cortexa9_0 -hwproject zed_hw_platform
|
|
|
|
build -name fsbl
|
|
|
|
quit
|
|
|
|
!
|
|
|
|
host> xsdk -batch -source fsbl.tcl
|
|
|
|
host> cat <<! > boot.bif
|
|
|
|
the_ROM_image:
|
|
|
|
{
|
|
|
|
[bootloader]./fsbl/fsbl/Debug/fsbl.elf
|
|
|
|
<bitstream>.bit
|
|
|
|
./u-boot-xlnx/build/u-boot.elf
|
|
|
|
}
|
|
|
|
!
|
|
|
|
host> bootgen -image ./boot.bif -o ./boot.bin -w on
|
|
|
|
host> cp boot.bin /media/SDCARD
|
|
|
|
host> sync
|
|
|
|
```
|
|
|
|
|
|
|
|
## On the ZedBoard, set U-Boot environment variables and boot the Linux kernel
|
|
|
|
|
|
|
|
Unmount the SD card, insert it in the SD card slot of the ZedBoard, configure the jumpers to boot from the SD Card, connect the Ethernet cable, the USB UART cable, the power cable and power on. Launch `minicom` (or equivalent) on `<host>`:
|
|
|
|
|
|
|
|
```bash
|
|
|
|
host> minicom -D /dev/ttyACM0
|
|
|
|
```
|
|
|
|
|
|
|
|
and stop U-Boot by pressing a key before the end of the countdown.
|
|
|
|
|
|
|
|
Set the following U-Boot environment variables (please pay attention to the simple and double quotes):
|
|
|
|
|
|
|
|
```
|
|
|
|
zynq-uboot> setenv ethaddr <zedboard_mac_address>
|
|
|
|
zynq-uboot> setenv ipaddr <zedboard_ip_address>
|
|
|
|
zynq-uboot> setenv serverip <server_ip_address>
|
|
|
|
zynq-uboot> setenv nfsdir <nfsrootdir>/debianrootfs4zynq
|
|
|
|
zynq-uboot> setenv tftpdir <tftpdir>
|
|
|
|
zynq-uboot> setenv netboot 'tftpboot ${kernel_load_address} ${tftpdir}/${kernel_image} && tftpboot ${devicetree_load_address} ${tftpdir}/${devicetree_image} && bootm ${kernel_load_address} - ${devicetree_load_address}'
|
|
|
|
zynq-uboot> setenv bootargs "console=ttyPS0,115200 root=/dev/nfs rw nfsroot=${serverip}:${nfsdir} ip=${ipaddr}:${serverip}:${serverip}:255.255.255.0:zynq:eth0:off nfsrootdebug earlyprintk"
|
|
|
|
```
|
|
|
|
|
|
|
|
If the PL must be configured by U-Boot add the following `netboot` variable redefinition:
|
|
|
|
|
|
|
|
```
|
|
|
|
setenv netboot "tftpboot 0x4000000 ${tftpdir}/<bitstream>.bit && fpga loadb 0 0x4000000 4045671 && ${netboot}"
|
|
|
|
```
|
|
|
|
|
|
|
|
Save the environment variables in the SPI flash memory of the ZedBoard:
|
|
|
|
|
|
|
|
```
|
|
|
|
zynq-uboot> saveenv
|
|
|
|
zynq-uboot> run netboot
|
|
|
|
...
|
|
|
|
Debian GNU/Linux 7 MyZedBoard ttyPS0
|
|
|
|
|
|
|
|
MyZedBoard login: root
|
|
|
|
Password:
|
|
|
|
Last login: Thu Jan 1 00:01:57 UTC 1970 on ttyPS0
|
|
|
|
Linux MyZedBoard 3.18.0-xilinx-06524-gd51de5a #1 SMP PREEMPT Fri Apr 10 14:39:03 CEST 2015 armv7l
|
|
|
|
|
|
|
|
The programs included with the Debian GNU/Linux system are free software;
|
|
|
|
the exact distribution terms for each program are described in the
|
|
|
|
individual files in /usr/share/doc/*/copyright.
|
|
|
|
|
|
|
|
Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
|
|
|
|
permitted by applicable law.
|
|
|
|
root@MyZedBoard:~# df
|
|
|
|
Filesystem 1K-blocks Used Available Use% Mounted on
|
|
|
|
rootfs 967864 373036 544828 41% /
|
|
|
|
<server_ip_address>:<nfsdir>/debianrootfs4zynq 967864 373036 544828 41% /
|
|
|
|
devtmpfs 248100 0 248100 0% /dev
|
|
|
|
tmpfs 51284 132 51152 1% /run
|
|
|
|
tmpfs 5120 0 5120 0% /run/lock
|
|
|
|
tmpfs 102560 0 102560 0% /run/shm
|
|
|
|
tmpfs 256400 0 256400 0% /tmp
|
|
|
|
root@MyZedBoard:~#
|
|
|
|
```
|
|
|
|
|
|
|
|
If the PL must be configured from the running Linux kernel, this can be done with:
|
|
|
|
|
|
|
|
```bash
|
|
|
|
root@MyZedBoard:~# cat /opt/bistreams/<bitstream>.bit > /dev/xdevcfg
|
|
|
|
```
|
|
|
|
|
|
|
|
To avoid leaving your NFS root file system in an unstable state, always shut down properly:
|
|
|
|
|
|
|
|
```bash
|
|
|
|
root@MyZedBoard:~# poweroff
|
|
|
|
...
|
|
|
|
[info] Will now halt.
|
|
|
|
reboot: System halted
|
|
|
|
```
|
|
|
|
|
|
|
|
before turning the power off. Remember that the root file system is on `<server>` and that resetting the ZedBoard or powering it off without a proper shut down can definitively compromise your NFS share.
|
|
|
|
|
|
|
|
## Maintaining the NFS share
|
|
|
|
|
|
|
|
If the NFS share on `<server>` still appears busy after the client ZedBoard has been properly shut down, as happens sometimes, it can be unmounted with:
|
|
|
|
|
|
|
|
```bash
|
|
|
|
server> sudo exportfs -u <zedboard_ip_address>/32:<nfsdir>/debianrootfs4zynq
|
|
|
|
server> sudo umount -l <nfsdir>/debianrootfs4zynq
|
|
|
|
```
|
|
|
|
|
|
|
|
To re-mount and re-export the NFS share on `<server>`:
|
|
|
|
|
|
|
|
```bash
|
|
|
|
server> cd <nfsdir>
|
|
|
|
server> sudo mount -o loop debianrootfs4zynq.img debianrootfs4zynq
|
|
|
|
server> sudo mount -t devpts devpts debianrootfs4zynq/dev/pts
|
|
|
|
server> sudo mount -t proc proc debianrootfs4zynq/proc
|
|
|
|
server> sudo exportfs <zedboard_ip_address>/32:<nfsdir>/debianrootfs4zynq
|
|
|
|
```
|
|
|
|
|
|
|
|
To chroot in the NFS share:
|
|
|
|
|
|
|
|
```bash
|
|
|
|
server> sudo chroot debianrootfs4zynq /bin/bash
|
|
|
|
server-chrooted> apt-get update
|
|
|
|
...
|
|
|
|
```
|
|
|
|
|
|
|
|
<!-- vim: set tabstop=4 softtabstop=4 shiftwidth=4 noexpandtab textwidth=0: --> |