Updating Linux in a device based on Altera SoC FPGA chip and gaining access to shared resources of a Windows server



The company recently Terasic started selling a very interesting board dE0-the Nano-Kit of SoC . It is interesting in that for a very modest price, a very powerful and functionally rich developer kit based on the Altera Cyclone V SoC FPGA chip with an integrated dual-core ARM Cortex-A9 processor is offered. In addition, the manufacturer, complete with the board, provides Linux, which is deployed to a MicroSD memory card.

But when I got this board at my disposal, I quickly came across several problems due to the fact that Linux was compiled from the Yocto Project sources. Basically, all the problems were related to the lack of public repositories from which the missing components could be added to the system. For example, in order to access the shared resources of a Windows server from this device via a network, the kernel lacked the Cifs file system support module.

Therefore, first of all, it was decided to update the kernel, replace Yocto with the more familiar Debian Wheezy and reinstall everything that is needed to access the shared resources of the Windows server.

The assembly process was studied by me and was carried out following the recommendations from this article , for which many thanks to its author Des333 !

A complete alteration was not included in my plans, so it was decided to leave the bootloaders on my card - from the Linux 3.13 image that came with the board. So the section with type A2, it was decided not to touch at all.

Tasks


  • Update Linux kernel
  • Replace RootFS with Debian 7
  • Refine the image so that it can be updated from the Internet
  • Mount the directory shared on the Windows server

Kernel assembly


Since my main working environment for life is Windows, all the steps for building Linux were performed from the Linux Mint 17.2 Cinnamon OS installed on the virtual machine.

1. Start the terminal and enter root mode - so as not to type the sudo command each time:
sudo -i

In this case, / root will be our home directory - we will do everything in it.

2. We will compile the kernel using the cross-compiler included in the Altera SoC Embedded Design Suite (EDS) package. Therefore, download and install the latest Altera SoC EDS package. Altera SoC EDS is currently version 15.0. You can download this package directly from the Altera website .

Altera SoC EDS will be installed in the /root/altera/15.0 directory.

3. Install build-essential:
apt-get install build-essential

4. Install libncurses:
apt-get install libncurses5-dev

5. Download the linux-socfpga sources from the Altera repositories and unpack them into the home directory:

  • Go to linux-socfpga releases in Altera repositories
  • We find the necessary release. I chose version 4.1 - since it was the latest stable version at the moment
  • Download the archive with source
  • Unpack the source into the home directory

As a result, the directory /root/linux-socfpga-4.1 with the source code of the Linux kernel version 4.1 appears.

Amendment (02/11/2016):
It is necessary to take not master and not tags but socfpga- * brandies .
For example, socfpga-4.3.
This is where patches with the necessary SoC functionality are applied.
Therefore, for the source you need to go here . Many thanks to Des333 for the tip!

6. Run the Alter script, which will launch a new BASH and correct some environment variables in it (for example, PATH). We will carry out all compilation actions without leaving this BASH:
cd /root/altera/15.0/embedded
./embedded_command_shell.sh

7. We create several environment variables:
export ARCH=arm
export CROSS_COMPILE=arm-linux-gnueabihf-
export LOADADDR=0x8000

8. We create default configuration for socfpga:
cd /root/linux-socfpga-4.1
make socfpga_defconfig

This will create a .config configuration file, sharpened for compilation under ARM.

9. Add the missing components to the kernel configuration (or remove the extra ones):
make menuconfig

This opens a pseudo-graphic window with menus.



We need to add the CIFS file system driver - in order to be able to access shared network resources. There are two ways to add drivers to the system - add directly to the kernel or add as external plug-ins.

So, we go along the path File Systems -> Network File Systems , stand on CIFS Support and press the space bar - the letter M should appear opposite the CIFS Suport line - that means the plug-in will be used. It will be necessary later to compile it separately and put it in the directory of external modules. If you press the spacebar again, the letter Mwill change to an asterisk symbol - that means the driver will be built directly into the kernel.

Note : later, when checking the system’s operability, it turned out that the external cifs module crashes when trying to copy a file from a shared Windows server disk. The cifs driver built into the kernel worked perfectly fine. Although when using external modules with other versions of the kernel (for example, 3.19), such problems did not arise. I could not find out the reason for what was happening.

