From b57739cac724bb9b1984003fe5ea19a60f33deb7 Mon Sep 17 00:00:00 2001 From: Ji Luo Date: Sun, 26 Aug 2018 19:46:16 +0800 Subject: [iot] Support fastboot variable 'at-vboot-state' Add support for fastboot variable 'at-vboot-state', it's composed by 6 sub-variable: 'bootloader-locked', 'bootloader-min-versions', 'avb-perm-attr-set', 'avb-locked', 'avb-unlock-disabled' and 'avb-min-versions'. Test: All 'at-vboot-state' variables are returned correctly on imx7d_pico and AIY. Change-Id: Ibb855cbcc7c41657af62dafb98a96c4dfb96ef22 Signed-off-by: Ji Luo --- arch/arm/mach-imx/imx8m/soc.c | 2 +- arch/arm/mach-imx/mx7/soc.c | 2 +- drivers/usb/gadget/f_fastboot.c | 196 ++++++++++++++++++++++++++++- include/configs/imx8mq_evk_androidthings.h | 7 ++ lib/avb/fsl/fsl_avb_ab_flow.c | 13 ++ lib/avb/fsl/fsl_avbkey.h | 9 ++ 6 files changed, 222 insertions(+), 7 deletions(-) diff --git a/arch/arm/mach-imx/imx8m/soc.c b/arch/arm/mach-imx/imx8m/soc.c index 2250460548a..436b6cb3a16 100644 --- a/arch/arm/mach-imx/imx8m/soc.c +++ b/arch/arm/mach-imx/imx8m/soc.c @@ -28,7 +28,7 @@ DECLARE_GLOBAL_DATA_PTR; -#if defined(CONFIG_SECURE_BOOT) +#if defined(CONFIG_SECURE_BOOT) || defined(CONFIG_AVB_ATX) struct imx_sec_config_fuse_t const imx_sec_config_fuse = { .bank = 1, .word = 3, diff --git a/arch/arm/mach-imx/mx7/soc.c b/arch/arm/mach-imx/mx7/soc.c index 5ee67acb2d8..ea7112abd00 100644 --- a/arch/arm/mach-imx/mx7/soc.c +++ b/arch/arm/mach-imx/mx7/soc.c @@ -97,7 +97,7 @@ static void isolate_resource(void) } #endif -#if defined(CONFIG_SECURE_BOOT) +#if defined(CONFIG_SECURE_BOOT) || defined(CONFIG_AVB_ATX) struct imx_sec_config_fuse_t const imx_sec_config_fuse = { .bank = 1, .word = 3, diff --git a/drivers/usb/gadget/f_fastboot.c b/drivers/usb/gadget/f_fastboot.c index 1374bbfcbde..6545d06ae80 100644 --- a/drivers/usb/gadget/f_fastboot.c +++ b/drivers/usb/gadget/f_fastboot.c @@ -75,6 +75,8 @@ extern void trusty_os_init(void); #ifdef CONFIG_ANDROID_THINGS_SUPPORT #include #include +#include "../lib/avb/fsl/fsl_avbkey.h" +#include "../arch/arm/include/asm/mach-imx/hab.h" #endif #define FASTBOOT_VERSION "0.4" @@ -155,6 +157,22 @@ char *fastboot_common_var[FASTBOOT_COMMON_VAR_NUM] = { #endif }; +/* at-vboot-state variable list */ +#ifdef CONFIG_AVB_ATX +#define AT_VBOOT_STATE_VAR_NUM 6 +extern struct imx_sec_config_fuse_t const imx_sec_config_fuse; +extern int fuse_read(u32 bank, u32 word, u32 *val); + +char *fastboot_at_vboot_state_var[AT_VBOOT_STATE_VAR_NUM] = { + "bootloader-locked", + "bootloader-min-versions", + "avb-perm-attr-set", + "avb-locked", + "avb-unlock-disabled", + "avb-min-versions" +}; +#endif + /* Boot metric variables */ boot_metric metrics = { .bll_1 = 0, @@ -2957,7 +2975,7 @@ int get_imx8m_baseboard_id(void); static int get_single_var(char *cmd, char *response) { char *str = cmd; - size_t chars_left; + int chars_left; const char *s; struct mmc *mmc; int mmc_dev_no; @@ -3085,6 +3103,138 @@ static int get_single_var(char *cmd, char *response) } else snprintf(response + strlen(response), chars_left, "0x%x", baseboard_id); } +#endif +#ifdef CONFIG_AVB_ATX + else if (!strcmp_l1("bootloader-locked", cmd)) { + + /* Below is basically copied from is_hab_enabled() */ + struct imx_sec_config_fuse_t *fuse = + (struct imx_sec_config_fuse_t *)&imx_sec_config_fuse; + uint32_t reg; + int ret; + + /* Read the secure boot status from fuse. */ + ret = fuse_read(fuse->bank, fuse->word, ®); + if (ret) { + printf("\nSecure boot fuse read error!\n"); + strncat(response, "Secure boot fuse read error!", chars_left); + return -1; + } + /* Check if the secure boot bit is enabled */ + if ((reg & 0x2000000) == 0x2000000) + strncat(response, "1", chars_left); + else + strncat(response, "0", chars_left); + } else if (!strcmp_l1("bootloader-min-versions", cmd)) { +#ifndef CONFIG_ARM64 + /* We don't support bootloader rbindex protection for + * ARM32(like imx7d) and the format is: "bootloader,tee". */ + strncat(response, "-1,-1", chars_left); + +#elif defined(CONFIG_DUAL_BOOTLOADER) + /* Rbindex protection for bootloader is supported only when the + * 'dual bootloader' feature is enabled. U-boot will get the rbindx + * from RAM which is passed by spl because we can only get the rbindex + * at spl stage. The format in this case is: "spl,atf,tee,u-boot". + */ + struct bl_rbindex_package *bl_rbindex; + uint32_t rbindex; + + bl_rbindex = (struct bl_rbindex_package *)BL_RBINDEX_LOAD_ADDR; + if (!strncmp(bl_rbindex->magic, BL_RBINDEX_MAGIC, + BL_RBINDEX_MAGIC_LEN)) { + rbindex = bl_rbindex->rbindex; + snprintf(response + strlen(response), chars_left, + "-1,%d,%d,%d",rbindex, rbindex, rbindex); + } else { + printf("Error bootloader rbindex magic!\n"); + strncat(response, "Get bootloader rbindex fail!", chars_left); + return -1; + } +#else + /* Return -1 for all partition if 'dual bootloader' feature + * is not enabled */ + strncat(response, "-1,-1,-1,-1", chars_left); +#endif + } else if (!strcmp_l1("avb-perm-attr-set", cmd)) { + if (perm_attr_are_fused()) + strncat(response, "1", chars_left); + else + strncat(response, "0", chars_left); + } else if (!strcmp_l1("avb-locked", cmd)) { + FbLockState status; + + status = fastboot_get_lock_stat(); + if (status == FASTBOOT_LOCK) + strncat(response, "1", chars_left); + else if (status == FASTBOOT_UNLOCK) + strncat(response, "0", chars_left); + else { + printf("Get lock state error!\n"); + strncat(response, "Get lock state failed!", chars_left); + return -1; + } + } else if (!strcmp_l1("avb-unlock-disabled", cmd)) { + if (at_unlock_vboot_is_disabled()) + strncat(response, "1", chars_left); + else + strncat(response, "0", chars_left); + } else if (!strcmp_l1("avb-min-versions", cmd)) { + int i = 0; + /* rbindex location/value can be very large + * number so we reserve enough space here. + */ + char buffer[35]; + uint32_t rbindex_location[AVB_MAX_NUMBER_OF_ROLLBACK_INDEX_LOCATIONS + 2]; + uint32_t location; + uint64_t rbindex; + + memset(buffer, '\0', sizeof(buffer)); + + /* Set rbindex locations. */ + for (i = 0; i < AVB_MAX_NUMBER_OF_ROLLBACK_INDEX_LOCATIONS; i++) + rbindex_location[i] = i; + + /* Set Android Things key version rbindex locations */ + rbindex_location[AVB_MAX_NUMBER_OF_ROLLBACK_INDEX_LOCATIONS] + = AVB_ATX_PIK_VERSION_LOCATION; + rbindex_location[AVB_MAX_NUMBER_OF_ROLLBACK_INDEX_LOCATIONS + 1] + = AVB_ATX_PSK_VERSION_LOCATION; + + /* Read rollback index and set the reponse*/ + for (i = 0; i < AVB_MAX_NUMBER_OF_ROLLBACK_INDEX_LOCATIONS + 2; i++) { + location = rbindex_location[i]; + if (fsl_avb_ops.read_rollback_index(&fsl_avb_ops, + location, &rbindex) + != AVB_IO_RESULT_OK) { + printf("Read rollback index error!\n"); + snprintf(response, sizeof(response), + "INFOread rollback index error when get avb-min-versions"); + return -1; + } + /* Generate the "location:value" pair */ + snprintf(buffer, sizeof(buffer), "%d:%lld", location, rbindex); + if (i != AVB_MAX_NUMBER_OF_ROLLBACK_INDEX_LOCATIONS + 1) + strncat(buffer, ",", strlen(",")); + + if ((chars_left - (int)strlen(buffer)) >= 0) { + strncat(response, buffer, strlen(buffer)); + chars_left -= strlen(buffer); + } else { + strncat(response, buffer, chars_left); + /* reponse buffer is full, send it first */ + fastboot_tx_write_more(response); + /* reset the reponse buffer for next round */ + memset(response, '\0', sizeof(response)); + strncpy(response, "INFO", 5); + /* Copy left strings from 'buffer' to 'response' */ + strncat(response, buffer + chars_left, strlen(buffer)); + chars_left = FASTBOOT_RESPONSE_LEN - + strlen(response) - 1; + } + } + + } #endif else { char envstr[32]; @@ -3108,10 +3258,10 @@ static void cb_getvar(struct usb_ep *ep, struct usb_request *req) int status = 0; int count = 0; char *cmd = req->buf; - char var_name[FASTBOOT_RESPONSE_LEN - 1]; + char var_name[FASTBOOT_RESPONSE_LEN]; char partition_base_name[MAX_PTN][16]; char slot_suffix[2][5] = {"a","b"}; - char response[FASTBOOT_RESPONSE_LEN - 1]; + char response[FASTBOOT_RESPONSE_LEN]; strsep(&cmd, ":"); if (!cmd) { @@ -3122,7 +3272,7 @@ static void cb_getvar(struct usb_ep *ep, struct usb_request *req) if (!strcmp_l1("all", cmd)) { - memset(response, '\0', FASTBOOT_RESPONSE_LEN - 1); + memset(response, '\0', FASTBOOT_RESPONSE_LEN); /* get common variables */ @@ -3132,6 +3282,14 @@ static void cb_getvar(struct usb_ep *ep, struct usb_request *req) fastboot_tx_write_more(response); } + /* get at-vboot-state variables */ +#ifdef CONFIG_AVB_ATX + for (n = 0; n < AT_VBOOT_STATE_VAR_NUM; n++) { + snprintf(response, sizeof(response), "INFO%s:", fastboot_at_vboot_state_var[n]); + get_single_var(fastboot_at_vboot_state_var[n], response); + fastboot_tx_write_more(response); + } +#endif /* get partition type */ for (n = 0; n < g_pcount; n++) { snprintf(response, sizeof(response), "INFOpartition-type:%s:", g_ptable[n].name); @@ -3191,7 +3349,35 @@ static void cb_getvar(struct usb_ep *ep, struct usb_request *req) fastboot_tx_write_more(response); return; - } else { + } +#ifdef CONFIG_AVB_ATX + else if (!strcmp_l1("at-vboot-state", cmd)) { + /* get at-vboot-state variables */ + for (n = 0; n < AT_VBOOT_STATE_VAR_NUM; n++) { + snprintf(response, sizeof(response), "INFO%s:", fastboot_at_vboot_state_var[n]); + get_single_var(fastboot_at_vboot_state_var[n], response); + fastboot_tx_write_more(response); + } + + strncpy(response, "OKAY", 5); + fastboot_tx_write_more(response); + + return; + } else if ((!strcmp_l1("bootloader-locked", cmd)) || + (!strcmp_l1("bootloader-min-versions", cmd)) || + (!strcmp_l1("avb-perm-attr-set", cmd)) || + (!strcmp_l1("avb-locked", cmd)) || + (!strcmp_l1("avb-unlock-disabled", cmd)) || + (!strcmp_l1("avb-min-versions", cmd))) { + + printf("Can't get this variable alone, get 'at-vboot-state' instead!\n"); + snprintf(response, sizeof(response), + "FAILCan't get this variable alone, get 'at-vboot-state' instead."); + fastboot_tx_write_str(response); + return; + } +#endif + else { strncpy(response, "OKAY", 5); status = get_single_var(cmd, response); diff --git a/include/configs/imx8mq_evk_androidthings.h b/include/configs/imx8mq_evk_androidthings.h index de00f44c2e9..f0884d96840 100644 --- a/include/configs/imx8mq_evk_androidthings.h +++ b/include/configs/imx8mq_evk_androidthings.h @@ -32,6 +32,13 @@ #define CONFIG_ANDROID_RECOVERY +/* Use below address to store the bootloader rbindex, + * it's 4k offset to CONFIG_SYS_SPL_PTE_RAM_BASE + * */ +#if defined(CONFIG_AVB_ATX) && defined(CONFIG_DUAL_BOOTLOADER) +#define BL_RBINDEX_LOAD_ADDR 0x4157F000 +#endif + #define CONFIG_CMD_BOOTA #define CONFIG_SUPPORT_RAW_INITRD #define CONFIG_SERIAL_TAG diff --git a/lib/avb/fsl/fsl_avb_ab_flow.c b/lib/avb/fsl/fsl_avb_ab_flow.c index 8a67de79ebd..eeb908fb8de 100644 --- a/lib/avb/fsl/fsl_avb_ab_flow.c +++ b/lib/avb/fsl/fsl_avb_ab_flow.c @@ -208,6 +208,9 @@ static int spl_verify_rbidx(struct mmc *mmc, AvbABSlotData *slot, kblb_hdr_t hdr; kblb_tag_t *rbk; uint64_t extract_idx; +#ifdef CONFIG_AVB_ATX + struct bl_rbindex_package *bl_rbindex; +#endif /* Make sure rollback index has been initialized before verify */ if (rpmb_init()) { @@ -241,6 +244,16 @@ static int spl_verify_rbidx(struct mmc *mmc, AvbABSlotData *slot, return -1; } +#ifdef CONFIG_AVB_ATX + /* Pass bootloader rbindex to u-boot here. */ + bl_rbindex = (struct bl_rbindex_package *)BL_RBINDEX_LOAD_ADDR; + memcpy(bl_rbindex->magic, BL_RBINDEX_MAGIC, BL_RBINDEX_MAGIC_LEN); + if (slot->successful_boot != 0) + bl_rbindex->rbindex = spl_image->rbindex; + else + bl_rbindex->rbindex = extract_idx; +#endif + return 0; } else { printf("Rollback index verify rejected!\n"); diff --git a/lib/avb/fsl/fsl_avbkey.h b/lib/avb/fsl/fsl_avbkey.h index 73b0c527183..863d8b1dbf0 100644 --- a/lib/avb/fsl/fsl_avbkey.h +++ b/lib/avb/fsl/fsl_avbkey.h @@ -31,6 +31,15 @@ #define AVB_KBLB_MAGIC "\0KBLB!" #define AVB_KBLB_MAGIC_LEN 6 +#if defined(CONFIG_AVB_ATX) && defined(CONFIG_DUAL_BOOTLOADER) +#define BL_RBINDEX_MAGIC "BL_RBINDEX" +#define BL_RBINDEX_MAGIC_LEN 11 +struct bl_rbindex_package { + char magic[BL_RBINDEX_MAGIC_LEN]; + uint32_t rbindex; +}; +#endif + #ifdef CONFIG_ANDROID_AUTO_SUPPORT #define RPMB_KEY_MAGIC "RPMB" #endif -- cgit v1.2.3