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>2019-07-19 13:14:15 +0800
commit2a43c3e702720fab67ae9af73634a958a1b62044 (patch)
tree0399901533ba4e194f3d89235496e04082da32cf /lib
parent3f94cf98113af6c31e146afcf394f34ff4d2bc00 (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>
Diffstat (limited to 'lib')
-rw-r--r--lib/avb/fsl/fsl_avb_ab_flow.c138
-rw-r--r--lib/avb/libavb_ab/avb_ab_flow.h8
2 files changed, 137 insertions, 9 deletions
diff --git a/lib/avb/fsl/fsl_avb_ab_flow.c b/lib/avb/fsl/fsl_avb_ab_flow.c
index 0dc6850434..446d650692 100644
--- a/lib/avb/fsl/fsl_avb_ab_flow.c
+++ b/lib/avb/fsl/fsl_avb_ab_flow.c
@@ -375,16 +375,50 @@ int mmc_load_image_parse_container_dual_uboot(
}
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[slot_index_to_boot]);
+
+ /* 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[slot_index_to_boot]);
+ ret = -1;
+ goto end;
+ } else {
+ ret = mmc_load_image_parse_container(spl_image, mmc, info.start);
+
+ /* Don't need to check rollback index for xen. */
+#ifndef CONFIG_XEN
+ /* Image loaded successfully, go to verify rollback index */
+ if (!ret && rpmbkey_is_set())
+ ret = spl_verify_rbidx(mmc, &ab_data.slots[slot_index_to_boot], 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 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]);
@@ -517,16 +551,72 @@ int mmc_load_image_raw_sector_dual_uboot(
}
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 and check HAB */
+ if (IS_ENABLED(CONFIG_SPL_LOAD_FIT) &&
+ image_get_magic(header) == FDT_MAGIC) {
+ struct spl_load_info load;
+
+ debug("Found FIT\n");
+ load.dev = mmc;
+ load.priv = NULL;
+ load.filename = NULL;
+ load.bl_len = mmc->read_bl_len;
+ load.read = h_spl_load_read;
+ ret = spl_load_simple_fit(spl_image, &load,
+ info.start, header);
+ } else {
+ ret = -1;
+ }
+
+ /* Fit 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);
+ }
+
+ 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]);
@@ -801,6 +891,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;