Altera’s tools for generating U-boot and Linux are a bit messy, outdated at best. For example, last time I checked their auto-generated U-boot dates back to 2014. Let’s try to build and run an up-to-date version of U-boot and Linux.

U-boot

build

First, clone the repository.

git clone https://github.com/u-boot/u-boot.git

A variety of defconfigs exist for different boards.

[xrn@a23pc07 u-boot]$ find . -iname "socfpga*defconfig"
./configs/socfpga_sockit_defconfig
./configs/socfpga_de10_nano_defconfig            
./configs/socfpga_is1_defconfig 
./configs/socfpga_cyclone5_defconfig             
./configs/socfpga_stratix10_defconfig
./configs/socfpga_de1_soc_defconfig                 
./configs/socfpga_de0_nano_soc_defconfig
./configs/socfpga_dbm_soc1_defconfig
./configs/socfpga_sr1500_defconfig
./configs/socfpga_socrates_defconfig                                                
./configs/socfpga_arria5_defconfig                                                  
./configs/socfpga_vining_fpga_defconfig
./configs/socfpga_arria10_defconfig

For example, building U-boot for the Altera’s Cyclone V development kit:

make ARCH=arm CROSS_COMPILE=/opt/toolchain/gcc-linaro-7.2.1-2017.11-x86_64_arm-eabi/bin/arm-eabi- socfpga_cyclone5_defconfig
make ARCH=arm CROSS_COMPILE=/opt/toolchain/gcc-linaro-7.2.1-2017.11-x86_64_arm-eabi/bin/arm-eabi- -j8

This will result in a u-boot-with-spl.sfp file being created.

flash

The SoCFPGA boot ROM will look for a partition of type 0xa2 and execute it. This is where U-boot must be copied. The two other partitions will contain an ext4 filesystem with the rootfs and a FAT32 filesystem with the Linux kernel and its device tree. With the help of fdisk, partition the SD card (or eMMC) correctly. The following shows an example on a 16 GB SD card.

Note: it is advised that U-boot resides on the first partition.

Command (m for help): p

Disk /dev/sdj: 15.9 GB, 15931539456 bytes
64 heads, 32 sectors/track, 15193 cylinders, total 31116288 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0xcedaa4bc

   Device Boot      Start         End      Blocks   Id  System
/dev/sdj1            2048       99703       48828   a2  Unknown
/dev/sdj2           99704      490328      195312+  83  Linux
/dev/sdj3          490329    31116287    15312979+   b  W95 FAT32

Then, proceed to format the Linux and FAT32 partitions with mkfs. The 0xa2 partition doesn’t need any kind of formatting. Instead, we can perform a low-level copy of U-boot with the help of dd.

dd if=u-boot-with-spl.sfp of=/dev/sdj1
sync

Try it out, you should be greeted by a nice and up-to-date U-boot prompt.

U-Boot 2019.04-rc2-00032-g97f9830849 (Feb 21 2019 - 16:59:05 +0100)

CPU:   Altera SoCFPGA Platform
FPGA:  Altera Cyclone V, SE/A6 or SX/C6 or ST/D6, version 0x0
BOOT:  SD/MMC External Transceiver (1.8V)
DRAM:  1 GiB
MMC:   dwmmc0@ff704000: 0
Loading Environment from MMC... OK
In:    serial
Out:   serial
Err:   serial
Model: Altera SOCFPGA Cyclone V SoC Development Kit
Net:
Error: ethernet@ff702000 address not set.
eth-1: ethernet@ff702000
Hit any key to stop autoboot:  0
=>

Linux

build

Building Linux is not difficult either. The same defconfig is used by every board of the socfpga family. Only the device tree will show minor changes.

make ARCH=arm CROSS_COMPILE=/opt/toolchain/gcc-linaro-7.2.1-2017.11-x86_64_arm-eabi/bin/arm-eabi- socfpga_defconfig
make ARCH=arm CROSS_COMPILE=/opt/toolchain/gcc-linaro-7.2.1-2017.11-x86_64_arm-eabi/bin/arm-eabi- -j8
make ARCH=arm CROSS_COMPILE=/opt/toolchain/gcc-linaro-7.2.1-2017.11-x86_64_arm-eabi/bin/arm-eabi- socfpga_cyclone5_socdk.dtb

When you look at them, every socfpga board’s device tree includes the same socfpga_cyclone5.dtsi file. Adapting an existing device tree to a new socfpga board is easy and is generally just a matter of activating the right nodes with a status = “okay” string. Here are all the supported boards so far:

[xrn@a23pc07 linux]$ find . -iname "*socfpga*dts"
./arch/arm64/boot/dts/altera/socfpga_stratix10_socdk.dts
./arch/arm/boot/dts/socfpga_cyclone5_socrates.dts
./arch/arm/boot/dts/socfpga_cyclone5_sockit.dts
./arch/arm/boot/dts/socfpga_arria10_socdk_qspi.dts
./arch/arm/boot/dts/socfpga_cyclone5_de0_nano_soc.dts
./arch/arm/boot/dts/socfpga_cyclone5_socdk.dts
./arch/arm/boot/dts/socfpga_cyclone5_vining_fpga.dts
./arch/arm/boot/dts/socfpga_cyclone5_sodia.dts
./arch/arm/boot/dts/socfpga_arria10_socdk_nand.dts
./arch/arm/boot/dts/socfpga_arria10_socdk_sdmmc.dts
./arch/arm/boot/dts/socfpga_vt.dts
./arch/arm/boot/dts/socfpga_cyclone5_mcvevk.dts
./arch/arm/boot/dts/socfpga_arria5_socdk.dts

Use Buildroot to create a rootfs tailored to your needs.

flash

Untar your rootfs to the ext4 partition. Copy your zImage and socfpga_cyclone5_socdk.dtb to your SD card’s FAT32 partition. Start U-boot and run your kernel with the following command. You will successfully boot into your new kernel!

setenv bootargs console=ttyS0,115200 root=/dev/mmcblk0p3 rw rootwait; fatload mmc 0:2 0x10000 zImage; fatload mmc 0:2 0x1000 socfpga_cyclone5_socdk.dtb; bootz 0x10000 - 0x1000