You also need to enable HighMem support - otherwise the system will not be able to use the upper 256 megabytes of RAM. To do this, go along the path Kernel Features -> High Memory Support and also press the spacebar.

Exit the menu - press EXITuntil we get out. To the question - do I need to save the configuration - answer Yes .

10. Compile the kernel:
make uImage

In my case, only one core was given to the virtual machine. The compilation process took about 20 minutes. If compilation is performed in a machine with several cores, then for speed it is possible to parallelize the compilation process into several cores. To do this, you must explicitly set the number of cores through the -j option . For example, for compilation by forces of three cores:
make -j 3 uImage

11. We compile the dtb file corresponding to our device. If you use the old dtb-file, then either the device will hang at boot or there will be terrible glitches when working:

  • We are looking for all the files with the name cyclone5 and ending in dts:
    find ~/linux-socfpga-4.1 -name "*cyclone5*dts"

  • We select the most suitable of the found files. I just looked through their contents and in one of them I saw the word terasic . I thought that this is the most suitable file for this device - that’s what I used it for. The file was called socfpga_cyclone5_sockit.dts .
  • We start compilation socfpga_cyclone5_sockit.dtb:
    make socfpga_cyclone5_sockit.dtb
    


As a result of compilation, two files were created:
/root/linux-socfpga-4.1/arch/arm/boot/zImage
/root/linux-socfpga-4.1/arch/arm/boot/dts/socfpga_cyclone5_sockit.dtb

12. If you selected the option of using external modules at the configuration stage, you must compile them.
Compiling the CIFS module :
make M=fs/cifs

and compile cryptography modules - they will be needed when mounting shared Windows resources:
make M=crypto

13. Copy the kernel and dtb files to the card. Initially, the card was cut so that the kernel and the DTB file lay on a separate FAT32 partition. We are writing these files to it. The only remark: the DTB file needs to be renamed - so that it is named the same as the one that already lies on the FAT32 section of the card:

  • We connect the card to the virtual machine. I had to use an external card reader connected directly to the computer’s USB2 port. For some reason, it was not possible to do the same through the card reader built into the computer. Also, it was not possible to connect an external card reader to the virtual machine if it was connected via the USB3 port.
  • The card sections will be automatically mounted - you cannot unmount the sections through the GUI, because in this case the card reader is completely disconnected from the virtual machine.
  • We look at the names of mounted partitions:
    mount
    

    We will see something like this:
    /dev/sdb1 on /media/user/F725-1429 type vfat (rw,nosuid,nodev,uid=1000,gid=1000,shortname=mixed,dmask=0077,utf8=1,showexec,flush,uhelper=udisks2)
    /dev/sdb2 on /media/user/41cad05c-898e-49a3-9d00-02b92fa817ba type ext3 (rw,nosuid,nodev,uhelper=udisks2)
    

    A section like vfat (first line) is what we are interested in at the moment.
  • We look at what lies on the vfat section:
    ll /media/user/F725-1429
    

    We see something like that:
    -rw-r--r--  1 user user 1164128 Apr 20 20:23 de0_nano_soc.rbf
    -rw-r--r--  1 user user   15274 Jul 26 17:08 socfpga.dtb
    -rw-r--r--  1 user user     176 Apr 20 19:59 u-boot.scr
    -rw-r--r--  1 user user 3371472 Jul 29 16:50 zImage
    

    So the dtb file is called socfpga.dtb.
  • Copy our files to the card:
    cp /root/linux-socfpga-4.1/arch/arm/boot/zImage /media/user/F725-1429/
    cp /root/linux-socfpga-4.1/arch/arm/boot/dts/socfpga_cyclone5_sockit.dtb /media/user/F725-1429/socfpga.dtb
    


File system assembly


This subsection largely repeats what is written in this article , but nevertheless I give it completely, so that in the future it will be easier to use this manual.

We will build Debian 7 Wheezy:

1. Install the packages that will be needed to build the file system:
apt-get install debootstrap qemu-user-static binfmt-support

2. Create a directory and load all the necessary files into it:
cd /root
mkdir debian7
debootstrap --arch armel --foreign wheezy debian7 http://ftp.debian.org/debian

