Browse Source

MA-9409-1 enable avb on android things.

Fix issue for API changed from v2017.
porting below patch from v2016.
commit 44834fd12f

Change-Id: Ifaf0b86dd29648f9150646f00f54502676df9013
Signed-off-by: zhang sanshan <sanshan.zhang@nxp.com>
imx_v2017.03_4.9.11_1.0.0_ga
zhang sanshan 4 years ago
committed by Chen Guoyin
parent
commit
1c79796a52
56 changed files with 9367 additions and 10 deletions
  1. +8
    -0
      arch/arm/include/asm/arch-mx7/crm_regs.h
  2. +8
    -0
      common/image-android.c
  3. +259
    -10
      drivers/usb/gadget/f_fastboot.c
  4. +176
    -0
      include/fsl_avb.h
  5. +9
    -0
      include/fsl_fastboot.h
  6. +1
    -0
      lib/Makefile
  7. +14
    -0
      lib/avb/Makefile
  8. +5
    -0
      lib/avb/fsl/Makefile
  9. +35
    -0
      lib/avb/fsl/debug.h
  10. +414
    -0
      lib/avb/fsl/fsl_avb.c
  11. +717
    -0
      lib/avb/fsl/fsl_avbkey.c
  12. +44
    -0
      lib/avb/fsl/fsl_avbkey.h
  13. +176
    -0
      lib/avb/fsl/fsl_bootctl.c
  14. +51
    -0
      lib/avb/fsl/utils.c
  15. +25
    -0
      lib/avb/fsl/utils.h
  16. +17
    -0
      lib/avb/libavb/Makefile
  17. +64
    -0
      lib/avb/libavb/avb_chain_partition_descriptor.c
  18. +72
    -0
      lib/avb/libavb/avb_chain_partition_descriptor.h
  19. +113
    -0
      lib/avb/libavb/avb_crc32.c
  20. +373
    -0
      lib/avb/libavb/avb_crypto.c
  21. +165
    -0
      lib/avb/libavb/avb_crypto.h
  22. +160
    -0
      lib/avb/libavb/avb_descriptor.c
  23. +131
    -0
      lib/avb/libavb/avb_descriptor.h
  24. +54
    -0
      lib/avb/libavb/avb_footer.c
  25. +86
    -0
      lib/avb/libavb/avb_footer.h
  26. +61
    -0
      lib/avb/libavb/avb_hash_descriptor.c
  27. +73
    -0
      lib/avb/libavb/avb_hash_descriptor.h
  28. +69
    -0
      lib/avb/libavb/avb_hashtree_descriptor.c
  29. +83
    -0
      lib/avb/libavb/avb_hashtree_descriptor.h
  30. +58
    -0
      lib/avb/libavb/avb_kernel_cmdline_descriptor.c
  31. +81
    -0
      lib/avb/libavb/avb_kernel_cmdline_descriptor.h
  32. +214
    -0
      lib/avb/libavb/avb_ops.h
  33. +185
    -0
      lib/avb/libavb/avb_property_descriptor.c
  34. +107
    -0
      lib/avb/libavb/avb_property_descriptor.h
  35. +299
    -0
      lib/avb/libavb/avb_rsa.c
  36. +73
    -0
      lib/avb/libavb/avb_rsa.h
  37. +90
    -0
      lib/avb/libavb/avb_sha.h
  38. +390
    -0
      lib/avb/libavb/avb_sha256.c
  39. +388
    -0
      lib/avb/libavb/avb_sha512.c
  40. +1188
    -0
      lib/avb/libavb/avb_slot_verify.c
  41. +257
    -0
      lib/avb/libavb/avb_slot_verify.h
  42. +117
    -0
      lib/avb/libavb/avb_sysdeps.h
  43. +78
    -0
      lib/avb/libavb/avb_sysdeps_posix.c
  44. +64
    -0
      lib/avb/libavb/avb_sysdeps_uboot.c
  45. +403
    -0
      lib/avb/libavb/avb_util.c
  46. +277
    -0
      lib/avb/libavb/avb_util.h
  47. +308
    -0
      lib/avb/libavb/avb_vbmeta_image.c
  48. +290
    -0
      lib/avb/libavb/avb_vbmeta_image.h
  49. +34
    -0
      lib/avb/libavb/avb_version.c
  50. +63
    -0
      lib/avb/libavb/avb_version.h
  51. +50
    -0
      lib/avb/libavb/libavb.h
  52. +2
    -0
      lib/avb/libavb_ab/Makefile
  53. +516
    -0
      lib/avb/libavb_ab/avb_ab_flow.c
  54. +253
    -0
      lib/avb/libavb_ab/avb_ab_flow.h
  55. +79
    -0
      lib/avb/libavb_ab/avb_ab_ops.h
  56. +40
    -0
      lib/avb/libavb_ab/libavb_ab.h

+ 8
- 0
arch/arm/include/asm/arch-mx7/crm_regs.h View File

