Friday 10 January 2020

Unattended Linux Booting from SD Card

Foreword

In the previous post we managed to boot Linux on the Zybo board.

This was quite a manual orchestrated process, having to issue a number of XMD commands for loading the different parts for the Linux Kernel and then starting Linux.

In this post we will attempt to automate the Linux process by letting it boot unattended from a SD Card.

Booting U-Boot from SDCard

As the first step in the process, let us see what is involved in booting UBoot from the SD Card.

Firstly, you need to set the boot mode jumpers to SD, as follows:

With this setting the Zynq will look for a file called boot.bin on an active FAT32 partition, on an SDCard on bootup.

The file boot.bin should contain the First Stage Bootloader (FSBL) as well as the UBoot binary. This file is generated by using the bootgen utility which is present in the bin folder of the Xilinx SDK.

In order to the use the bootgen utility, one first need to create a boot.bif, which in our case will look as follows:

image : {
        [bootloader]fsbl_test.elf
        u-boot.elf
}

So, with the boot.bif file created, and both fsbl_test.elf and u-boot.elf present on the file path, we invoke bootgen as follows:

bootgen -image boot.bif -o i boot.bin

This will generate the file boot.bin. At this point I also would like to mention that for this exercise, using the FSBL and UBoot binary we created in the previous two posts will work just fine.

Next, we need to copy this boot.bin file to an SDCard. Preferably this file should be copied into an active FAT32 partition.

Now insert this SDCard into the SD Card slot on the Zybo board and power it up. As in the previous posts, we need to open a screen session to the Zybo board so we can see what is going on.

If all went well, you should see similar output within the screen session as I described in the previous two posts. If one missed the opportunity to abort the auto boot process, the UBoot will attempt to boot from other devices, but will eventually present you with the UBoot prompt.

Booting Linux from the SDCARD

In the previous post we booted in to Linux by issuing a couple of XMD commands for loading the Linux components into memory, followed by a bootm command in UBoot for launching Linux.

Let us see if we can follow a similar approach for booting Linux from the SD Card.

To load the related Linux files into memory, we can just include it within the boot.bin file. To create such a file with bootgen, we can use the following boot.bif file:

image : {
        [bootloader]fsbl_test.elf
        u-boot.elf
        [load=0x2a00000]zynq-zybo.dtb
        [load=0x2000000]uramdisk.image.gz
        [load=0x3000000]uImage.bin
}

Copy the the resulting boot.bin file again to the SD Card. When booting from SD Card, the FSBL will now load zynq-zybo.dtb, uramdisk.image.gz and uImage.bin into the requested addresses.

Once booted into the U-Boot prompt, you can start Linux again with the following command:

bootm 0x3000000 0x2000000 0x2a00000

Important that these steps will only work if you aborted the initial autoboot sequence. If you wait for the uboot prompt after the autoboot sequence, the above command will simply not work since the memory into which the Linux Binaries was loaded by the FSBL would have been overwritten.

At this point we are at a kind of a catch 22. The FSBL will happily load all the components for Linux into memory, but once we approach autoboot, where we want to be for unattended Linux Booting, these contents will have been overwritten.

It is clear that in order to autoboot Linux, we will need to let UBoot fetch the relevant Linux Components from the SDCard.

Autobooting Linux

As mentioned at the end of the previous section, one of the challenges for autobooting Linux from the SD Card, is to get the relevant Linux components into memory, since the FSBL loading attempt gets overwritten soon after the autoboot process started.

Luckily U-Boot provides a command called fatload that will load any file from a FAT32 partition into memory at an address of your choice. The following ssequence of commands will load all the Linux components into memory:

fatload mmc 0:1 0x2a00000 zynq-zybo.dtb
fatload mmc 0:1 0x2000000 uramdisk.image.gz 
fatload mmc 0:1 0x3000000 uImage.bin

Important here is that above mentioned files should be present as separate files on the same level as boot.bin. Although we already wrapped these files into boot.bin, fatload simply wouldn't be able to retrieve it from boot.bin.

After the three fatload commands above, you start booting linux with a bootm.

We just overcame another hurdle, but the question still remains: How do one autoboot Linux?

U-Boot provides an answer to this question by means of persistent environment variables. One of these environment variables is bootcmd.

With bootcmd you can basically specify a script that needs to be executed when autobooting.

At a U-Boot prompt enter the following:

setenv bootcmd "fatload mmc 0:1 0x2a00000 zynq-zybo.dtb; 
                fatload mmc 0:1 0x2000000 uramdisk.image.gz; 
                fatload mmc 0:1 0x3000000 uImage.bin; 
                bootm 0x3000000 0x2000000 0x2A00000"

saveenv



I have split the setenv command over multiple lines for better readability. However, this command should be entered in one line.

The saveenv command saves the environment variables to persistent storage, which by default on the Zybo Board will be the QSPI. In the next section we will change this storage area to a file on the SD Card.

If you now restart the Zybo Board, the autoboot sequence should take you into Linux.

Saving the environment on the SD Card

In the previous section we mentioned that we store the environment variables for UBoot on the QSPI flash located on the Zybo board.

There is probably nothing wrong storing the env variables on QPSI. However, it make sense to keep everything together on the SD Card, so if we have different images on different SD Cards, we can just swap out the SD Card with the need to worry about changing potential settings within the QSPI.

The path to the env persistent storage is hardcoded within the UBoot binary. To change it you will need to make some config changes to zynq_zybo_defconfig and rebuilt Uboot.

Looking for the correct settings within the config file can be quite a cumbersome task. To make the task easier, you can make use of make menuconfig, a similar utility available when you build the Linux Kernel. Please note, however, you will need to have Ncurses installed on your desktop Linux to run make menuconfig.

When you fire up make menuconfig, it is important that you load the config for the Zybo board. So, use the Right arrow key, move to the Load option and hit enter. When prompted to enter a file name enter configs/zynq_zybo_defconfig and hit <enter>.

Back in the Category menu, we are interested in the Environment section, so scroll down to this section and hit <enter> once again. We can clearly see i this section that SPI is selected for environment storage:


So, unselect SPI flash and select Fat filesystem:


We, are almost done. We need to scroll down and change a couple of more settings:


Here we specify that the FAT partition is present on a MMC device (e.g. SD Card), device number zero and partition one.

The file containing the settings will be called uboot.env.

Save the settings, rebuild uboot, repackage within boot.bin and copy again to the SD Card.

We haven't created the file uboot.env yet, so when we reboot the Zybo board with the SD Card we will eventually be presented with the Uboot prompt.

Follow the steps from the previous section again for setting bootcmd and save it.

When you now reboot, you will see that once again we automatically boot into Linux.

In Summary

In this post we managed to boot U-Boot and Linux from an SDCard.

The first boot attempt from the SD Card we performed a couple of manual steps, which were similar as described in the previous post.

We ended off the post by automating the boot process by defining a bootcmd environment variable, which is basically a script running the necessary steps to boot into Linux.

In the next post we will start playing with Linux Device Drivers. The eventual goal for this is to be able, eventually to display the Linux console on a VGA screen from the Zybo Board.

Till next time!

No comments:

Post a Comment