Pi3 USB boot support

OK, so i started from scratch.

I took the official u-boot repo from u-boot, master branch. Built and booted it, and it has USB out of the box (my boot partition still has the latest DTB files that i’ve just built with latest linux kernel from the repo).

U-Boot 2021.07-rc2-00175-g7a1638c263 (May 18 2021 - 23:51:50 +0200)

DRAM:  7.9 GiB
RPI 4 Model B (0xd03114)
MMC:   mmcnr@7e300000: 1, emmc2@7e340000: 0
Loading Environment from FAT... Unable to read "uboot.env" from mmc0:1... In:    serial
Out:   serial
Err:   serial
Net:   eth0: ethernet@7d580000
PCIe BRCM: link up, 5.0 Gbps x1 (SSC)
starting USB...
Bus xhci_pci: Register 5000420 NbrPorts 5
Starting the controller
USB XHCI 1.00
scanning bus xhci_pci for devices... 5 USB Device(s) found
       scanning usb for storage devices... 1 Storage Device(s) found
Hit any key to stop autoboot:  0 
U-Boot> usb start
U-Boot>

I then applied the patches as mentionned in mender from scratch, with adjustments as it is a little outdated. Here’s the total modification diff below. This one does not find the usb controller, and also not sure why but it’s complaining about the env address ? I did not notice it the first time, i’m not sure if that’s the reason or not.

Could maybe a Mender engineer review the diff and see why applying the mender modifications disables USB? @mirzak

U-Boot 2021.07-rc2-00176-ga7daea5634-dirty (May 19 2021 - 00:09:07 +0200)

DRAM:  7.9 GiB
RPI 4 Model B (0xd03114)
MMC:   mmcnr@7e300000: 1, emmc2@7e340000: 0
Loading Environment from FAT... *** Error - No Valid Environment Area found
*** Warning - bad env area, using default environment

Loading Environment from MMC... OK
In:    serial
Out:   serial
Err:   serial
Net:   
Warning: ethernet@7d580000 MAC addresses don't match:
Address in DT is                dc:a6:32:e7:97:8f
Address in environment is       b8:27:eb:9f:33:38
eth0: ethernet@7d580000
Hit any key to stop autoboot:  0 
U-Boot> usb start
starting USB...
No working controllers found
U-Boot> 
diff --git a/configs/rpi_4_32b_defconfig b/configs/rpi_4_32b_defconfig
index 47ea466454..04bcb2161d 100644
--- a/configs/rpi_4_32b_defconfig
+++ b/configs/rpi_4_32b_defconfig
@@ -59,3 +59,8 @@ CONFIG_PHYS_TO_BUS=y
 CONFIG_ADDR_MAP=y
 CONFIG_SYS_NUM_ADDR_MAP=2
 CONFIG_OF_LIBFDT_OVERLAY=y
+
+CONFIG_ENV_IS_IN_MMC=y
+CONFIG_ENV_OFFSET=0x400000
+CONFIG_ENV_OFFSET_REDUND=0x800000
+CONFIG_SYS_REDUNDAND_ENVIRONMENT=y
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..2c8cdc65f1
--- /dev/null
+++ b/include/config_mender_defines.h
@@ -0,0 +1,32 @@
+/* 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 "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 "uImage"
+#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 */
diff --git a/include/configs/rpi.h b/include/configs/rpi.h
index 834f1cd236..2da3229678 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
diff --git a/tools/env/fw_env.c b/tools/env/fw_env.c
index 2a61a5d6f0..b0bce1b5ac 100644
--- a/tools/env/fw_env.c
+++ b/tools/env/fw_env.c
@@ -20,6 +20,7 @@
 #include <ctype.h>
 #include <stdio.h>
 #include <stdlib.h>
+#include <stdint.h>
 #include <stddef.h>
 #include <string.h>
 #include <sys/types.h>