summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorJi Luo <ji.luo@nxp.com>2019-07-18 13:56:45 +0800
committerJi Luo <ji.luo@nxp.com>2022-04-18 16:40:08 +0800
commitd63fb59f6d4d92d7a24a9e69bb9e3ba9db20f57b (patch)
treeb1294997c8663691f9d6aed37631997c102f586f /lib
parentb258d3f62c779f144551dc1a75554fb52052473a (diff)
MA-15158 Set spl recovery mode for dual bootloader
The A/B slot selection is moved to spl, it may lead to hang if no bootable slots found. The only way to recover the board is re-flash images with uuu tool, which is quite inconvenient for some customers who can't enter serial download mode. This patch will set "spl recovery mode" which will give us a chance to re-flash images with fastboot commands. Test: Enter spl recovery mode and flash images when no bootable slots found. Change-Id: I31278f5212bde7609fe2f49e77b3849e92c0c516 Signed-off-by: Ji Luo <ji.luo@nxp.com> (cherry picked from commit 46cc755cf3f42422ee1d7783394e14e8125df2b6) (cherry picked from commit 047f09ef2ef33657d76fd92d8f5599e00158cd6b) (cherry picked from commit e96b68d22e89e4031d1117ab347f042577c5c8f1)
Diffstat (limited to 'lib')
-rw-r--r--lib/avb/fsl/fsl_avb_ab_flow.c98
-rw-r--r--lib/avb/libavb_ab/avb_ab_flow.h8
2 files changed, 101 insertions, 5 deletions
diff --git a/lib/avb/fsl/fsl_avb_ab_flow.c b/lib/avb/fsl/fsl_avb_ab_flow.c
index 3bd25f8a03..dcc2db3059 100644
--- a/lib/avb/fsl/fsl_avb_ab_flow.c
+++ b/lib/avb/fsl/fsl_avb_ab_flow.c
@@ -400,16 +400,74 @@ int mmc_load_image_raw_sector_dual_uboot(struct spl_image_info *spl_image,
}
if (slot_index_to_boot == 2) {
- /* No bootable slots! */
- printf("No bootable slots found.\n");
- ret = -1;
- goto end;
+ /* No bootable slots, try to boot into recovery! */
+ printf("No bootable slots found, try to boot into recovery mode...\n");
+
+ ab_data.spl_recovery = true;
+ if ((ab_data.last_boot != 0) && (ab_data.last_boot != 1))
+ slot_index_to_boot = 0;
+ else
+ slot_index_to_boot = ab_data.last_boot;
+
+ snprintf(partition_name, PARTITION_NAME_LEN,
+ PARTITION_BOOTLOADER"%s",
+ slot_suffixes[target_slot]);
+
+ /* Read part info from gpt */
+ if (part_get_info_by_name(dev_desc, partition_name, &info) == -1) {
+ printf("Can't get partition info of partition bootloader%s\n",
+ slot_suffixes[target_slot]);
+ ret = -1;
+ goto end;
+ } else {
+ header = (struct image_header *)(CONFIG_SYS_TEXT_BASE -
+ sizeof(struct image_header));
+
+ /* read image header to find the image size & load address */
+ count = blk_dread(dev_desc, info.start, 1, header);
+ if (count == 0) {
+ ret = -1;
+ goto end;
+ }
+
+ /* Load fit/container and check HAB */
+ load.dev = mmc;
+ load.priv = NULL;
+ load.filename = NULL;
+ load.bl_len = mmc->read_bl_len;
+ load.read = h_spl_load_read;
+ if (IS_ENABLED(CONFIG_SPL_LOAD_FIT) &&
+ image_get_magic(header) == FDT_MAGIC) {
+ /* Fit */
+ ret = spl_load_simple_fit(spl_image, &load,
+ info.start, header);
+ } else if (IS_ENABLED(CONFIG_SPL_LOAD_IMX_CONTAINER)) {
+ /* container */
+ ret = spl_load_imx_container(spl_image, &load, info.start);
+ } else
+ ret = -1;
+
+#if !defined(CONFIG_XEN) && defined(CONFIG_IMX_TRUSTY_OS)
+ /* Image loaded successfully, go to verify rollback index */
+ if (!ret)
+ ret = spl_verify_rbidx(mmc, &ab_data.slots[target_slot], spl_image);
+
+ /* Copy rpmb keyslot to secure memory. */
+ if (!ret)
+ fill_secure_keyslot_package(&kp);
+#endif
+ }
+
+ if (ret)
+ goto end;
} else if (!ab_data.slots[slot_index_to_boot].successful_boot &&
(ab_data.slots[slot_index_to_boot].tries_remaining > 0)) {
/* Set the bootloader_verified flag as if current slot only has one chance. */
if (ab_data.slots[slot_index_to_boot].tries_remaining == 1)
ab_data.slots[slot_index_to_boot].bootloader_verified = 1;
ab_data.slots[slot_index_to_boot].tries_remaining -= 1;
+
+ ab_data.last_boot = slot_index_to_boot;
}
printf("Booting from bootloader%s...\n", slot_suffixes[slot_index_to_boot]);
@@ -682,6 +740,38 @@ out:
return ret;
}
+
+extern AvbABOps fsl_avb_ab_ops;
+static bool spl_recovery_flag = false;
+bool is_spl_recovery(void)
+{
+ return spl_recovery_flag;
+}
+void check_spl_recovery(void)
+{
+ AvbABData ab_data, ab_data_orig;
+ AvbIOResult io_ret;
+
+ io_ret = fsl_load_metadata(&fsl_avb_ab_ops, &ab_data, &ab_data_orig);
+ if (io_ret != AVB_IO_RESULT_OK) {
+ printf("Load metadata fail, go to fail!\n");
+ hang();
+ }
+
+ spl_recovery_flag = ab_data.spl_recovery;
+ /* Clear spl recovery flag. */
+ ab_data.spl_recovery = false;
+ fsl_save_metadata_if_changed(&fsl_avb_ab_ops, &ab_data, &ab_data_orig);
+
+ if (spl_recovery_flag) {
+ printf("Enter spl recovery mode, only fastboot commands are supported!\n");
+
+ while (1) {
+ run_command("fastboot 0", 0);
+ }
+ }
+}
+
#else /* CONFIG_DUAL_BOOTLOADER */
/* For legacy i.mx6/7, we won't enable A/B due to the limitation of
* storage capacity, but we still want to verify boot/recovery with
diff --git a/lib/avb/libavb_ab/avb_ab_flow.h b/lib/avb/libavb_ab/avb_ab_flow.h
index 3757ba26ac..1e09d398f2 100644
--- a/lib/avb/libavb_ab/avb_ab_flow.h
+++ b/lib/avb/libavb_ab/avb_ab_flow.h
@@ -93,8 +93,14 @@ typedef struct AvbABData {
/* Per-slot metadata. */
AvbABSlotData slots[2];
+ /* Last boot slot */
+ uint8_t last_boot;
+
+ /* spl recovery mode */
+ bool spl_recovery;
+
/* Reserved for future use. */
- uint8_t reserved2[12];
+ uint8_t reserved2[10];
/* CRC32 of all 28 bytes preceding this field. */
uint32_t crc32;