Apalis i.MX6: update old u-boot / configblock from linux

Hi,

We have a deployment of apalis i.MX6Q boards for which we want to update the boot environment automatically (with a script).

Current Status:

  • Two different boards: 1.1A / 1.1B
    • On 1.1A-Boards:
      • U-Boot 2014.04 is installed
      • File /sys/firmware/devicetree/base/serial-number is NOT present
      • fw_env configuration: /dev/mmcblk1 0x80000 0x2000
    • On 1.1B-Boards:
      • U-Boot 2016.11 is installed
      • File /sys/firmware/devicetree/base/serial-number IS present
      • fw_env configuration: /dev/mmcblk1boot0 -0x2200 0x2000

This leads me to the following suspicions which you maybe can confirm or deny.

Suspicions:

  • The config block is on another address.
  • This will lead to the missing /sys-File
  • The different fw_env configuration is caused by the updated U-Boot version.
  • The mmcblk1 (instead of mmcblk0) is because we use a mainline kernel without the toradex-patch for fixed device enumeration (that’s OK, we use /dev/disk/by-path in the OS)

Now I started to update the boot environment.

What I managed to do:

  • manually Update U-Boot and SPL on a 1.1A-Board to U-Boot 2019.07 (Built with poky, mainline). I did not yet try a 1.1B-Board.
dd if=SPL of=/dev/mmcblk1 bs=512 seek=2   
dd if=u-boot.bin of=/dev/mmcblk1 bs=512 seek=138
  • After the U-Boot update, the fw_env configuration has to be changed to /dev/mmcblk1boot0 -0x2200 0x2000, the same as on the 1.1B-Boards.
  • After the U-Boot update, i got the following message in U-Boot: “MISSING TORADEX CONFIG BLOCK”. I managed to move the toradex config block with the following U-Boot commands:
setenv check_1 'setenv conf_blk_offset 0x1fff; mmc read ${loadaddr} ${conf_blk_offset} 1'
setenv check_2 'setenv conf_blk_offset 0xfff; mmc read ${loadaddr} ${conf_blk_offset} 1'
setenv check_3 'setenv conf_blk_offset 0x7ff; mmc read ${loadaddr} ${conf_blk_offset} 1'

setenv check_configblock 'setexpr toradex_oui_addr ${loadaddr} + 8; mw.l ${kernel_addr_r} 0x002d1400; mmc dev 0 1; run check_1 || run check_2 || run check_3; cmp.b ${kernel_addr_r} ${toradex_oui_addr} 3'

setenv migrate_configblock 'run check_configblock; mmc dev 0 0 && mmc read ${loadaddr} 0x500 1 && cmp.b ${kernel_addr_r} ${toradex_oui_addr} 3 && mmc dev 0 1 && mmc write ${loadaddr} ${conf_blk_offset} 1'

run migrate_configblock
  • After moving the config block, the File /sys/firmware/devicetree/base/serial-number becomes present.

I want to automate this whole process so that it can be run entirely in a running operating system. For this I have some questions:

Questions:

  • When updating u-boot / spl, why do I have to use /dev/mmcblk1 instead of /dev/mmcblk1boot0? Is this caused by the moved config block (which is read by the kernel)?
  • Can I use /dev/mmcblk1 for u-boot / spl update anyways, or do I have to use /dev/mmcblk1boot0 after moving the config block?
  • did the u-boot env location change, or is this just different because of the difference in partition layout?
  • Is there a way to move the config block from the updater script?
  • If not, is the method for moving the config block above save to use on boards which already have a migrated config block?
  • Do I get feedback from migrate_configblock if the migration was necessary or skipped?

Thanks a lot in advance!
Christof

Hi,

In the meantime I could answer a lot of the questions I asked above. To help other people, here is my current update script:

#fix partition links for old angstrom-based image
if [ ! -e /dev/disk/by-path/platform-2198000.usdhc-boot0 ] ; then
    ln -s /dev/mmcblk0boot0 /dev/disk/by-path/platform-2198000.usdhc-boot0
    ln -sf /dev/mmcblk0 /dev/disk/by-path/platform-2198000.usdhc #was: /dev/mmcblk0boot0
fi