@ -1999,6 +1999,14 @@ struct mxc_ccm_anatop_reg {
#define TEMPMON_HW_ANADIG_TEMPSENSE_TRIM_TOG_T_MUX_ADDR_SHIFT 29
#define TEMPMON_HW_ANADIG_TEMPSENSE_TRIM_TOG_T_MUX_ADDR(x) (((uint32_t)(((uint32_t)(x))<<TEMPMON_HW_ANADIG_TEMPSENSE_TRIM_TOG_T_MUX_ADDR_SHIFT))&TEMPMON_HW_ANADIG_TEMPSENSE_TRIM_TOG_T_MUX_ADDR_MASK)
#define MXC_CCM_CCGR36_CAAM_DOMAIN3_OFFSET 12
#define MXC_CCM_CCGR36_CAAM_DOMAIN3_MASK (3 << MXC_CCM_CCGR36_CAAM_DOMAIN3_OFFSET)
#define MXC_CCM_CCGR36_CAAM_DOMAIN2_OFFSET 8
#define MXC_CCM_CCGR36_CAAM_DOMAIN2_MASK (3 << MXC_CCM_CCGR36_CAAM_DOMAIN2_OFFSET)
#define MXC_CCM_CCGR36_CAAM_DOMAIN1_OFFSET 4
#define MXC_CCM_CCGR36_CAAM_DOMAIN1_MASK (3 << MXC_CCM_CCGR36_CAAM_DOMAIN1_OFFSET)
#define MXC_CCM_CCGR36_CAAM_DOMAIN0_OFFSET 0
#define MXC_CCM_CCGR36_CAAM_DOMAIN0_MASK (3 << MXC_CCM_CCGR36_CAAM_DOMAIN0_OFFSET)
#define CCM_GPR(i) (CCM_BASE_ADDRESS + CCM_GPR0_OFFSET + 0x10 * (i))
#define CCM_OBSERVE(i) (CCM_BASE_ADDRESS + CCM_OBSERVE0_OFFSET + 0x10 * (i))


+ 8
- 0
common/image-android.c View File

@ -117,6 +117,14 @@ int android_image_get_kernel(const struct andr_img_hdr *hdr, int verify,
#ifdef CONFIG_FSL_BOOTCTL
sprintf(newbootargs, " androidboot.slot_suffix=%s", get_slot_suffix());
strcat(commandline, newbootargs);
#endif
#ifdef CONFIG_AVB_SUPPORT
/* secondary cmdline added by avb */
char *bootargs_sec = getenv("bootargs_sec");
if (bootargs_sec) {
strcat(commandline, " ");
strcat(commandline, bootargs_sec);
}
#endif
setenv("bootargs", commandline);


+ 259
- 10
drivers/usb/gadget/f_fastboot.c View File

@ -55,6 +55,9 @@
#include "bcb.h"
#endif
#ifdef CONFIG_AVB_SUPPORT
#include <fsl_avb.h>
#endif
#define FASTBOOT_VERSION "0.4"
@ -97,6 +100,7 @@ static inline struct f_fastboot *func_to_fastboot(struct usb_function *f)
static struct f_fastboot *fastboot_func;
static unsigned int download_size;
static unsigned int download_bytes;
static int strcmp_l1(const char *s1, const char *s2);
static struct usb_endpoint_descriptor fs_ep_in = {
.bLength = USB_DT_ENDPOINT_SIZE,
@ -790,8 +794,7 @@ static void process_flash_sata(const char *cmdbuf)
/* Next is the partition name */
ptn = fastboot_flash_find_ptn(cmdbuf);
if (ptn == 0) {
printf("Partition:'%s' does not exist\n", ptn->name);
if (ptn == NULL) {
fastboot_fail("partition does not exist");
} else if ((download_bytes >
ptn->length * MMC_SATA_BLOCK_SIZE) &&
@ -927,11 +930,22 @@ static void process_flash_mmc(const char *cmdbuf)
{
if (download_bytes) {
struct fastboot_ptentry *ptn;
#ifdef CONFIG_AVB_SUPPORT
if (!strcmp_l1(FASTBOOT_PARTITION_AVBKEY, cmdbuf)) {
printf("pubkey len %d\n", download_bytes);
if (avbkey_init(interface.transfer_buffer, download_bytes) != 0) {
fastboot_fail("fail to Write partition");
} else {
printf("init 'avbkey' DONE!\n");
fastboot_okay("OKAY");
}
return;
}
#endif
/* Next is the partition name */
ptn = fastboot_flash_find_ptn(cmdbuf);
if (ptn == 0) {
printf("Partition:'%s' does not exist\n", ptn->name);
if (ptn == NULL) {
fastboot_fail("partition does not exist");
} else if ((download_bytes >
ptn->length * MMC_SATA_BLOCK_SIZE) &&
@ -1213,6 +1227,9 @@ static int _fastboot_parts_add_ptable_entry(int ptable_index,
strcpy(ptable[ptable_index].name, name);
#endif
#ifdef CONFIG_PARTITION_UUIDS
strcpy(ptable[ptable_index].uuid, (const char *)info.uuid);
#endif
return 0;
}
@ -1632,6 +1649,25 @@ void board_recovery_setup(void)
#endif /*CONFIG_ANDROID_RECOVERY*/
#endif /*CONFIG_FSL_FASTBOOT*/
#if defined(CONFIG_AVB_SUPPORT) && defined(CONFIG_MMC)
static AvbABOps fsl_avb_ab_ops = {
.read_ab_metadata = fsl_read_ab_metadata,
.write_ab_metadata = fsl_write_ab_metadata,
.ops = NULL
};
static AvbOps fsl_avb_ops = {
.ab_ops = &fsl_avb_ab_ops,
.read_from_partition = fsl_read_from_partition_multi,
.write_to_partition = fsl_write_to_partition,
.validate_vbmeta_public_key = fsl_validate_vbmeta_public_key_rpmb,
.read_rollback_index = fsl_read_rollback_index_rpmb,
.write_rollback_index = fsl_write_rollback_index_rpmb,
.read_is_device_unlocked = fsl_read_is_device_unlocked,
.get_unique_guid_for_partition = fsl_get_unique_guid_for_partition
};
#endif
void fastboot_setup(void)
{
struct tag_serialnr serialnr;
@ -1652,6 +1688,9 @@ void fastboot_setup(void)
_fastboot_load_partitions();
parameters_setup();
#ifdef CONFIG_AVB_SUPPORT
fsl_avb_ab_ops.ops = &fsl_avb_ops;
#endif
}
/* Write the bcb with fastboot bootloader commands */
@ -1765,6 +1804,172 @@ bootimg_print_image_hdr(struct andr_img_hdr *hdr)
static struct andr_img_hdr boothdr __aligned(ARCH_DMA_MINALIGN);
#if defined(CONFIG_AVB_SUPPORT) && defined(CONFIG_MMC)
/* we can use avb to verify Trusty if we want */
const char *requested_partitions[] = {"boot", 0};
int do_boota(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) {
ulong addr = 0;
struct andr_img_hdr *hdr = NULL;
struct andr_img_hdr *hdrload;
ulong image_size;
AvbABFlowResult avb_result;
AvbSlotVerifyData *avb_out_data;
AvbPartitionData *avb_loadpart;
#ifdef CONFIG_FASTBOOT_LOCK
/* check lock state */
FbLockState lock_status = fastboot_get_lock_stat();
if (lock_status == FASTBOOT_LOCK_ERROR) {
printf("In boota get fastboot lock status error. Set lock status\n");
fastboot_set_lock_stat(FASTBOOT_LOCK);
lock_status = FASTBOOT_LOCK;
}
bool allow_fail = (lock_status == FASTBOOT_UNLOCK ? true : false);
/* if in lock state, do avb verify */
avb_result = avb_ab_flow(&fsl_avb_ab_ops, requested_partitions, allow_fail, &avb_out_data);
if (avb_result == AVB_AB_FLOW_RESULT_OK) {
assert(avb_out_data != NULL);
/* load the first partition */
avb_loadpart = avb_out_data->loaded_partitions;
assert(avb_loadpart != NULL);
/* we should use avb_part_data->data as boot image */
/* boot image is already read by avb */
hdr = (struct andr_img_hdr *)avb_loadpart->data;
if (android_image_check_header(hdr)) {
printf("boota: bad boot image magic\n");
goto fail;
}
printf(" verify OK, boot '%s%s'\n", avb_loadpart->partition_name, avb_out_data->ab_suffix);
char bootargs_sec[2048];
sprintf(bootargs_sec, "androidboot.slot_suffix=%s %s", avb_out_data->ab_suffix, avb_out_data->cmdline);
setenv("bootargs_sec", bootargs_sec);
#ifdef CONFIG_SYSTEM_RAMDISK_SUPPORT
if(!is_recovery_mode)
fastboot_setup_system_boot_args(avb_out_data->ab_suffix);
#endif
image_size = avb_loadpart->data_size;
memcpy((void *)load_addr, (void *)hdr, image_size);
} else if (lock_status == FASTBOOT_LOCK) { /* && verify fail */
/* if in lock state, verify enforce fail */
printf(" verify FAIL, state: LOCK\n");
goto fail;
} else { /* lock_status == FASTBOOT_UNLOCK && verify fail */
/* if in unlock state, log the verify state */
printf(" verify FAIL, state: UNLOCK\n");
#endif
/* if lock/unlock not enabled or verify fail
* in unlock state, will try boot */
size_t num_read;
hdr = &boothdr;
char bootimg[8];
char *slot = select_slot(&fsl_avb_ab_ops);
if (slot == NULL) {
printf("boota: no bootable slot\n");
goto fail;
}
sprintf(bootimg, "boot%s", slot);
printf(" boot '%s' still\n", bootimg);
/* maybe we should use bootctl to select a/b
* but libavb doesn't export a/b select */
if (fsl_avb_ops.read_from_partition(&fsl_avb_ops, bootimg,
0, sizeof(boothdr), hdr, &num_read) != AVB_IO_RESULT_OK &&
num_read != sizeof(boothdr)) {
printf("boota: read bootimage head error\n");
goto fail;
}
if (android_image_check_header(hdr)) {
printf("boota: bad boot image magic\n");
goto fail;
}
image_size = android_image_get_end(hdr) - (ulong)hdr;
if (fsl_avb_ops.read_from_partition(&fsl_avb_ops, bootimg,
0, image_size, (void *)load_addr, &num_read) != AVB_IO_RESULT_OK &&
num_read != image_size) {
printf("boota: read boot image error\n");
goto fail;
}
char bootargs_sec[ANDR_BOOT_ARGS_SIZE];
sprintf(bootargs_sec, "androidboot.slot_suffix=%s", slot);
setenv("bootargs_sec", bootargs_sec);
#ifdef CONFIG_SYSTEM_RAMDISK_SUPPORT
if(!is_recovery_mode)
fastboot_setup_system_boot_args(slot);
#endif
#ifdef CONFIG_FASTBOOT_LOCK
}
#endif
flush_cache((ulong)load_addr, image_size);
addr = load_addr;
hdrload = (struct andr_img_hdr *)load_addr;
ulong img_ramdisk, img_ramdisk_len;
if(android_image_get_ramdisk(hdrload, &img_ramdisk, &img_ramdisk_len) != 0) {
printf("boota: mmc failed to read ramdisk\n");
goto fail;
}
memcpy((void *)hdrload->ramdisk_addr, (void *)img_ramdisk, img_ramdisk_len);
/* flush cache after read */
flush_cache((ulong)hdrload->ramdisk_addr, img_ramdisk_len); /* FIXME */
#ifdef CONFIG_OF_LIBFDT
/* load the dtb file */
if (hdrload->second_size && hdrload->second_addr) {
ulong img_fdt, img_fdt_len;
if (android_image_get_fdt(hdrload, &img_fdt, &img_fdt_len) != 0) {
printf("boota: mmc failed to dtb\n");
goto fail;
}
memcpy((void *)hdrload->second_addr, (void *)img_fdt, img_fdt_len);
/* flush cache after read */
flush_cache((ulong)hdrload->second_addr, img_fdt_len); /* FIXME */
}
#endif /*CONFIG_OF_LIBFDT*/
printf("kernel @ %08x (%d)\n", hdrload->kernel_addr, hdrload->kernel_size);
printf("ramdisk @ %08x (%d)\n", hdrload->ramdisk_addr, hdrload->ramdisk_size);
#ifdef CONFIG_OF_LIBFDT
if (hdrload->second_size)
printf("fdt @ %08x (%d)\n", hdrload->second_addr, hdrload->second_size);
#endif /*CONFIG_OF_LIBFDT*/
char boot_addr_start[12];
char ramdisk_addr[25];
char fdt_addr[12];
char *bootm_args[] = { "bootm", boot_addr_start, ramdisk_addr, fdt_addr};
sprintf(boot_addr_start, "0x%lx", addr);
sprintf(ramdisk_addr, "0x%x:0x%x", hdrload->ramdisk_addr, hdrload->ramdisk_size);
sprintf(fdt_addr, "0x%x", hdrload->second_addr);
if (avb_out_data != NULL)
avb_slot_verify_data_free(avb_out_data);
do_bootm(NULL, 0, 4, bootm_args);
/* This only happens if image is somehow faulty so we start over */
do_reset(NULL, 0, 0, NULL);
return 1;
fail:
/* avb has no recovery */
if (avb_out_data != NULL)
avb_slot_verify_data_free(avb_out_data);
return run_command("fastboot 0", 0);
}
U_BOOT_CMD(
boota, 2, 1, do_boota,
"boota - boot android bootimg \n",
"boot from current mmc with avb verify\n"
);
#else /* CONFIG_AVB_SUPPORT */
/* boota <addr> [ mmc0 | mmc1 [ <partition> ] ] */
int do_boota(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
{
@ -2114,11 +2319,11 @@ U_BOOT_CMD(
"\t 'partition' (optional) is the partition id of your device, "
"if no partition give, will going to 'boot' partition\n"
);
#endif /* CONFIG_AVB_SUPPORT */
#endif /* CONFIG_CMD_BOOTA */
#endif
static void rx_handler_command(struct usb_ep *ep, struct usb_request *req);
static int strcmp_l1(const char *s1, const char *s2);
static char *fb_response_str;
@ -2400,10 +2605,13 @@ static void cb_getvar(struct usb_ep *ep, struct usb_request *req)
}
else if (is_slotvar(cmd)) {
#ifdef CONFIG_FSL_BOOTCTL
get_slotvar(cmd, response, chars_left);
fastboot_tx_write_str(response);
return;
#ifdef CONFIG_AVB_SUPPORT
if (get_slotvar_avb(&fsl_avb_ab_ops, cmd,
response + strlen(response), chars_left + 1) < 0)
goto fail;
#elif CONFIG_FSL_BOOTCTL
if (get_slotvar(cmd, response + strlen(response), chars_left + 1) < 0)
goto fail;
#else
strncat(response, FASTBOOT_VAR_NO, chars_left);
#endif
@ -2457,6 +2665,11 @@ static void cb_getvar(struct usb_ep *ep, struct usb_request *req)
}
}
fastboot_tx_write_str(response);
return;
fail:
strncpy(response, "FAIL", 4);
fastboot_tx_write_str(response);
return;
}
static unsigned int rx_bytes_expected(struct usb_ep *ep)
@ -2819,6 +3032,37 @@ static void cb_erase(struct usb_ep *ep, struct usb_request *req)
}
#endif
#ifdef CONFIG_AVB_SUPPORT
static void cb_set_active_avb(struct usb_ep *ep, struct usb_request *req)
{
AvbIOResult ret;
int slot = 0;
char *cmd = req->buf;
strsep(&cmd, ":");
if (!cmd) {
error("missing slot suffix\n");
fastboot_tx_write_str("FAILmissing slot suffix");
return;
}
slot = slotidx_from_suffix(cmd);
if (slot < 0) {
fastboot_tx_write_str("FAILerr slot suffix");
return;
}
ret = avb_ab_mark_slot_active(&fsl_avb_ab_ops, slot);
if (ret != AVB_IO_RESULT_OK)
fastboot_tx_write_str("avb IO error");
else
fastboot_tx_write_str("OKAY");
return;
}
#endif /*CONFIG_AVB_SUPPORT*/
#ifdef CONFIG_FSL_FASTBOOT
static void cb_reboot_bootloader(struct usb_ep *ep, struct usb_request *req)
{
@ -2879,7 +3123,12 @@ static const struct cmd_dispatch_info cmd_dispatch_info[] = {
.cb = cb_flashing,
},
#endif
#ifdef CONFIG_FSL_BOOTCTL
#ifdef CONFIG_AVB_SUPPORT
{
.cmd = "set_active",
.cb = cb_set_active_avb,
},
#elif CONFIG_FSL_BOOTCTL
{
.cmd = "set_active",
.cb = cb_set_active,


+ 176
- 0
include/fsl_avb.h View File

@ -0,0 +1,176 @@
/*
* Copyright (C) 2016 Freescale Semiconductor, Inc.
*
* SPDX-License-Identifier: GPL-2.0+
*/
#ifndef __FSL_AVB_H__
#define __FSL_AVB_H__
#include "../lib/avb/libavb_ab/libavb_ab.h"
/* Reads |num_bytes| from offset |offset| from partition with name
* |partition| (NUL-terminated UTF-8 string). If |offset| is
* negative, its absolute value should be interpreted as the number
* of bytes from the end of the partition.
*
* This function returns AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION if
* there is no partition with the given name,
* AVB_IO_RESULT_ERROR_RANGE_OUTSIDE_PARTITION if the requested
* |offset| is outside the partition, and AVB_IO_RESULT_ERROR_IO if
* there was an I/O error from the underlying I/O subsystem. If the
* operation succeeds as requested AVB_IO_RESULT_OK is returned and
* the data is available in |buffer|.
*
* The only time partial I/O may occur is if reading beyond the end
* of the partition. In this case the value returned in
* |out_num_read| may be smaller than |num_bytes|.
*/
AvbIOResult fsl_read_from_partition(AvbOps* ops, const char* partition,
int64_t offset, size_t num_bytes,
void* buffer, size_t* out_num_read);
/* multi block read version
* */
AvbIOResult fsl_read_from_partition_multi(AvbOps* ops, const char* partition,
int64_t offset, size_t num_bytes,
void* buffer, size_t* out_num_read);
/* Writes |num_bytes| from |bffer| at offset |offset| to partition
* with name |partition| (NUL-terminated UTF-8 string). If |offset|
* is negative, its absolute value should be interpreted as the
* number of bytes from the end of the partition.
*
* This function returns AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION if
* there is no partition with the given name,
* AVB_IO_RESULT_ERROR_RANGE_OUTSIDE_PARTITION if the requested
* byterange goes outside the partition, and AVB_IO_RESULT_ERROR_IO
* if there was an I/O error from the underlying I/O subsystem. If
* the operation succeeds as requested AVB_IO_RESULT_OK is
* returned.
*
* This function never does any partial I/O, it either transfers all
* of the requested bytes or returns an error.
*/
AvbIOResult fsl_write_to_partition(AvbOps* ops, const char* partition,
int64_t offset, size_t num_bytes,
const void* buffer);
/* Reads A/B metadata from persistent storage. Returned data is
* properly byteswapped. Returns AVB_IO_RESULT_OK on success, error
* code otherwise.
*
* If the data read is invalid (e.g. wrong magic or CRC checksum
* failure), the metadata shoule be reset using avb_ab_data_init()
* and then written to persistent storage.
*
* Implementations will typically want to use avb_ab_data_read()
* here to use the 'misc' partition for persistent storage.
*/
AvbIOResult fsl_read_ab_metadata(AvbABOps* ab_ops, struct AvbABData* data);
/* Writes A/B metadata to persistent storage. This will byteswap and
* update the CRC as needed. Returns AVB_IO_RESULT_OK on success,
* error code otherwise.
*
* Implementations will typically want to use avb_ab_data_write()
* here to use the 'misc' partition for persistent storage.
*/
AvbIOResult fsl_write_ab_metadata(AvbABOps* ab_ops, const struct AvbABData* data);
/* Checks if the given public key used to sign the 'vbmeta'
* partition is trusted. Boot loaders typically compare this with
* embedded key material generated with 'avbtool
* extract_public_key'.
*
* If AVB_IO_RESULT_OK is returned then |out_is_trusted| is set -
* true if trusted or false if untrusted.
*/
AvbIOResult fsl_validate_vbmeta_public_key_rpmb(AvbOps* ops,
const uint8_t* public_key_data,
size_t public_key_length,
const uint8_t* public_key_metadata,
size_t public_key_metadata_length,
bool* out_is_trusted);
/* Gets the rollback index corresponding to the slot given by
* |rollback_index_slot|. The value is returned in
* |out_rollback_index|. Returns AVB_IO_RESULT_OK if the rollback
* index was retrieved, otherwise an error code.
*
* A device may have a limited amount of rollback index slots (say,
* one or four) so may error out if |rollback_index_slot| exceeds
* this number.
*/
AvbIOResult fsl_read_rollback_index_rpmb(AvbOps* ops, size_t rollback_index_slot,
uint64_t* out_rollback_index);
/* Sets the rollback index corresponding to the slot given by
* |rollback_index_slot| to |rollback_index|. Returns
* AVB_IO_RESULT_OK if the rollback index was set, otherwise an
* error code.
*
* A device may have a limited amount of rollback index slots (say,
* one or four) so may error out if |rollback_index_slot| exceeds
* this number.
*/
AvbIOResult fsl_write_rollback_index_rpmb(AvbOps* ops, size_t rollback_index_slot,
uint64_t rollback_index);
/* Gets whether the device is unlocked. The value is returned in
* |out_is_unlocked| (true if unlocked, false otherwise). Returns
* AVB_IO_RESULT_OK if the state was retrieved, otherwise an error
* code.
*/
AvbIOResult fsl_read_is_device_unlocked(AvbOps* ops, bool* out_is_unlocked);
/* Gets the unique partition GUID for a partition with name in
* |partition| (NUL-terminated UTF-8 string). The GUID is copied as
* a string into |guid_buf| of size |guid_buf_size| and will be NUL
* terminated. The string must be lower-case and properly
* hyphenated. For example:
*
* 527c1c6d-6361-4593-8842-3c78fcd39219
*
* Returns AVB_IO_RESULT_OK on success, otherwise an error code.
*/
AvbIOResult fsl_get_unique_guid_for_partition(AvbOps* ops,
const char* partition,
char* guid_buf,
size_t guid_buf_size);
/* check if the fastboot getvar cmd is for query [avb] bootctl's slot var
* cmd is the fastboot getvar's cmd in
* return true if it is a bootctl related cmd, false if it's not.
* */
bool is_slotvar_avb(char *cmd);
/* return 0 for the first slot
* return 1 for the second slot
* return -1 for not supported slot
* */
int slotidx_from_suffix(char *suffix);
/* return fastboot's getvar cmd response
* cmd is the fastboot getvar's cmd in
* if return 0, buffer is bootctl's slot var out
* if return -1, buffer is error string
* */
int get_slotvar_avb(AvbABOps *ab_ops, char *cmd, char *buffer, size_t size);
/* reset rollback_index part in avbkey partition
* used in the switch from LOCK to UNLOCK
* return 0 if success, non 0 if fail.
* */
int rbkidx_erase(void);
/* init the avbkey in rpmb partition, include the header/public key/rollback index
* for public key/rollback index part, use caam to do encrypt
* return 0 if success, non 0 if fail.
* */
int avbkey_init(uint8_t *plainkey, uint32_t keylen);
/* read a/b metadata to get curr slot
* return slot suffix '_a'/'_b' or NULL */
char *select_slot(AvbABOps *ab_ops);
#endif /* __FSL_AVB_H__ */

+ 9
- 0
include/fsl_fastboot.h View File

@ -42,6 +42,11 @@
#define FASTBOOT_PARTITION_DATA "userdata"
#define FASTBOOT_PARTITION_BOOT_B "boot_b"
#define FASTBOOT_PARTITION_SYSTEM_B "system_b"
#ifdef CONFIG_AVB_SUPPORT
#define FASTBOOT_PARTITION_VBMETA_A "vbmeta_a"
#define FASTBOOT_PARTITION_VBMETA_B "vbmeta_b"
#define FASTBOOT_PARTITION_AVBKEY "avbkey"
#endif
#define FASTBOOT_PARTITION_MISC "misc"
#define FASTBOOT_PARTITION_GPT "gpt"
#define FASTBOOT_PARTITION_PRDATA "prdata"
@ -153,6 +158,10 @@ struct fastboot_ptentry {
unsigned int partition_id;
/* partition number in block device */
unsigned int partition_index;
/* filesystem UUID as string, if exists */
#ifdef CONFIG_PARTITION_UUIDS
char uuid[37];
#endif
};
struct fastboot_device_info {


+ 1
- 0
lib/Makefile View File

@ -16,6 +16,7 @@ obj-$(CONFIG_BZIP2) += bzip2/
obj-$(CONFIG_TIZEN) += tizen/
obj-$(CONFIG_FIT) += libfdt/
obj-$(CONFIG_CMD_DHRYSTONE) += dhry/
obj-$(CONFIG_AVB_SUPPORT) += avb/
obj-$(CONFIG_AES) += aes.o
obj-$(CONFIG_USB_TTY) += circbuf.o


+ 14
- 0
lib/avb/Makefile View File

@ -0,0 +1,14 @@
subdir-ccflags-y += -D_FILE_OFFSET_BITS=64 \
-D_POSIX_C_SOURCE=199309L \
-Wa,--noexecstack \
-Werror \
-Wall \
-Wextra \
-Wformat=2 \
-Wno-psabi \
-Wno-unused-parameter \
-ffunction-sections \
-std=gnu99
obj-y += libavb/
obj-y += libavb_ab/
obj-y += fsl/

+ 5
- 0
lib/avb/fsl/Makefile View File

@ -0,0 +1,5 @@
ccflags-$(CONFIG_AVB_DEBUG) += -DAVB_DEBUG
obj-y += fsl_avb.o
obj-y += fsl_avbkey.o
obj-y += fsl_bootctl.o
obj-y += utils.o

+ 35
- 0
lib/avb/fsl/debug.h View File

@ -0,0 +1,35 @@
/*
* Copyright (C) 2016 Freescale Semiconductor, Inc.
*
* SPDX-License-Identifier: GPL-2.0+
*/
#ifndef __AVB_DEBUG_H__
#define __AVB_DEBUG_H__
#ifdef AVB_VVDEBUG
#define AVB_VDEBUG
#define VVDEBUG(format, ...) printf(" %s: "format, __func__, ##__VA_ARGS__)
#else
#define VVDEBUG(format, ...)
#endif
#ifdef AVB_VDEBUG
#define AVB_DEBUG
#define VDEBUG(format, ...) printf(" %s: "format, __func__, ##__VA_ARGS__)
#else
#define VDEBUG(format, ...)
#endif
#ifdef AVB_DEBUG
#define DEBUGAVB(format, ...) printf(" %s: "format, __func__, ##__VA_ARGS__)
#else
#define DEBUGAVB(format, ...)
#endif
#define ERR(format, ...) printf("%s: "format, __func__, ##__VA_ARGS__)
#define HEXDUMP_COLS 16
#define HEXDUMP_WIDTH 1
#endif

+ 414
- 0
lib/avb/fsl/fsl_avb.c View File

@ -0,0 +1,414 @@
/*
* Copyright (C) 2016 Freescale Semiconductor, Inc.
*
* SPDX-License-Identifier: GPL-2.0+
*/
#include <common.h>
#include <part.h>
#include <stdlib.h>
#include <fsl_fastboot.h>
#include <fsl_caam.h>
#include "../../../drivers/usb/gadget/fastboot_lock_unlock.h"
#include <fsl_avb.h>
#include "fsl_avbkey.h"
#include "utils.h"
#include "debug.h"
#define FSL_AVB_DEV "mmc"
static struct blk_desc *fs_dev_desc = NULL;
static struct blk_desc *get_mmc_desc(void) {
extern int mmc_get_env_dev(void);
int dev_no = mmc_get_env_dev();
return blk_get_dev(FSL_AVB_DEV, dev_no);
}
/* Reads |num_bytes| from offset |offset| from partition with name
* |partition| (NUL-terminated UTF-8 string). If |offset| is
* negative, its absolute value should be interpreted as the number
* of bytes from the end of the partition.
*
* This function returns AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION if
* there is no partition with the given name,
* AVB_IO_RESULT_ERROR_RANGE_OUTSIDE_PARTITION if the requested
* |offset| is outside the partition, and AVB_IO_RESULT_ERROR_IO if
* there was an I/O error from the underlying I/O subsystem. If the
* operation succeeds as requested AVB_IO_RESULT_OK is returned and
* the data is available in |buffer|.
*
* The only time partial I/O may occur is if reading beyond the end
* of the partition. In this case the value returned in
* |out_num_read| may be smaller than |num_bytes|.
*/
AvbIOResult fsl_read_from_partition(AvbOps* ops, const char* partition,
int64_t offset, size_t num_bytes,
void* buffer, size_t* out_num_read)
{
struct fastboot_ptentry *pte;
unsigned char *bdata;
unsigned char *out_buf = (unsigned char *)buffer;
unsigned long blksz;
unsigned long s, cnt;
size_t num_read = 0;
lbaint_t part_start, part_end, bs, be;
margin_pos_t margin;
AvbIOResult ret;
DEBUGAVB("[%s]: offset=%ld, num_bytes=%zu\n", partition, (long)offset, num_bytes);
assert(buffer != NULL && out_num_read != NULL);
if (!fs_dev_desc && (fs_dev_desc = get_mmc_desc()) == NULL) {
ERR("mmc device not found\n");
return AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION;
}
pte = fastboot_flash_find_ptn(partition);
if (!pte) {
ERR("no %s partition\n", partition);
return AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION;
}
blksz = fs_dev_desc->blksz;
part_start = pte->start;
part_end = pte->start + pte->length - 1;
VDEBUG("blksz: %ld, part_end: %ld, part_start: %ld:\n",
blksz, part_end, part_start);
if(get_margin_pos((uint64_t)part_start, (uint64_t)part_end, blksz,
&margin, offset, num_bytes, true))
return AVB_IO_RESULT_ERROR_RANGE_OUTSIDE_PARTITION;
bs = (lbaint_t)margin.blk_start;
be = (lbaint_t)margin.blk_end;
s = margin.start;
// alloc a blksz mem
bdata = (unsigned char *)memalign(ALIGN_BYTES, blksz);
if (bdata == NULL)
return AVB_IO_RESULT_ERROR_OOM;
// one block a time
while (bs <= be) {
memset(bdata, 0, blksz);
if (!fs_dev_desc->block_read(fs_dev_desc, bs, 1, bdata)) {
ret = AVB_IO_RESULT_ERROR_IO;
goto fail;
}
cnt = blksz - s;
if (num_read + cnt > num_bytes)
cnt = num_bytes - num_read;
VDEBUG("cur: bs=%ld, start=%ld, cnt=%ld bdata=0x%08x\n",
bs, s, cnt, bdata);
memcpy(out_buf, bdata + s, cnt);
bs++;
num_read += cnt;
out_buf += cnt;
s = 0;
}
*out_num_read = num_read;
ret = AVB_IO_RESULT_OK;
#ifdef AVB_VVDEBUG
printf("\nnum_read=%zu", num_read);
printf("\n----dump---\n");
print_buffer(0, buffer, HEXDUMP_WIDTH, num_read, 0);
printf("--- end ---\n");
#endif
fail:
free(bdata);
return ret;
}
/* multi block read version of read_from_partition */
AvbIOResult fsl_read_from_partition_multi(AvbOps* ops, const char* partition,
int64_t offset, size_t num_bytes,
void* buffer, size_t* out_num_read)
{
struct fastboot_ptentry *pte;
unsigned char *bdata;
unsigned char *out_buf = (unsigned char *)buffer;
unsigned char *dst, *dst64 = NULL;
unsigned long blksz;
unsigned long s, cnt;
size_t num_read = 0;
lbaint_t part_start, part_end, bs, be, bm, blk_num;
margin_pos_t margin;
AvbIOResult ret;
DEBUGAVB("[%s]: offset=%ld, num_bytes=%zu\n", partition, (long)offset, num_bytes);
assert(buffer != NULL && out_num_read != NULL);
if (!fs_dev_desc && (fs_dev_desc = get_mmc_desc()) == NULL) {
ERR("mmc device not found\n");
return AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION;
}
pte = fastboot_flash_find_ptn(partition);
if (!pte) {
ERR("no %s partition\n", partition);
return AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION;
}
blksz = fs_dev_desc->blksz;
part_start = pte->start;
part_end = pte->start + pte->length - 1;
VDEBUG("blksz: %ld, part_end: %ld, part_start: %ld:\n",
blksz, part_end, part_start);
if(get_margin_pos((uint64_t)part_start, (uint64_t)part_end, blksz,
&margin, offset, num_bytes, true))
return AVB_IO_RESULT_ERROR_RANGE_OUTSIDE_PARTITION;
bs = (lbaint_t)margin.blk_start;
be = (lbaint_t)margin.blk_end;
s = margin.start;
bm = margin.multi;
// alloc a blksz mem
bdata = (unsigned char *)memalign(ALIGN_BYTES, blksz);
if (bdata == NULL)
return AVB_IO_RESULT_ERROR_OOM;
// support multi blk read
while (bs <= be) {
if (!s && bm > 1) {
dst = out_buf;
dst64 = PTR_ALIGN(out_buf, 64); //for mmc blk read alignment
VDEBUG("cur: dst=0x%08x, dst64=0x%08x\n", dst, dst64);
if (dst64 != dst) {
dst = dst64;
bm--;
}
blk_num = bm;
cnt = bm * blksz;
bm = 0; //no more multi blk
} else {
blk_num = 1;
cnt = blksz - s;
if (num_read + cnt > num_bytes)
cnt = num_bytes - num_read;
dst = bdata;
}
VDEBUG("cur: bs=%ld, num=%ld, start=%ld, cnt=%ld dst=0x%08x\n",
bs, blk_num, s, cnt, dst);
if (!fs_dev_desc->block_read(fs_dev_desc, bs, blk_num, dst)) {
ret = AVB_IO_RESULT_ERROR_IO;
goto fail;
}
if (dst == bdata)
memcpy(out_buf, bdata + s, cnt);
else if (dst == dst64)
memcpy(out_buf, dst, cnt); //internal copy
s = 0;
bs += blk_num;
num_read += cnt;
out_buf += cnt;
#ifdef AVB_VVDEBUG
printf("\nnum_read=%ld", cnt);
printf("\n----dump---\n");
print_buffer(0, buffer, HEXDUMP_WIDTH, cnt, 0);
printf("--- end ---\n");
#endif
}
*out_num_read = num_read;
ret = AVB_IO_RESULT_OK;
#ifdef AVB_VVDEBUG
printf("\nnum_read=%zu", num_read);
printf("\n----dump---\n");
print_buffer(0, buffer, HEXDUMP_WIDTH, num_read, 0);
printf("--- end ---\n");
#endif
fail:
free(bdata);
return ret;
}
/* Writes |num_bytes| from |bffer| at offset |offset| to partition
* with name |partition| (NUL-terminated UTF-8 string). If |offset|
* is negative, its absolute value should be interpreted as the
* number of bytes from the end of the partition.
*
* This function returns AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION if
* there is no partition with the given name,
* AVB_IO_RESULT_ERROR_RANGE_OUTSIDE_PARTITION if the requested
* byterange goes outside the partition, and AVB_IO_RESULT_ERROR_IO
* if there was an I/O error from the underlying I/O subsystem. If
* the operation succeeds as requested AVB_IO_RESULT_OK is
* returned.
*
* This function never does any partial I/O, it either transfers all
* of the requested bytes or returns an error.
*/
AvbIOResult fsl_write_to_partition(AvbOps* ops, const char* partition,
int64_t offset, size_t num_bytes,
const void* buffer)
{
struct fastboot_ptentry *pte;
unsigned char *bdata;
unsigned char *in_buf = (unsigned char *)buffer;
unsigned long blksz;
unsigned long s, cnt;
size_t num_write = 0;
lbaint_t part_start, part_end, bs;
margin_pos_t margin;
AvbIOResult ret;
DEBUGAVB("[%s]: offset=%ld, num_bytes=%zu\n", partition, (long)offset, num_bytes);
assert(buffer != NULL);
if (!fs_dev_desc && (fs_dev_desc = get_mmc_desc()) == NULL) {
ERR("mmc device not found\n");
return AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION;
}
pte = fastboot_flash_find_ptn(partition);
if (!pte) {
ERR("no %s partition\n", partition);
return AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION;
}
blksz = fs_dev_desc->blksz;
part_start = pte->start;
part_end = pte->start + pte->length - 1;
VDEBUG("blksz: %ld, part_end: %ld, part_start: %ld:\n",
blksz, part_end, part_start);
if(get_margin_pos((uint64_t)part_start, (uint64_t)part_end, blksz,
&margin, offset, num_bytes, false))
return AVB_IO_RESULT_ERROR_RANGE_OUTSIDE_PARTITION;
bs = (lbaint_t)margin.blk_start;
s = margin.start;
// alloc a blksz mem
bdata = (unsigned char *)memalign(ALIGN_BYTES, blksz);
if (bdata == NULL)
return AVB_IO_RESULT_ERROR_OOM;
while (num_write < num_bytes) {
memset(bdata, 0, blksz);
cnt = blksz - s;
if (num_write + cnt > num_bytes)
cnt = num_bytes - num_write;
if (!s || cnt != blksz) { //read blk first
if (!fs_dev_desc->block_read(fs_dev_desc, bs, 1, bdata)) {
ret = AVB_IO_RESULT_ERROR_IO;
goto fail;
}
}
memcpy(bdata + s, in_buf, cnt); //change data
VDEBUG("cur: bs=%ld, start=%ld, cnt=%ld bdata=0x%08x\n",
bs, s, cnt, bdata);
if (!fs_dev_desc->block_write(fs_dev_desc, bs, 1, bdata)) {
ret = AVB_IO_RESULT_ERROR_IO;
goto fail;
}
bs++;
num_write += cnt;
in_buf += cnt;
if (s != 0)
s = 0;
}
ret = AVB_IO_RESULT_OK;
fail:
free(bdata);
return ret;
}
/* Reads A/B metadata from persistent storage. Returned data is
* properly byteswapped. Returns AVB_IO_RESULT_OK on success, error
* code otherwise.
*
* If the data read is invalid (e.g. wrong magic or CRC checksum
* failure), the metadata shoule be reset using avb_ab_data_init()
* and then written to persistent storage.
*
* Implementations will typically want to use avb_ab_data_read()
* here to use the 'misc' partition for persistent storage.
*/
AvbIOResult fsl_read_ab_metadata(AvbABOps* ab_ops, struct AvbABData* data)
{
return avb_ab_data_read(ab_ops, data);
}
/* Writes A/B metadata to persistent storage. This will byteswap and
* update the CRC as needed. Returns AVB_IO_RESULT_OK on success,
* error code otherwise.
*
* Implementations will typically want to use avb_ab_data_write()
* here to use the 'misc' partition for persistent storage.
*/
AvbIOResult fsl_write_ab_metadata(AvbABOps* ab_ops, const struct AvbABData* data)
{
return avb_ab_data_write(ab_ops, data);
}
/* Gets whether the device is unlocked. The value is returned in
* |out_is_unlocked| (true if unlocked, false otherwise). Returns
* AVB_IO_RESULT_OK if the state was retrieved, otherwise an error
* code.
*/
AvbIOResult fsl_read_is_device_unlocked(AvbOps* ops, bool* out_is_unlocked) {
FbLockState status;
assert(out_is_unlocked != NULL);
*out_is_unlocked = false;
status = fastboot_get_lock_stat();
if (status != FASTBOOT_LOCK_ERROR) {
if (status == FASTBOOT_LOCK)
*out_is_unlocked = false;
else
*out_is_unlocked = true;
} else
return AVB_IO_RESULT_ERROR_IO;
DEBUGAVB("is_unlocked=%d\n", *out_is_unlocked);
return AVB_IO_RESULT_OK;
}
/* Gets the unique partition GUID for a partition with name in
* |partition| (NUL-terminated UTF-8 string). The GUID is copied as
* a string into |guid_buf| of size |guid_buf_size| and will be NUL
* terminated. The string must be lower-case and properly
* hyphenated. For example:
*
* 527c1c6d-6361-4593-8842-3c78fcd39219
*
* Returns AVB_IO_RESULT_OK on success, otherwise an error code.
*/
AvbIOResult fsl_get_unique_guid_for_partition(AvbOps* ops,
const char* partition,
char* guid_buf,
size_t guid_buf_size) {
assert(guid_buf != NULL);
#ifdef CONFIG_PARTITION_UUIDS
struct fastboot_ptentry *pte;
pte = fastboot_flash_find_ptn(partition);
if (!pte) {
ERR("no %s partition\n", partition);
return AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION;
}
strncpy(guid_buf, (const char *)pte->uuid, guid_buf_size);
guid_buf[guid_buf_size - 1] = '\0';
DEBUGAVB("[%s]: GUID=%s\n", partition, guid_buf);
return AVB_IO_RESULT_OK;
#else
return AVB_IO_RESULT_ERROR_IO;
#endif
}

+ 717
- 0
lib/avb/fsl/fsl_avbkey.c View File

@ -0,0 +1,717 @@
/*
* Copyright (C) 2016 Freescale Semiconductor, Inc.
*
* SPDX-License-Identifier: GPL-2.0+
*/
#include <common.h>
#include <stdlib.h>
#include <fsl_caam.h>
#include <fuse.h>
#include <mmc.h>
#include <fsl_avb.h>
#include "fsl_avbkey.h"
#include "utils.h"
#include "debug.h"
#define INITFLAG_FUSE_OFFSET 0
#define INITFLAG_FUSE_MASK 0x00000001
#define INITFLAG_FUSE 0x00000001
#define RPMB_BLKSZ 256
#define RPMBKEY_FUSE_OFFSET 1
#define RPMBKEY_LENGTH 32
#define RPMBKEY_FUSE_LEN ((RPMBKEY_LENGTH) + (CAAM_PAD))
#define RPMBKEY_FUSE_LENW (RPMBKEY_FUSE_LEN / 4)
static int mmc_dev_no = -1;
static struct mmc *get_mmc(void) {
extern int mmc_get_env_devno(void);
struct mmc *mmc;
if (mmc_dev_no < 0 && (mmc_dev_no = mmc_get_env_dev()) < 0)
return NULL;
mmc = find_mmc_device(mmc_dev_no);
if (!mmc || mmc_init(mmc))
return NULL;
return mmc;
}
static int fsl_fuse_ops(uint32_t *buffer, uint32_t length, uint32_t offset,
const uint8_t read) {
unsigned short bs, ws, bksz, cnt;
unsigned short num_done = 0;
margin_pos_t margin;
int i;
/* read from fuse */
bksz = CONFIG_AVB_FUSE_BANK_SIZEW;
if(get_margin_pos(CONFIG_AVB_FUSE_BANK_START, CONFIG_AVB_FUSE_BANK_END, bksz,
&margin, offset, length, false))
return -1;
bs = (unsigned short)margin.blk_start;
ws = (unsigned short)margin.start;
while (num_done < length) {
cnt = bksz - ws;
if (num_done + cnt > length)
cnt = length - num_done;
for (i = 0; i < cnt; i++) {
VDEBUG("cur: bank=%d, word=%d\n",bs, ws);
if (read) {
#ifdef CONFIG_AVB_FUSE
if (fuse_sense(bs, ws, buffer)) {
#else
if (fuse_read(bs, ws, buffer)) {
#endif
ERR("read fuse bank %d, word %d error\n", bs, ws);
return -1;
}
} else {
#ifdef CONFIG_AVB_FUSE
if (fuse_prog(bs, ws, *buffer)) {
#else
if (fuse_override(bs, ws, *buffer)) {
#endif
ERR("write fuse bank %d, word %d error\n", bs, ws);
return -1;
}
}
ws++;
buffer++;
}
bs++;
num_done += cnt;
ws = 0;
}
return 0;
}
static int fsl_fuse_read(uint32_t *buffer, uint32_t length, uint32_t offset) {
return fsl_fuse_ops(
buffer,
length,
offset,
1
);
}
static int fsl_fuse_write(const uint32_t *buffer, uint32_t length, uint32_t offset) {
return fsl_fuse_ops(
(uint32_t *)buffer,
length,
offset,
0
);
}
static int rpmb_key(struct mmc *mmc) {
char original_part;
uint8_t blob[RPMBKEY_FUSE_LEN];
uint8_t plain_key[RPMBKEY_LENGTH];
int ret;
DEBUGAVB("[rpmb]: set kley\n");
/* Switch to the RPMB partition */
original_part = mmc->block_dev.hwpart;
if (mmc->block_dev.hwpart != MMC_PART_RPMB) {
if (mmc_switch_part(mmc, MMC_PART_RPMB) != 0)
return -1;
mmc->block_dev.hwpart = MMC_PART_RPMB;
}
/* use caam hwrng to generate */
caam_open();
if (caam_hwrng(plain_key, RPMBKEY_LENGTH)) {
ERR("ERROR - caam rng\n");
ret = -1;
goto fail;
}
/* generate keyblob and program to fuse */
if (caam_gen_blob((uint32_t)plain_key, (uint32_t)blob, RPMBKEY_LENGTH)) {
ERR("gen rpmb key blb error\n");
ret = -1;
goto fail;
}
if (fsl_fuse_write((uint32_t *)blob, RPMBKEY_FUSE_LENW, RPMBKEY_FUSE_OFFSET)){
ERR("write rpmb key to fuse error\n");
ret = -1;
goto fail;
}
#ifdef CONFIG_AVB_FUSE
/* program key to mmc */
if (mmc_rpmb_set_key(mmc, plain_key)) {
ERR("Key already programmed ?\n");
ret = -1;
goto fail;
}
#endif
ret = 0;
#ifdef CONFIG_AVB_DEBUG
/* debug */
uint8_t ext_key[RPMBKEY_LENGTH];
printf(" RPMB plain kay---\n");
print_buffer(0, plain_key, HEXDUMP_WIDTH, RPMBKEY_LENGTH, 0);
if (fsl_fuse_read((uint32_t *)blob, RPMBKEY_FUSE_LENW, RPMBKEY_FUSE_OFFSET)){
ERR("read rpmb key to fuse error\n");
ret = -1;
goto fail;
}
printf(" RPMB blob---\n");
print_buffer(0, blob, HEXDUMP_WIDTH, RPMBKEY_FUSE_LEN, 0);
if (caam_decap_blob((uint32_t)ext_key, (uint32_t)blob, RPMBKEY_LENGTH)) {
ret = -1;
goto fail;
}
printf(" RPMB extract---\n");
print_buffer(0, ext_key, HEXDUMP_WIDTH, RPMBKEY_LENGTH, 0);
/* debug done */
#endif
fail:
/* Return to original partition */
if (mmc->block_dev.hwpart != original_part) {
if (mmc_switch_part(mmc, original_part) != 0)
return -1;
mmc->block_dev.hwpart = original_part;
}
return ret;
}
static int rpmb_read(struct mmc *mmc, uint8_t *buffer, size_t num_bytes, int64_t offset) {
unsigned char *bdata = NULL;
unsigned char *out_buf = (unsigned char *)buffer;
unsigned long s, cnt;
unsigned long blksz;
size_t num_read = 0;
unsigned short part_start, part_length, part_end, bs, be;
margin_pos_t margin;
char original_part;
uint8_t extract_key[RPMBKEY_LENGTH];
uint8_t blob[RPMBKEY_FUSE_LEN];
int ret;
blksz = RPMB_BLKSZ;
part_length = mmc->capacity_rpmb >> 8;
part_start = 0;
part_end = part_start + part_length - 1;
DEBUGAVB("[rpmb]: offset=%ld, num_bytes=%zu\n", (long)offset, num_bytes);
if(get_margin_pos(part_start, part_end, blksz,
&margin, offset, num_bytes, false))
return -1;
bs = (unsigned short)margin.blk_start;
be = (unsigned short)margin.blk_end;
s = margin.start;
/* Switch to the RPMB partition */
original_part = mmc->block_dev.hwpart;
if (mmc->block_dev.hwpart != MMC_PART_RPMB) {
if (mmc_switch_part(mmc, MMC_PART_RPMB) != 0)
return -1;
mmc->block_dev.hwpart = MMC_PART_RPMB;
}
/* get rpmb key */
if (fsl_fuse_read((uint32_t *)blob, RPMBKEY_FUSE_LENW, RPMBKEY_FUSE_OFFSET)){
ERR("read rpmb key error\n");
ret = -1;
goto fail;
}
caam_open();
if (caam_decap_blob((uint32_t)extract_key, (uint32_t)blob, RPMBKEY_LENGTH)) {
ERR("decap rpmb key error\n");
ret = -1;
goto fail;
}
// alloc a blksz mem
bdata = (unsigned char *)memalign(ALIGN_BYTES, blksz);
if (bdata == NULL) {
ret = -1;
goto fail;
}
// one block a time
while (bs <= be) {
memset(bdata, 0, blksz);
if (mmc_rpmb_read(mmc, bdata, bs, 1, extract_key) != 1) {
ret = -1;
goto fail;
}
cnt = blksz - s;
if (num_read + cnt > num_bytes)
cnt = num_bytes - num_read;
VDEBUG("cur: bs=%d, start=%ld, cnt=%ld bdata=0x%p\n",
bs, s, cnt, bdata);
memcpy(out_buf, bdata + s, cnt);
bs++;
num_read += cnt;
out_buf += cnt;
s = 0;
}
ret = 0;
fail:
/* Return to original partition */
if (mmc->block_dev.hwpart != original_part) {
if (mmc_switch_part(mmc, original_part) != 0)
return -1;
mmc->block_dev.hwpart = original_part;
}
if (bdata != NULL)
free(bdata);
return ret;
}
static int rpmb_write(struct mmc *mmc, uint8_t *buffer, size_t num_bytes, int64_t offset) {
unsigned char *bdata = NULL;
unsigned char *in_buf = (unsigned char *)buffer;
unsigned long s, cnt;
unsigned long blksz;
size_t num_write = 0;
unsigned short part_start, part_length, part_end, bs;
margin_pos_t margin;
char original_part;
uint8_t extract_key[RPMBKEY_LENGTH];
uint8_t blob[RPMBKEY_FUSE_LEN];
int ret;
blksz = RPMB_BLKSZ;
part_length = mmc->capacity_rpmb >> 8;
part_start = 0;
part_end = part_start + part_length - 1;
DEBUGAVB("[rpmb]: offset=%ld, num_bytes=%zu\n", (long)offset, num_bytes);
if(get_margin_pos(part_start, part_end, blksz,
&margin, offset, num_bytes, false)) {
ERR("get_margin_pos err\n");
return -1;
}
bs = (unsigned short)margin.blk_start;
s = margin.start;
/* Switch to the RPMB partition */
original_part = mmc->block_dev.hwpart;
if (mmc->block_dev.hwpart != MMC_PART_RPMB) {
if (mmc_switch_part(mmc, MMC_PART_RPMB) != 0)
return -1;
mmc->block_dev.hwpart = MMC_PART_RPMB;
}
/* get rpmb key */
if (fsl_fuse_read((uint32_t *)blob, RPMBKEY_FUSE_LENW, RPMBKEY_FUSE_OFFSET)){
ERR("read rpmb key error\n");
ret = -1;
goto fail;
}
caam_open();
if (caam_decap_blob((uint32_t)extract_key, (uint32_t)blob, RPMBKEY_LENGTH)) {
ERR("decap rpmb key error\n");
ret = -1;
goto fail;
}
// alloc a blksz mem
bdata = (unsigned char *)memalign(ALIGN_BYTES, blksz);
if (bdata == NULL) {
ret = -1;
goto fail;
}
while (num_write < num_bytes) {
memset(bdata, 0, blksz);
cnt = blksz - s;
if (num_write + cnt > num_bytes)
cnt = num_bytes - num_write;
if (!s || cnt != blksz) { //read blk first
if (mmc_rpmb_read(mmc, bdata, bs, 1, extract_key) != 1) {
ERR("mmc_rpmb_read err, mmc= 0x%08x\n", (unsigned int)mmc);
ret = -1;
goto fail;
}
}
memcpy(bdata + s, in_buf, cnt); //change data
VDEBUG("cur: bs=%d, start=%ld, cnt=%ld\n", bs, s, cnt);
if (mmc_rpmb_write(mmc, bdata, bs, 1, extract_key) != 1) {
ret = -1;
goto fail;
}
bs++;
num_write += cnt;
in_buf += cnt;
if (s != 0)
s = 0;
}
ret = 0;
fail:
/* Return to original partition */
if (mmc->block_dev.hwpart != original_part) {
if (mmc_switch_part(mmc, original_part) != 0)
return -1;
mmc->block_dev.hwpart = original_part;
}
if (bdata != NULL)
free(bdata);
return ret;
}
int rbkidx_erase(void) {
int i;
kblb_hdr_t hdr;
kblb_tag_t *tag;
struct mmc *mmc_dev;
if ((mmc_dev = get_mmc()) == NULL) {
ERR("err get mmc device\n");
return -1;
}
/* read the kblb header */
if (rpmb_read(mmc_dev, (uint8_t *)&hdr, sizeof(hdr), 0) != 0) {
ERR("read RPMB error\n");
return -1;
}
if (memcmp(hdr.magic, AVB_KBLB_MAGIC, AVB_KBLB_MAGIC_LEN) != 0) {
ERR("magic not match\n");
return -1;
}
/* reset rollback index */
uint32_t offset = AVB_RBIDX_START;
uint32_t rbidx_len = AVB_RBIDX_LEN;
uint8_t *rbidx = malloc(rbidx_len);
if (rbidx == NULL)
return -1;
memset(rbidx, 0, rbidx_len);
*(uint64_t *)rbidx = AVB_RBIDX_INITVAL;
for (i = 0; i < AVB_MAX_NUMBER_OF_ROLLBACK_INDEX_LOCATIONS; i++) {
tag = &hdr.rbk_tags[i];
tag->flag = AVB_RBIDX_FLAG;
tag->offset = offset;
tag->len = rbidx_len;
/* write */
if (rpmb_write(mmc_dev, rbidx, tag->len, tag->offset) != 0) {
ERR("write RBKIDX RPMB error\n");
free(rbidx);
return -1;
}
offset += AVB_RBIDX_ALIGN;
}
free(rbidx);
/* write back hdr */
if (rpmb_write(mmc_dev, (uint8_t *)&hdr, sizeof(hdr), 0) != 0) {
ERR("write RPMB hdr error\n");
return -1;
}
return 0;
}
int avbkey_init(uint8_t *plainkey, uint32_t keylen) {
int i;
kblb_hdr_t hdr;
kblb_tag_t *tag;
struct mmc *mmc_dev;
uint32_t init_flag;
/* int ret; */
assert(plainkey != NULL);
/* check overflow */
if (keylen > AVB_RBIDX_START - AVB_PUBKY_OFFSET) {
ERR("key len overflow\n");
return -1;
}
/* check init status */
if (fsl_fuse_read(&init_flag, 1, INITFLAG_FUSE_OFFSET)) {
ERR("ERROR - read fuse init flag error\n");
return -1;
}
if ((init_flag & INITFLAG_FUSE_MASK) == INITFLAG_FUSE) {
ERR("ERROR - already inited\n");
return -1;
}
init_flag = INITFLAG_FUSE & INITFLAG_FUSE_MASK;
/* generate and write key to mmc/fuse */
if ((mmc_dev = get_mmc()) == NULL) {
ERR("ERROR - get mmc device\n");
return -1;
}
if (rpmb_key(mmc_dev)) {
ERR("ERROR - write mmc rpmb key\n");
return -1;
}