Marek Vasut | 59e3d1b | 2021-03-25 01:20:48 +0100 | [diff] [blame] | 1 | i.MX7D/i.MX8MM SRC_GPR10 PERSIST_SECONDARY_BOOT for bootloader A/B switching |
| 2 | ============================================================================ |
| 3 | |
| 4 | Introduction |
| 5 | ------------ |
| 6 | Since at least iMX53 until iMX8MM, it is possible to have two copies of |
| 7 | bootloader in SD/eMMC and switch between them. The switch is triggered |
| 8 | either by the BootROM in case the bootloader image is faulty OR can be |
| 9 | enforced by the user. |
| 10 | |
| 11 | Operation |
| 12 | --------- |
| 13 | #. Upon Power-On Reset (POR) |
| 14 | |
| 15 | - SRC_GPR10 bit PERSIST_SECONDARY_BOOT is set to 0 |
| 16 | - BootROM attempts to start bootloader A-copy |
| 17 | |
| 18 | - if A-copy valid |
| 19 | |
| 20 | - BootROM starts A-copy |
| 21 | - END |
| 22 | |
| 23 | - if A-copy NOT valid |
| 24 | |
| 25 | - BootROM sets SRC_GPR10 bit PERSIST_SECONDARY_BOOT to 1 |
| 26 | - BootROM triggers WARM reset, GOTO 1) |
| 27 | - END |
| 28 | |
| 29 | #. Upon COLD Reset |
| 30 | |
| 31 | - GOTO 1) |
| 32 | - END |
| 33 | |
| 34 | #. Upon WARM Reset |
| 35 | |
| 36 | - SRC_GPR10 bit PERSIST_SECONDARY_BOOT is retained |
| 37 | |
| 38 | - if SRC_GPR10 bit PERSIST_SECONDARY_BOOT is 0 |
| 39 | |
| 40 | - BootROM attempts to start bootloader A-copy |
| 41 | |
| 42 | - if A-copy valid |
| 43 | |
| 44 | - BootROM starts A-copy |
| 45 | - END |
| 46 | |
| 47 | - if A-copy NOT valid |
| 48 | |
| 49 | - BootROM sets SRC_GPR10 bit PERSIST_SECONDARY_BOOT to 1 |
| 50 | - BootROM triggers WARM reset. GOTO 1.3) |
| 51 | - END |
| 52 | |
| 53 | - if SRC_GPR10 bit PERSIST_SECONDARY_BOOT is 1 |
| 54 | |
| 55 | - BootROM attempts to start bootloader B-copy |
| 56 | |
| 57 | - if B-copy valid |
| 58 | |
| 59 | - BootROM starts B-copy |
| 60 | - END |
| 61 | |
| 62 | - if B-copy NOT valid |
| 63 | - System hangs |
| 64 | - END |
| 65 | |
| 66 | Setup |
| 67 | ----- |
| 68 | The bootloader A-copy must be placed at predetermined offset in SD/eMMC. The |
| 69 | bootloader B-copy area offset is determined by an offset stored in Secondary |
| 70 | Image Table (SIT). The SIT must be placed at predetermined offset in SD/eMMC. |
| 71 | |
| 72 | The following table contains offset of SIT, bootloader A-copy and recommended |
| 73 | bootloader B-copy offset. The offsets are in 512 Byte sector units (that is |
| 74 | offset 0x1 means 512 Bytes from the start of SD/eMMC card data partition). |
| 75 | For details on the addition of two numbers in recommended B-copy offset, see |
| 76 | SIT format below. |
| 77 | |
| 78 | +----------+--------------------+-----------------------+-----------------------------+ |
| 79 | | SoC | SIT offset (fixed) | A-copy offset (fixed) | B-copy offset (recommended) | |
| 80 | +----------+--------------------+-----------------------+-----------------------------+ |
| 81 | | iMX7D | 0x1 | 0x2 | 0x800+0x2 | |
| 82 | +----------+--------------------+-----------------------+-----------------------------+ |
| 83 | | iMX8MM | 0x41 | 0x42 | 0x1000+0x42 | |
| 84 | +----------+--------------------+-----------------------+-----------------------------+ |
| 85 | |
| 86 | SIT format |
| 87 | ~~~~~~~~~~ |
| 88 | SIT is a 20 byte long structure containing of 5 32-bit words. Those encode |
| 89 | bootloader B-copy area offset (called "firstSectorNumber"), magic value |
| 90 | (called "tag") that is always 0x00112233, and three unused words set to 0. |
Heinrich Schuchardt | 41ad972 | 2021-04-11 17:03:53 +0200 | [diff] [blame] | 91 | SIT is documented in [1]_ and [2]_. Example SIT are below:: |
Marek Vasut | 59e3d1b | 2021-03-25 01:20:48 +0100 | [diff] [blame] | 92 | |
| 93 | $ hexdump -vC sit-mx7d.bin |
| 94 | 00000000 00 00 00 00 |
| 95 | 00000004 00 00 00 00 |
| 96 | 00000008 33 22 11 00 <--- This is the "tag" |
| 97 | 0000000c 00 08 00 00 <--- This is the "firstSectorNumber" |
| 98 | 00000010 00 00 00 00 |
| 99 | |
| 100 | $ hexdump -vC sit-mx8mm.bin |
| 101 | 00000000 00 00 00 00 |
| 102 | 00000004 00 00 00 00 |
| 103 | 00000008 33 22 11 00 <--- This is the "tag" |
| 104 | 0000000c 00 10 00 00 <--- This is the "firstSectorNumber" |
| 105 | 00000010 00 00 00 00 |
| 106 | |
| 107 | B-copy area offset ("firstSectorNumber") is offset, in units of 512 Byte |
| 108 | sectors, that is added to the start of boot media when switching between |
| 109 | A-copy and B-copy. For A-copy, this offset is 0x0. For B-copy, this offset |
| 110 | is determined by SIT (e.g. if firstSectorNumber is 0x1000 as it is above |
| 111 | in sit-mx8mm.bin, then the B-copy offset is 0x1000 sectors = 2 MiB). |
| 112 | |
| 113 | Bootloader A-copy (e.g. u-boot.imx or flash.bin) is placed at fixed offset |
| 114 | from A-copy area offset (e.g. 0x2 sectors from sector 0x0 for iMX7D, which |
| 115 | means u-boot.imx A-copy must be written to sector 0x2). |
| 116 | |
| 117 | The same applies to bootloader B-copy, which is placed at fixed offset from |
| 118 | B-copy area offset determined by SIT (e.g. 0x2 sectors from sector 0x800 [see |
| 119 | sit-mx7d.bin example above, this can be changed in SIT firstSectorNumber] for |
| 120 | iMX7D, which means u-boot.imx B-copy must be written to sector 0x802) |
| 121 | |
| 122 | **WARNING:** |
| 123 | B-copy area offset ("firstSectorNumber") is NOT equal to bootloader |
| 124 | (image, which is u-boot.imx or flash.bin) B-copy offset. |
| 125 | |
| 126 | To generate SIT, use for example the following bourne shell printf command:: |
| 127 | |
| 128 | $ printf '\x0\x0\x0\x0\x0\x0\x0\x0\x33\x22\x11\x00\x00\x08\x00\x00\x0\x0\x0\x0' > sit-mx7d.bin |
| 129 | $ printf '\x0\x0\x0\x0\x0\x0\x0\x0\x33\x22\x11\x00\x00\x10\x00\x00\x0\x0\x0\x0' > sit-mx8mm.bin |
| 130 | |
| 131 | Write bootloader A/B copy and SIT to SD/eMMC |
| 132 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| 133 | |
| 134 | Examples of writing SIT and two copies of bootloader to SD or eMMC: |
| 135 | |
| 136 | - iMX8MM, SD card at /dev/sdX, Linux command line |
| 137 | :: |
| 138 | |
| 139 | $ dd if=sit-mx8mm.bin of=/dev/sdX bs=512 seek=65 |
| 140 | $ dd if=flash.bin of=/dev/sdX bs=512 seek=66 |
| 141 | $ dd if=flash.bin of=/dev/sdX bs=512 seek=4162 |
| 142 | |
| 143 | - iMX8MM, eMMC 1 data partition, U-Boot command line |
| 144 | :: |
| 145 | |
| 146 | => mmc partconf 1 0 0 0 |
| 147 | |
| 148 | => dhcp ${loadaddr} sit-mx8mm.bin |
| 149 | => mmc dev 1 |
| 150 | => mmc write ${loadaddr} 0x41 0x1 |
| 151 | |
| 152 | => dhcp ${loadaddr} flash.bin |
Marek Vasut | 3c73c5e | 2021-04-11 18:30:36 +0200 | [diff] [blame] | 153 | => setexpr blkcnt ${filesize} + 0x1ff && setexpr blkcnt ${blkcnt} / 0x200 |
Marek Vasut | 59e3d1b | 2021-03-25 01:20:48 +0100 | [diff] [blame] | 154 | => mmc dev 1 |
| 155 | => mmc write ${loadaddr} 0x42 ${blkcnt} |
| 156 | => mmc write ${loadaddr} 0x1042 ${blkcnt} |
| 157 | |
| 158 | WARM reset into B-copy using WDT |
| 159 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| 160 | |
| 161 | To perform a reboot into B-copy, the PERSIST_SECONDARY_BOOT must be set |
| 162 | in SRC_GPR0 register. Example on iMX8MM:: |
| 163 | |
| 164 | => mw 0x30390098 0x40000000 |
| 165 | |
| 166 | A WARM reset can be triggered using WDT as follows:: |
| 167 | |
| 168 | => mw.w 0x30280000 0x25 |
| 169 | |
| 170 | References |
| 171 | ---------- |
| 172 | |
| 173 | .. [1] i.MX 7Dual Applications Processor Reference Manual, Rev. 1, 01/2018 ; section 6.6.5.3.5 Redundant boot support for expansion device |
| 174 | .. [2] i.MX 8M Mini Applications Processor Reference Manual, Rev. 3, 11/2020 ; section 6.1.5.4.5 Redundant boot support for expansion device |