#We have two different locations, one for the U-Boot 2014 and one for the U-Boot 2016:
# 2014: /dev/disk/by-path/platform-2198000.usdhc 0x80000 0x2000
# 2016: /dev/disk/by-path/platform-2198000.usdhc-boot0 -0x2200 0x2000
for configfile in /etc/fw_env*.config ; do

    test=$(fw_printenv --config $configfile 2>&1 1>/dev/null) #this will give output if there was an error reading the u-boot-env
    
    if [ "$test" == "" ] ; then
        FWENV_CONFIG="--config $configfile"
        echo "FWENV_CONFIG=$FWENV_CONFIG"
        break
    fi
done

if [ "${FWENV_CONFIG}" == "" ] ; then
    echo "Could not find correct FWENV_CONFIG"
    exit 0
fi

# disable readonly-mode. Since mmc order is not always the same, set force_ro = 0 on both possible locations.
echo 0 > /sys/block/mmcblk0boot0/force_ro
echo 0 > /sys/block/mmcblk1boot0/force_ro


#update u-boot. Here I found that there are two possible locations, once at the beginning of /dev/mmcblk0, and once at the beginning of /dev/mmcblk0boot1
dd if=/boot/SPL of=/dev/disk/by-path/platform-2198000.usdhc bs=512 seek=2
dd if=/boot/u-boot.bin of=/dev/disk/by-path/platform-2198000.usdhc bs=512 seek=138
dd if=/boot/SPL of=/dev/disk/by-path/platform-2198000.usdhc-boot0 bs=512 seek=2
dd if=/boot/u-boot.bin of=/dev/disk/by-path/platform-2198000.usdhc-boot0 bs=512 seek=138

#read ethaddr
ETHADDR=`fw_printenv $FWENV_CONFIG ethaddr | sed s/^.*=//` 

#write the new config
fw_printenv | sed 's/=.*//' > /boot/u-boot-env-edited.txt #delete all existing entries
cat /boot/u-boot-env.txt >> /boot/u-boot-env-edited.txt #add new entries
echo ethaddr $ETHADDR >> /boot/u-boot-env-edited.txt #set ethaddr from backup
fw_setenv -s /boot/u-boot-env-edited.txt # write the new bootenv

For migrating the config block I have added some lines to the u-boot-env. The check_and_migrate_configblock basically guarantees that the migration is tried only once after the update, not on every reboot. The remaining script is toradex-provided.

#config block movement
check_and_migrate_configblock echo check_and_migrate_configblock ; if test ${configblock_moved} != 1 ; then setenv configblock_moved 1 ; saveenv ; run migrate_configblock ; reset ; fi
#below is toradex provided
check_1 setenv conf_blk_offset 0x1fff; mmc read ${loadaddr} ${conf_blk_offset} 1
check_2 setenv conf_blk_offset 0xfff; mmc read ${loadaddr} ${conf_blk_offset} 1
check_3 setenv conf_blk_offset 0x7ff; mmc read ${loadaddr} ${conf_blk_offset} 1
check_configblock setexpr toradex_oui_addr ${loadaddr} + 8; mw.l ${kernel_addr_r} 0x002d1400; mmc dev 0 1; run check_1 || run check_2 || run check_3; cmp.b ${kernel_addr_r} ${toradex_oui_addr} 3
migrate_configblock echo migrate_configblock ; run check_configblock; mmc dev 0 0 && mmc read ${loadaddr} 0x500 1 && cmp.b ${kernel_addr_r} ${toradex_oui_addr} 3 && mmc dev 0 1 && mmc write ${loadaddr} ${conf_blk_offset} 1

Now, there is one remaining question:
For the 1.1A-Boards (originally delivered with U-Boot 2014 I have to write the updated U-Boot binaries to /dev/mmcblk0 (seek 2, seek 138). For the 1.1B-Boards I have to write U-Boot to /dev/mmcblk0boot1. Currently I just write to both locations. What’s the reason for this? Change in the ROM where the bootloader should be found? Could this cause any problems? (I did not notice any…)

This all has to do with newer modules being fused to boot from the primary eMMC hardware boot area partition using a special boot mode thereof called fast boot:

You may find this all being very well documented in resp. PCN as well:

Well there is no PCN for the Apalis iMX6Q 1GB V1.1B in the list you linked. Thanks for the Links :slight_smile:

You are very welcome. Please note that a Product Change Notification (PCN) document is usually only available for the product being changed and not the new one (;-p).