Changes between Initial Version and Version 1 of ventana/bootloader/falcon-mode


Ignore:
Timestamp:
10/22/2017 05:28:45 AM (7 years ago)
Author:
trac
Comment:

--

Legend:

Unmodified
Added
Removed
Modified
  • ventana/bootloader/falcon-mode

    v1 v1  
     1[[PageOutline]]
     2
     3=== Speeding Up Boot Times ===
     4In addition to Falcon mode, please also review the [wiki:boot_speed boot speed Wiki page]
     5= Falcon Mode =
     6'''Note that Falcon mode is currently only supported in Gateworks U-Boot 2015.04 branch which is not considered stable and thus not yet available as a pre-built binary. You can build it and install it using the instructions on the [wiki:ventana/bootloader?#building]'''
     7
     8Falcon mode refers to having the Secondary Program Loader (SPL) boot the OS directly and bypass the U-Boot bootloader entirely. The purpose of this is to speed up booting and it can easily shave 3 to 5 seconds off the boot process depending on your boot medium, kernel/initrd/fdt size, and filesystem.
     9
     10The Gateworks Ventana SPL supports loading images from:
     11 * NAND Flash
     12 * micro-SD (baseboard IMX6 micro-SD controller, not a USB based micro-SD reader/writer such as what is on the GW16103)
     13
     14Note that it is technically possible to support booting from other media using the SPL but that requires additional work: The IMX6 BOOT ROM can additionally boot from SATA which is supported via mSATA on man Ventana boards with an IMX6Q SoC however that support is not currently in the U-Boot SPL codebase. Additionally booting from devices that are not supported by the IMX6 BOOT ROM such as Ethernet, CDROM, or USB can technically be achieved by first booting to something like the SPL from a supported boot device and adding support to the SPL. Freescale has a method discussed in the IMX reference manuals called a 'plugin' image for this kind of thing.
     15
     16In order to enable falcon mode to boot Linux you first need to configure and store the data that gets passed to the Linux kernel. This configuration is typically done via the U-Boot bootm command and involves customizing the device-tree for the board characteristics such as memory size, kernel params (bootargs), device-tree fixups, and MTD partitions. For falcon mode this configuration can be done by loading the kernel and device-tree then using the {{{spl export fdt}}} command instead of the bootm command.
     17
     18Typically one would custom build the SPL for falcon mode and have something like a GPIO pushbutton that can allow you to select booting to U-Boot for configuration instead of booting falcon mode. Because not all Gateworks Ventana boards have pushbuttons, we chose to have the SPL read the U-Boot env variables and use them for configuration.
     19
     20It is important to realize that if you choose to use Falcon mode you should do this once you are fairly far along in your development cycle as once you set the env to boot directly to the OS the only way to get back into U-Boot is to alter your environment (and if you've bricked your firmware for example, you would need to do this via JTAG for NAND flash and by mounting micro-SD on another system if using micro-SD). Also, you will need to be clear what kernel bootargs you should use, which you can get from a running system via {{{cat /proc/cmdline}}}. For this reason get your firmware running the way you want, then invoke Falcon mode if you want to use Falcon make it boot quicker.
     21
     22To understand Falcon mode its useful to understand what a bootloader like U-Boot usually does for you. The steps towards booting to Linux via U-Boot can be summarized as:
     23 1. load the kernel from non-volatile storage into RAM (this can be from raw flash or block dev sectors, or via high level filesystems)
     24 2. load the kernel device-tree binary (dtb) into RAM (again, this can be from raw flash or block dev sectors or via high level filesystems)
     25 3. prepare the '''args''' data to pass to the kernel. For modern ARM linux, this is a device-tree binary with its address passed in via a register. The 'prepare' step here is often taken for granted. This step involvs modifying the loaded device-tree with properties that may be board or environment dependent such as the memory size, and peripheral set. The U-Boot board support function {{{ft_board_setup}}} does most of this customization although some of the more common things like setting up the kernel cmdline are done before this is called in common bootm code.
     26 4. optionally an initial ramdisk is loaded as well
     27 5. registers are setup with the RAM location of the flattened device-tree binary, the kernel, and the optional initial ramdisk then the kernel is jumped to.
     28
     29Most of the above is done by boot scripts which implement complex behavior based on env variables.
     30
     31When Falcon mode is used all these things must be done by the SPL, which is why it saves time by not loading the code for and invoking U-Boot. When Falcon mode is used you do steps 1-4 above then invoke the {{{spl export fdt}}} command which prepares the flattened device-tree but does not jump to the kernel. Then you store this pre-prepared '''args''' structure in non-volatile memory where the SPL expects to find it and set the env var that tells the SPL to load it and the kernel and jump to the kernel.
     32
     33Note that there are certain properties within the device-tree which are 'board specific' meaning they vary from board to board. For example the board serial-number, and Ethernet controller mac addresses come from the on-board EEPROM. For this reason you do not want to 'provision' multiple boards using the '''args''' data created from a different board.
     34
     35
     36For more information about Falcon mode:
     37 * [http://www.denx.de/wiki/pub/U-Boot/MiniSummitELCE2013/2013-ELCE-U-Boot-Falcon-Boot.pdf 2013 ELCE presentation]
     38
     39
     40[=#nand]
     41== booting Linux on NAND flash ==
     42To use falcon mode on NAND flash for Ventana we need to store the kernel and args in raw flash. This is because typically we store the kernel in the mtd rootfs partition using ubifs, yet the SPL doesn't support ubifs and adding ubifs support to the SPL would likely exceed the maximum code-space of the SPL as well as completely defeat the purpose of booting fast.
     43
     44We choose the following flash layout (dictated by compile-time options in include/configs/gw_ventana.h):
     45||= Start =||= Size  =||= Usage   =||
     46|| 0MB     || 14MB    || SPL       ||
     47|| 14MB    || 2MB     || U-Boot    ||
     48|| 16MB    || 256KB   || env       ||
     49|| 17MB    || 1MB     || args      ||
     50|| 18MB    || 10MB    || kernel    ||
     51|| 28MB    || rootfs  || rootfs    ||
     52
     53To configure falcon mode on a board that boots to NAND and is flashed with latest bootloader supporting Falcon mode do the following:
     54 1. setup a TFTP server with the kernel (uImage), device-tree (ie imx6q-gw52xx), and rootfs ubi (ie openwrt-imx6-ventana-rootfs_normal.ubi) (these are all located in the build artifacts of your BSP).
     55 2. make sure the board has the latest SPL and U-Boot supporitng Falcon mode on it (ie JTAG u-boot_spl.bin)
     56 3. power on the board with serial console and ethernet, break into U-boot, and re-configure flash with:
     57{{{
     58# change mtd partitions to the above mapping
     59setenv mtdparts 'mtdparts=nand:14m(spl),2m(uboot),1m(env),1m(args),10m(kernel),-(rootfs)'
     60# re-flash rootfs at 28MB
     61tftp ${loadaddr} ventana/openwrt-imx6-ventana-rootfs_${flash_layout}.ubi && \
     62  nand erase.part rootfs && nand write ${loadaddr} rootfs ${filesize}
     63# load the device-tree
     64tftp ${fdt_addr} ventana/${fdt_file2}
     65# load the kernel
     66tftp ${loadaddr} ventana/uImage
     67# flash kernel at 18MB
     68nand erase.part kernel && nand write ${loadaddr} kernel ${filesize}
     69# set kernel args for the console and rootfs (used by spl export)
     70setenv bootargs 'console=ttymxc1,115200 root=ubi0:rootfs ubi.mtd=5 rootfstype=ubifs quiet'
     71# use the spl export command to create args based on env, board, EEPROM, and dtb
     72spl export fdt ${loadaddr} - ${fdt_addr}
     73# flash args at 17MB
     74nand erase.part args && nand write 18000000 args 100000
     75# set boot_os env var
     76setenv boot_os 1
     77saveenv
     78}}}
     79 * Note the bootargs above which you may want or need to customize for your purpose. If you are not sure what bootargs to use, you should boot without falcon mode and get them from /proc/cmdline
     80
     81Once you have switched to Falcon mode you can update the kernel in a number of ways (now that you can't do it via U-Boot):
     82 * via Linux booted on the IMX6 based target board:
     83{{{
     84cd /tmp
     85wget http://192.168.1.146/uImage
     86flash_erase /dev/mtd4 0 0
     87nandwrite -p /dev/mtd4 uImage
     88}}}
     89 * On a Linux host with the micro-SD as /dev/sdc:
     90{{{
     91sudo dd if=uImage of=/dev/sdc bs=1m seek=2 && sync
     92}}}
     93 * via JTAG:
     94{{{
     95mkimage_jtag -s uImage@18M > image.bin
     96jtag_usbv4 -p image.bin
     97}}}
     98
     99If you need to get back into the bootloader you need to clear the U-Boot env area:
     100 * via Linux booted on the IMX6 based target board:
     101{{{
     102flash_erase /dev/mtd2 0 0
     103}}}
     104 * via JTAG
     105{{{
     106dd if=/dev/zero of=env bs=1k count=1 && ./mkimage_jtag -s env@16M > env.bin
     107jtag_usbv4 -p env.bin
     108}}}
     109
     110Note that the above flash-map is not set in stone but it is set at compile time from defines in include/configs/gw_ventana.h
     111
     112
     113[=#microsd]
     114== booting Linux on a NAND-less board booting from a micro-SD device ==
     115To use falcon mode to boot directly to Linux on a micro-SD device for Ventana we need to store the kernel and args on the microSD. Note that we typically we store the kernel in an ext partition yet we have chosen to not enable filesystem support in the SPL (doing so will increase the size of the SPL, and the time necessary to boot, thus defeating the purpose of Falcon mode al-together).
     116
     117To store the kernel, and args on a block storage device, we will use the following partitioning scheme:
     118||= Start KB / blocks =||= Size KB / blocks =||= Usage             =||
     119|| 0K                  || 1KB    (2)         || Partition Table etc ||
     120|| 1KB   (2))          || 68KB   (0x88)      || SPL                 ||
     121|| 69KB  (0x8a)        || 640KB  (0x500)     || U-Boot              ||
     122|| 709KB (0x58a)       || 256KB  (0x512)     || env (redundant)     || 
     123|| 965KB               || 59KB               || unused              ||
     124|| 1MB   (0x800)       || 1MB    (0x800)     || args                ||
     125|| 2MB   (0x1000)      || 8M     (0x4000)    || kernel              ||
     126|| 10M   (0x5000)      || partitions         || rootfs              ||
     127 * Note that U-Boot defines MMC offsets and size in sectors which are 512 bytes and that U-Boot cmdline parameters are in hex
     128
     129To configure a micro-SD to boot directly to Linux from the SPL for a NAND-less board you will need the following firmware artifacts:
     130 * SPL (http://svn.gateworks.com/ventana/images/SPL)
     131 * u-boot.img (http://svn.gateworks.com/ventana/images/u-boot.img)
     132 * rootfs tarball (containing kernel and device-tree dtb files in boot/ subdir)
     133
     134Procedure:
     135 1. Insert your micro-SD card/reader into your Linux host and determine what device it is (here we assume /dev/sdc)
     136 2. prepare the micro-SD per the specifications above:
     137{{{
     138DEV=/dev/sdc
     139# zero out 1MB of device
     140sudo dd if=/dev/zero of=$DEV count=1 bs=1M oflag=sync status=none && sync
     141# copy SPL to 1KB offset
     142sudo dd if=SPL of=$DEV bs=1K seek=1 oflag=sync status=none && sync
     143# copy U-Boot to 69KB offset
     144sudo dd if=u-boot.img of=$DEV bs=1K seek=69 oflag=sync status=none && sync
     145# create a partition table with a single rootfs partition starting at 10MB
     146printf "10,,L\n" | sudo sfdisk --in-order --no-reread -L -uM $DEV && sync
     147# format partition
     148sudo mkfs.ext4 -L root ${DEV}1
     149# mount the partition
     150sudo udisks --mount ${DEV}1
     151# extract filesystem
     152sudo tar xvf rootfs.tar.gz -C /media/root
     153# flush and unmount
     154sync && sudo umount /media/root
     155}}}
     156 3. Boot the board with the prepared micro-SD and break out in U-Boot::
     157{{{
     158# load device-tree from rootfs
     159ext2load mmc 0:1 ${fdt_addr} boot/${fdt_file2}
     160# load kernel from rootfs
     161ext2load mmc 0:1 ${loadaddr} boot/uImage
     162# write kernel at 2MB offset
     163mmc write ${loadaddr} 0x1000 0x4000
     164# setup kernel args bootargs
     165setenv bootargs 'console=ttymxc1,115200 root=/dev/mmcblk0p1 rootfstype=ext4 rootwait rw quiet'
     166# prepare args and write the 1MB data (0x800 sectors) to 1MB offset (0x800 sectors)
     167spl export fdt ${loadaddr} - ${fdt_addr} && mmc write 18000000 0x800 0x800
     168# set boot_os to enable falcon mode
     169setenv boot_os 1 && saveenv
     170}}}
     171 * Note the bootargs above which you may want or need to customize for your purpose. If you are not sure what bootargs to use, you should boot without falcon mode and get them from /proc/cmdline
     172
     173
     174Once you have switched to Falcon mode you can update the kernel in a number of ways (now that you can't do it via U-Boot):
     175 * via Linux booted on the IMX6 based target board:
     176{{{
     177cd /tmp
     178wget http://192.168.1.146/uImage
     179dd if=uImage of=/dev/mmcblk0 bs=1m seek=2 && sync
     180}}}
     181 * On a Linux host with the micro-SD as /dev/sdc:
     182{{{
     183sudo dd if=uImage of=/dev/sdc bs=1m seek=2 && sync
     184}}}
     185 * via JTAG:
     186{{{
     187mkimage_jtag -s uImage@18M > image.bin
     188jtag_usbv4 -p image.bin
     189}}}
     190
     191If you need to get back into the bootloader you need to clear the U-Boot env area:
     192 * via Linux booted on the IMX6 based target board:
     193{{{
     194dd if=/dev/zero of=/dev/mmcblk0 bs=1k seek=709 count=256 && sync
     195}}}
     196 * On a Linux host with the micro-SD as /dev/sdc:
     197{{{
     198sudo dd if=/dev/zero of=/dev/sdc bs=1k seek=709 count=256 && sync
     199}}}
     200
     201
     202Keep in mind, that because there are certain properties within the device-tree which are 'board specific' (such as board serial-number, and Ethernet controller mac addresses which come from the on-board EEPROM) once a micro-SD is imaged with the procedure above, you should not move it to another board without re-creating the args data.