3. To run applications built for the ARM architecture, we will use qemu static . To do this, copy the file to our debian7 directory:
cp /usr/bin/qemu-arm-static debian7/usr/bin/

4. Go to our new file system:
chroot debian7 /bin/bash

5. If the interpreter prompt changed to “I have no name! @Hostname: / #”, then everything went well.
Finish the assembly process:
/debootstrap/debootstrap --second-stage

6. In / etc / inittab we leave the following lines:
/etc/inittab
id:5:initdefault:
si::sysinit:/etc/init.d/rcS
~~:S:wait:/sbin/sulogin
l0:0:wait:/etc/init.d/rc 0
l1:1:wait:/etc/init.d/rc 1
l2:2:wait:/etc/init.d/rc 2
l3:3:wait:/etc/init.d/rc 3
l4:4:wait:/etc/init.d/rc 4
l5:5:wait:/etc/init.d/rc 5
l6:6:wait:/etc/init.d/rc 6
z6:6:respawn:/sbin/sulogin
S:2345:respawn:/sbin/getty 115200 console

7. Set the password for the root account:
passwd

8. We pack the new file system into the archive:
tar -cpzf debian7.tar.gz --exclude=debian7.tar.gz  /

9. Exit chroot:
exit

10. Unmount and then format the ext3 partition on the card (see the names of the partitions in clause 13 from the kernel assembly):
umount /dev/sdb2
mkfs.ext3 /dev/sdb2

11. Mount the ext3 partition:
mount /dev/sdb2 /mnt/

12. Unpack the archive with the file system on the card in the ext3 section:
tar -xzf /root/debian7/debian7.tar.gz -C /mnt/

13. If you selected the option of using external modules during kernel assembly, you must write to the card external modules compiled in step 12 of the kernel assembly process:
cd /mnt/lib
mkdir modules
mkdir modules/4.1.0
mkdir modules/4.1.0/extra
mkdir modules/4.1.0/kernel
mkdir modules/4.1.0/kernel/crypto
cp /root/linux-socfpga-4.1/fs/cifs/cifs.ko ./modules/4.1.0/extra/
cp /root/linux-socfpga-4.1/crypto/*.ko ./modules/4.1.0/kernel/crypto/

14. Unmount the sections:
umount /dev/sdb1
umount /dev/sdb2

That's all - the card is ready, you can install it in the device and boot.

Final refinement


After loading the device, we upload the image in place:

1. Log in to Debian on the device by connecting to it via the built-in serial port.

2. If during the kernel assembly the option of using external modules was chosen, then it is necessary to generate files with information about external kernel modules:
depmod -a

3. Add the Debian 7 repository to the list of repositories (I added a German server):
echo"deb http://ftp.de.debian.org/debian wheezy main" > /etc/apt/sources.list

4. Connect the device to the Ethernet network. We get the address via DHCP:
dhclient -4 eth0

5. We raise NTP, since with the wrong time it will not be possible to mount the shared resources:
apt-get update
apt-get install ntp

6. Set our time zone:
dpkg-reconfigure tzdata

7. To verify that everything was going fine, mount the server ball. For example, in my case, I did it like this:
mount //192.168.48.4/distrib /mnt -o username=jok40

8. Install the SSH server. Using the serial port is inconvenient, since when working through it, the typed commands are turned up to the beginning of the line after reaching column 80:
apt-get install openssh

9. Assign a static address to the eth0 interface - so that in the future it would be easier to connect to the device via SSH. To do this, edit the interfaces file:
nano /etc/network/interfaces

In my case, it began to look like this:
# interfaces(5) file used by ifup(8) and ifdown(8)
auto lo
iface lo inet loopback
# The primary network interface
allow-hotplug eth0
iface eth0 inet static
address   192.168.48.27
netmask   255.255.255.0
gateway   192.168.48.1
network   192.168.48.0
broadcast 192.168.48.255
auto eth0

10. We edit the resolv.conf file - so that the DNS client works normally:
nano /etc/resolv.conf

Add the lines to it:
nameserver 192.168.48.1
nameserver 8.8.8.8

11. Reboot the device.

12. To verify that everything is done correctly
connect to the device via SSH via Ethernet:



Thank you all for your attention!

Also popular now: