[sherlock] 9.20221010.3.176 u-boot source GitOrigin-RevId: a6d3993ddd37fe5c304ac8201a8d9ebc4c6ce96d Change-Id: Ia900dabbc2a7edca14776d46bf9550e58b7a037e Reviewed-on: https://turquoise-internal-review.googlesource.com/c/third_party/u-boot/+/655994 Reviewed-by: David Pursell <dpursell@google.com>
diff --git a/arb_version.txt b/arb_version.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/arb_version.txt
@@ -0,0 +1 @@ +1
diff --git a/arch/arm/lib/bootm.c b/arch/arm/lib/bootm.c index 92b4267..30e5cdb 100644 --- a/arch/arm/lib/bootm.c +++ b/arch/arm/lib/bootm.c
@@ -85,12 +85,12 @@ } #ifndef CONFIG_TA_VX -static inline void vx_finalize(void) {} +static inline void vx_finalize_or_panic(void) {} #else -static void vx_finalize(void) +static void vx_finalize_or_panic(void) { printf("VX: finalizing policies and configurations...\n"); - ta_vx_exit_bootloader(); // Panics on error. + ta_vx_exit_bootloader_or_panic(); // Panics on error. } #endif /* CONFIG_TA_VX */ @@ -116,7 +116,7 @@ #endif /* Finalize Verified Execution policies and configurations. */ - vx_finalize(); + vx_finalize_or_panic(); board_quiesce_devices();
diff --git a/board/amlogic/g12b_newman_bx/zircon_partition_map.c b/board/amlogic/g12b_newman_bx/zircon_partition_map.c index 65a449a..5a2f164 100644 --- a/board/amlogic/g12b_newman_bx/zircon_partition_map.c +++ b/board/amlogic/g12b_newman_bx/zircon_partition_map.c
@@ -5,6 +5,7 @@ */ #include <common.h> +#include <emmc_partitions.h> #include <mmc.h> #include <zircon_uboot/partition_internal.h> @@ -193,7 +194,14 @@ .name = "fvm", .fastboot_locked_access = ZIRCON_PARTITION_ACCESS_FLAG_WRITE, .gpt_name = "fuchsia-fvm", - } + }, + { + .name = MMC_SECURE_STORAGE_NAME, + .fastboot_locked_access = ZIRCON_PARTITION_ACCESS_DEV_ONLY, + .gpt_name = "reserved", + .gpt_offset = MMC_SECURE_STORAGE_OFFSET, + .size = MMC_SECURE_STORAGE_SIZE, + }, }; const size_t zircon_partition_map_count = ARRAY_SIZE(zircon_partition_map);
diff --git a/common/Kconfig b/common/Kconfig index 4f90eae..f07b201 100644 --- a/common/Kconfig +++ b/common/Kconfig
@@ -641,14 +641,6 @@ bool "Support Verified Execution Trusted App" default n -config TA_VX_AUTO_PROVISION_RPMB - bool "Automatically provision RPMB in the VX TA" - help - Configure the VX TA such that it will automatically provision the - RPMB if the RPMB authentication key is not already programmed. - depends on TA_VX - default n - config TA_VX_TESTS bool "Enable `fastboot oem vx-test` and `vx test` commands." help
diff --git a/common/ta_vx_helper.c b/common/ta_vx_helper.c index b6d0412..2406b3e 100644 --- a/common/ta_vx_helper.c +++ b/common/ta_vx_helper.c
@@ -9,47 +9,13 @@ #include <tee/ta_helper.h> #include <tee/ta_vx.h> #include <tee/ta_vx_helper.h> +#include <zircon_uboot/boot_args.h> #ifdef CONFIG_TA_VX #define VX_PERM_ATTR_HASH_SIZE 32 static struct tee_optee_ta_uuid vx_uuid = TA_VX_UUID; -static int ta_vx_setup(void) -{ - uint32_t options = 0; - static bool setup_done = false; - static int setup_result = 0; - - if (setup_done) { - return setup_result; - } - -#ifdef CONFIG_TA_VX_AUTO_PROVISION_RPMB - options |= VX_OPTION_AUTO_PROVISION_RPMB; -#endif - - if (options) { - struct tee_param params[1] = { 0 }; - params[0].attr = TEE_PARAM_ATTR_TYPE_VALUE_INPUT; - params[0].u.value.a = options; - setup_result = ta_call(&vx_uuid, TA_VX_CMD_SET_OPTIONS, - ARRAY_SIZE(params), params); - } - - setup_done = true; - return setup_result; -} - -#define SETUP_OR_FAIL() \ - do { \ - int rc = ta_vx_setup(); \ - if (rc) { \ - printf("ta_vx_setup() failed, rc = %d.", rc); \ - return rc; \ - } \ - } while (0) - static int ta_vx_read_lock_state(enum vx_lock_state *lock_state) { int rc; @@ -57,8 +23,6 @@ struct tee_param param = { 0 }; param.attr = TEE_PARAM_ATTR_TYPE_VALUE_OUTPUT; - SETUP_OR_FAIL(); - rc = ta_call(&vx_uuid, TA_VX_CMD_READ_LOCK_STATE, 1, ¶m); if (!rc) { *lock_state = param.u.value.a; @@ -73,16 +37,55 @@ param.attr = TEE_PARAM_ATTR_TYPE_VALUE_INPUT; param.u.value.a = lock_state; - SETUP_OR_FAIL(); - return ta_call(&vx_uuid, TA_VX_CMD_WRITE_LOCK_STATE, 1, ¶m); } int ta_vx_lock(void) { + int rc = zircon_clear_stored_cmdline(); + if (rc) { + printf("Failed to clear stored boot args\n"); + return rc; + } + return ta_vx_write_lock_state(VX_LOCKED); } +int ta_vx_lock_if_ephemerally_unlocked(void) +{ + int rc; + uint32_t vars; + + rc = ta_vx_getvar_all(&vars); + if (rc) { + return rc; + } + + if (!(vars & VX_VAR_EPHEMERALLY_UNLOCKED)) { + return 0; + } + + printf("Locking up an ephemerally unlocked device\n"); + rc = ta_vx_lock(); + if (!rc) { + printf("ta_vx_lock() failed\n"); + return rc; + } + + rc = ta_vx_getvar_all(&vars); + if (rc) { + return rc; + } + + if (vars & VX_VAR_EPHEMERALLY_UNLOCKED) { + printf("SHOCKED: device is still ephemerally unlocked after " + "successful locking\n"); + return -EINVAL; + } + + return 0; +} + int ta_vx_unlock(void) { return ta_vx_write_lock_state(VX_UNLOCKED); @@ -103,8 +106,6 @@ int rc; struct tee_param params[2] = { 0 }; - SETUP_OR_FAIL(); - params[0].attr = TEE_PARAM_ATTR_TYPE_VALUE_INPUT; params[0].u.value.a = slot; @@ -124,8 +125,6 @@ { struct tee_param params[2] = { 0 }; - SETUP_OR_FAIL(); - params[0].attr = TEE_PARAM_ATTR_TYPE_VALUE_INPUT; params[0].u.value.a = slot; @@ -149,8 +148,6 @@ size_t key_len = strlen(name) + 1; - SETUP_OR_FAIL(); - /* Connect to TA. */ rc = ta_open(&vx_uuid, &context); if (rc) @@ -206,8 +203,6 @@ size_t key_len = strlen(name) + 1; - SETUP_OR_FAIL(); - /* Connect to TA. */ rc = ta_open(&vx_uuid, &context); if (rc) @@ -254,8 +249,6 @@ struct tee_shm *shm_key = NULL; size_t key_len = strlen(name) + 1; - SETUP_OR_FAIL(); - /* Connect to TA. */ rc = ta_open(&vx_uuid, &context); if (rc) @@ -287,8 +280,6 @@ struct tee_param params[1] = { 0 }; struct tee_shm *shm_buf = NULL; - SETUP_OR_FAIL(); - if (!(buf && buf_len)) return -EINVAL; @@ -318,26 +309,16 @@ return rc; } -void ta_vx_exit_bootloader(void) +void ta_vx_exit_bootloader_or_panic(void) { - /* Exiting bootloader should panic on failure so call ta_vx_setup() - directly rather than using SETUP_OR_FAIL. */ - int rc = ta_vx_setup(); - if (rc) { - printf("ta_vx_setup() failed, rc = %d.", rc); - panic("VX setup failed!"); - } + uint32_t vars; if (ta_call(&vx_uuid, TA_VX_CMD_EXIT_BOOTLOADER, 0, NULL)) { panic("VX finalization failed!"); } /* Make sure we are indeed beyond the bootloader security domain. */ - struct tee_param params[1] = { 0 }; - params[0].attr = TEE_PARAM_ATTR_TYPE_VALUE_INPUT; - params[0].u.value.a = VX_OPTION_FOR_TESTING; - if (!ta_call(&vx_uuid, TA_VX_CMD_SET_OPTIONS, ARRAY_SIZE(params), - params)) { + if (ta_vx_getvar_all(&vars) || !(vars & VX_VAR_OUT_OF_BOOTLOADER)) { panic("VX finalization verification failed."); } @@ -352,8 +333,6 @@ struct tee_shm *shm_buf = NULL; - SETUP_OR_FAIL(); - if (!(buf && buf_len)) { return -EINVAL; } @@ -400,8 +379,6 @@ struct tee_shm *shm_buf = NULL; - SETUP_OR_FAIL(); - if (!(buf && buf_len)) return -EINVAL; @@ -438,8 +415,6 @@ int rc; struct tee_param params[1] = { 0 }; - SETUP_OR_FAIL(); - params[0].attr = TEE_PARAM_ATTR_TYPE_VALUE_OUTPUT; rc = ta_call(&vx_uuid, TA_VX_CMD_GET_RPMB_STATUS, ARRAY_SIZE(params), params); @@ -459,15 +434,26 @@ int ta_vx_provision_rpmb(void) { - SETUP_OR_FAIL(); - return ta_call(&vx_uuid, TA_VX_CMD_PROVISION_RPMB, 0, NULL); } +int ta_vx_reroute_rpmb_till_reboot(void) +{ + return ta_call(&vx_uuid, TA_VX_CMD_REROUTE_RPMB_TILL_REBOOT, 0, NULL); +} + +int ta_vx_reroute_rpmb_to_software(void) +{ + return ta_call(&vx_uuid, TA_VX_CMD_REROUTE_RPMB_TO_SOFTWARE, 0, NULL); +} + +int ta_vx_reroute_rpmb_to_hardware(void) +{ + return ta_call(&vx_uuid, TA_VX_CMD_REROUTE_RPMB_TO_HARDWARE, 0, NULL); +} + int ta_vx_delete_perm_attr(void) { - SETUP_OR_FAIL(); - return ta_call(&vx_uuid, TA_VX_CMD_DELETE_PERM_ATTR, 0, NULL); } @@ -479,8 +465,6 @@ struct tee_shm *shm_buf = NULL; - SETUP_OR_FAIL(); - if (!buf || (buf_len < VX_PERM_ATTR_HASH_SIZE)) return -EINVAL; @@ -523,8 +507,6 @@ struct tee_param param = { 0 }; param.attr = TEE_PARAM_ATTR_TYPE_VALUE_OUTPUT; - SETUP_OR_FAIL(); - rc = ta_call(&vx_uuid, TA_VX_CMD_GET_PERM_ATTR_STATUS, 1, ¶m); if (!rc) { if (status) { @@ -537,15 +519,11 @@ int ta_vx_lock_perm_attr(void) { - SETUP_OR_FAIL(); - return ta_call(&vx_uuid, TA_VX_CMD_LOCK_PERM_ATTR, 0, NULL); } int ta_vx_provision_usb_hash(void) { - SETUP_OR_FAIL(); - return ta_call(&vx_uuid, TA_VX_CMD_PROVISION_USBBOOT_PWD_HASH, 0, NULL); } @@ -556,8 +534,6 @@ struct tee_param param = { 0 }; param.attr = TEE_PARAM_ATTR_TYPE_VALUE_OUTPUT; - SETUP_OR_FAIL(); - rc = ta_call(&vx_uuid, TA_VX_CMD_GET_USBBOOT_STATUS, 1, ¶m); if (!rc) { if (status) { @@ -568,6 +544,26 @@ return rc; } +int ta_vx_getvar_all(uint32_t *out_vars) +{ + int rc; + struct tee_param params[1] = { 0 }; + + if (!out_vars) { + return -EINVAL; + } + + params[0].attr = TEE_PARAM_ATTR_TYPE_VALUE_OUTPUT; + rc = ta_call(&vx_uuid, TA_VX_CMD_GETVAR_ALL, ARRAY_SIZE(params), + params); + if (rc) { + return rc; + } + + *out_vars = params[0].u.value.a; + return 0; +} + #ifdef CONFIG_TA_VX_TESTS int ta_vx_run_tests(const char *name) { @@ -577,8 +573,6 @@ size_t name_len = strlen(name) + 1; struct tee_shm *shm_buf = NULL; - SETUP_OR_FAIL(); - rc = ta_open(&vx_uuid, &context); if (rc) return rc; @@ -616,6 +610,11 @@ return ta_vx_fail(__func__); } +int ta_vx_lock_if_ephemerally_unlocked() +{ + return ta_vx_fail(__func__); +} + int ta_vx_unlock() { return ta_vx_fail(__func__); @@ -658,7 +657,7 @@ return ta_vx_fail(__func__); } -void ta_vx_exit_bootloader() +void ta_vx_exit_bootloader_or_panic() { /* Unlike other VX stubs, this one succeeds by default as a no-op if the VX TA is disabled. */ @@ -704,6 +703,21 @@ return ta_vx_fail(__func__); } +int ta_vx_reroute_rpmb_till_reboot(void) +{ + return ta_vx_fail(__func__); +} + +int ta_vx_reroute_rpmb_to_software(void) +{ + return ta_vx_fail(__func__); +} + +int ta_vx_reroute_rpmb_to_hardware(void) +{ + return ta_vx_fail(__func__); +} + int ta_vx_provision_usb_hash(void) { return ta_vx_fail(__func__); @@ -714,4 +728,9 @@ return ta_vx_fail(__func__); } +int ta_vx_getvar_all(uint32_t *out_vars) +{ + return ta_vx_fail(__func__); +} + #endif // CONFIG_TA_VX
diff --git a/common/zircon_partition.c b/common/zircon_partition.c index 9960d0b..20a61cc 100644 --- a/common/zircon_partition.c +++ b/common/zircon_partition.c
@@ -20,7 +20,7 @@ /* Temporary buffer when we need to cache data locally. Only valid for use within a single call, do not expect the contents to be consistent across multiple calls since other functions may have modified it. */ -static uint8_t temp_buffer[ERASE_GROUP_SIZE] = { 0 }; +static uint8_t temp_buffer[ERASE_GROUP_SIZE] __aligned(ARCH_DMA_MINALIGN); static int store_call_setup(const zircon_partition *part, uint64_t offset, size_t length) @@ -107,6 +107,49 @@ return -1; } + // store_write() offset must be at a block boundary. If our |offset| is + // not, read the first partial block, modify and write back manually. + // Compute the unaligned write offset within the first block. + size_t first_block_write_offset = + offset % part->data->mmc->write_bl_len; + if (first_block_write_offset) { + static uint8_t scratch_buffer[512] __aligned(ARCH_DMA_MINALIGN); + assert(sizeof(scratch_buffer) == part->data->mmc->write_bl_len); + // The aligned offset of the first block. + size_t first_block_offset = offset - first_block_write_offset; + + // Read the block + int res = gpt_part_read(part, first_block_offset, + scratch_buffer, sizeof(scratch_buffer)); + if (res) { + return res; + } + + // The amount of data to write for the first block. It's the smaller + // of the total length and the remaining part in the block. + size_t first_block_write_length = + min(length, + sizeof(scratch_buffer) - first_block_write_offset); + + // Modify + memcpy(scratch_buffer + first_block_write_offset, buffer, + first_block_write_length); + + // Write back the modified data. + res = gpt_part_write(part, first_block_offset, scratch_buffer, + sizeof(scratch_buffer)); + if (res) { + return res; + } + + offset += first_block_write_length; + length -= first_block_write_length; + buffer = (const uint8_t *)(buffer) + first_block_write_length; + if (length == 0) { + return 0; + } + } + return store_write(part->data->gpt_name, part->data->gpt_offset + offset, length, buffer); } @@ -860,6 +903,16 @@ return NULL; } + // If we are not in dev build, check if access is dev only. +#if !defined(DEV_BUILD_CONFIG) + if (part->data->fastboot_locked_access & + ZIRCON_PARTITION_ACCESS_DEV_ONLY) { + part->write = NULL; + part->erase = NULL; + return part; + } +#endif + if (unlocked) { return part; }
diff --git a/common/zircon_vboot.c b/common/zircon_vboot.c index 1635e4c..9248ed5 100644 --- a/common/zircon_vboot.c +++ b/common/zircon_vboot.c
@@ -376,6 +376,11 @@ NULL }; + int ret = ta_vx_lock_if_ephemerally_unlocked(); + if (ret) { + return ret; + } + AvbSlotVerifyData *verify_data = NULL; AvbSlotVerifyResult result = @@ -383,7 +388,7 @@ AVB_SLOT_VERIFY_FLAGS_NONE, AVB_HASHTREE_ERROR_MODE_EIO, &verify_data); - int ret = process_verify_data(&ops, result, verify_data, &context, zbi, + ret = process_verify_data(&ops, result, verify_data, &context, zbi, capacity, has_successfully_booted); if (verify_data) { avb_slot_verify_data_free(verify_data); @@ -521,6 +526,11 @@ ramboot_ops.user_data = (void *)&context; + int ret = ta_vx_lock_if_ephemerally_unlocked(); + if (ret) { + return ret; + } + AvbSlotVerifyData *verify_data = NULL; AvbSlotVerifyResult result = @@ -528,7 +538,7 @@ AVB_SLOT_VERIFY_FLAGS_NONE, AVB_HASHTREE_ERROR_MODE_EIO, &verify_data); - int ret = process_verify_data(&ramboot_ops, result, verify_data, NULL, + ret = process_verify_data(&ramboot_ops, result, verify_data, NULL, zbi, capacity, false); if (verify_data) { avb_slot_verify_data_free(verify_data);
diff --git a/configs/g12b_newman_bx_zircon_defconfig b/configs/g12b_newman_bx_zircon_defconfig index d76e341..5df275e 100644 --- a/configs/g12b_newman_bx_zircon_defconfig +++ b/configs/g12b_newman_bx_zircon_defconfig
@@ -12,7 +12,6 @@ CONFIG_TEE=y CONFIG_OPTEE=y CONFIG_TA_VX=y -CONFIG_TA_VX_AUTO_PROVISION_RPMB=y CONFIG_SUPPORT_EMMC_RPMB=y CONFIG_CMD_TEE=y CONFIG_DM_GPIO=y @@ -225,3 +224,4 @@ CONFIG_LZ4=y CONFIG_NET=n CONFIG_AML_GPT_SYNC_ENTIRE_ENTRY=y +CONFIG_OPTEE_RAW_PARTITION_IO=y
diff --git a/drivers/mmc/aml_emmc_partition.c b/drivers/mmc/aml_emmc_partition.c index 0aa40c3..0e19001 100644 --- a/drivers/mmc/aml_emmc_partition.c +++ b/drivers/mmc/aml_emmc_partition.c
@@ -119,25 +119,36 @@ }; struct virtual_partition virtual_partition_table[] = { - /* partition for name idx, off & size will not be used! */ +/* partition for name idx, off & size will not be used! */ #if (CONFIG_PTBL_MBR) - VIRTUAL_PARTITION_ELEMENT(MMC_MBR_NAME, MMC_MBR_OFFSET, MMC_MBR_SIZE), + VIRTUAL_PARTITION_ELEMENT(MMC_MBR_NAME, MMC_MBR_OFFSET, MMC_MBR_SIZE), #endif - VIRTUAL_PARTITION_ELEMENT(MMC_BOOT_NAME0, 0, 0), - VIRTUAL_PARTITION_ELEMENT(MMC_BOOT_NAME1, 0, 0), + VIRTUAL_PARTITION_ELEMENT(MMC_BOOT_NAME0, 0, 0), + VIRTUAL_PARTITION_ELEMENT(MMC_BOOT_NAME1, 0, 0), /* virtual partition in reserved partition, take care off and size */ #ifdef CONFIG_AML_PARTITION - VIRTUAL_PARTITION_ELEMENT(MMC_TABLE_NAME, MMC_TABLE_OFFSET, MMC_TABLE_SIZE), + VIRTUAL_PARTITION_ELEMENT(MMC_TABLE_NAME, MMC_TABLE_OFFSET, + MMC_TABLE_SIZE), #endif - VIRTUAL_PARTITION_ELEMENT(MMC_KEY_NAME, EMMCKEY_RESERVE_OFFSET, MMC_KEY_SIZE), - VIRTUAL_PARTITION_ELEMENT(MMC_PATTERN_NAME, CALI_PATTERN_OFFSET, CALI_PATTERN_SIZE), + VIRTUAL_PARTITION_ELEMENT(MMC_KEY_NAME, EMMCKEY_RESERVE_OFFSET, + MMC_KEY_SIZE), + VIRTUAL_PARTITION_ELEMENT(MMC_PATTERN_NAME, CALI_PATTERN_OFFSET, + CALI_PATTERN_SIZE), #ifndef DTB_BIND_KERNEL VIRTUAL_PARTITION_ELEMENT(MMC_DTB_NAME, DTB_OFFSET, DTB_SIZE), #endif VIRTUAL_PARTITION_ELEMENT(MMC_FASTBOOT_CONTEXT_NAME, - FASTBOOT_CONTEXT_OFFSET, FASTBOOT_CONTEXT_SIZE), - VIRTUAL_PARTITION_ELEMENT(MMC_DDR_PARAMETER_NAME,DDR_PARAMETER_OFFSET, DDR_PARAMETER_SIZE), + FASTBOOT_CONTEXT_OFFSET, + FASTBOOT_CONTEXT_SIZE), + VIRTUAL_PARTITION_ELEMENT(MMC_DDR_PARAMETER_NAME, DDR_PARAMETER_OFFSET, + DDR_PARAMETER_SIZE), + // Partition for storing secure storage data. + // Rerserve the entry here so that merging of any upstream code change + // on the table will be made aware of this local change. + VIRTUAL_PARTITION_ELEMENT(MMC_SECURE_STORAGE_NAME, + MMC_SECURE_STORAGE_OFFSET, + MMC_SECURE_STORAGE_SIZE), }; int get_emmc_partition_arraysize(void)
diff --git a/drivers/mmc/mmc_write.c b/drivers/mmc/mmc_write.c index c53a624..82ade52 100644 --- a/drivers/mmc/mmc_write.c +++ b/drivers/mmc/mmc_write.c
@@ -134,8 +134,20 @@ return 0; } -static ulong mmc_write_blocks(struct mmc *mmc, lbaint_t start, - lbaint_t blkcnt, const void *src) +static int mmc_set_blockcount(struct mmc *mmc, unsigned int blockcount) +{ + struct mmc_cmd cmd = { 0 }; + + cmd.cmdidx = MMC_CMD_SET_BLOCK_COUNT; + cmd.cmdarg = min(blockcount, (unsigned int)MMC_BLOCK_COUNT_MAX); + cmd.cmdarg |= MMC_RELIABLE_WRITE_ARG; + cmd.resp_type = MMC_RSP_R1; + + return mmc_send_cmd(mmc, &cmd, NULL); +} + +static ulong mmc_write_blocks(struct mmc *mmc, lbaint_t start, lbaint_t blkcnt, + const void *src) { struct mmc_cmd cmd; struct mmc_data data; @@ -146,13 +158,20 @@ return 0; } + if (mmc->ext_csd[EXT_CSD_DATA_SECTOR_SIZE] != + EXT_CSD_DATA_SECTOR_SIZE_512) { + printf("MMC: mmc is not operating in 512 bytes sector size.\n"); + return 0; + } + if (blkcnt == 0) return 0; - else if (blkcnt == 1) - cmd.cmdidx = MMC_CMD_WRITE_SINGLE_BLOCK; - else - cmd.cmdidx = MMC_CMD_WRITE_MULTIPLE_BLOCK; + // Set block count and activate reliable write. + if (mmc_set_blockcount(mmc, blkcnt)) + return 0; + + cmd.cmdidx = MMC_CMD_WRITE_MULTIPLE_BLOCK; if (mmc->high_capacity) cmd.cmdarg = start; else @@ -170,18 +189,7 @@ return 0; } - /* SPI multiblock writes terminate using a special - * token, not a STOP_TRANSMISSION request. - */ - if (!mmc_host_is_spi(mmc) && blkcnt > 1) { - cmd.cmdidx = MMC_CMD_STOP_TRANSMISSION; - cmd.cmdarg = 0; - cmd.resp_type = MMC_RSP_R1b; - if (mmc_send_cmd(mmc, &cmd, NULL)) { - printf("mmc fail to send stop cmd\n"); - return 0; - } - } + // Pre-defined block count. No need for stop command. /* Waiting for the ready status */ if (mmc_send_status(mmc, timeout)) @@ -220,9 +228,10 @@ return 0; do { - cur = (blocks_todo > mmc->cfg->b_max) ? - mmc->cfg->b_max : blocks_todo; - + cur = min(blocks_todo, (lbaint_t)mmc->cfg->b_max); + // Reliable write requires to set block count, which is only 2 bytes. + // Thus limit the write size to no more than 0xffff blocks. + cur = min((lbaint_t)MMC_BLOCK_COUNT_MAX, cur); if (mmc_write_blocks(mmc, start, cur, src) != cur) return 0;
diff --git a/drivers/tee/optee/Kconfig b/drivers/tee/optee/Kconfig index d489834..e7ca2ec 100644 --- a/drivers/tee/optee/Kconfig +++ b/drivers/tee/optee/Kconfig
@@ -22,6 +22,13 @@ The TA can support the "avb" subcommands "read_rb", "write"rb" and "is_unlocked". +config OPTEE_RAW_PARTITION_IO + bool "Enable secure storage backed by a raw partition" + help + Enables supplicant support for routing raw IO requests to a designated + partition. + default n + endmenu endif
diff --git a/drivers/tee/optee/Makefile b/drivers/tee/optee/Makefile index 928d3f8..fb4b79e 100644 --- a/drivers/tee/optee/Makefile +++ b/drivers/tee/optee/Makefile
@@ -3,3 +3,4 @@ obj-y += core.o obj-y += supplicant.o obj-$(CONFIG_SUPPORT_EMMC_RPMB) += rpmb.o +obj-$(CONFIG_OPTEE_RAW_PARTITION_IO) += raw_io.o
diff --git a/drivers/tee/optee/optee_msg_supplicant.h b/drivers/tee/optee/optee_msg_supplicant.h index a0fb806..9891c2b 100644 --- a/drivers/tee/optee/optee_msg_supplicant.h +++ b/drivers/tee/optee/optee_msg_supplicant.h
@@ -237,4 +237,37 @@ * End of definitions for messages with .cmd == OPTEE_MSG_RPC_CMD_SOCKET */ +/* + * Raw partition IO + * + * Starting with 0x100 to avoid conflicts with the upstream: + * https://github.com/OP-TEE/optee_client/blob/master/tee-supplicant/src/optee_msg_supplicant.h + */ +#define OPTEE_MSG_RPC_CMD_RAW 0x100 + + +/* + * Definitions for messages with .cmd == OPTEE_MSG_RPC_CMD_RAW + */ + +/* + * Read bytes from a RAW partition + * + * [in] param[0].u.value.a OPTEE_MRC_RAW_READ + * [in] param[0].u.value.b offset into the partition + * [in] param[0].u.value.c length in bytes + * [in] param[1].u.tmem buffer to receive the bytes + */ +#define OPTEE_MRC_RAW_READ 0 + +/* + * Write bytes to a RAW partition + * + * [in] param[0].u.value.a OPTEE_MRC_RAW_WRITE + * [in] param[0].u.value.b offset into the partition + * [in] param[0].u.value.c length in bytes + * [in] param[1].u.tmem buffer containing the bytes + */ +#define OPTEE_MRC_RAW_WRITE 1 + #endif /* __OPTEE_MSG_SUPPLICANT_H */
diff --git a/drivers/tee/optee/optee_private.h b/drivers/tee/optee/optee_private.h index 1db953a..ba9e04a 100644 --- a/drivers/tee/optee/optee_private.h +++ b/drivers/tee/optee/optee_private.h
@@ -62,4 +62,21 @@ } #endif +#ifdef CONFIG_OPTEE_RAW_PARTITION_IO + +/** + * optee_suppl_cmd_raw_io() - basic IO to a designated raw partition + * @arg: OP-TEE message holding the request details. + */ +void optee_suppl_cmd_raw_io(struct optee_msg_arg *arg); + +#else + +static inline void optee_suppl_cmd_raw_io(struct optee_msg_arg *arg) +{ + arg->ret = TEE_ERROR_NOT_IMPLEMENTED; +} + +#endif /* CONFIG_OPTEE_RAW_PARTITION_IO */ + #endif /* __OPTEE_PRIVATE_H */
diff --git a/drivers/tee/optee/raw_io.c b/drivers/tee/optee/raw_io.c new file mode 100644 index 0000000..dfb8baa --- /dev/null +++ b/drivers/tee/optee/raw_io.c
@@ -0,0 +1,163 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2022 Google + */ + +#include <common.h> +#include <emmc_partitions.h> +#include <tee.h> +#include <tee/optee.h> +#include <zircon_uboot/partition.h> + +#include "optee_msg.h" +#include "optee_msg_supplicant.h" +#include "optee_private.h" + +/* + * Read `length` bytes from `offset` of a designated raw partition into + * `buffer`. Buffer size is guaranteed to be >= `length`. + */ +static u32 do_read(u64 offset, u64 length, void *buffer) +{ + zircon_partition *part = zircon_get_partition(MMC_SECURE_STORAGE_NAME); + if (!part) { + return TEE_ERROR_ITEM_NOT_FOUND; + } + + if (!part->read) { + printf("Optee raw IO: no read implementation\n"); + zircon_free_partition(part); + return TEE_ERROR_NOT_SUPPORTED; + } + + // Boundary check will be performed in read(). The API supports unaligned + // read. + int res = part->read(part, offset, buffer, length); + if (res) { + printf("Optee raw IO: read failed. %d\n", res); + zircon_free_partition(part); + return TEE_ERROR_GENERIC; + } + + zircon_free_partition(part); + return TEE_SUCCESS; +} + +/* + * Write `length` bytes from `buffer` into a designated raw partition at + * `offset`. Buffer size is guaranteed to be >= `length`. + */ +static u32 do_write(u64 offset, u64 length, const void *buffer) +{ + zircon_partition *part = zircon_get_partition(MMC_SECURE_STORAGE_NAME); + if (!part) { + return TEE_ERROR_ITEM_NOT_FOUND; + } + + if (!part->write) { + printf("Optee raw IO: no write implementation\n"); + zircon_free_partition(part); + return TEE_ERROR_NOT_SUPPORTED; + } + + // Boundary check will be performed in write(). The API supports unaligned + // write. + int res = part->write(part, offset, buffer, length); + if (res) { + printf("Optee raw IO: write failed. %d\n", res); + zircon_free_partition(part); + return TEE_ERROR_GENERIC; + } + + zircon_free_partition(part); + return TEE_SUCCESS; +} + +void optee_suppl_cmd_raw_io(struct optee_msg_arg *arg) +{ + u64 offset; + u64 length; + void *buffer; + u64 buffer_size; + + /* The supplicant is part of the REE<>TEE communications stack. */ + arg->ret_origin = TEE_ORIGIN_COMMS; + + if (!(arg->num_params == 2 && + arg->params[0].attr == OPTEE_MSG_ATTR_TYPE_VALUE_INPUT)) { + arg->ret = TEE_ERROR_BAD_PARAMETERS; + return; + } + + offset = arg->params[0].u.value.b; + length = arg->params[0].u.value.c; + buffer = (u8 *)arg->params[1].u.tmem.buf_ptr; + buffer_size = arg->params[1].u.tmem.size; + if (!(buffer && buffer_size > 0 && buffer_size >= length)) { + arg->ret = TEE_ERROR_BAD_PARAMETERS; + return; + } + + switch (arg->params[0].u.value.a) { + case OPTEE_MRC_RAW_READ: + if (arg->params[1].attr != OPTEE_MSG_ATTR_TYPE_TMEM_OUTPUT) { + arg->ret = TEE_ERROR_BAD_PARAMETERS; + return; + } + + arg->ret = do_read(offset, length, buffer); + break; + case OPTEE_MRC_RAW_WRITE: + if (arg->params[1].attr != OPTEE_MSG_ATTR_TYPE_TMEM_INPUT) { + arg->ret = TEE_ERROR_BAD_PARAMETERS; + return; + } + + arg->ret = do_write(offset, length, buffer); + break; + default: + arg->ret = TEE_ERROR_BAD_PARAMETERS; + break; + } + + return; +} + +#if defined(DEV_BUILD_CONFIG) +int optee_suppl_cmd_raw_io_wrapper(enum optee_suppl_cmd_raw_io_op op, + void *buffer, size_t offset, size_t length) +{ + struct optee_suppl_cmd_raw_io_test_param { + struct optee_msg_arg arg; + struct optee_msg_param params[2]; + } test_arg = { + .arg = { + .num_params = 2, + }, + .params[0] = { + .attr = OPTEE_MSG_ATTR_TYPE_VALUE_INPUT, + .u.value.b = offset, + .u.value.c = length, + }, + .params[1] = { + .u.tmem.buf_ptr = (u64)buffer, + .u.tmem.size = length, + }, + }; + switch (op) { + case optee_suppl_cmd_raw_io_read: + test_arg.arg.params[1].attr = OPTEE_MSG_ATTR_TYPE_TMEM_OUTPUT; + test_arg.arg.params[0].u.value.a = OPTEE_MRC_RAW_READ; + break; + case optee_suppl_cmd_raw_io_write: + test_arg.arg.params[1].attr = OPTEE_MSG_ATTR_TYPE_TMEM_INPUT; + test_arg.arg.params[0].u.value.a = OPTEE_MRC_RAW_WRITE; + break; + default: + return -1; + } + + optee_suppl_cmd_raw_io(&test_arg.arg); + return test_arg.arg.ret == TEE_SUCCESS ? 0 : -1; +} +#endif \ No newline at end of file
diff --git a/drivers/tee/optee/supplicant.c b/drivers/tee/optee/supplicant.c index d5338b2..03351aa 100644 --- a/drivers/tee/optee/supplicant.c +++ b/drivers/tee/optee/supplicant.c
@@ -75,6 +75,10 @@ case OPTEE_MSG_RPC_CMD_RPMB: optee_suppl_cmd_rpmb(dev, arg); break; + case OPTEE_MSG_RPC_CMD_RAW: + /* Raw partition IO */ + optee_suppl_cmd_raw_io(arg); + break; default: arg->ret = TEE_ERROR_NOT_IMPLEMENTED; }
diff --git a/drivers/usb/gadget/f_fastboot.c b/drivers/usb/gadget/f_fastboot.c index 3e5f057..1d62557 100644 --- a/drivers/usb/gadget/f_fastboot.c +++ b/drivers/usb/gadget/f_fastboot.c
@@ -32,6 +32,7 @@ #include <mmc.h> #include <stdalign.h> #include <tee/ta_vx.h> +#include <tee/optee.h> #include <version.h> #include <zircon_uboot/boot_args.h> #include <zircon_uboot/bootimg.h> @@ -550,6 +551,23 @@ return false; } +#if defined(DEV_BUILD_CONFIG) +static bool fb_run_again_to_confirm_or_fail(void) +{ + static uint32_t nth_run = 0; + + nth_run++; + + if (nth_run % 2) { + fastboot_fail("RERUN COMMAND TO CONFIRM YOU KNOW WHAT YOU ARE " + "DOING!"); + return true; + } + + return false; +} +#endif // DEV_BUILD_CONFIG + static void cb_reboot(struct usb_ep *ep, struct usb_request *req) { char *cmd = req->buf; @@ -861,6 +879,17 @@ return unlocked ? "no" : "yes"; } +static const char *get_dev_key_enabled(const char *arg) +{ + uint32_t vars = 0; + + if (ta_vx_getvar_all(&vars)) { + return "error"; + } + + return !!(vars & VX_VAR_DEV_KEY_ENABLED)? "yes" : "no"; +} + static const char *get_rpmb_key_programmed(const char *arg) { uint32_t flags = 0; @@ -894,6 +923,17 @@ return (flags & VX_RPMB_PROVISIONING_ALLOWED) ? "yes": "no"; } +static const char *get_rpmb_protection_level(const char *arg) +{ + uint32_t flags = 0; + + if (ta_vx_get_rpmb_status(&flags, /* out_write_count= */NULL)) { + return "error"; + } + + return (flags & VX_RPMB_REROUTING_TRAFFIC) ? "100": "1000"; +} + static const char *get_rpmb_total_bytes(const char *arg) { uint8_t rpmb_size_mult; @@ -961,6 +1001,10 @@ .func = get_current_slot, }, { + .name = "dev-key-enabled", + .func = get_dev_key_enabled, + }, + { .name = "emmc-firmware-revision", .func = get_emmc_firmware_revision, }, @@ -1001,6 +1045,10 @@ .func = get_rpmb_key_verified, }, { + .name = "rpmb-protection-level", + .func = get_rpmb_protection_level, + }, + { .name = "rpmb-provisioning-allowed", .func = get_rpmb_provisioning_allowed, }, @@ -1526,6 +1574,102 @@ fastboot_okay(NULL); } +#if defined(DEV_BUILD_CONFIG) +static void cb_kill_rpmb_till_reboot(struct usb_ep *ep, + struct usb_request *req) +{ + int rc; + uint32_t flags = 0; + + rc = ta_vx_reroute_rpmb_till_reboot(); + if (rc) { + fastboot_fail("Request somehow got rejected."); + return; + } + + rc = ta_vx_get_rpmb_status(&flags, /* out_write_count= */NULL); + if (rc) { + fastboot_fail("Failed to query RPMB status."); + return; + } + + if (!(flags & VX_RPMB_REROUTING_TRAFFIC)) { + fastboot_fail("Request went through but didn't take effect."); + return; + } + + fastboot_okay(NULL); +} + +static void cb_kill_rpmb(struct usb_ep *ep, struct usb_request *req) +{ + int rc; + uint32_t flags = 0; + + if (fb_run_again_to_confirm_or_fail()) { + return; + } + + rc = ta_vx_reroute_rpmb_to_software(); + if (rc) { + fastboot_fail("Rejected. Have you killed RPMB before?"); + return; + } + + rc = ta_vx_get_rpmb_status(&flags, /* out_write_count= */NULL); + if (rc) { + fastboot_fail("Failed to query RPMB status."); + return; + } + + if (!(flags & VX_RPMB_REROUTING_TRAFFIC)) { + fastboot_fail("Request went through but didn't take effect!"); + return; + } + + fastboot_okay(NULL); +} + +static void cb_unkill_rpmb(struct usb_ep *ep, struct usb_request *req) +{ + int rc; + uint32_t flags = 0; + static bool just_need_fastboot_okay = false; + + if (just_need_fastboot_okay) { + just_need_fastboot_okay = false; + fastboot_okay(NULL); + return; + } + + rc = ta_vx_get_rpmb_status(&flags, /* out_write_count= */NULL); + if (rc) { + fastboot_fail("Failed to query RPMB status."); + return; + } + + if (!(flags & VX_RPMB_REROUTING_TRAFFIC)) { + fastboot_fail("Your RPMB is alive, maybe kill it first?"); + return; + } + + if (fb_run_again_to_confirm_or_fail()) { + return; + } + + rc = ta_vx_reroute_rpmb_to_hardware(); + if (rc) { + fastboot_fail("Request somehow got rejected."); + return; + } + + /* Reboot is required to take effect because it is not safe or reliable + * for TEE to revert rerouting. */ + just_need_fastboot_okay = true; + fastboot_info("Please reboot device to take effect."); +} +#endif /* defined(DEV_BUILD_CONFIG) */ + static void cb_provision_rpmb(struct usb_ep *ep, struct usb_request *req) { @@ -1621,12 +1765,7 @@ static void cb_vx_lock(struct usb_ep *ep, struct usb_request *req) { - if (zircon_clear_stored_cmdline()) { - FB_ERR("Failed to clear stored boot args\n"); - fastboot_fail("Failed to clear boot args"); - return; - } - + // ta_vx_lock() will clear any stored boot args. if (ta_vx_lock()) { FB_ERR("Failed to lock\n"); fastboot_fail("Failed to lock"); @@ -1842,6 +1981,57 @@ fastboot_okay(NULL); } +#if defined(DEV_BUILD_CONFIG) +static void cb_optee_suppl_cmd_raw_io(struct usb_ep *ep, + struct usb_request *req) +{ + // usage: oem optee-supl-cmd-raw-io <"read"|"write"> <off> <len> + const char usage[] = "Usage: optee-supl-cmd-raw-io <read|write> <off> <len>"; + + char *name = req->buf; + + // skip past "oem optee-supl-cmd-raw-io" + if (!(strsep(&name, " ") && strsep(&name, " ") && name)) { + fastboot_fail(usage); + return; + } + + enum optee_suppl_cmd_raw_io_op op = optee_suppl_cmd_raw_io_write; + if (strncmp(name, "read", strlen("read")) == 0) { + op = optee_suppl_cmd_raw_io_read; + } else if (strncmp(name, "write", strlen("write") - 1)) { + fastboot_fail(usage); + return; + } + + // offset + if (!strsep(&name, " ")) { + fastboot_fail(usage); + return; + } + uint64_t offset = simple_strtoul(name, NULL, 16); + + // length + if (!strsep(&name, " ")) { + fastboot_fail(usage); + return; + } + uint64_t length = simple_strtoul(name, NULL, 16); + + int res = optee_suppl_cmd_raw_io_wrapper( + op, (void *)CONFIG_FASTBOOT_BUF_ADDR, offset, length); + if (res) { + fastboot_fail("IO failed"); + return; + } + + if (op == optee_suppl_cmd_raw_io_read) + upload_size = length; + + fastboot_okay(""); +} +#endif + static void cb_staged_bootloader_file(struct usb_ep *ep, struct usb_request *req) { @@ -2056,6 +2246,20 @@ .cb = cb_erase, }, #endif +#if defined(DEV_BUILD_CONFIG) + { + .cmd = "oem kill-rpmb-till-reboot", + .cb = cb_kill_rpmb_till_reboot, + }, + { + .cmd = "oem kill-rpmb", + .cb = cb_kill_rpmb, + }, + { + .cmd = "oem unkill-rpmb", + .cb = cb_unkill_rpmb, + }, +#endif { .cmd = "oem stage-partition", .cb = cb_stage_partition, @@ -2102,6 +2306,12 @@ .cmd = "oem gpt-update", .cb = cb_gpt_update, }, +#if defined(DEV_BUILD_CONFIG) + { + .cmd = "oem optee-supl-cmd-raw-io", + .cb = cb_optee_suppl_cmd_raw_io, + }, +#endif #ifdef CONFIG_FACTORY_BOOT_KVS { .cmd = "oem factory-boot-kvs-get",
diff --git a/include/emmc_partitions.h b/include/emmc_partitions.h index e8f4bc5..d964586 100644 --- a/include/emmc_partitions.h +++ b/include/emmc_partitions.h
@@ -114,6 +114,10 @@ #define GPT_LBA_COUNT 34 #define GPT_TOTAL_SIZE (GPT_LBA_COUNT * 512) +#define MMC_SECURE_STORAGE_NAME "secure-storage" +#define MMC_SECURE_STORAGE_OFFSET (SZ_1M * 32) +#define MMC_SECURE_STORAGE_SIZE (SZ_1M * 32) + struct virtual_partition { char name[MAX_MMC_PART_NAME_LEN]; uint64_t offset;
diff --git a/include/mmc.h b/include/mmc.h index 8c5ffa7..90a6803 100644 --- a/include/mmc.h +++ b/include/mmc.h
@@ -165,6 +165,8 @@ #define MMC_DISCARD_ARG 0x00000003 #define MMC_SECURE_TRIM1_ARG 0x80000001 #define MMC_SECURE_TRIM2_ARG 0x80008000 +#define MMC_RELIABLE_WRITE_ARG (1 << 31) +#define MMC_BLOCK_COUNT_MAX (0xFFFF) #define MMC_STATUS_MASK (~0x0206BF7F) #define MMC_STATUS_SWITCH_ERROR (1 << 7) @@ -208,6 +210,7 @@ * EXT_CSD fields */ #define EXT_CSD_CLASS_6_CTRL 59 /*R/W/E_P*/ +#define EXT_CSD_DATA_SECTOR_SIZE 61 #define EXT_CSD_ENH_START_ADDR 136 /* R/W */ #define EXT_CSD_ENH_SIZE_MULT 140 /* R/W */ #define EXT_CSD_GP_SIZE_MULT 143 /* R/W */ @@ -301,6 +304,8 @@ #define EXT_CSD_WR_DATA_REL_USR (1 << 0) /* user data area WR_REL */ #define EXT_CSD_WR_DATA_REL_GP(x) (1 << ((x)+1)) /* GP part (x+1) WR_REL */ +#define EXT_CSD_DATA_SECTOR_SIZE_512 0 + #define R1_ILLEGAL_COMMAND (1 << 22) #define R1_APP_CMD (1 << 5)
diff --git a/include/tee/optee.h b/include/tee/optee.h index 9446928f..b4a35d1 100644 --- a/include/tee/optee.h +++ b/include/tee/optee.h
@@ -67,4 +67,18 @@ } #endif +#if defined(DEV_BUILD_CONFIG) +enum optee_suppl_cmd_raw_io_op { + optee_suppl_cmd_raw_io_read, + optee_suppl_cmd_raw_io_write, +}; + +// A helper based on `optee_suppl_cmd_raw_io()` for writing/reading data +// to/from the reserved partition. The helper is mainly for firmware testing by +// fastboot oem command +// `fastboot oem optee-supl-cmd-raw-io <"read"|"write"> <off> <len>` +int optee_suppl_cmd_raw_io_wrapper(enum optee_suppl_cmd_raw_io_op op, + void *buffer, size_t offset, size_t length); +#endif + #endif /* _OPTEE_H */
diff --git a/include/tee/ta_vx.h b/include/tee/ta_vx.h index fe2e589..6744ceb 100644 --- a/include/tee/ta_vx.h +++ b/include/tee/ta_vx.h
@@ -16,6 +16,14 @@ VX_UNLOCKED = 1, } vx_lock_state_t; +/* VX variables. */ +typedef enum vx_variable { + VX_VAR_NONE = 0x0, + VX_VAR_DEV_KEY_ENABLED = 0x01, + VX_VAR_OUT_OF_BOOTLOADER = 0x02, + VX_VAR_EPHEMERALLY_UNLOCKED = 0x04, +} vx_variable_t; + /* * Gets the rollback index corresponding to the given rollback index slot. * @@ -142,9 +150,17 @@ #define TA_VX_CMD_READ_PERM_ATTR 13 enum vx_rpmb_status { + /* eMMC claims the RPMB key has been programmed. */ VX_RPMB_AUTH_KEY_PROGRAMMED = 0x01, + + /* RPMB key has been verified by the firmware. */ VX_RPMB_AUTH_KEY_VERIFIED = 0x02, + + /* RPMB provisioning is no longer allowed (mitigates key phishing). */ VX_RPMB_PROVISIONING_ALLOWED = 0x04, + + /* Reroute RPMB traffic (to REE controlled storage). */ + VX_RPMB_REROUTING_TRAFFIC = 0x08, }; /* Reads the RPMB provisioning status. @@ -210,8 +226,13 @@ #define TA_VX_CMD_LOCK_PERM_ATTR 17 typedef enum { + /* Programmed to RPMB. */ VX_PERM_ATTR_PROGRAMMED = (1 << 0), + + /* SHA256 digest stored in OTP. */ VX_PERM_ATTR_LOCKED = (1 << 1), + + /* Hardcoded. */ VX_PERM_ATTR_HARDCODED = (1 << 2), } perm_attr_status_t; @@ -235,40 +256,8 @@ */ #define TA_VX_CMD_DELETE_PERM_ATTR 19 -typedef enum vx_option { - /* If set, automatically provisions RPMB if RPMB is not already - * provisioned. Default unset. */ - VX_OPTION_AUTO_PROVISION_RPMB = (1 << 1), - /* For testing use. e.g. The Bootloader uses this to make sure options - * CAN NOT be set after issuing CMD_EXIT_BOOTLOADER. */ - VX_OPTION_FOR_TESTING = (1 << 3), -} vx_option_t; - -/* - * Sets certain options for the VX TA. - * - * This command is only available to the Bootloader. - * - * in params[0].value.a: Options flags to set (VX_OPTION_*). - * - * Returns - * TEE_SUCCESS on success, - * TEE_ERROR_* otherwise. - */ -#define TA_VX_CMD_SET_OPTIONS 20 - -/* - * Unsets certain options for the VX TA. - * - * This command is only available to the Bootloader. - * - * in params[0].value.a: Options flags to unset (VX_OPTION_*). - * - * Returns - * TEE_SUCCESS on success, - * TEE_ERROR_* otherwise. - */ -#define TA_VX_CMD_UNSET_OPTIONS 21 +#define TA_VX_CMD_SET_OPTIONS_DEPRECATED 20 +#define TA_VX_CMD_UNSET_OPTIONS_DEPRECATED 21 /* Provisions the USBBOOT password hash. * @@ -303,6 +292,76 @@ */ #define TA_VX_CMD_GET_USBBOOT_STATUS 23 +/* Sets the OTA Config option. + * + * Args: + * in params[0].value.a: config option. + * + * Returns: + * TEE_SUCCESS if the option value was set successfully. + * Otherwise TEE_ERROR_*. + */ +#define TA_VX_CMD_OTA_CONFIG_SET 24 + +/* Reads the OTA Config option. + * + * Args: + * in params[0].value.a: default value for option, which will be returned if + * there is no stored value in secure storage. + * out params[1].value.a: config option + * + * Returns: + * TEE_SUCCESS if the option value was read successfully. + * Otherwise TEE_ERROR_*. + */ +#define TA_VX_CMD_OTA_CONFIG_GET 25 + +/* + * Delete the OTA Config. + * + * Returns: + * TEE_SUCCESS if the config was deleted successfully. + * Otherwise TEE_ERROR_*. + */ +#define TA_VX_CMD_OTA_CONFIG_DELETE 26 + +/* + * Query VX variables. + * + * out params[0].value.a: or'ed VX_VAR_* + */ +#define TA_VX_CMD_GETVAR_ALL 27 + +/* + * Force reroute RPMB until reboot. + * + * For testing on dev-key hardware only. + * + * Returns: + * TEE_SUCCESS if successful. Otherwise TEE_ERROR_*. + */ +#define TA_VX_CMD_REROUTE_RPMB_TILL_REBOOT 28 + +/* + * Force reroute RPMB to REE-controlled secure storage. + * + * Works on dev-key hardware only. + * + * Returns: + * TEE_SUCCESS if successful. Otherwise TEE_ERROR_*. + */ +#define TA_VX_CMD_REROUTE_RPMB_TO_SOFTWARE 29 + +/* + * Force route RPMB to hardware (eMMC). + * + * Works on dev-key hardware only. + * + * Returns: + * TEE_SUCCESS if successful. Otherwise TEE_ERROR_*. + */ +#define TA_VX_CMD_REROUTE_RPMB_TO_HARDWARE 30 + /** * Persistent Nonces Management. */
diff --git a/include/tee/ta_vx_helper.h b/include/tee/ta_vx_helper.h index 2b78f3d..d2bf2f3 100644 --- a/include/tee/ta_vx_helper.h +++ b/include/tee/ta_vx_helper.h
@@ -27,6 +27,13 @@ int ta_vx_lock(void); /** + * ta_vx_lock_if_ephemerally_unlocked() + * + * Return: 0 if successful, non-zero error code on failure. + */ +int ta_vx_lock_if_ephemerally_unlocked(void); + +/** * ta_vx_unlock() - Unlocks the device. * * Return: 0 if successful, non-zero error code on failure. @@ -101,10 +108,10 @@ int ta_vx_cprng_draw(void *buf, size_t buf_len); /** - * ta_vx_exit_bootloader() - Finalize verified execution policies and + * ta_vx_exit_bootloader_or_panic() - Finalize verified execution policies and * configurations. Panics on any error. */ -void ta_vx_exit_bootloader(void); +void ta_vx_exit_bootloader_or_panic(void); /** * ta_vx_read_perm_attr() - Read permanent attributes @@ -149,6 +156,28 @@ int ta_vx_provision_rpmb(void); /** + * ta_vx_reroute_rpmb_till_reboot() - Reroute RPMB traffic till reboot for + * testing. + * + * Return: 0 if successful, non-zero code otherwise. + */ +int ta_vx_reroute_rpmb_till_reboot(void); + +/** + * ta_vx_reroute_rpmb_to_software() - Persistently reroute RPMB traffic. + * + * Return: 0 if successful, non-zero code otherwise. + */ +int ta_vx_reroute_rpmb_to_software(void); + +/** + * ta_vx_reroute_rpmb_to_hardware() - Permanently restore RPMB traffic. + * + * Return: 0 if successful, non-zero code otherwise. + */ +int ta_vx_reroute_rpmb_to_hardware(void); + +/** * ta_vx_read_perm_attr_hash() - Read permanent attributes hash * @buf: Buffer to write value into. * @buf_len: Length of buf. @@ -197,6 +226,15 @@ */ int ta_vx_get_usbboot_status(uint32_t *status); +/** + * ta_vx_getvar_all() - Query hardware capabilities + * + * @out_caps: Receives VX_HARDWARE_* flags as defined in tee/ta_vx.h + * + * Return: 0 if successful, non-zero error code otherwise. + */ +int ta_vx_getvar_all(uint32_t *out_caps); + #ifdef CONFIG_TA_VX_TESTS /** * ta_vx_run_tests() - Run tests defined in the VX TA.
diff --git a/include/zircon_uboot/partition_internal.h b/include/zircon_uboot/partition_internal.h index 55286e2..76fbe32 100644 --- a/include/zircon_uboot/partition_internal.h +++ b/include/zircon_uboot/partition_internal.h
@@ -18,6 +18,9 @@ // erase if the user can write anyway. #define ZIRCON_PARTITION_ACCESS_FLAG_ERASE (1 << 0) #define ZIRCON_PARTITION_ACCESS_FLAG_WRITE (1 << 1) +// write/erase access is only allowed when variant is dev, regardless of +// lock/unlock status. +#define ZIRCON_PARTITION_ACCESS_DEV_ONLY (1 << 2) typedef enum { // Alias for partition within GPT on eMMC USER hardware partition.