diff mbox series

[v2] sunxi: fix initial environment loading without MMC

Message ID 20220624161209.1644097-1-andre.przywara@arm.com
State Accepted
Commit e008e5132f7e160320dcc0ffb8fe7fef5264aecd
Delegated to: Andre Przywara
Headers show
Series [v2] sunxi: fix initial environment loading without MMC | expand

Commit Message

Andre Przywara June 24, 2022, 4:12 p.m. UTC
From: Samuel Holland <samuel@sholland.org>

Commit e42dad4168fe ("sunxi: use boot source for determining environment
location") changed our implementation of env_get_location() and enabled
it for every board, even those without MMC support (like the C.H.I.P.
boards). However the default fallback location of ENVL_FAT requires MMC
support compiled in, so the board hangs when trying to initially load
the environment.

Change the algorithm to only return configured environment locations,
and improve the fallback algorithm on the way.

The env_init() routine calling this function here does not behave well
if the return value is ENVL_UNKNOWN on the very first call: it will make
U-Boot proper silently hang very early.
Work around this issue by making sure we return some configured (dummy)
environment location when prio is 0. This for instance happens when
booting via FEL.

This fixes U-Boot loading on the C.H.I.P. boards.

Fixes: e42dad4168fe ("sunxi: use boot source for determining environment location")
Reported-by: Chris Morgan <macroalpha82@gmail.com>
Signed-off-by: Samuel Holland <samuel@sholland.org>
[Andre: fix FEL boot case by not returning ENVL_UNKNOWN when prio==0]
Signed-off-by: Andre Przywara <andre.przywara@arm.com>
---
Hi Samuel,

I cheekily added your Signed-off-by:, as I made this your patch (since
you came up with it in that email reply some weeks ago). I hope that's
fine.
I tested this briefly on a Pine64-LTS, booting from FEL, SD card, eMMC
and SPI. I also simulated a CHIP board, by just defining ENV_IS_NOWHERE,
then booting, as this was the case that broke.
If no one complains, I would like to push this ASAP, to make it into
the 2022.07 release still.

Cheers,
Andre

 board/sunxi/board.c | 49 +++++++++++++++++++++++++++------------------
 1 file changed, 29 insertions(+), 20 deletions(-)

Comments

Andre Przywara June 27, 2022, 12:13 a.m. UTC | #1
On Fri, 24 Jun 2022 17:12:09 +0100
Andre Przywara <andre.przywara@arm.com> wrote:

> From: Samuel Holland <samuel@sholland.org>
> 
> Commit e42dad4168fe ("sunxi: use boot source for determining environment
> location") changed our implementation of env_get_location() and enabled
> it for every board, even those without MMC support (like the C.H.I.P.
> boards). However the default fallback location of ENVL_FAT requires MMC
> support compiled in, so the board hangs when trying to initially load
> the environment.
> 
> Change the algorithm to only return configured environment locations,
> and improve the fallback algorithm on the way.
> 
> The env_init() routine calling this function here does not behave well
> if the return value is ENVL_UNKNOWN on the very first call: it will make
> U-Boot proper silently hang very early.
> Work around this issue by making sure we return some configured (dummy)
> environment location when prio is 0. This for instance happens when
> booting via FEL.
> 
> This fixes U-Boot loading on the C.H.I.P. boards.
> 
> Fixes: e42dad4168fe ("sunxi: use boot source for determining environment location")
> Reported-by: Chris Morgan <macroalpha82@gmail.com>
> Signed-off-by: Samuel Holland <samuel@sholland.org>
> [Andre: fix FEL boot case by not returning ENVL_UNKNOWN when prio==0]
> Signed-off-by: Andre Przywara <andre.przywara@arm.com>

Applied to sunxi/master, for v2022.07.

Cheers,
Andre

> ---
> Hi Samuel,
> 
> I cheekily added your Signed-off-by:, as I made this your patch (since
> you came up with it in that email reply some weeks ago). I hope that's
> fine.
> I tested this briefly on a Pine64-LTS, booting from FEL, SD card, eMMC
> and SPI. I also simulated a CHIP board, by just defining ENV_IS_NOWHERE,
> then booting, as this was the case that broke.
> If no one complains, I would like to push this ASAP, to make it into
> the 2022.07 release still.
> 
> Cheers,
> Andre
> 
>  board/sunxi/board.c | 49 +++++++++++++++++++++++++++------------------
>  1 file changed, 29 insertions(+), 20 deletions(-)
> 
> diff --git a/board/sunxi/board.c b/board/sunxi/board.c
> index 806e3bcb69..21a2407e06 100644
> --- a/board/sunxi/board.c
> +++ b/board/sunxi/board.c
> @@ -128,26 +128,37 @@ void i2c_init_board(void)
>   * Try to use the environment from the boot source first.
>   * For MMC, this means a FAT partition on the boot device (SD or eMMC).
>   * If the raw MMC environment is also enabled, this is tried next.
> + * When booting from NAND we try UBI first, then NAND directly.
>   * SPI flash falls back to FAT (on SD card).
>   */
>  enum env_location env_get_location(enum env_operation op, int prio)
>  {
> -	enum env_location boot_loc = ENVL_FAT;
> +	if (prio > 1)
> +		return ENVL_UNKNOWN;
>  
> -	gd->env_load_prio = prio;
> +	/* NOWHERE is exclusive, no other option can be defined. */
> +	if (IS_ENABLED(CONFIG_ENV_IS_NOWHERE))
> +		return ENVL_NOWHERE;
>  
>  	switch (sunxi_get_boot_device()) {
>  	case BOOT_DEVICE_MMC1:
>  	case BOOT_DEVICE_MMC2:
> -		boot_loc = ENVL_FAT;
> +		if (prio == 0 && IS_ENABLED(CONFIG_ENV_IS_IN_FAT))
> +			return ENVL_FAT;
> +		if (IS_ENABLED(CONFIG_ENV_IS_IN_MMC))
> +			return ENVL_MMC;
>  		break;
>  	case BOOT_DEVICE_NAND:
> +		if (prio == 0 && IS_ENABLED(CONFIG_ENV_IS_IN_UBI))
> +			return ENVL_UBI;
>  		if (IS_ENABLED(CONFIG_ENV_IS_IN_NAND))
> -			boot_loc = ENVL_NAND;
> +			return ENVL_NAND;
>  		break;
>  	case BOOT_DEVICE_SPI:
> -		if (IS_ENABLED(CONFIG_ENV_IS_IN_SPI_FLASH))
> -			boot_loc = ENVL_SPI_FLASH;
> +		if (prio == 0 && IS_ENABLED(CONFIG_ENV_IS_IN_SPI_FLASH))
> +			return ENVL_SPI_FLASH;
> +		if (IS_ENABLED(CONFIG_ENV_IS_IN_FAT))
> +			return ENVL_FAT;
>  		break;
>  	case BOOT_DEVICE_BOARD:
>  		break;
> @@ -155,21 +166,19 @@ enum env_location env_get_location(enum env_operation op, int prio)
>  		break;
>  	}
>  
> -	/* Always try to access the environment on the boot device first. */
> -	if (prio == 0)
> -		return boot_loc;
> -
> -	if (prio == 1) {
> -		switch (boot_loc) {
> -		case ENVL_SPI_FLASH:
> +	/*
> +	 * If we come here for the first time, we *must* return a valid
> +	 * environment location other than ENVL_UNKNOWN, or the setup sequence
> +	 * in board_f() will silently hang. This is arguably a bug in
> +	 * env_init(), but for now pick one environment for which we know for
> +	 * sure to have a driver for. For all defconfigs this is either FAT
> +	 * or UBI, or NOWHERE, which is already handled above.
> +	 */
> +	if (prio == 0) {
> +		if (IS_ENABLED(CONFIG_ENV_IS_IN_FAT))
>  			return ENVL_FAT;
> -		case ENVL_FAT:
> -			if (IS_ENABLED(CONFIG_ENV_IS_IN_MMC))
> -				return ENVL_MMC;
> -			break;
> -		default:
> -			break;
> -		}
> +		if (IS_ENABLED(CONFIG_ENV_IS_IN_UBI))
> +			return ENVL_UBI;
>  	}
>  
>  	return ENVL_UNKNOWN;
Samuel Holland June 27, 2022, 12:59 a.m. UTC | #2
Hi Andre,

On 6/24/22 11:12 AM, Andre Przywara wrote:
> From: Samuel Holland <samuel@sholland.org>
> 
> Commit e42dad4168fe ("sunxi: use boot source for determining environment
> location") changed our implementation of env_get_location() and enabled
> it for every board, even those without MMC support (like the C.H.I.P.
> boards). However the default fallback location of ENVL_FAT requires MMC
> support compiled in, so the board hangs when trying to initially load
> the environment.
> 
> Change the algorithm to only return configured environment locations,
> and improve the fallback algorithm on the way.
> 
> The env_init() routine calling this function here does not behave well
> if the return value is ENVL_UNKNOWN on the very first call: it will make
> U-Boot proper silently hang very early.
> Work around this issue by making sure we return some configured (dummy)
> environment location when prio is 0. This for instance happens when
> booting via FEL.
> 
> This fixes U-Boot loading on the C.H.I.P. boards.
> 
> Fixes: e42dad4168fe ("sunxi: use boot source for determining environment location")
> Reported-by: Chris Morgan <macroalpha82@gmail.com>
> Signed-off-by: Samuel Holland <samuel@sholland.org>
> [Andre: fix FEL boot case by not returning ENVL_UNKNOWN when prio==0]
> Signed-off-by: Andre Przywara <andre.przywara@arm.com>
> ---
> Hi Samuel,
> 
> I cheekily added your Signed-off-by:, as I made this your patch (since
> you came up with it in that email reply some weeks ago). I hope that's
> fine.

Yes, this is fine with me.

Regards,
Samuel
diff mbox series

Patch

diff --git a/board/sunxi/board.c b/board/sunxi/board.c
index 806e3bcb69..21a2407e06 100644
--- a/board/sunxi/board.c
+++ b/board/sunxi/board.c
@@ -128,26 +128,37 @@  void i2c_init_board(void)
  * Try to use the environment from the boot source first.
  * For MMC, this means a FAT partition on the boot device (SD or eMMC).
  * If the raw MMC environment is also enabled, this is tried next.
+ * When booting from NAND we try UBI first, then NAND directly.
  * SPI flash falls back to FAT (on SD card).
  */
 enum env_location env_get_location(enum env_operation op, int prio)
 {
-	enum env_location boot_loc = ENVL_FAT;
+	if (prio > 1)
+		return ENVL_UNKNOWN;
 
-	gd->env_load_prio = prio;
+	/* NOWHERE is exclusive, no other option can be defined. */
+	if (IS_ENABLED(CONFIG_ENV_IS_NOWHERE))
+		return ENVL_NOWHERE;
 
 	switch (sunxi_get_boot_device()) {
 	case BOOT_DEVICE_MMC1:
 	case BOOT_DEVICE_MMC2:
-		boot_loc = ENVL_FAT;
+		if (prio == 0 && IS_ENABLED(CONFIG_ENV_IS_IN_FAT))
+			return ENVL_FAT;
+		if (IS_ENABLED(CONFIG_ENV_IS_IN_MMC))
+			return ENVL_MMC;
 		break;
 	case BOOT_DEVICE_NAND:
+		if (prio == 0 && IS_ENABLED(CONFIG_ENV_IS_IN_UBI))
+			return ENVL_UBI;
 		if (IS_ENABLED(CONFIG_ENV_IS_IN_NAND))
-			boot_loc = ENVL_NAND;
+			return ENVL_NAND;
 		break;
 	case BOOT_DEVICE_SPI:
-		if (IS_ENABLED(CONFIG_ENV_IS_IN_SPI_FLASH))
-			boot_loc = ENVL_SPI_FLASH;
+		if (prio == 0 && IS_ENABLED(CONFIG_ENV_IS_IN_SPI_FLASH))
+			return ENVL_SPI_FLASH;
+		if (IS_ENABLED(CONFIG_ENV_IS_IN_FAT))
+			return ENVL_FAT;
 		break;
 	case BOOT_DEVICE_BOARD:
 		break;
@@ -155,21 +166,19 @@  enum env_location env_get_location(enum env_operation op, int prio)
 		break;
 	}
 
-	/* Always try to access the environment on the boot device first. */
-	if (prio == 0)
-		return boot_loc;
-
-	if (prio == 1) {
-		switch (boot_loc) {
-		case ENVL_SPI_FLASH:
+	/*
+	 * If we come here for the first time, we *must* return a valid
+	 * environment location other than ENVL_UNKNOWN, or the setup sequence
+	 * in board_f() will silently hang. This is arguably a bug in
+	 * env_init(), but for now pick one environment for which we know for
+	 * sure to have a driver for. For all defconfigs this is either FAT
+	 * or UBI, or NOWHERE, which is already handled above.
+	 */
+	if (prio == 0) {
+		if (IS_ENABLED(CONFIG_ENV_IS_IN_FAT))
 			return ENVL_FAT;
-		case ENVL_FAT:
-			if (IS_ENABLED(CONFIG_ENV_IS_IN_MMC))
-				return ENVL_MMC;
-			break;
-		default:
-			break;
-		}
+		if (IS_ENABLED(CONFIG_ENV_IS_IN_UBI))
+			return ENVL_UBI;
 	}
 
 	return ENVL_UNKNOWN;