Now, it's time to install whatever we needed on our target system; since the ESPRESSObin is sold with just the bootloader, we have to do some work in order to get a fully functional system with a proper OS.
Setting up the target machine
Getting ready
Even if the ESPRESSObin can boot from different media, we're going to use a microSD since it's the most easy and useful way to set up the system. For different media, please refer to the ESPRESSObin's wiki pages—see http://wiki.espressobin.net/tiki-index.php?page=Boot+from+removable+storage+-+Ubuntu for some examples.
How to do it...
To set up the microSD, we have to use our host PC, so plug it in and then locate the corresponding device.
- If we're using an SD/microSD slot, as soon as we plug the media in, we'll get something like this in the kernel messages:
mmc0: cannot verify signal voltage switch
mmc0: new ultra high speed SDR50 SDHC card at address aaaa
mmcblk0: mmc0:aaaa SL08G 7.40 GiB
mmcblk0: p1
However, if we're going to use a microSD to USB adapter kernel, messages will look like the following:
usb 1-6: new high-speed USB device number 5 using xhci_hcd
usb 1-6: New USB device found, idVendor=05e3, idProduct=0736
usb 1-6: New USB device strings: Mfr=3, Product=4, SerialNumber=2
usb 1-6: Product: USB Storage
usb 1-6: Manufacturer: Generic
usb 1-6: SerialNumber: 000000000272
usb-storage 1-6:1.0: USB Mass Storage device detected
scsi host4: usb-storage 1-6:1.0
usbcore: registered new interface driver usb-storage
usbcore: registered new interface driver uas
scsi 4:0:0:0: Direct-Access Generic STORAGE DEVICE 0272 PQ: 0 ANSI: 0
sd 4:0:0:0: Attached scsi generic sg3 type 0
sd 4:0:0:0: [sdc] 15523840 512-byte logical blocks: (7.95 GB/7.40 GiB)
sd 4:0:0:0: [sdc] Write Protect is off
sd 4:0:0:0: [sdc] Mode Sense: 0b 00 00 08
sd 4:0:0:0: [sdc] No Caching mode page found
sd 4:0:0:0: [sdc] Assuming drive cache: write through
sdc: sdc1
sd 4:0:0:0: [sdc] Attached SCSI removable disk
- Another easy way to locate the media is by using the lsblk command, as follows:
$ lsblk
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
loop0 7:0 0 5M 1 loop /snap/gedit/66
loop1 7:1 0 4.9M 1 loop /snap/canonical-livepatch/50
...
sdb 8:16 0 931.5G 0 disk
└─sdb1 8:17 0 931.5G 0 part /run/schroot/mount/ubuntu-xenial-amd64-f72c490
sr0 11:0 1 1024M 0 rom
mmcblk0 179:0 0 7.4G 0 disk
└─mmcblk0p1
179:1 0 7.4G 0 part /media/giometti/5C60-6750
- It's now obvious that our microSD card is here listed as /dev/mmcblk0 but it is not empty. Since we want to clear everything from it, we have to clear it first by using the following command:
$ sudo dd if=/dev/zero of=/dev/mmcblk0 bs=1M count=100
- You may need to unmount the device before proceeding with the clearing in order to work safely on the media device, so let's unmount all of the device's partitions by using the umount command on all of them as I will do in the following with the only defined partition on my microSD:
$ sudo umount /dev/mmcblk0p1
You have to just repeat this command for each defined partition on your microSD.
- Now, we will create a new partition, /dev/mmcblk0p1, on the empty SD card with the next command:
$ (echo n; echo p; echo 1; echo ''; echo ''; echo w) | sudo fdisk /dev/mmcblk0
If everything works well, our microSD media should appear formatted, as in the following:
$ sudo fdisk -l /dev/mmcblk0
Disk /dev/mmcblk0: 7.4 GiB, 7948206080 bytes, 15523840 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
Disklabel type: dos
Disk identifier: 0x34f32673
Device Boot Start End Sectors Size Id Type
/dev/mmcblk0p1 2048 15523839 15521792 7.4G 83 Linux
- Then, we have to format it as EXT4 with the following command:
$ sudo mkfs.ext4 -O ^metadata_csum,^64bit -L root /dev/mmcblk0p1
$ sudo mkfs.ext4 -L root /dev/mmcblk0p1
- Next, mount this partition on your local Linux machine:
$ sudo mount /dev/mmcblk0p1 /mnt/
$ ls -ld /media/$USER/root
drwxr-xr-x 3 root root 4096 Jan 10 14:28 /media/giometti/root/
Adding Debian files
I decided to use Debian as the target OS since it's my favorite distribution for development (and, when possible, for production) systems:
- To install it, we use QEMU software again, using the following command:
$ sudo qemu-debootstrap \
--arch=arm64 \
--include="sudo,file,openssh-server" \
--exclude="debfoster" \
stretch ./debian-stretch-arm64 http://deb.debian.org/debian
W: Cannot check Release signature;
- Once finished, we should find, in debian-stretch-arm64, a clean Debian root filesystem for the ESPRESSObin but, before transferring it into the microSD, we should fix the hostname file contents as shown here:
$ sudo bash -c 'echo espressobin | cat > ./debian-stretch-arm64/etc/hostname'
- Then, we have to add the serial device ttyMV0 to the /etc/securetty file in order to be able to log in as the root user through the serial device, /dev/ttyMV0. Use the following command:
$ sudo bash -c 'echo -e "\n# Marvell serial ports\nttyMV0" | \
cat >> ./debian-stretch-arm64/etc/securetty'
- And, as a last step, we have to set up a root password:
$ sudo chroot debian-stretch-arm64/ passwd
Enter new UNIX password:
Retype new UNIX password:
passwd: password updated successfully
Here, I used the root string as password for the root user (it is up to you to choose yours).
Now, we can safely copy all files into our microSD using the following command:
$ sudo cp -a debian-stretch-arm64/* /media/$USER/root/
Here is what the microSD content should look like:
$ ls /media/$USER/root/
bin dev home lost+found mnt proc run srv tmp var
boot etc lib media opt root sbin sys usr
Adding the kernel
After OS files, we need also kernel images to get a running kernel and, in the previous section, we got the kernel image into the arch/arm64/boot/Image file and the device tree binary into the arch/arm64/boot/dts/marvell/armada-3720-espressobin.dtb file, which are ready to be transferred into our freshly created microSD:
- Let's copy them into the /boot directory as done here:
$ sudo cp arch/arm64/boot/Image \
arch/arm64/boot/dts/marvell/armada-3720-espressobin.dtb \
/media/$USER/root/boot/
$ sudo mkdir /media/$USER/root/boot
Then, the /boot directory should look like this:
$ ls /media/$USER/root/boot/
armada-3720-espressobin.dtb Image
- The preceding files are sufficient to boot the system; however, to also install kernel modules and headers files, which are useful for compiling new software, we can use the next commands after all Debian files have been installed into the microSD (to avoid overwriting with Debian files):
$ sudo -E make modules_install INSTALL_MOD_PATH=/media/$USER/root/
$ sudo -E make headers_install INSTALL_HDR_PATH=/media/$USER/root/usr/
Well, now we are finally ready to tie it all up and run our new Debian system, so let's unmount the microSD and plug it into the ESPRESSObin.
Setting up the booting variables
After powering up, we should get the bootloader's messages from the serial console and then we should see a timeout running to 0 before doing the autoboot:
- Quickly stop the countdown by hitting the Enter key on the keyboard to get the bootloader's prompt, as follows:
Model: Marvell Armada 3720 Community Board ESPRESSOBin
CPU @ 1000 [MHz]
L2 @ 800 [MHz]
TClock @ 200 [MHz]
DDR @ 800 [MHz]
DRAM: 2 GiB
U-Boot DComphy-0: USB3 5 Gbps
Comphy-1: PEX0 2.5 Gbps
Comphy-2: SATA0 6 Gbps
SATA link 0 timeout.
AHCI 0001.0300 32 slots 1 ports 6 Gbps 0x1 impl SATA mode
flags: ncq led only pmp fbss pio slum part sxs
PCIE-0: Link down
MMC: sdhci@d0000: 0
SF: Detected w25q32dw with page size 256 Bytes, erase size 4 KiB, total 4 MiB
Net: eth0: neta@30000 [PRIME]
Hit any key to stop autoboot: 0
Marvell>>
- Now, let's check again that the microSD card has the necessary files using the ext4ls command, as follows:
Marvell>> ext4ls mmc 0:1 boot
<DIR> 4096 .
<DIR> 4096 ..
18489856 Image
8359 armada-3720-espressobin.dtb
OK, everything is in place, so there are only a few variables required to boot from the microSD card.
- We can display the currently defined variables at any point by using the echo command and optionally reconfigure them by using setenv command. First, check and set proper image and device tree paths and names:
Marvell>> echo $image_name
Image
Marvell>> setenv image_name boot/Image
Marvell>> echo $fdt_name
armada-3720-espressobin.dtb
Marvell>> setenv fdt_name boot/armada-3720-espressobin.dtb
- Next, define the bootcmd variable, which we will use to boot from the microSD card:
Marvell>> setenv bootcmd 'mmc dev 0; \
ext4load mmc 0:1 $kernel_addr $image_name; \
ext4load mmc 0:1 $fdt_addr $fdt_name; \
setenv bootargs $console root=/dev/mmcblk0p1 rw rootwait; \
booti $kernel_addr - $fdt_addr'
- Save the set variables at any time using the saveenv command.
- Finally, we boot up the ESPRESSObin by simply typing the reset command and, if everything works well, we should see the system start and running and, at the end, we should get system login prompt, as follows:
Debian GNU/Linux 9 espressobin ttyMV0
giometti-VirtualBox login:
- Now, log in as root with the root password that was previously set up:
Debian GNU/Linux 9 espressobin ttyMV0
espressobin login: root
Password:
Linux espressobin 4.18.0 #2 SMP PREEMPT Sun Jan 13 13:05:03 CET 2019 aarch64
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@espressobin:~#
Setting up the networking
OK, now our ESPRESSObin is ready to execute our code and our drivers! However, before ending this section, let's take a look at the networking configuration since it can be further useful to log in to the board using an SSH connection or just to copy files from/to the board quickly (even if we can remove the microSD and then copy our files from the host PC directly):
- Taking a look at available network interfaces on the ESPRESSObin, we see the following:
# ip link
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT
group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
2: eth0: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode DEFAULT group
default qlen 532
link/ether 3a:ac:9b:44:90:e9 brd ff:ff:ff:ff:ff:ff
3: wan@eth0: <BROADCAST,MULTICAST,M-DOWN> mtu 1500 qdisc noop state DOWN mode DE
FAULT group default qlen 1000
link/ether 3a:ac:9b:44:90:e9 brd ff:ff:ff:ff:ff:ff
4: lan0@eth0: <BROADCAST,MULTICAST,M-DOWN> mtu 1500 qdisc noop state DOWN mode D
EFAULT group default qlen 1000
link/ether 3a:ac:9b:44:90:e9 brd ff:ff:ff:ff:ff:ff
5: lan1@eth0: <BROADCAST,MULTICAST,M-DOWN> mtu 1500 qdisc noop state DOWN mode D
EFAULT group default qlen 1000
link/ether 3a:ac:9b:44:90:e9 brd ff:ff:ff:ff:ff:ff
The eth0 interface is the one that connects the CPU with the Ethernet switch while the wan, lan0, and lan1 interfaces are the ones where we can physically connect our Ethernet cables (note that the system calls them wan@eth0, lan0@eth0, and lan1@eth1 just to underline the fact they are slaves of eth0). Following is a photograph of the ESPRESSObin, where we can see each Ethernet port with its label:
- Despite their names, all ports are equivalent so connect the Ethernet cable into one port (I'm going to use wan) and then enable it after eth0, as follows:
# ip link set eth0 up
mvneta d0030000.ethernet eth0: configuring for fixed/rgmii-id link mode
mvneta d0030000.ethernet eth0: Link is Up - 1Gbps/Full - flow control off
# ip link set wan up
mv88e6085 d0032004.mdio-mii:01 wan: configuring for phy/ link mode
mv88e6085 d0032004.mdio-mii:01 wan: Link is Up - 100Mbps/Full - flow control rx/tx
- Now, we can manually set an IP address or we can ask our DHCP server whatever we need to surf the internet with the dhclient command:
# dhclient wan
Here is my network configuration:
# ip addr show wan
3: wan@eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP g
roup default qlen 1000
link/ether 9e:9f:6b:5c:cf:fc brd ff:ff:ff:ff:ff:ff
inet 192.168.0.100/24 brd 192.168.0.255 scope global wan
valid_lft forever preferred_lft forever
- Now, we're ready to install new software or to try to establish an SSH connection to the ESPRESSObin; to do so, let's verify that we have the following SSH server's configuration in the/etc/ssh/sshd_config file:
# grep 'PermitRootLogin yes' /etc/ssh/sshd_config
PermitRootLogin yes
- If we get no output, we cannot log in as root into our ESPRESSObin, so we must change the PermitRootLogin setting to yes and then restart the daemon:
# /etc/init.d/ssh restart
Restarting ssh (via systemctl): ssh.service.
- Now, on the host PC, we can try the login via SSH, as follows:
$ ssh root@192.168.0.100
root@192.168.0.100's password:
Linux espressobin 4.18.0 #2 SMP PREEMPT Sun Jan 13 13:05:03 CET 2019 aarch64
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.
Last login: Thu Nov 3 17:16:59 2016
-bash: warning: setlocale: LC_ALL: cannot change locale (en_GB.UTF-8)
See also
- To get more information regarding how to set up the ESPRESSObin even on different OSes, you can take a look at http://wiki.espressobin.net/tiki-index.php?page=Software+HowTo.
- For further information regarding qemu-debootstrap, a good starting point is at https://wiki.ubuntu.com/ARM/RootfsFromScratch/QemuDebootstrap. To manage Ethernet devices and for further information about networking on a Debian OS, you can take a look at the following: https://wiki.debian.org/NetworkConfiguration.