Pi3 USB boot support

The forum does not let me upload the .diff file, so here it is:

Activate Mender and USB boot from vanilla u-boot repo

diff --git a/configs/rpi_4_32b_defconfig b/configs/rpi_4_32b_defconfig
index 47ea466454..0090c62b31 100644
--- a/configs/rpi_4_32b_defconfig
+++ b/configs/rpi_4_32b_defconfig
@@ -59,3 +59,11 @@ CONFIG_PHYS_TO_BUS=y
 CONFIG_ADDR_MAP=y
 CONFIG_SYS_NUM_ADDR_MAP=2
 CONFIG_OF_LIBFDT_OVERLAY=y
+
+CONFIG_ENV_FAT_INTERFACE="usb"
+CONFIG_SYS_REDUNDAND_ENVIRONMENT=y
+# CONFIG_ENV_IS_IN_MMC=y
+# CONFIG_ENV_OFFSET=0x400000
+# CONFIG_ENV_OFFSET_REDUND=0x800000
+# CONFIG_PREBOOT="usb start; load usb 0 $kernel_addr_r /u-boot_splash.bmp; bmp display $kernel_addr_r m m; load usb 0:1 ${kernel_addr_r} /uboot.env; env import -c ${kernel_addr_r} 0x4000;"
+# CONFIG_PREBOOT="usb start; load usb 0 $kernel_addr_r ; load usb 0:1 ${kernel_addr_r} /uboot.env; env import -c ${kernel_addr_r} 0x4000;"
diff --git a/include/config_mender.h b/include/config_mender.h
new file mode 100644
index 0000000000..3377ab0a1b
--- /dev/null
+++ b/include/config_mender.h
@@ -0,0 +1,98 @@
+/*
+  Copyright 2017 Northern.tech AS
+
+  This program is free software; you can redistribute it and/or
+  modify it under the terms of the GNU General Public License
+  as published by the Free Software Foundation; either version 2
+  of the License, or (at your option) any later version.
+
+  This program is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+*/
+
+#ifndef HEADER_CONFIG_MENDER_H
+#define HEADER_CONFIG_MENDER_H
+
+/* Avoid Mender specific code if we are just probing for configuration. */
+#ifndef MENDER_AUTO_PROBING
+
+#include <config_mender_defines.h>
+
+#ifdef CONFIG_ENV_IS_NOWHERE
+# error A CONFIG_ENV_IS_IN_<storage-type> define is required for Mender to work. For standard Mender setups this should be CONFIG_ENV_IS_IN_MMC for HD/SSD/MMC/SD storage setup, and CONFIG_ENV_IS_IN_UBI for Flash/UBI storage.
+#endif
+
+#ifndef CONFIG_BOOTCOUNT_LIMIT
+# error CONFIG_BOOTCOUNT_LIMIT is required for Mender to work. Make sure that: 1) All the instructions at https://docs.mender.io/system-updates-yocto-project/board-integration/bootloader-support/u-boot have been followed. 2) All required layers are included in bblayers.conf, including any board specific layers such as meta-mender-<board>
+#endif
+
+/* Currently Mender needs bootcount to reside in environment. */
+#ifndef CONFIG_BOOTCOUNT_ENV
+# error CONFIG_BOOTCOUNT_ENV is required for Mender to work. Make sure that: 1) All the instructions at https://docs.mender.io/system-updates-yocto-project/board-integration/bootloader-support/u-boot have been followed. 2) All required layers are included in bblayers.conf, including any board specific layers such as meta-mender-<board>
+#endif
+
+#ifndef CONFIG_SYS_REDUNDAND_ENVIRONMENT
+# error CONFIG_SYS_REDUNDAND_ENVIRONMENT is required for Mender to work. Make sure that: 1) All the instructions at https://docs.mender.io/system-updates-yocto-project/board-integration/bootloader-support/u-boot have been followed. 2) All required layers are included in bblayers.conf, including any board specific layers such as meta-mender-<board>. Check also https://docs.mender.io/troubleshoot/yocto-project-build for Known Issues when upgrading.
+#endif
+
+#ifdef MENDER_UBI
+# ifndef CONFIG_MTDIDS_DEFAULT
+#  define CONFIG_MTDIDS_DEFAULT MENDER_MTDIDS
+# endif
+# ifndef CONFIG_MTDPARTS_DEFAULT
+#  define CONFIG_MTDPARTS_DEFAULT "mtdparts=" ## MENDER_MTDPARTS
+# endif
+# ifndef CONFIG_ENV_UBI_PART
+#  define CONFIG_ENV_UBI_PART          MENDER_MTD_UBI_DEVICE_NAME
+# endif
+# ifndef CONFIG_ENV_UBI_VOLUME
+#  define CONFIG_ENV_UBI_VOLUME        "u-boot-env-1"
+# endif
+# ifndef CONFIG_ENV_UBI_VOLUME_REDUND
+#  define CONFIG_ENV_UBI_VOLUME_REDUND "u-boot-env-2"
+# endif
+#else
+# if defined(CONFIG_ENV_OFFSET)
+#  if CONFIG_ENV_OFFSET != MENDER_UBOOT_ENV_STORAGE_DEVICE_OFFSET_1
+#   error CONFIG_ENV_OFFSET is not the same as MENDER_UBOOT_ENV_STORAGE_DEVICE_OFFSET_1. Either set it to the same value (check for example in the defconfig file), or make sure it is not defined at all. Make sure that: 1) All the instructions at https://docs.mender.io/system-updates-yocto-project/board-integration/bootloader-support/u-boot have been followed. 2) All required layers are included in bblayers.conf, including any board specific layers such as meta-mender-<board>. Check also https://docs.mender.io/troubleshoot/yocto-project-build for Known Issues when upgrading.
+#  endif
+# else
+#  define CONFIG_ENV_OFFSET MENDER_UBOOT_ENV_STORAGE_DEVICE_OFFSET_1
+# endif
+# if defined(CONFIG_ENV_OFFSET_REDUND)
+#  if CONFIG_ENV_OFFSET_REDUND != MENDER_UBOOT_ENV_STORAGE_DEVICE_OFFSET_2
+#   error CONFIG_ENV_OFFSET_REDUND is not the same as MENDER_ENV_OFFSET_REDUND. Either set it to the same value (check for example in the defconfig file), or make sure it is not defined at all. Make sure that: 1) All the instructions at https://docs.mender.io/system-updates-yocto-project/board-integration/bootloader-support/u-boot have been followed. 2) All required layers are included in bblayers.conf, including any board specific layers such as meta-mender-<board>. Check also https://docs.mender.io/troubleshoot/yocto-project-build for Known Issues when upgrading.
+#  endif
+# else
+#  define CONFIG_ENV_OFFSET_REDUND MENDER_UBOOT_ENV_STORAGE_DEVICE_OFFSET_2
+# endif
+# ifdef CONFIG_SYS_MMC_ENV_DEV
+#  if CONFIG_SYS_MMC_ENV_DEV != MENDER_UBOOT_STORAGE_DEVICE
+#   error CONFIG_SYS_MMC_ENV_DEV is not the same as MENDER_UBOOT_STORAGE_DEVICE. Either set it to the same value (check for example in the defconfig file), or make sure it is not defined at all. Make sure that: 1) All the instructions at https://docs.mender.io/system-updates-yocto-project/board-integration/bootloader-support/u-boot have been followed. 2) All required layers are included in bblayers.conf, including any board specific layers such as meta-mender-<board>
+#  endif
+# else
+#  define CONFIG_SYS_MMC_ENV_DEV   MENDER_UBOOT_STORAGE_DEVICE
+# endif
+# ifndef CONFIG_SYS_MMC_ENV_PART
+   /* Use MMC partition zero to select whole user area of memory card. */
+#  define CONFIG_SYS_MMC_ENV_PART  0
+# endif
+#endif
+
+#ifdef CONFIG_ENV_SIZE
+# if MENDER_BOOTENV_SIZE != CONFIG_ENV_SIZE
+#  error 'CONFIG_ENV_SIZE' define must be equal to bitbake variable 'BOOTENV_SIZE' set in U-Boot build recipe.
+# endif
+#else
+# define CONFIG_ENV_SIZE MENDER_BOOTENV_SIZE
+#endif
+
+#endif /* !MENDER_AUTO_PROBING */
+
+#endif /* HEADER_CONFIG_MENDER_H */
diff --git a/include/config_mender_defines.h b/include/config_mender_defines.h
new file mode 100644
index 0000000000..1bb2aec7fb
--- /dev/null
+++ b/include/config_mender_defines.h
@@ -0,0 +1,33 @@
+/* AUTOGENERATED FILE - DO NOT EDIT! */
+/* This file is provided by the meta-mender layer. */
+
+#ifndef HEADER_CONFIG_MENDER_DEFINES_H
+#define HEADER_CONFIG_MENDER_DEFINES_H
+
+/* Shell variables */
+#define MENDER_BOOT_PART_NUMBER 1
+#define MENDER_BOOT_PART_NUMBER_HEX 1
+#define MENDER_ROOTFS_PART_A_NUMBER 2
+#define MENDER_ROOTFS_PART_A_NUMBER_HEX 2
+#define MENDER_ROOTFS_PART_B_NUMBER 3
+#define MENDER_ROOTFS_PART_B_NUMBER_HEX 3
+#define MENDER_UBOOT_STORAGE_INTERFACE "usb"
+// #define MENDER_UBOOT_STORAGE_INTERFACE "mmc"
+#define MENDER_UBOOT_STORAGE_DEVICE 0
+
+/* BB variables. */
+#define MENDER_STORAGE_DEVICE_BASE "/dev/sda"
+#define MENDER_UBOOT_ENV_STORAGE_DEVICE_OFFSET_1 0x400000
+#define MENDER_UBOOT_ENV_STORAGE_DEVICE_OFFSET_2 0x800000
+#define MENDER_ROOTFS_PART_A_NAME "/dev/sda2"
+#define MENDER_ROOTFS_PART_B_NAME "/dev/sda3"
+
+/* For sanity checks. */
+#define MENDER_BOOTENV_SIZE 0x4000
+
+#define MENDER_BOOT_KERNEL_TYPE "bootm"
+#define MENDER_KERNEL_NAME "kernel7l-uboot.img"
+#define MENDER_DTB_NAME "bcm2711-rpi-4-b.dtb"
+#define MENDER_UBOOT_PRE_SETUP_COMMANDS ""
+#define MENDER_UBOOT_POST_SETUP_COMMANDS ""
+#endif /* !HEADER_CONFIG_MENDER_DEFINES_H */
\ No newline at end of file
diff --git a/include/configs/rpi.h b/include/configs/rpi.h
index 834f1cd236..3eb3faac47 100644
--- a/include/configs/rpi.h
+++ b/include/configs/rpi.h
@@ -97,6 +97,9 @@
 /* Environment */
 #define CONFIG_SYS_LOAD_ADDR		0x1000000
 
