MA-15814 Check 'successful_boot' flag before marking unbootable
authorJi Luo <ji.luo@nxp.com>
Mon, 11 May 2020 03:47:46 +0000 (11:47 +0800)
committerJi Luo <ji.luo@nxp.com>
Thu, 13 May 2021 01:49:17 +0000 (09:49 +0800)
Slot will be marked as "unbootable" state if error happens during
image load/verify process, this may cause the board never boot up
if some random failures happen (like eMMC/DRAM access error at some
critical temperature).

Check the "successful_boot" flag before marking the slot as "unbootable",
this will help ease the "no bootable slot" issue.

Test: slot switch on imx8qm_mek.

Signed-off-by: Ji Luo <ji.luo@nxp.com>
(cherry picked from commit 6db8ebe2224ab6656e8e798288bd1b3c0472c0c0)
(cherry picked from commit b64a9dcd87da333265c2ac4da2be8a735186b77e)

Change-Id: Ib060b11cc6687a3bacd09cecda7dd925beba6316

lib/avb/fsl/fsl_avb_ab_flow.c

index dcc2db3..ec700b4 100644 (file)
@@ -388,11 +388,19 @@ int mmc_load_image_raw_sector_dual_uboot(struct spl_image_info *spl_image,
 
                /* Set current slot to unbootable if load/verify fail. */
                if (ret != 0) {
-                       printf("Load or verify bootloader%s fail, setting unbootable..\n",
-                              slot_suffixes[target_slot]);
-                       fsl_slot_set_unbootable(&ab_data.slots[target_slot]);
-                       /* Switch to another slot. */
-                       target_slot = (target_slot == 1 ? 0 : 1);
+                       /* Reboot if current slot has booted succefully before, this prevents
+                        * slot been marked as "unbootable" due to some random failures (like
+                        * eMMC/DRAM access error at some critical temperature).
+                        */
+                       if (ab_data.slots[target_slot].successful_boot)
+                               do_reset(NULL, 0, 0, NULL);
+                       else {
+                               printf("Load or verify bootloader%s fail, setting unbootable..\n",
+                                      slot_suffixes[target_slot]);
+                               fsl_slot_set_unbootable(&ab_data.slots[target_slot]);
+                               /* Switch to another slot. */
+                               target_slot = (target_slot == 1 ? 0 : 1);
+                       }
                } else {
                        slot_index_to_boot = target_slot;
                        n = 2;
@@ -650,20 +658,28 @@ AvbABFlowResult avb_flow_dual_uboot(AvbABOps* ab_ops,
        }
 
        if (set_slot_unbootable) {
-               avb_errorv("Error verifying slot ",
-                          slot_suffixes[target_slot],
-                          " with result ",
-                          avb_slot_verify_result_to_string(verify_result),
-                          " - setting unbootable.\n",
-                          NULL);
-               fsl_slot_set_unbootable(&ab_data.slots[target_slot]);
-
-               /* Only the slot chosen by SPL will be verified here so we
-                * return AVB_AB_FLOW_RESULT_ERROR_NO_BOOTABLE_SLOTS if the
-                * slot should be set unbootable.
+               /* Reboot if current slot has booted succefully before, this prevents
+                * slot been marked as "unbootable" due to some random failures (like
+                * eMMC/DRAM access error at some critical temperature).
                 */
-               ret = AVB_AB_FLOW_RESULT_ERROR_NO_BOOTABLE_SLOTS;
-               goto out;
+               if (ab_data.slots[target_slot].successful_boot)
+                       do_reset(NULL, 0, 0, NULL);
+               else {
+                       avb_errorv("Error verifying slot ",
+                                  slot_suffixes[target_slot],
+                                  " with result ",
+                                  avb_slot_verify_result_to_string(verify_result),
+                                  " - setting unbootable.\n",
+                                  NULL);
+                       fsl_slot_set_unbootable(&ab_data.slots[target_slot]);
+
+                       /* Only the slot chosen by SPL will be verified here so we
+                        * return AVB_AB_FLOW_RESULT_ERROR_NO_BOOTABLE_SLOTS if the
+                        * slot should be set unbootable.
+                        */
+                       ret = AVB_AB_FLOW_RESULT_ERROR_NO_BOOTABLE_SLOTS;
+                       goto out;
+               }
        }
 
        /* Update stored rollback index only when the slot has been marked
@@ -968,14 +984,22 @@ AvbABFlowResult avb_ab_flow_fast(AvbABOps* ab_ops,
                }
 
                if (set_slot_unbootable) {
-                       avb_errorv("Error verifying slot ",
-                                  slot_suffixes[target_slot],
-                                  " with result ",
-                                  avb_slot_verify_result_to_string(verify_result),
-                                  " - setting unbootable.\n",
-                                  NULL);
-                       fsl_slot_set_unbootable(&ab_data.slots[target_slot]);
-                       set_slot_unbootable = false;
+                       /* Reboot if current slot has booted succefully before, this prevents
+                        * slot been marked as "unbootable" due to some random failures (like
+                        * eMMC/DRAM access error at some critical temperature).
+                        */
+                       if (ab_data.slots[target_slot].successful_boot)
+                               do_reset(NULL, 0, 0, NULL);
+                       else {
+                               avb_errorv("Error verifying slot ",
+                                          slot_suffixes[target_slot],
+                                          " with result ",
+                                          avb_slot_verify_result_to_string(verify_result),
+                                          " - setting unbootable.\n",
+                                          NULL);
+                               fsl_slot_set_unbootable(&ab_data.slots[target_slot]);
+                               set_slot_unbootable = false;
+                       }
                }
                /* switch to another slot */
                target_slot = (target_slot == 1 ? 0 : 1);