summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorJi Luo <ji.luo@nxp.com>2019-01-14 18:28:08 +0800
committerJi Luo <ji.luo@nxp.com>2019-01-18 12:07:21 +0800
commit71562aae3b8123ccd7503e596e478951568fcd24 (patch)
tree30dd62bf0a3534a144ba5b7b8ff50a7fa3094172 /lib
parent1614541095c7e91989556b52b7d7605f7d8570af (diff)
MA-13938 [Android] imx8q: Support dual bootloader feature
Support dual bootloader feature for imx8q which uses the container format. Move the A/B slot select and verify to SPL stage, the bootloader rollback index will be stored at the last 8K bytes of eMMC rpmb storage. Test: Boot and rbindex verify pass on imx8q. Change-Id: I0a48210f65984a083037a0cd3f9558951029ed7d Signed-off-by: Ji Luo <ji.luo@nxp.com>
Diffstat (limited to 'lib')
-rw-r--r--lib/avb/fsl/fsl_avb_ab_flow.c124
-rw-r--r--lib/avb/fsl/fsl_avbkey.c115
2 files changed, 180 insertions, 59 deletions
diff --git a/lib/avb/fsl/fsl_avb_ab_flow.c b/lib/avb/fsl/fsl_avb_ab_flow.c
index eee630cdf4..f015bad105 100644
--- a/lib/avb/fsl/fsl_avb_ab_flow.c
+++ b/lib/avb/fsl/fsl_avb_ab_flow.c
@@ -63,6 +63,8 @@ bool fsl_slot_is_bootable(AvbABSlotData* slot) {
#define PARTITION_BOOTLOADER "bootloader"
extern int mmc_switch(struct mmc *mmc, u8 set, u8 index, u8 value);
+extern int mmc_load_image_parse_container(struct spl_image_info *spl_image,
+ struct mmc *mmc, unsigned long sector);
/* Pre-declaration of h_spl_load_read(), see detail implementation in
* common/spl/spl_mmc.c.
@@ -164,10 +166,10 @@ int fsl_load_metadata_dual_uboot(struct blk_desc *dev_desc,
printf("Can't get partition info of partition: misc\n");
return -1;
} else {
- read_from_partition_in_bytes(
- dev_desc, &info, FSL_AB_METADATA_MISC_PARTITION_OFFSET,
- sizeof(AvbABData),
- (void *)ab_data, &num_bytes );
+ read_from_partition_in_bytes(dev_desc, &info,
+ FSL_AB_METADATA_MISC_PARTITION_OFFSET,
+ sizeof(AvbABData),
+ (void *)ab_data, &num_bytes );
if (num_bytes != sizeof(AvbABData)) {
printf("Error--read metadata fail!\n");
return -1;
@@ -262,6 +264,119 @@ static int spl_verify_rbidx(struct mmc *mmc, AvbABSlotData *slot,
}
+#ifdef CONFIG_PARSE_CONTAINER
+int mmc_load_image_parse_container_dual_uboot(
+ struct spl_image_info *spl_image, struct mmc *mmc)
+{
+ disk_partition_t info;
+ int ret = 0, n = 0;
+ char partition_name[PARTITION_NAME_LEN];
+ struct blk_desc *dev_desc;
+ AvbABData ab_data, ab_data_orig;
+ size_t slot_index_to_boot, target_slot;
+ struct keyslot_package kp;
+
+ /* Check if gpt is valid */
+ dev_desc = mmc_get_blk_desc(mmc);
+ if (dev_desc) {
+ if (part_get_info(dev_desc, 1, &info)) {
+ printf("GPT is invalid, please flash correct GPT!\n");
+ return -1;
+ }
+ } else {
+ printf("Get block desc fail!\n");
+ return -1;
+ }
+
+ /* Read RPMB keyslot package */
+ read_keyslot_package(&kp);
+ if (strcmp(kp.magic, KEYPACK_MAGIC)) {
+ if (rpmbkey_is_set()) {
+ printf("\nFATAL - RPMB key was destroyed!\n");
+ hang();
+ } else
+ printf("keyslot package magic error, do nothing here!\n");
+ } else {
+ /* Set power-on write protection to boot1 partition. */
+ if (mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_BOOT_WP, BOOT1_PWR_WP)) {
+ printf("Unable to set power-on write protection to boot1!\n");
+ return -1;
+ }
+ }
+ /* Load AB metadata from misc partition */
+ if (fsl_load_metadata_dual_uboot(dev_desc, &ab_data,
+ &ab_data_orig)) {
+ return -1;
+ }
+
+ slot_index_to_boot = 2; // Means not 0 or 1
+ target_slot =
+ (ab_data.slots[1].priority > ab_data.slots[0].priority) ? 1 : 0;
+
+ for (n = 0; n < 2; n++) {
+ if (!fsl_slot_is_bootable(&ab_data.slots[target_slot])) {
+ target_slot = (target_slot == 1 ? 0 : 1);
+ continue;
+ }
+ /* Choose slot to load. */
+ 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 {
+ ret = mmc_load_image_parse_container(spl_image, mmc, info.start);
+
+ /* Image loaded successfully, go to verify rollback index */
+ if (!ret && rpmbkey_is_set())
+ 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);
+ }
+
+ /* 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);
+ } else {
+ slot_index_to_boot = target_slot;
+ n = 2;
+ }
+ }
+
+ if (slot_index_to_boot == 2) {
+ /* No bootable slots! */
+ printf("No bootable slots found.\n");
+ ret = -1;
+ goto end;
+ } else if (!ab_data.slots[slot_index_to_boot].successful_boot &&
+ (ab_data.slots[slot_index_to_boot].tries_remaining > 0)) {
+ ab_data.slots[slot_index_to_boot].tries_remaining -= 1;
+ }
+ printf("Booting from bootloader%s...\n", slot_suffixes[slot_index_to_boot]);
+
+end:
+ /* Save metadata if changed. */
+ if (fsl_save_metadata_if_changed_dual_uboot(dev_desc, &ab_data, &ab_data_orig)) {
+ ret = -1;
+ }
+
+ if (ret)
+ return -1;
+ else
+ return 0;
+}
+#else /* CONFIG_PARSE_CONTAINER */
int mmc_load_image_raw_sector_dual_uboot(
struct spl_image_info *spl_image, struct mmc *mmc)
{
@@ -431,6 +546,7 @@ int spl_fit_get_rbindex(const void *fit, int images)
return index;
}
+#endif /* CONFIG_PARSE_CONTAINER */
/* For normal build */
#elif !defined(CONFIG_SPL_BUILD)
diff --git a/lib/avb/fsl/fsl_avbkey.c b/lib/avb/fsl/fsl_avbkey.c
index 4ef914aa39..719ff02aac 100644
--- a/lib/avb/fsl/fsl_avbkey.c
+++ b/lib/avb/fsl/fsl_avbkey.c
@@ -134,6 +134,57 @@ fail:
return ret;
}
+bool rpmbkey_is_set(void)
+{
+ int mmcc;
+ bool ret;
+ uint8_t *buf;
+ struct mmc *mmc;
+ char original_part;
+ struct blk_desc *desc = NULL;
+
+ /* Get current mmc device. */
+ mmcc = mmc_get_env_dev();
+ mmc = find_mmc_device(mmcc);
+ if (!mmc) {
+ printf("error - cannot find '%d' mmc device\n", mmcc);
+ return false;
+ }
+
+ desc = mmc_get_blk_desc(mmc);
+ original_part = desc->hwpart;
+
+ /* Switch to the RPMB partition */
+ if (desc->hwpart != MMC_PART_RPMB) {
+ if (mmc_switch_part(mmc, MMC_PART_RPMB) != 0) {
+ printf("ERROR - can't switch to rpmb partition \n");
+ return false;
+ }
+ desc->hwpart = MMC_PART_RPMB;
+ }
+
+ /* Try to read the first one block, return count '1' means the rpmb
+ * key has been set, otherwise means the key hasn't been set.
+ */
+ buf = (uint8_t *)memalign(ALIGN_BYTES, desc->blksz);
+ if (mmc_rpmb_read(mmc, buf, 0, 1, NULL) != 1)
+ ret = false;
+ else
+ ret = true;
+
+ /* return to original partition. */
+ if (desc->hwpart != original_part) {
+ if (mmc_switch_part(mmc, original_part) != 0)
+ ret = false;
+ desc->hwpart = original_part;
+ }
+ /* remember to free the buffer */
+ if (buf != NULL)
+ free(buf);
+
+ return ret;
+}
+
#ifdef CONFIG_FSL_CAAM_KB
int rpmb_read(struct mmc *mmc, uint8_t *buffer, size_t num_bytes, int64_t offset) {
@@ -354,7 +405,7 @@ int rpmb_init(void) {
ERR("ERROR - get mmc device\n");
return -1;
}
- /* The bootloader rollback index is stored in the last 8 blocks of
+ /* The bootloader rollback index is stored in the last 8k bytes of
* RPMB which is different from the rollback index for vbmeta and
* ATX key versions.
*/
@@ -642,8 +693,8 @@ int rbkidx_erase(void) {
}
return 0;
}
-#endif /* CONFIG_FSL_CAAM_KB */
#endif /* CONFIG_IMX_TRUSTY_OS */
+#endif /* CONFIG_FSL_CAAM_KB */
#else /* AVB_RPMB */
int rbkidx_erase(void) {
return 0;
@@ -660,8 +711,13 @@ int check_rpmb_blob(struct mmc *mmc)
read_keyslot_package(&kp);
if (strcmp(kp.magic, KEYPACK_MAGIC)) {
- printf("keyslot package magic error, do nothing here!\n");
- return 0;
+ if (rpmbkey_is_set()) {
+ printf("\nFATAL - RPMB key was destroyed!\n");
+ hang();
+ } else {
+ printf("keyslot package magic error, do nothing here!\n");
+ return 0;
+ }
}
/* If keyslot package valid, copy it to secure memory */
fill_secure_keyslot_package(&kp);
@@ -983,57 +1039,6 @@ int at_disable_vboot_unlock(void)
#endif /* CONFIG_AVB_ATX */
#if defined(CONFIG_IMX_TRUSTY_OS) && !defined(CONFIG_AVB_ATX)
-bool rpmbkey_is_set(void)
-{
- int mmcc;
- bool ret;
- uint8_t *buf;
- struct mmc *mmc;
- char original_part;
- struct blk_desc *desc = NULL;
-
- /* Get current mmc device. */
- mmcc = mmc_get_env_dev();
- mmc = find_mmc_device(mmcc);
- if (!mmc) {
- printf("error - cannot find '%d' mmc device\n", mmcc);
- return false;
- }
-
- desc = mmc_get_blk_desc(mmc);
- original_part = desc->hwpart;
-
- /* Switch to the RPMB partition */
- if (desc->hwpart != MMC_PART_RPMB) {
- if (mmc_switch_part(mmc, MMC_PART_RPMB) != 0) {
- printf("ERROR - can't switch to rpmb partition \n");
- return false;
- }
- desc->hwpart = MMC_PART_RPMB;
- }
-
- /* Try to read the first one block, return count '1' means the rpmb
- * key has been set, otherwise means the key hasn't been set.
- */
- buf = (uint8_t *)memalign(ALIGN_BYTES, desc->blksz);
- if (mmc_rpmb_read(mmc, buf, 0, 1, NULL) != 1)
- ret = false;
- else
- ret = true;
-
- /* return to original partition. */
- if (desc->hwpart != original_part) {
- if (mmc_switch_part(mmc, original_part) != 0)
- ret = false;
- desc->hwpart = original_part;
- }
- /* remember to free the buffer */
- if (buf != NULL)
- free(buf);
-
- return ret;
-}
-
int do_rpmb_key_set(uint8_t *key, uint32_t key_size)
{
int ret = 0;