+#define CONFIG_BOOTCOUNT_LIMIT
+#define CONFIG_BOOTCOUNT_ENV
+
 /* Shell */
 
 /* ATAGs support for bootm/bootz */
diff --git a/include/env_default.h b/include/env_default.h
index 1ddd64ba8f..5343964cb0 100644
--- a/include/env_default.h
+++ b/include/env_default.h
@@ -8,6 +8,7 @@
  */
 
 #include <env_callback.h>
+#include <env_mender.h>
 #include <linux/stringify.h>
 
 #ifdef DEFAULT_ENV_INSTANCE_EMBEDDED
@@ -24,6 +25,7 @@ uchar default_environment[] = {
 #else
 const uchar default_environment[] = {
 #endif
+    MENDER_ENV_SETTINGS
 #ifndef CONFIG_USE_DEFAULT_ENV_FILE
 #ifdef	CONFIG_ENV_CALLBACK_LIST_DEFAULT
 	ENV_CALLBACK_VAR "=" CONFIG_ENV_CALLBACK_LIST_DEFAULT "\0"
@@ -34,8 +36,8 @@ const uchar default_environment[] = {
 #ifdef	CONFIG_USE_BOOTARGS
 	"bootargs="	CONFIG_BOOTARGS			"\0"
 #endif
-#ifdef	CONFIG_BOOTCOMMAND
-	"bootcmd="	CONFIG_BOOTCOMMAND		"\0"
+#ifdef	CONFIG_MENDER_BOOTCOMMAND
+	"bootcmd="	CONFIG_MENDER_BOOTCOMMAND	"\0"
 #endif
 #ifdef	CONFIG_RAMBOOTCOMMAND
 	"ramboot="	CONFIG_RAMBOOTCOMMAND		"\0"
diff --git a/include/env_mender.h b/include/env_mender.h
new file mode 100644
index 0000000000..261775afd5
--- /dev/null
+++ b/include/env_mender.h
@@ -0,0 +1,156 @@
+/*
+  Copyright 2017 Northern.tech AS
+
+  This program is free software; you can redistribute it and/or
+  modify it under the terms of the GNU General Public License
+  as published by the Free Software Foundation; either version 2
+  of the License, or (at your option) any later version.
+
+  This program is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+*/
+
+#ifndef HEADER_ENV_MENDER_H
+#define HEADER_ENV_MENDER_H
+
+/* Avoid Mender specific code if we are just probing for configuration. */
+#ifdef MENDER_AUTO_PROBING
+#define MENDER_ENV_SETTINGS
+#else
+
+#include <config_mender_defines.h>
+
+#ifdef MENDER_NO_DEFAULT_ALTBOOTCMD
+# define MENDER_DEFAULT_ALTBOOTCMD
+#else
+# define MENDER_DEFAULT_ALTBOOTCMD "altbootcmd=run mender_altbootcmd; " \
+    "run bootcmd\0"
+#endif
+
+#ifdef MENDER_UBI
+# define MENDER_UBI_SETTINGS \
+    "mender_mtd_ubi_dev_name=" MENDER_MTD_UBI_DEVICE_NAME "\0"
+#else
+# define MENDER_UBI_SETTINGS
+#endif
+
+#define MENDER_ENV_SETTINGS                                             \
+    MENDER_DEFAULT_ALTBOOTCMD                                           \
+    MENDER_UBI_SETTINGS                                                 \
+                                                                        \
+    "bootlimit=1\0"                                                     \
+    "bootcount=0\0"                                                     \
+                                                                        \
+    "upgrade_available=0\0"                                             \
+                                                                        \
+    "mender_boot_part=" __stringify(MENDER_ROOTFS_PART_A_NUMBER) "\0"   \
+                                                                        \
+    "mender_boot_part_hex=" __stringify(MENDER_ROOTFS_PART_A_NUMBER_HEX) "\0"   \
+                                                                        \
+    "mender_uboot_boot=" MENDER_UBOOT_STORAGE_INTERFACE " " __stringify(MENDER_UBOOT_STORAGE_DEVICE) ":" __stringify(MENDER_BOOT_PART_NUMBER_HEX) "\0" \
+                                                                        \
+    "mender_uboot_if=" MENDER_UBOOT_STORAGE_INTERFACE "\0"              \
+                                                                        \
+    "mender_uboot_dev=" __stringify(MENDER_UBOOT_STORAGE_DEVICE) "\0"   \
+                                                                        \
+    "mender_boot_kernel_type=" MENDER_BOOT_KERNEL_TYPE "\0"             \
+                                                                        \
+    "mender_kernel_name=" MENDER_KERNEL_NAME "\0"                       \
+                                                                        \
+    "mender_dtb_name=" MENDER_DTB_NAME "\0"                             \
+                                                                        \
+    "mender_pre_setup_commands=" MENDER_UBOOT_PRE_SETUP_COMMANDS "\0"   \
+                                                                        \
+    "mender_post_setup_commands=" MENDER_UBOOT_POST_SETUP_COMMANDS "\0" \
+                                                                        \
+    "mender_check_saveenv_canary=1\0"                                   \
+                                                                        \
+    "mender_setup="                                                     \
+    "if test \"${mender_saveenv_canary}\" != \"1\"; then "              \
+    "setenv mender_saveenv_canary 1; "                                  \
+    "saveenv; "                                                         \
+    "fi; "                                                              \
+    "if test \"${mender_pre_setup_commands}\" != \"\"; "                \
+    "then "                                                             \
+    "run mender_pre_setup_commands; "                                   \
+    "fi; "                                                              \
+    "if test \"${mender_systemd_machine_id}\" != \"\"; "                \
+    "then "                                                             \
+    "setenv bootargs \"systemd.machine_id=${mender_systemd_machine_id} ${bootargs}\"; " \
+    "fi; "                                                              \
+    "setenv mender_kernel_root " MENDER_STORAGE_DEVICE_BASE "${mender_boot_part}; "    \
+    "if test ${mender_boot_part} = " __stringify(MENDER_ROOTFS_PART_A_NUMBER) "; "     \
+    "then "                                                                            \
+    "setenv mender_boot_part_name " MENDER_ROOTFS_PART_A_NAME "; "                     \
+    "else "                                                                             \
+    "setenv mender_boot_part_name " MENDER_ROOTFS_PART_B_NAME "; "                     \
+    "fi; "                                                                             \
+    "setenv mender_kernel_root_name ${mender_boot_part_name}; "         \
+    "setenv mender_uboot_root " MENDER_UBOOT_STORAGE_INTERFACE " " __stringify(MENDER_UBOOT_STORAGE_DEVICE) ":${mender_boot_part_hex}; " \
+    "setenv mender_uboot_root_name ${mender_boot_part_name}; "          \
+    "setenv expand_bootargs \"setenv bootargs \\\\\"${bootargs}\\\\\"\"; "              \
+    "run expand_bootargs; "                                             \
+    "setenv expand_bootargs; "                                          \
+    "if test \"${mender_post_setup_commands}\" != \"\"; "               \
+    "then "                                                             \
+    "run mender_post_setup_commands; "                                  \
+    "fi\0"                                                              \
+                                                                        \
+    "mender_altbootcmd="                                                \
+    "if test ${mender_boot_part} = " __stringify(MENDER_ROOTFS_PART_A_NUMBER) "; "     \
+    "then "                                                                            \
+    "setenv mender_boot_part " __stringify(MENDER_ROOTFS_PART_B_NUMBER) "; "           \
+    "setenv mender_boot_part_hex " __stringify(MENDER_ROOTFS_PART_B_NUMBER_HEX) "; "           \
+    "else "                                                                            \
+    "setenv mender_boot_part " __stringify(MENDER_ROOTFS_PART_A_NUMBER) "; "           \
+    "setenv mender_boot_part_hex " __stringify(MENDER_ROOTFS_PART_A_NUMBER_HEX) "; "           \
+    "fi; "                                                              \
+    "setenv upgrade_available 0; "                                      \
+    "saveenv; "                                                         \
+    "run mender_setup\0"                                                \
+                                                                        \
+    "mender_try_to_recover="                                            \
+    "if test ${upgrade_available} = 1; "                                \
+    "then reset; "                                                      \
+    "fi\0"
+
+#ifdef MENDER_UBI
+# define MENDER_BOOTARGS                                                \
+    "setenv bootargs root=${mender_kernel_root} "                       \
+    "${mtdparts} "                                                      \
+    "ubi.mtd=${mender_mtd_ubi_dev_name} "                               \
+    "rootfstype=ubifs "                                                 \
+    "${bootargs}; "
+# define MENDER_LOAD_KERNEL_AND_FDT                                     \
+    "ubi part ${mender_mtd_ubi_dev_name}; "                             \
+    "ubifsmount ${mender_uboot_root_name}; "                            \
+    "if test \"${fdt_addr_r}\" != \"\"; then "                          \
+    "ubifsload ${fdt_addr_r} /boot/${mender_dtb_name}; "                \
+    "fi; "                                                              \
+    "ubifsload ${kernel_addr_r} /boot/${mender_kernel_name}; "
+#else
+# define MENDER_BOOTARGS                                                \
+    "setenv bootargs root=${mender_kernel_root} ${bootargs}; "
+# define MENDER_LOAD_KERNEL_AND_FDT                                     \
+    "if test \"${fdt_addr_r}\" != \"\"; then "                          \
+    "load ${mender_uboot_root} ${fdt_addr_r} /boot/${mender_dtb_name}; " \
+    "fi; "                                                              \
+    "load ${mender_uboot_root} ${kernel_addr_r} /boot/${mender_kernel_name}; "
+#endif
+
+#define CONFIG_MENDER_BOOTCOMMAND                                       \
+    "run mender_setup; "                                                \
+    MENDER_BOOTARGS                                                     \
+    MENDER_LOAD_KERNEL_AND_FDT                                          \
+    "${mender_boot_kernel_type} ${kernel_addr_r} - ${fdt_addr_r}; "     \
+    "run mender_try_to_recover"
+
+#endif /* !MENDER_AUTO_PROBING */
+
+#endif /* HEADER_ENV_MENDER_H */
diff --git a/scripts/Makefile.autoconf b/scripts/Makefile.autoconf
index 0bfc1b2a62..104826c18b 100644
--- a/scripts/Makefile.autoconf
+++ b/scripts/Makefile.autoconf
@@ -108,7 +108,8 @@ define filechk_config_h
 	echo \#include \<configs/$(CONFIG_SYS_CONFIG_NAME).h\>;		\
 	echo \#include \<asm/config.h\>;				\
 	echo \#include \<linux/kconfig.h\>;				\
-	echo \#include \<config_fallbacks.h\>;)
+	echo \#include \<config_fallbacks.h\>;				\
+	echo \#include \<config_mender.h\>;)
 endef
 
 include/config.h: scripts/Makefile.autoconf create_symlink FORCE

How did you do it ? I’ve set up some dtoverlays in config.txt and they’re not being loaded. Does removing the dtb from uboot suffice to let the firmware handle it all ?

I figured that the lines loading the fdt in u-boot had to be commented out, and that the kernel had to be passed the address of the fdt as fdt_addr instead of fdt_addr_r.

Now i’m stuck on fw_printenv not being able to find the right u-boot env, thus falling back to a default env and mender not accepting remote updates. I found a few threads that mention these issues, but i did not find an answer for the case of usb booting:

Here’s my fw_printenv output:

Warning: Bad CRC, using default environment
bootargs=
bootcmd=
bootdelay=2
baudrate=115200
arch=sandbox
cpu=sandbox
board=sandbox
board_name=sandbox
stdin=serial,cros-ec-keyb,usbkbd
stdout=serial,vidconsole
stderr=serial,vidconsole
ethaddr=00:00:11:22:33:44
eth1addr=00:00:11:22:33:45
eth3addr=00:00:11:22:33:46
eth5addr=00:00:11:22:33:47
ipaddr=1.2.3.4
host_boot=if host dev ${devnum}; then setenv devtype host; run scan_dev_for_boot_part; fi
boot_net_pci_enum=pci enum
boot_net_usb_start=usb start
usb_boot=usb start; if usb dev ${devnum}; then setenv devtype usb; run scan_dev_for_boot_part; fi
boot_prefixes=/ /boot/
boot_scripts=boot.scr.uimg boot.scr
boot_script_dhcp=boot.scr.uimg
boot_targets=host1 host0 
boot_extlinux=sysboot ${devtype} ${devnum}:${distro_bootpart} any ${scriptaddr} ${prefix}extlinux/extlinux.conf
scan_dev_for_extlinux=if test -e ${devtype} ${devnum}:${distro_bootpart} ${prefix}extlinux/extlinux.conf; then echo Found ${prefix}extlinux/extlinux.conf; run boot_extlinux; echo SCRIPT FAILED: continuing...; fi
boot_a_script=load ${devtype} ${devnum}:${distro_bootpart} ${scriptaddr} ${prefix}${script}; source ${scriptaddr}
scan_dev_for_scripts=for script in ${boot_scripts}; do if test -e ${devtype} ${devnum}:${distro_bootpart} ${prefix}${script}; then echo Found U-Boot script ${prefix}${script}; run boot_a_script; echo SCRIPT FAILED: continuing...; fi; done
scan_dev_for_boot=echo Scanning ${devtype} ${devnum}:${distro_bootpart}...; for prefix in ${boot_prefixes}; do run scan_dev_for_extlinux; run scan_dev_for_scripts; done;
scan_dev_for_boot_part=part list ${devtype} ${devnum} -bootable devplist; env exists devplist || setenv devplist 1; for distro_bootpart in ${devplist}; do if fstype ${devtype} ${devnum}:${distro_bootpart} bootfstype; then run scan_dev_for_boot; fi; done
bootcmd_host1=setenv devnum 1; run host_boot
bootcmd_host0=setenv devnum 0; run host_boot
distro_bootcmd=for target in ${boot_targets}; do run bootcmd_${target}; done
bootm_size=0x10000000
kernel_addr_r=0x1000000
fdt_addr_r=0xc00000
ramdisk_addr_r=0x2000000
scriptaddr=0x1000
pxefile_addr_r=0x2000
# systemctl status mender-client
● mender-client.service - Mender OTA update service
   Loaded: loaded (/lib/systemd/system/mender-client.service; enabled; vendor preset: enabled)
   Active: failed (Result: exit-code) since Fri 2021-06-11 18:13:10 CEST; 2 days ago
  Process: 967 ExecStart=/usr/bin/mender daemon (code=exited, status=1/FAILURE)
 Main PID: 967 (code=exited, status=1/FAILURE)

juin 11 18:13:10 cosmyx-nova systemd[1]: Started Mender OTA update service.
juin 11 18:13:10 cosmyx-nova mender[967]: time="2021-06-11T18:13:10+02:00" level=info msg="Loaded configuration file: /etc/mender/mender.conf"
juin 11 18:13:10 cosmyx-nova mender[967]: time="2021-06-11T18:13:10+02:00" level=error msg="Failed to read the current active partition: No match between boot and root partitions.: exit status 1"
juin 11 18:13:10 cosmyx-nova mender[967]: time="2021-06-11T18:13:10+02:00" level=error msg="mkdir /var/lib/mender: file exists"
juin 11 18:13:10 cosmyx-nova mender[967]: time="2021-06-11T18:13:10+02:00" level=error msg="Failed to read the current active partition: No match between boot and root partitions.: exit status 1"
juin 11 18:13:10 cosmyx-nova mender[967]: time="2021-06-11T18:13:10+02:00" level=error msg="mkdir /var/lib/mender: file exists"
juin 11 18:13:10 cosmyx-nova systemd[1]: mender-client.service: Main process exited, code=exited, status=1/FAILURE
juin 11 18:13:10 cosmyx-nova systemd[1]: mender-client.service: Failed with result 'exit-code'.

config_mender_defines.h

/* BB variables. */
#define MENDER_STORAGE_DEVICE_BASE "/dev/sda"
#define MENDER_UBOOT_ENV_STORAGE_DEVICE_OFFSET_1 0x400000
#define MENDER_UBOOT_ENV_STORAGE_DEVICE_OFFSET_2 0x800000
#define MENDER_ROOTFS_PART_A_NAME "/dev/sda2"
#define MENDER_ROOTFS_PART_B_NAME "/dev/sda3"

/* For sanity checks. */
#define MENDER_BOOTENV_SIZE 0x4000
# cat /etc/fw_env.config 
/dev/sda    0x400000    0x4000
/dev/sda    0x800000    0x4000

partition alignment:

sfdisk ${DEVICE} << EOF
label: dos
unit: sectors

start=       24576, size=      524288,   type=c, bootable
start=      548864, size=      31457280, type=83
start=    32006144, size=      31457280, type=83
start=    63463424, size=      53767984, type=83
EOF

Any direction i could be looking into ?

My best guess is that the STORAGE_DEVICE_OFFSET values are wrong. They seem pretty large. I would expect to see them somewhere just before the start of a partition if my understanding is correct.

Drew

Thanks for your input. These values are default from both upstream u-boot and the Mender fork, as well as what’s recommended in Mender from scratch.

When is the env supposed to be written to that space, and how can I inspect it ? My build process involves creating a golden master with the OS, then making an image of that that is inserted in an sd card, which job is to flash the internal SSD with the image. It all works except this part.

Strangely, the golden master does manage to connect to mender, even though fw_printenv shows a similar output. Any leads on this ?

golden master fw_printenv

Warning: Bad CRC, using default environment
bootargs=
bootcmd=
bootdelay=2
baudrate=115200
arch=sandbox
cpu=sandbox
board=sandbox
board_name=sandbox
stdin=serial,cros-ec-keyb,usbkbd
stdout=serial,vidconsole
stderr=serial,vidconsole
ethaddr=00:00:11:22:33:44
eth1addr=00:00:11:22:33:45
eth3addr=00:00:11:22:33:46
eth5addr=00:00:11:22:33:47
ipaddr=1.2.3.4
host_boot=if host dev ${devnum}; then setenv devtype host; run scan_dev_for_boot_part; fi
boot_net_pci_enum=pci enum
boot_net_usb_start=usb start
usb_boot=usb start; if usb dev ${devnum}; then setenv devtype usb; run scan_dev_for_boot_part; fi
boot_prefixes=/ /boot/
boot_scripts=boot.scr.uimg boot.scr
boot_script_dhcp=boot.scr.uimg
boot_targets=host1 host0 
boot_extlinux=sysboot ${devtype} ${devnum}:${distro_bootpart} any ${scriptaddr} ${prefix}extlinux/extlinux.conf
scan_dev_for_extlinux=if test -e ${devtype} ${devnum}:${distro_bootpart} ${prefix}extlinux/extlinux.conf; then echo Found ${prefix}extlinux/extlinux.conf; run boot_extlinux; echo SCRIPT FAILED: continuing...; fi
boot_a_script=load ${devtype} ${devnum}:${distro_bootpart} ${scriptaddr} ${prefix}${script}; source ${scriptaddr}
scan_dev_for_scripts=for script in ${boot_scripts}; do if test -e ${devtype} ${devnum}:${distro_bootpart} ${prefix}${script}; then echo Found U-Boot script ${prefix}${script}; run boot_a_script; echo SCRIPT FAILED: continuing...; fi; done
scan_dev_for_boot=echo Scanning ${devtype} ${devnum}:${distro_bootpart}...; for prefix in ${boot_prefixes}; do run scan_dev_for_extlinux; run scan_dev_for_scripts; done;
scan_dev_for_boot_part=part list ${devtype} ${devnum} -bootable devplist; env exists devplist || setenv devplist 1; for distro_bootpart in ${devplist}; do if fstype ${devtype} ${devnum}:${distro_bootpart} bootfstype; then run scan_dev_for_boot; fi; done
bootcmd_host1=setenv devnum 1; run host_boot
bootcmd_host0=setenv devnum 0; run host_boot
distro_bootcmd=for target in ${boot_targets}; do run bootcmd_${target}; done
bootm_size=0x10000000
kernel_addr_r=0x1000000
fdt_addr_r=0xc00000
ramdisk_addr_r=0x2000000
scriptaddr=0x1000
pxefile_addr_r=0x2000
● mender-client.service - Mender OTA update service
   Loaded: loaded (/lib/systemd/system/mender-client.service; enabled; vendor preset: enabled)
   Active: active (running) since Fri 2021-06-11 17:52:06 CEST; 2 days ago
 Main PID: 953 (mender)
    Tasks: 13 (limit: 4915)
   CGroup: /system.slice/mender-client.service
           └─953 /usr/bin/mender daemon

juin 14 16:45:18 cosmyx-nova mender[953]: time="2021-06-14T16:45:18+02:00" level=info msg="State transition: check-wait [Idle] -> update-check [Syn
juin 14 16:45:19 cosmyx-nova mender[953]: time="2021-06-14T16:45:19+02:00" level=info msg="State transition: update-check [Sync] -> check-wait [Idl
juin 14 16:45:23 cosmyx-nova mender[953]: time="2021-06-14T16:45:23+02:00" level=info msg="State transition: check-wait [Idle] -> update-check [Syn
juin 14 16:45:23 cosmyx-nova mender[953]: time="2021-06-14T16:45:23+02:00" level=info msg="State transition: update-check [Sync] -> check-wait [Idl
juin 14 16:45:28 cosmyx-nova mender[953]: time="2021-06-14T16:45:28+02:00" level=info msg="State transition: check-wait [Idle] -> update-check [Syn
juin 14 16:45:28 cosmyx-nova mender[953]: time="2021-06-14T16:45:28+02:00" level=info msg="State transition: update-check [Sync] -> check-wait [Idl
juin 14 16:45:33 cosmyx-nova mender[953]: time="2021-06-14T16:45:33+02:00" level=info msg="State transition: check-wait [Idle] -> update-check [Syn
juin 14 16:45:33 cosmyx-nova mender[953]: time="2021-06-14T16:45:33+02:00" level=info msg="State transition: update-check [Sync] -> check-wait [Idl
juin 14 16:45:38 cosmyx-nova mender[953]: time="2021-06-14T16:45:38+02:00" level=info msg="State transition: check-wait [Idle] -> update-check [Syn
juin 14 16:45:38 cosmyx-nova mender[953]: time="2021-06-14T16:45:38+02:00" level=info msg="State transition: update-check [Sync] -> check-wait [Idl

maybe @mirzak could explain why these values are 0x400000 and 0x800000 instead of for instance 0x0 and 0x4000 which as far as i can tell would do the same. Anyway the problem seem to lie at least partly elsewhere, as mender-client is able to run on the golden master, even though i’m not sure it manages to properly read the environment and thus correctly manage the OS in terms of partition switching…

I’m not surprised that they need to be adjusted when switching from MMC to USB/SATA.

The other possibility is you still have CONFIG_ENV_IS_IN_MMC defined in the U-Boot config in which case it would be trying to read the environment from MMC instead of USB. I’m not sure if CONFIG_ENV_IS_IN_USB or SATA is supported in U-Boot.

I guess it may be related to these lines being removed from the config in order to make USB work

In case it rings any bells,

u-boot $ cat .config | grep CONFIG_ENV
CONFIG_ENV_SIZE=0x4000
CONFIG_ENV_VARS_UBOOT_CONFIG=y
CONFIG_ENV_SUPPORT=y
# CONFIG_ENV_OVERWRITE is not set
# CONFIG_ENV_IS_NOWHERE is not set
# CONFIG_ENV_IS_IN_EEPROM is not set
CONFIG_ENV_IS_IN_FAT=y
# CONFIG_ENV_IS_IN_EXT4 is not set
# CONFIG_ENV_IS_IN_FLASH is not set
# CONFIG_ENV_IS_IN_MMC is not set
# CONFIG_ENV_IS_IN_NAND is not set
# CONFIG_ENV_IS_IN_NVRAM is not set
# CONFIG_ENV_IS_IN_ONENAND is not set
# CONFIG_ENV_IS_IN_REMOTE is not set
CONFIG_ENV_FAT_INTERFACE="usb"
CONFIG_ENV_FAT_DEVICE_AND_PART="0:1"
CONFIG_ENV_FAT_FILE="uboot.env"
CONFIG_ENV_FAT_FILE_REDUND="uboot-redund.env"
CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG=y
# CONFIG_ENV_IMPORT_FDT is not set
# CONFIG_ENV_APPEND is not set
# CONFIG_ENV_WRITEABLE_LIST is not set
# CONFIG_ENV_ACCESS_IGNORE_FORCE is not set

now trying to play with what @drewmoseley indicated.

adding

CONFIG_ENV_OFFSET=0x400000
CONFIG_ENV_OFFSET_REDUND=0x800000

did not change the .config file, so i guess they’re ignored if they’re not with

CONFIG_ENV_IS_IN_MMC=y
CONFIG_ENV_OFFSET=0x400000
CONFIG_ENV_OFFSET_REDUND=0x800000

that yields the following .config

$ cat .config | grep CONFIG_ENV | grep -v "# "
CONFIG_ENV_SIZE=0x4000
CONFIG_ENV_OFFSET=0x400000
CONFIG_ENV_OFFSET_REDUND=0x800000
CONFIG_ENV_VARS_UBOOT_CONFIG=y
CONFIG_ENV_SUPPORT=y
CONFIG_ENV_IS_IN_FAT=y
CONFIG_ENV_IS_IN_MMC=y
CONFIG_ENV_FAT_INTERFACE="usb"
CONFIG_ENV_FAT_DEVICE_AND_PART="0:1"
CONFIG_ENV_FAT_FILE="uboot.env"
CONFIG_ENV_FAT_FILE_REDUND="uboot-redund.env"
CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG=y

Which surprisingly boots over USB, contrary to the previous post i had made earlier where these lines disabled USB detection in u-boot. The resulting booted environment then still does not seem to be correct and shows Warning: Bad CRC, using default environment.

EDIT

Investigating further, I seem to understand that CONFIG_ENV_IS_IN_FAT means to write env in the boot partition’s uboot.env and uboot-redund.env, whereas CONFIG_ENV_IS_IN_MMC means to write at the device block level with offsets, and originally for mmcblk* type devices, but somewhat overused for USB devices.

I found that a uboot-redund.env file has been created on by boot partition, but not a uboot.env file, that’s quite strange. Then modifying /etc/fw_env.config:

# cat /etc/fw_env.config 
/boot/u-boot/uboot-redund.env  0x0000     0x4000

the file is taken into account as i’ve made path mistakes that resulted in fw_printenv mentioning the file does not exist, so it does for /boot/u-boot/uboot.env as it has not been created. However the output of fw_printenv still mentions Bad CRC, using default environment.

EDIT

I found this thread to be quite informative. I think u-boot should not need to write the env to a raw device and writing to a file should be sufficient, and that works for us to write in the boot partition for now. However i can’t figure out why the env file is not getting written and why the CRC is wrong.

From the u-boot console, run mender_setup works without issues, and is supposed to write the config using saveenv. Even manually executing saveenv, does not create uboot.env on the boot partition. uboot-rendund.env is written but the CRC is incorrect. I don’t understand how that happens…

EDIT

I’ve just tested to double-check. Removed /boot/u-boot/uboot-redund.env, reboot, the file has been re-created by u-boot on startup, and the CRC is still incorrect. How is it possible that u-boot writes a file with an incorrect CRC?

EDIT

I could not find a resolution for this. To allow the device to boot, i’ve copied the output of printenv in u-boot prompt to a uEnv.txt files and executed mkenvimage to create a properly CRC checked file in the boot partition, which fw_printenv can read so that mender-client can connect. However i’m pretty sure this will not allow switching partitions from mender, as u-boot does not seem to be able to write this file. I summed up the issue here.

Still no luck @peac ?

@peac sorry for disappearing like that. I suspect you might be having an issue similar to what I ran into on my Pi3. It turned out that since it doesn’t run start usb until later in the boot process, it isn’t able to automatically load the environment file and thus falls back to the default environment. There may be a better way to handle this, but I just set the following in the u-boot config and it fixed the problem for me. (The bmp part can be ignored).

CONFIG_PREBOOT="usb start; load usb 0 $kernel_addr_r /u-boot_splash.bmp; bmp display $kernel_addr_r m m; load usb 0:1 ${kernel_addr_r} /uboot.env; env import -c ${kernel_addr_r} 0x4000;"

I hadn’t set up the uboot-redund.env file in my config, so thanks for that tip!

Also, perhaps you could post your final diff somewhere like github’s gist? I’m sure others will appreciate your hard work and having it somewhere that’s easy to link to handy.

1 Like

Hi there, still no luck.

@stiltr my preboot is inspired from what you shared earlier:

PREBOOT="                                          \
pci enum;                                          \
usb start;                                         \
load usb 0:1  \${kernel_addr_r} \/boot-splash.bmp; \
bmp display   \${kernel_addr_r};                   \
load usb 0:1  \${kernel_addr_r} \/uboot.env;       \
env import -c \${kernel_addr_r} 0x4000;            \
"

This part works fine as the BMP file gets displayed and the boot log shows it reads from FAT successfully.

What does not work, is saveenv.

Currently the system boots because i’ve created uboot.env manually using mkenvimage from the dumped env of uboot’s prompt.

However, saveenv does not write uboot.env, it does write uboot-redund.env but with a wrong CRC, which makes it unreadable by fw_printenv when mender starts.

So i’ve configured fw_printenv to read the manually created uboot.env (that is not written by saveenv) instead of the corrupted automatically created uboot-redund.env (that is written by saveenv).

This way does not enable me to update the opposite partition or detect failed boots, as the env mechanism is basically broken. Any help appreciated.

EDIT:

I’ve dumped (mkenvimage manually created) uboot.env and (saveenv-created) uboot-redund.env with hexdump and diffed them:

# diff uboot-redund.txt uboot.txt 
1c1
< 00000000  20 9e 7d 1c 03 61 6c 74  62 6f 6f 74 63 6d 64 3d  | .}..altbootcmd=|
---
> 00000000  20 9e 7d 1c 02 61 6c 74  62 6f 6f 74 63 6d 64 3d  | .}..altbootcmd=|

The 5th byte is different.

EDIT:

There seems to actually be no issues of CRC, probably just issues of a file not being the right one with redundant environment. I think that the above 02/03 byte difference is actually meant to be this way.

So the only issue would be that saveenv does write uboot-redund.env but not uboot.env.

Update: the function that handles the file writing seems to be here.

Here’s a test i’m doing in case it lights up ideas in someone’s head:

U-Boot CosmOS > env set toto tata
U-Boot CosmOS > env print toto
toto=tata
U-Boot CosmOS > saveenv
Saving Environment to FAT... OK
U-Boot CosmOS > boot
6694592 bytes read in 47 ms (135.8 MiB/s)
## Booting kernel from Legacy Image at 00080000 ...
   Image Name:   Linux kernel (CosmOS)
   Image Type:   ARM Linux Kernel Image (uncompressed)
   Data Size:    6694528 Bytes = 6.4 MiB
   Load Address: 00008000
   Entry Point:  00008000
   Verifying Checksum ... OK
## Flattened Device Tree blob at 2eff3a00
   Booting using the fdt blob at 0x2eff3a00
   Loading Kernel Image
   Using Device Tree in place at 2eff3a00, end 2f002f6b

Starting kernel ...
root@pi:~ fw_printenv | grep toto
root@pi:~ cat /etc/fw_env.config 
/boot/u-boot/uboot.env         0x0000 0x4000
/boot/u-boot/uboot-redund.env  0x0000 0x4000
root@pi:~ cat /etc/fstab
proc			/proc				proc	defaults			0	0
/dev/root		/					ext4	defaults,noatime	0	1
/dev/sda1		/boot/u-boot		vfat	defaults			0	2
/dev/sda4		/data				ext4	defaults			0	2

rpi_4_32b_defconfig

CONFIG_ENV_SIZE=0x4000
CONFIG_ENV_FAT_DEVICE_AND_PART="0:1"
CONFIG_ENV_FAT_INTERFACE="usb"
CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG=y
CONFIG_SYS_RELOC_GD_ENV_ADDR=y
CONFIG_SYS_REDUNDAND_ENVIRONMENT=y

new non-working test:

CONFIG_SYS_REDUNDAND_ENVIRONMENT=n
include/config_mender.h:41:3: error: #error CONFIG_SYS_REDUNDAND_ENVIRONMENT is required for Mender to work. Make sure that: 1) All the instructions at https:
   41 | # error CONFIG_SYS_REDUNDAND_ENVIRONMENT is required for Mender to work. Make sure that: 1) All the instructions at https://docs.mender.io/system-updates-yocto-project/board-integration/bootloader-support/u-boot have been followed. 2) All required layers are included in bblayers.conf, including any board specific layers such as meta-mender-<board>. Check also https://docs.mender.io/troubleshoot/yocto-project-build for Known Issues when upgrading.

Hi there @peac , @stiltr

Did you end up getting mender working with Pi 4 USB boot?

1 Like

Also wondering about this one!