When working on low level kernel code, the indication that something 
went wrong is often noticed as a kernel oops, or even a totally silent 
system.  This usually implies a modify-recompile-reboot cycle which can 
become very very annoying if the reboot step implies popping out an SD 
card from the board, inserting it into the work PC, mounting it, copying 
the newly compiled kernel over, unmounting, moving the SD card back to 
the board, to finally hit the reset button.

If you are an old fashioned kernel developer like me and live by the 
simplest development environment (bash, vi, gcc) and your most trusted 
debugging tool is printk(), then having the ability to quickly boot a 
new kernel after moving printk traces around in order to pinpoint a 
crash location is vital.  But even for validation purposes on a remote 
board, not needing physical intervention is really nice.

So, by popular demand, here's how I accomplished this on VirtualExpress 
with a TC2 tile.  This probably applies to other VirtualExpress 
configurations too, but TC2 is the only one I tested.

Obtaining U-Boot
----------------

I don't have a particular affection for any bootloaders.  They tend to 
ask for more and more attention and visibility while their raison d'ĂȘtre 
is actually to get out of the way and disappear as fast as possible.

While U-Boot has many things that certainly gets on my nerves, it has a 
good point for itself which is its networking support.  And here is the 
key: let's fetch everything we need to boot the board over the network, 
script it, so not to have to deal with the bootloader (or bootloaders in 
this case) anymore.

First, let's get a copy of the U-Boot source tree.  I used the Linaro 
version as it includes Versatile Express support.

$ git clone git://git.linaro.org/boot/u-boot-linaro-stable.git
$ cd u-boot-linaro-stable/

Now... to get rid of U-Boot's most obnoxious feature (my opinion), 
the following patch should be applied:

diff --git a/include/configs/vexpress_common.h 
b/include/configs/vexpress_common.h
index 88a2c95..3328443 100644
--- a/include/configs/vexpress_common.h
+++ b/include/configs/vexpress_common.h
@@ -177,6 +177,8 @@
 #define CONFIG_CMD_SAVEENV
 #define CONFIG_CMD_RUN
 #define CONFIG_CMD_BOOTD
+#define CONFIG_CMD_BOOTZ
+#define CONFIG_SUPPORT_RAW_INITRD
 #define CONFIG_CMD_ECHO
 
 #define CONFIG_CMD_FAT

That basically enables U-Boot to boot a plain ARM Linux zImage file 
without going through the mkimage step (the bootz command), and load a 
plain ramdisk image without having to run mkimage on it.  This mkimage 
step is just extra fuss I can dispense with when working on and booting 
kernels frequently.

Now let's build it.  There is no TC2 (ca15 or ca7) config, however the 
ca5 one appears to be close enough for our needs:

$ make vexpress_ca5x2

You should end up with a u-boot.bin to be used later.

ARM Versatile Express Boot Monitor
----------------------------------

This is the native boot loader on the Virtual Express.  In fact there 
are many instances of different loaders even on different processors 
making the whole system rather weird but flexible.  It lacks the ability 
to load files from the network though.  But that's what a second stage 
bootloader such as U-Boot is for.

Good information on setting up a Virtual Express already exists.  While 
the instructions listed therein may or may not all apply to our case, I 
still recommend to read the following pages to get familiar with this 
beast:

  https://wiki.linaro.org/PawelMoll/BootingVEMadeEasy

The script to generate a boot script to generate an ATAGS block is a 
rather nice hack. But I want runtime DTB support and I prefer booting 
over the network, especially when playing with ramdisk images which is 
otherwise long to get reflashed.  Still this page provides a nice 
introduction to Virtual Express setup and gives good insights on the 
micro switch usage and the VE boot monitor structure.

  https://wiki.linaro.org/ARM/VersatileExpressSetup

This page shows how to install U-Boot on a Virtual Express and that's 
what we want here.  you should follow the instructions listed for the 
CA15x2 CoreTile, except that the U-Boot binary to use is the one we just 
compiled above.  Also, for TC2 the images.txt file is located in 
SITE1/HBI0249A/.

In short, once the internal MicroSD card is mounted over USb, the 
u-boot.bin file we compiled should be copied to SOFTWARE/u-boot.bin.  
Then the file SITE1/HBI0249A/images.txt should be updated to contain 
something similar to this:

