Changes between Initial Version and Version 1 of venice/boot


Ignore:
Timestamp:
06/11/2020 09:16:26 PM (2 years ago)
Author:
Tim Harvey
Comment:

initial page

Legend:

Unmodified
Added
Removed
Modified
  • venice/boot

    v1 v1  
     1[[PageOutline]]
     2
     3= Venice Boot Firmware
     4The 'Boot Firmware' for Venice is defined as the combination of the firmware stages through up to and including the bootloader. This can be broken down into the following stages:
     5 * Boot ROM (internal on i.MX8 SoC): fetch first level boot firmware from boot device (ie MMC or SPI FLASH) into L2 cache
     6 * SPL (Secondary Program Loader) - (U-Boot)
     7 * ATF (ARM Trusted Firmware)
     8 * Bootloader (U-Boot)
     9
     10Gateworks provides pre-built Boot Firmware [http://dev.gateworks.com/venice/boot_firmware/flash.bin flash.bin] ready to flash onto boot devices as well as source for building and/or modifying the boot firmware yourself.
     11
     12[=#bootrom]
     13== i.MX8 BOOT ROM
     14The BOOT ROM is firmware baked into the SoC and is in charge of loading code from the 'boot device' into an L2 cache scratchpad, verifying signatures (if using trusted boot) and executing it.
     15
     16The BOOT ROM fetches code from an offset of 33KiB on the boot device which leaves the first 33KiB available for other firmware needs.
     17
     18[=#firmware-image]
     19== Boot Firmware Image
     20The firmware image contains all of the components of the 'Boot Firmware':
     21- MBR partition table
     22- ATF
     23- Device Tree Binary
     24- U-Boot
     25
     26Venice Boot Firmware Image Map:
     27||= start-end                 =||= len =||= item =||= notes =||
     28|| 0x0000000 - 0x0008400 || 33KiB  || MBR Partition Table || only first 512B used ||
     29|| 0x0008400 - 0x0060000 || 350KiB || SPL || Loads and u-boot.itb and transfers control to the ATF ||
     30|| 0x0060000 - 0x0FF0000 || 15MiB  || u-boot.itb || FIT image containing u-boot, ATF, and fdt ||
     31|| 0x0FF0000 - 0x1000000 || 64KB   || U-Boot env || redudant 32KB env ||
     32|| 0x1000000 -           ||        || Disk Partitions || used by the OS ||
     33
     34The firmware image starting at the 33KB offset is the 'flash.bin' file created by U-Boot which contains the u-boot.itb.
     35
     36
     37[=#disk-images]
     38== Building a Bootable Disk Images
     39Gateworks releases compressed disk images that can be easily flashed using the U-Boot Bootloader. These disk images contain a partition table so they are tailored to the specific device size they are intended for. Additionally they are commonly configured for a small partition size to keep flash programming time at a minimum. This requires resizing the rootfs filesystem in order to take advantage of the remaining flash space.
     40
     41Once you have a root filesystem directory/tarball and have a kernel Image you can create a compressed disk image that can be installed easily from the bootloader.
     42
     43This is process is demonstrated in the [http://github.com/Gateworks/bsp-venice/Makefile Venice BSP makefile]
     44
     45Once you have a compressed disk image you can install this using the methods described in [wiki:venice#firmware-update venice/firware-update]. For example in the bootloader:
     46{{{#!bash
     47setenv dev 2 # emmc device; use mmc list to see all mmc devs
     48tftpboot ${loadaddr} focal-venice.img.gz && gzwrite mmc ${dev} ${loadaddr} ${filesize}
     49}}}
     50
     51If you created a filesystem that did not stretch to the partition it was installed on (as we create a minimally sized filesystem image to fit within the eMMC device for faster programming) you will want to resize it after booting to Linux. This is a one time operation after flashing a compressed disk image and can be done using the 'growpart_once' script that we install on the Ubuntu Root filesystems found in the script [https://github.com/Gateworks/ubuntu-rootfs/blob/master/ubuntu-rootfs.sh here] (search for growpart_once)
     52
     53To install the kernel and root filesystem on a removable block storage device see [wiki:linux/blockdev].
     54
     55
     56[=#u-boot]
     57== U-Boot Bootloader
     58Gateworks supports the U-Boot Bootloader for the Venice product family.
     59
     60The purpose of a bootloader is to load the Linux kernel and execute it passing it configuration parameters such as an optional kernel command-line, an optional initial ramdisk filesystem, and a device-tree.
     61
     62
     63[=#distro-config]
     64== Distro Config
     65The Venice Bootloader uses U-Boot's 'Distro Config' which is a well defined U-Boot env intended to make it easier for distro maintainers to develop compatible bootscripts. This primarily entails a set of 'boot scripts' and variables that control them.
     66
     67Ultimately this U-Boot environment is looking for a U-Boot [#bootscript boot script] on a 'bootable' partition (partitions with the 'boot' flag enabled). It searches in this order with these rules:
     68 - **boot_targets** - list of target device type/nums to search: defaults to mmc1 mmc2 usb0 usb1 pxe
     69 - **devplist** - ''dynamically created'' list of all partitions flagged as 'bootable'
     70 - **boot_prefixes** - list of directories within a partition searched for bootscripts
     71 - **boot_scripts** - list of boot script names searched for
     72
     73
     74[=#bootscript]
     75== Boot Scripts
     76When writing bootscripts compatible with [#distro-config Distro Config] you can assume the following env variables:
     77 - **devtype** - the device type the script was loaded from (mmc|usb|sata)
     78 - **devnum** - the device number the script was loaded from (ie 0 for mmc0, 1 for mmc1, etc)
     79 - **distro_bootpart** - the partition number the script was loaded from (ie 0, 1, etc)
     80 - **fdtcontroladdr** - the address the device-tree is at (Note that the Venice bootloader does not load/manipulate the device-tree itself - this is done by the SPL which loads/manipulates the device-tree and passes it to the bootloader)
     81 - **kernel_addr_r** - address where kernel can be loaded
     82 - **bootargs** - default bootargs to pass to the kernel - you probably want to add to this and not overwrite it
     83 - **console** - the serial console device to pass to the kernel
     84
     85Additionally you should note the following:
     86 - use load/ls/save commands which support FAT/ext filesystem types automatically instead of the fs specific commands
     87 - if using a root filesystem that is not supported by the bootloader (ie F2FS or BTRFS) you can place your bootscript and kernel image in the FAT12 filesystem on partition 1 of the boot device. This filesystem is part of the 16MB 'Boot Firmware' image. If doing so you will need to compress the kernel and package it into a [#fit FIT image] in order to fit it in the available space.
     88
     89The Distro-Config environment supports legacy uImage scripts (it does not support FIT images with scripts). You can create these with the {{{mkimage}}} tool from U-Boot as such:
     90{{{#!bash
     91mkimage -A arm64 -T script -C none -d boot.txt boot.scr
     92}}}
     93
     94The bootscript can be updated at runtime on the Linux target. For example:
     95{{{#!bash
     96mkimage -A arm64 -T script -C none -d boot.txt /boot/boot.scr
     97}}}
     98
     99
     100[=#boot_targets]
     101=== Boot Device Order (boot_targets)
     102While the Venice product family can only boot from its primary boot device (typically eMMC), once you are booted to the bootloader you can choose from a wider variety of devices to boot the OS from.
     103
     104This OS boot device order is specified by the [#distro-config Distro Config] environment. Specifically it is controlled by the {{{boot_targets}}} env variable which defaults to {{{mmc1 mmc2 usb0 usb1 pxe}}}.
     105
     106For example, to limit OS booting to only USB:
     107{{{#!bash
     108setenv boot_targets usb0 usb1
     109saveenv
     110}}}
     111
     112
     113[=#fit]
     114== Flattened Image Tree (FIT) images
     115The U-Boot bootloader supports Flattened Image Tree (FIT) images which expand greatly on the legacy U-Boot image (uImage) format by allowing multiple binary blobs within an image. These blobs can be kernel images, ramdisk images, device-tree blobs, and bootloader scripts. Each image can also be optionally compressed (meaning U-Boot will decompress it) and check-sumed with a variety of hash mechanisms (meaning U-Boot will verify the image before using it).
     116
     117Quick summary of FIT Images:
     118 * introduced to resolve limitations with original single-image formats and follow-on multi-image format supported by UBoot bootm (boot memory)
     119 * uses power of the Device-Tree-Compiler (DTC)
     120 * FIT .itb files can be created with mkimage by passing in a .its file which in device-tree notation describes the images
     121 * U-Boot supports FIT with several commands:
     122  - {{{source <addr>:<name>}}} # source a script by name from FIT image in memory
     123  - {{{iminfo <fitaddress>}}} # print all the info contained in a FIT image in memory and verify (just not boot it)
     124  - {{{imextract <fitaddress> <item> <addr>}}} # extract item (ie kernel@1) to addr
     125  - {{{bootm <fitaddress>[#conf] - $fdtcontroladdr}}} # boot default or 'conf' configuration (ie #config@1)
     126  - {{{bootm start <fitaddress>[#conf] - $fdtcontroladdr}}} # boot from memory a specific configuration (or default configuration) from FIT image
     127
     128Example:
     129 * kernel.its with a single compressed kernel for ARM64
     130{{{#!bash
     131/dts-v1/;
     132/ {
     133        description = "Simple image with single Linux kernel";
     134        #address-cells = <1>;
     135        images {
     136                kernel@1 {
     137                        description = "Linux kernel";
     138                        data = /incbin/("./Image.gz");
     139                        type = "kernel";
     140                        arch = "arm64";
     141                        os = "linux";
     142                        compression = "gzip";
     143                        load = <0x40200000>;
     144                        entry = <0x40200000>;
     145                        hash@1 {
     146                                algo = "sha256";
     147                        };
     148                };
     149        };
     150
     151        configurations {
     152                default = "conf@1";
     153                conf@1 {
     154                        description = "Boot Linux kernel";
     155                        kernel = "kernel@1";
     156                };
     157        };
     158};
     159}}}
     160 * create image:
     161{{{#!bash
     162cp arch/arm64/boot/Image .
     163gzip Image
     164mkimage -f kernel.its /tftpboot/kernel.itb
     165}}}
     166 * boot the default configuration from U-Boot:
     167{{{#!bash
     168tftpboot $loadaddr kernel.itb && bootm $loadaddr - $fdtcontroladdr
     169}}}
     170
     171References:
     172 * [http://git.denx.de/?p=u-boot.git;a=tree;f=doc/uImage.FIT doc/uImage.FIT]
     173 * http://www.denx.de/wiki/pub/U-Boot/Documentation/multi_image_booting_scenarios.pdf
     174 * http://elinux.org/images/f/f4/Elc2013_Fernandes.pdf
     175
     176
     177= U-boot env tools
     178A detailed description of u-boot-tools usage can be found [wiki:/ventana/bootloader#U-Bootenvtoolsfw_printenvfw_setenv here]. 
     179
     180In order to configure u-boot-tools to work correctly for Ventana you will need a fw_env.config file the appropriate values. 
     181
     182To create this file:
     183{{{#!bash
     184cat << EOF > /etc/fw_env.config
     185# Device               offset          Env. size
     186/dev/mmcblk0           0xff0000        0x8000
     187/dev/mmcblk0           0xff8000        0x8000
     188EOF
     189}}}
     190