NOR4UPDATE: AUTO
NOR4ADDRESS: 0f800000
NOR4FILE: \SOFTWARE\u-boot.bin
NOR4LOAD: 0x80800000
NOR4ENTRY: 0x80800000

We also need a boot script to start U-Boot automatically:

NOR5UPDATE: AUTO
NOR5NAME: BOOTSCRIPT
NOR5ADDRESS: 00000000
NOR5FILE: \SOFTWARE\boot.txt

Here the "BOOTSCRIPT" name is important otherwise the script won't be 
found and executed.

The number after "NOR" may differ, depending on the other images your 
images.txt may already contain.  Don't forget to update the TOTALIMAGES 
value at the top to reflect the number of image definitions you have, 
especially if you added new ones.

Finally, the content of SOFTWARE/boot.txt only needs to contain one 
line:

flash run u-boot

That's it!  unmounting the USB disk, setting SW[0] down and booting the 
main board (entering the "reboot" command on the serial console) should 
bring you to an U-Boot prompt.

The U-Boot configuration
------------------------

Once at the U-Boot prompt, it is necessary to set a couple environment 
variables:

VExpress# setenv bootcmd run loadbootscript\; source \$fileaddr
VExpress# setenv loadbootscript dhcp 0x84000000 192.168.2.2:tc2_boot.scr
VExpress# saveenv

In the loadbootscript definition, I used an explicit IP address to 
prefix the file name.  This is because my DHCP server is not the same 
machine as my TFTP server used to provide the location for the loaded 
files.  If your DHCP configuration already provides that information 
then it is not necessary to provide such prefix.  If you prefer using a 
fixed IP address for the board, you may simply set the ipaddr, netmask 
and gatewayip environment variables accordingly, and replace dhcp with 
tftp in the definition of loadbootscript.  And don't forget to saveenv 
again.

That's it!  Once the script is loaded over the network, we don't need to 
deal with U-Boot's configuration anymore.

The U-Boot boot script
----------------------

Now you need a TFTP server (normally tftpd) on your PC or laptop.  In 
its content directory, there should be a file called tc2_boot.scr.  
Unfortunately, the U-Boot obnoxiousness is striking back at us since 
this must be mkimage wrapped.  Let's start with the source, say 
tc2_boot.txt which should contain the following U-Boot commands:

# set the TFTP server address (the dhcp command clobbers it)
setenv serverip 192.168.2.2
# load a DTB
tftp 0x82000000 vexpress-v2p-iks-tc2.dtb
# tell U-Boot about it
fdt addr $fileaddr
# load a ramdisk image
tftp 0x88000000 initrd.gz
# remember its location and size for later
setenv rd_addr $fileaddr
setenv rd_size $filesize
# load the kernel
tftp 0x81000000 zImage
# set our kernel parameters
setenv bootargs console=ttyAMA0,38400 earlyprintk debug root=/dev/sda1 rootwait
# boot the kernel
bootz $fileaddr $rd_addr:$rd_size $fdtaddr

The above is what I use and can be adapted to your needs.  Again, maybe 
you don't need to override serverip.  Maybe you wish to use a NFS root. 
Etc. That's the beauty of it: it is just a .txt file on your PC that you 
can modify at will without having to flash it anywhere.  Temporary 
changes to the DTB with the fdt commands are also possible without 
having to modify and recompile the corresponding .dts, etc.

However we need to ubootize it into tc2_boot.scr before it is usable:

$ mkimage -A ARM -T script -C none -d tc2_boot.txt tc2_boot.scr

(The one who tells me how to avoid this step gets a cookie.)

Suffice to copy the desired kernel zImage and initrd files there too for 
the boot to proceed.  It might even be possible to use a symbolic link 
towards the zImage produced by the compilation of the kernel directly so 
to avoid that copy, but I didn't push my own laziness that far.

Let's boot!
-----------

Now you may use the "reboot" command at the "Cmd>" prompt provided by 
the microcontroller to power up the board.  When the board is booted, 
this prompt is moved from UART 0 to UART 1 while the kernel console 
output is going to UART 0, so it is possible to shutdown or reboot the 
board over UART 1 entirely unattended and remotely when both serial 
ports are connected to a computer.

Enjoy !


Nicolas
_______________________________________________
linaro-dev mailing list
linaro-dev@lists.linaro.org
http://lists.linaro.org/mailman/listinfo/linaro-dev

Reply via email to