diff options
author | Winter Wang <wente.wang@nxp.com> | 2016-11-23 16:42:22 +0800 |
---|---|---|
committer | Winter Wang <wente.wang@nxp.com> | 2016-11-23 17:05:50 +0800 |
commit | ed19ae430eb769322d8b353c621a056f0b54e48a (patch) | |
tree | bea7b82182bf72586de5783b6d9affaab7f0bb50 | |
parent | 08762032aac126483ce0505834032d1aee9781a1 (diff) | |
download | u-boot-imx-ed19ae430eb769322d8b353c621a056f0b54e48a.zip u-boot-imx-ed19ae430eb769322d8b353c621a056f0b54e48a.tar.gz u-boot-imx-ed19ae430eb769322d8b353c621a056f0b54e48a.tar.bz2 |
libavb: update avb
update avb to:
https://android.googlesource.com/platform/external/avb/
commit:baf59e232e48d0111e4b38f74c60c89e6f8f0b14
Change-Id: I4bff97d5bbd819217e25367b69a220400c7095af
Signed-off-by: Winter Wang <wente.wang@nxp.com>
-rw-r--r-- | drivers/usb/gadget/f_fastboot.c | 33 | ||||
-rw-r--r-- | include/libavb_ab.h | 42 | ||||
-rw-r--r-- | lib/Makefile | 2 | ||||
-rw-r--r-- | lib/avb/Makefile | 14 | ||||
-rw-r--r-- | lib/avb/fsl/Makefile (renamed from lib/libavb/fsl/Makefile) | 0 | ||||
-rw-r--r-- | lib/avb/fsl/debug.h (renamed from lib/libavb/fsl/debug.h) | 0 | ||||
-rw-r--r-- | lib/avb/fsl/fsl_avb.c (renamed from lib/libavb/fsl/fsl_avb.c) | 9 | ||||
-rw-r--r-- | lib/avb/fsl/fsl_avb.h (renamed from lib/libavb/fsl/fsl_avb.h) | 10 | ||||
-rw-r--r-- | lib/avb/fsl/fsl_avbkey.c (renamed from lib/libavb/fsl/fsl_avbkey.c) | 0 | ||||
-rw-r--r-- | lib/avb/fsl/fsl_avbkey.h (renamed from lib/libavb/fsl/fsl_avbkey.h) | 0 | ||||
-rw-r--r-- | lib/avb/fsl/fsl_bootctl.c (renamed from lib/libavb/fsl/fsl_bootctl.c) | 16 | ||||
-rw-r--r-- | lib/avb/libavb/Makefile (renamed from lib/libavb/Makefile) | 15 | ||||
-rw-r--r-- | lib/avb/libavb/avb_ab_flow.c (renamed from lib/libavb/avb_ab_flow.c) | 0 | ||||
-rw-r--r-- | lib/avb/libavb/avb_ab_flow.h (renamed from lib/libavb/avb_ab_flow.h) | 0 | ||||
-rw-r--r-- | lib/avb/libavb/avb_chain_partition_descriptor.c (renamed from lib/libavb/avb_chain_partition_descriptor.c) | 0 | ||||
-rw-r--r-- | lib/avb/libavb/avb_chain_partition_descriptor.h (renamed from lib/libavb/avb_chain_partition_descriptor.h) | 0 | ||||
-rw-r--r-- | lib/avb/libavb/avb_crc32.c (renamed from lib/libavb/avb_crc32.c) | 0 | ||||
-rw-r--r-- | lib/avb/libavb/avb_crypto.c (renamed from lib/libavb/avb_crypto.c) | 0 | ||||
-rw-r--r-- | lib/avb/libavb/avb_crypto.h (renamed from lib/libavb/avb_crypto.h) | 0 | ||||
-rw-r--r-- | lib/avb/libavb/avb_descriptor.c (renamed from lib/libavb/avb_descriptor.c) | 0 | ||||
-rw-r--r-- | lib/avb/libavb/avb_descriptor.h (renamed from lib/libavb/avb_descriptor.h) | 0 | ||||
-rw-r--r-- | lib/avb/libavb/avb_footer.c (renamed from lib/libavb/avb_footer.c) | 0 | ||||
-rw-r--r-- | lib/avb/libavb/avb_footer.h (renamed from lib/libavb/avb_footer.h) | 0 | ||||
-rw-r--r-- | lib/avb/libavb/avb_hash_descriptor.c (renamed from lib/libavb/avb_hash_descriptor.c) | 0 | ||||
-rw-r--r-- | lib/avb/libavb/avb_hash_descriptor.h (renamed from lib/libavb/avb_hash_descriptor.h) | 0 | ||||
-rw-r--r-- | lib/avb/libavb/avb_hashtree_descriptor.c (renamed from lib/libavb/avb_hashtree_descriptor.c) | 0 | ||||
-rw-r--r-- | lib/avb/libavb/avb_hashtree_descriptor.h (renamed from lib/libavb/avb_hashtree_descriptor.h) | 0 | ||||
-rw-r--r-- | lib/avb/libavb/avb_kernel_cmdline_descriptor.c (renamed from lib/libavb/avb_kernel_cmdline_descriptor.c) | 0 | ||||
-rw-r--r-- | lib/avb/libavb/avb_kernel_cmdline_descriptor.h (renamed from lib/libavb/avb_kernel_cmdline_descriptor.h) | 0 | ||||
-rw-r--r-- | lib/avb/libavb/avb_ops.h (renamed from lib/libavb/avb_ops.h) | 22 | ||||
-rw-r--r-- | lib/avb/libavb/avb_property_descriptor.c (renamed from lib/libavb/avb_property_descriptor.c) | 0 | ||||
-rw-r--r-- | lib/avb/libavb/avb_property_descriptor.h (renamed from lib/libavb/avb_property_descriptor.h) | 0 | ||||
-rw-r--r-- | lib/avb/libavb/avb_rsa.c (renamed from lib/libavb/avb_rsa.c) | 0 | ||||
-rw-r--r-- | lib/avb/libavb/avb_rsa.h (renamed from lib/libavb/avb_rsa.h) | 0 | ||||
-rw-r--r-- | lib/avb/libavb/avb_sha.h (renamed from lib/libavb/avb_sha.h) | 0 | ||||
-rw-r--r-- | lib/avb/libavb/avb_sha256.c (renamed from lib/libavb/avb_sha256.c) | 0 | ||||
-rw-r--r-- | lib/avb/libavb/avb_sha512.c (renamed from lib/libavb/avb_sha512.c) | 0 | ||||
-rw-r--r-- | lib/avb/libavb/avb_slot_verify.c (renamed from lib/libavb/avb_slot_verify.c) | 0 | ||||
-rw-r--r-- | lib/avb/libavb/avb_slot_verify.h (renamed from lib/libavb/avb_slot_verify.h) | 11 | ||||
-rw-r--r-- | lib/avb/libavb/avb_sysdeps.h (renamed from lib/libavb/avb_sysdeps.h) | 0 | ||||
-rw-r--r-- | lib/avb/libavb/avb_sysdeps_uboot.c (renamed from lib/libavb/avb_sysdeps_uboot.c) | 0 | ||||
-rw-r--r-- | lib/avb/libavb/avb_util.c (renamed from lib/libavb/avb_util.c) | 0 | ||||
-rw-r--r-- | lib/avb/libavb/avb_util.h (renamed from lib/libavb/avb_util.h) | 0 | ||||
-rw-r--r-- | lib/avb/libavb/avb_vbmeta_image.c (renamed from lib/libavb/avb_vbmeta_image.c) | 0 | ||||
-rw-r--r-- | lib/avb/libavb/avb_vbmeta_image.h (renamed from lib/libavb/avb_vbmeta_image.h) | 0 | ||||
-rw-r--r-- | lib/avb/libavb/libavb.h (renamed from include/libavb.h) | 29 | ||||
-rw-r--r-- | lib/avb/libavb_ab/Makefile | 2 | ||||
-rw-r--r-- | lib/avb/libavb_ab/avb_ab_flow.c | 431 | ||||
-rw-r--r-- | lib/avb/libavb_ab/avb_ab_flow.h | 226 | ||||
-rw-r--r-- | lib/avb/libavb_ab/avb_ab_ops.h | 78 |
50 files changed, 852 insertions, 88 deletions
diff --git a/drivers/usb/gadget/f_fastboot.c b/drivers/usb/gadget/f_fastboot.c index 4ab75d4..ab00dd7 100644 --- a/drivers/usb/gadget/f_fastboot.c +++ b/drivers/usb/gadget/f_fastboot.c @@ -48,7 +48,7 @@ #endif #ifdef CONFIG_AVB_SUPPORT -#include <libavb.h> +#include <libavb_ab.h> #endif #define FASTBOOT_VERSION "0.4" @@ -1852,17 +1852,19 @@ 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) -static AvbOps fsl_avb_ops = { - .read_from_partition = fsl_read_from_partition_multi, - /* .read_from_partition = fsl_read_from_partition, */ - .write_to_partition = fsl_write_to_partition, +static AvbABOps fsl_avb_ab_ops = { + .ops = { + .read_from_partition = fsl_read_from_partition_multi, + /* .read_from_partition = fsl_read_from_partition, */ + .write_to_partition = fsl_write_to_partition, + .validate_vbmeta_public_key = fsl_validate_vbmeta_public_key, + .read_rollback_index = fsl_read_rollback_index, + .write_rollback_index = fsl_write_rollback_index, + .read_is_device_unlocked = fsl_read_is_device_unlocked, + .get_unique_guid_for_partition = fsl_get_unique_guid_for_partition + }, .read_ab_metadata = fsl_read_ab_metadata, - .write_ab_metadata = fsl_write_ab_metadata, - .validate_vbmeta_public_key = fsl_validate_vbmeta_public_key, - .read_rollback_index = fsl_read_rollback_index, - .write_rollback_index = fsl_write_rollback_index, - .read_is_device_unlocked = fsl_read_is_device_unlocked, - .get_unique_guid_for_partition = fsl_get_unique_guid_for_partition + .write_ab_metadata = fsl_write_ab_metadata }; /* we can use avb to verify Trusty if we want */ @@ -1878,6 +1880,7 @@ int do_boota(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { AvbABFlowResult avb_result; AvbSlotVerifyData *avb_out_data; AvbPartitionData *avb_loadpart; + AvbOps fsl_avb_ops = fsl_avb_ab_ops.ops; #ifdef CONFIG_FASTBOOT_LOCK /* check lock state */ @@ -1888,7 +1891,7 @@ int do_boota(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { lock_status = FASTBOOT_LOCK; } /* if in lock state, do avb verify */ - avb_result = avb_ab_flow(&fsl_avb_ops, requested_partitions, &avb_out_data); + avb_result = avb_ab_flow(&fsl_avb_ab_ops, requested_partitions, &avb_out_data); if (avb_result == AVB_AB_FLOW_RESULT_OK) { assert(avb_out_data != NULL); /* load the first partition */ @@ -1919,7 +1922,7 @@ int do_boota(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { hdr = &boothdr; char bootimg[8]; - char *slot = select_slot(&fsl_avb_ops); + char *slot = select_slot(&fsl_avb_ab_ops); if (slot == NULL) { printf("boota: no bootable slot\n"); goto fail; @@ -2697,7 +2700,7 @@ static void cb_getvar(struct usb_ep *ep, struct usb_request *req) #endif #ifdef CONFIG_AVB_SUPPORT else if (is_slotvar_avb(cmd)) { - if (get_slotvar_avb(&fsl_avb_ops, cmd, + if (get_slotvar_avb(&fsl_avb_ab_ops, cmd, response + strlen(response), chars_left + 1) < 0) goto fail; } @@ -3145,7 +3148,7 @@ static void cb_set_active_avb(struct usb_ep *ep, struct usb_request *req) return; } - ret = avb_ab_mark_slot_active(&fsl_avb_ops, slot); + 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 diff --git a/include/libavb_ab.h b/include/libavb_ab.h new file mode 100644 index 0000000..52a1297 --- /dev/null +++ b/include/libavb_ab.h @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef LIBAVB_AB_H_ +#define LIBAVB_AB_H_ + +#include "../lib/avb/libavb/libavb.h" + +/* The AVB_INSIDE_LIBAVB_AB_H preprocessor symbol is used to enforce + * library users to include only this file. All public interfaces, and + * only public interfaces, must be included here. + */ + +#define AVB_INSIDE_LIBAVB_AB_H +#include "../lib/avb/libavb_ab/avb_ab_flow.h" +#include "../lib/avb/libavb_ab/avb_ab_ops.h" +#undef AVB_INSIDE_LIBAVB_AB_H + +#include "../lib/avb/fsl/fsl_avb.h" + +#endif /* LIBAVB_AB_H_ */ diff --git a/lib/Makefile b/lib/Makefile index 2be2aa6..64c1062 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -15,7 +15,7 @@ obj-$(CONFIG_BZIP2) += bzip2/ obj-$(CONFIG_TIZEN) += tizen/ obj-$(CONFIG_OF_LIBFDT) += libfdt/ obj-$(CONFIG_FIT) += libfdt/ -obj-$(CONFIG_AVB_SUPPORT) += libavb/ +obj-$(CONFIG_AVB_SUPPORT) += avb/ obj-$(CONFIG_AES) += aes.o obj-$(CONFIG_USB_TTY) += circbuf.o diff --git a/lib/avb/Makefile b/lib/avb/Makefile new file mode 100644 index 0000000..f5a264a --- /dev/null +++ b/lib/avb/Makefile @@ -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/ diff --git a/lib/libavb/fsl/Makefile b/lib/avb/fsl/Makefile index 362c917..362c917 100644 --- a/lib/libavb/fsl/Makefile +++ b/lib/avb/fsl/Makefile diff --git a/lib/libavb/fsl/debug.h b/lib/avb/fsl/debug.h index c1165ec..c1165ec 100644 --- a/lib/libavb/fsl/debug.h +++ b/lib/avb/fsl/debug.h diff --git a/lib/libavb/fsl/fsl_avb.c b/lib/avb/fsl/fsl_avb.c index 23d19f3..a1bd160 100644 --- a/lib/libavb/fsl/fsl_avb.c +++ b/lib/avb/fsl/fsl_avb.c @@ -37,6 +37,7 @@ typedef struct margin_pos margin_pos_t; static block_dev_desc_t *fs_dev_desc = NULL; static block_dev_desc_t *get_mmc_desc(void) { + extern int mmc_get_env_devno(void); int dev_no = mmc_get_env_devno(); return get_dev(FSL_AVB_DEV, dev_no); } @@ -394,9 +395,9 @@ fail: * Implementations will typically want to use avb_ab_data_read() * here to use the 'misc' partition for persistent storage. */ -AvbIOResult fsl_read_ab_metadata(AvbOps* ops, struct AvbABData* data) +AvbIOResult fsl_read_ab_metadata(AvbABOps* ab_ops, struct AvbABData* data) { - return avb_ab_data_read(ops, data); + return avb_ab_data_read(ab_ops, data); } /* Writes A/B metadata to persistent storage. This will byteswap and @@ -406,9 +407,9 @@ AvbIOResult fsl_read_ab_metadata(AvbOps* ops, struct AvbABData* data) * Implementations will typically want to use avb_ab_data_write() * here to use the 'misc' partition for persistent storage. */ -AvbIOResult fsl_write_ab_metadata(AvbOps* ops, const struct AvbABData* data) +AvbIOResult fsl_write_ab_metadata(AvbABOps* ab_ops, const struct AvbABData* data) { - return avb_ab_data_write(ops, data); + return avb_ab_data_write(ab_ops, data); } /* Checks if the given public key used to sign the 'vbmeta' diff --git a/lib/libavb/fsl/fsl_avb.h b/lib/avb/fsl/fsl_avb.h index 180186a..2230931 100644 --- a/lib/libavb/fsl/fsl_avb.h +++ b/lib/avb/fsl/fsl_avb.h @@ -7,7 +7,7 @@ #ifndef __FSL_AVB_H__ #define __FSL_AVB_H__ -#include <libavb.h> +#include <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 @@ -66,7 +66,7 @@ AvbIOResult fsl_write_to_partition(AvbOps* ops, const char* partition, * Implementations will typically want to use avb_ab_data_read() * here to use the 'misc' partition for persistent storage. */ -AvbIOResult fsl_read_ab_metadata(AvbOps* ops, struct AvbABData* data); +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, @@ -75,7 +75,7 @@ AvbIOResult fsl_read_ab_metadata(AvbOps* ops, struct AvbABData* data); * Implementations will typically want to use avb_ab_data_write() * here to use the 'misc' partition for persistent storage. */ -AvbIOResult fsl_write_ab_metadata(AvbOps* ops, const struct AvbABData* data); +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 @@ -153,7 +153,7 @@ int slotidx_from_suffix(char *suffix); * if return 0, buffer is bootctl's slot var out * if return -1, buffer is error string * */ -int get_slotvar_avb(AvbOps *ops, char *cmd, char *buffer, size_t size); +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 @@ -169,6 +169,6 @@ int avbkeyblb_init(uint8_t *plainkey, uint32_t keylen, const char *kblb_part /*" /* read a/b metadata to get curr slot * return slot suffix '_a'/'_b' or NULL */ -char *select_slot(AvbOps *ops); +char *select_slot(AvbABOps *ab_ops); #endif /* __FSL_AVB_H__ */ diff --git a/lib/libavb/fsl/fsl_avbkey.c b/lib/avb/fsl/fsl_avbkey.c index db0f068..db0f068 100644 --- a/lib/libavb/fsl/fsl_avbkey.c +++ b/lib/avb/fsl/fsl_avbkey.c diff --git a/lib/libavb/fsl/fsl_avbkey.h b/lib/avb/fsl/fsl_avbkey.h index 988158f..988158f 100644 --- a/lib/libavb/fsl/fsl_avbkey.h +++ b/lib/avb/fsl/fsl_avbkey.h diff --git a/lib/libavb/fsl/fsl_bootctl.c b/lib/avb/fsl/fsl_bootctl.c index 23625a1..94392cf 100644 --- a/lib/libavb/fsl/fsl_bootctl.c +++ b/lib/avb/fsl/fsl_bootctl.c @@ -68,13 +68,13 @@ static int get_curr_slot(AvbABData *ab_data) { return -1; } -int get_slotvar_avb(AvbOps *ops, char *cmd, char *buffer, size_t size) { +int get_slotvar_avb(AvbABOps *ab_ops, char *cmd, char *buffer, size_t size) { AvbABData ab_data; AvbABSlotData *slot_data; int slot; - assert(ops != NULL && cmd != NULL && buffer != NULL); + assert(ab_ops != NULL && cmd != NULL && buffer != NULL); char *str = cmd; if (!strcmp_l1("has-slot:", cmd)) { @@ -95,8 +95,8 @@ int get_slotvar_avb(AvbOps *ops, char *cmd, char *buffer, size_t size) { } /* load ab meta */ - if (ops->read_ab_metadata == NULL || - ops->read_ab_metadata(ops, &ab_data) != AVB_IO_RESULT_OK) { + if (ab_ops->read_ab_metadata == NULL || + ab_ops->read_ab_metadata(ab_ops, &ab_data) != AVB_IO_RESULT_OK) { strlcpy(buffer, "ab data read error", size); return -1 ; } @@ -157,15 +157,15 @@ int get_slotvar_avb(AvbOps *ops, char *cmd, char *buffer, size_t size) { return 0; } -char *select_slot(AvbOps *ops) { +char *select_slot(AvbABOps *ab_ops) { AvbABData ab_data; int curr; - assert(ops != NULL); + assert(ab_ops != NULL); /* load ab meta */ - if (ops->read_ab_metadata == NULL || - ops->read_ab_metadata(ops, &ab_data) != AVB_IO_RESULT_OK) { + if (ab_ops->read_ab_metadata == NULL || + ab_ops->read_ab_metadata(ab_ops, &ab_data) != AVB_IO_RESULT_OK) { return NULL; } curr = get_curr_slot(&ab_data); diff --git a/lib/libavb/Makefile b/lib/avb/libavb/Makefile index a768a8c..2badd60 100644 --- a/lib/libavb/Makefile +++ b/lib/avb/libavb/Makefile @@ -1,17 +1,5 @@ ccflags-y += -DAVB_COMPILATION -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 += avb_ab_flow.o \ - avb_descriptor.o \ +obj-y += avb_descriptor.o \ avb_kernel_cmdline_descriptor.o \ avb_sha512.o \ avb_vbmeta_image.o \ @@ -27,4 +15,3 @@ obj-y += avb_ab_flow.o \ avb_sha256.o \ avb_util.o \ avb_sysdeps_uboot.o -obj-y += fsl/ diff --git a/lib/libavb/avb_ab_flow.c b/lib/avb/libavb/avb_ab_flow.c index bcd6740..bcd6740 100644 --- a/lib/libavb/avb_ab_flow.c +++ b/lib/avb/libavb/avb_ab_flow.c diff --git a/lib/libavb/avb_ab_flow.h b/lib/avb/libavb/avb_ab_flow.h index c19f846..c19f846 100644 --- a/lib/libavb/avb_ab_flow.h +++ b/lib/avb/libavb/avb_ab_flow.h diff --git a/lib/libavb/avb_chain_partition_descriptor.c b/lib/avb/libavb/avb_chain_partition_descriptor.c index 40e8bb5..40e8bb5 100644 --- a/lib/libavb/avb_chain_partition_descriptor.c +++ b/lib/avb/libavb/avb_chain_partition_descriptor.c diff --git a/lib/libavb/avb_chain_partition_descriptor.h b/lib/avb/libavb/avb_chain_partition_descriptor.h index 817f74f..817f74f 100644 --- a/lib/libavb/avb_chain_partition_descriptor.h +++ b/lib/avb/libavb/avb_chain_partition_descriptor.h diff --git a/lib/libavb/avb_crc32.c b/lib/avb/libavb/avb_crc32.c index 55971af..55971af 100644 --- a/lib/libavb/avb_crc32.c +++ b/lib/avb/libavb/avb_crc32.c diff --git a/lib/libavb/avb_crypto.c b/lib/avb/libavb/avb_crypto.c index 9bd4720..9bd4720 100644 --- a/lib/libavb/avb_crypto.c +++ b/lib/avb/libavb/avb_crypto.c diff --git a/lib/libavb/avb_crypto.h b/lib/avb/libavb/avb_crypto.h index 40740c3..40740c3 100644 --- a/lib/libavb/avb_crypto.h +++ b/lib/avb/libavb/avb_crypto.h diff --git a/lib/libavb/avb_descriptor.c b/lib/avb/libavb/avb_descriptor.c index db465aa..db465aa 100644 --- a/lib/libavb/avb_descriptor.c +++ b/lib/avb/libavb/avb_descriptor.c diff --git a/lib/libavb/avb_descriptor.h b/lib/avb/libavb/avb_descriptor.h index 8086a12..8086a12 100644 --- a/lib/libavb/avb_descriptor.h +++ b/lib/avb/libavb/avb_descriptor.h diff --git a/lib/libavb/avb_footer.c b/lib/avb/libavb/avb_footer.c index 5f6ed71..5f6ed71 100644 --- a/lib/libavb/avb_footer.c +++ b/lib/avb/libavb/avb_footer.c diff --git a/lib/libavb/avb_footer.h b/lib/avb/libavb/avb_footer.h index 6607c75..6607c75 100644 --- a/lib/libavb/avb_footer.h +++ b/lib/avb/libavb/avb_footer.h diff --git a/lib/libavb/avb_hash_descriptor.c b/lib/avb/libavb/avb_hash_descriptor.c index 2e427de..2e427de 100644 --- a/lib/libavb/avb_hash_descriptor.c +++ b/lib/avb/libavb/avb_hash_descriptor.c diff --git a/lib/libavb/avb_hash_descriptor.h b/lib/avb/libavb/avb_hash_descriptor.h index 2668118..2668118 100644 --- a/lib/libavb/avb_hash_descriptor.h +++ b/lib/avb/libavb/avb_hash_descriptor.h diff --git a/lib/libavb/avb_hashtree_descriptor.c b/lib/avb/libavb/avb_hashtree_descriptor.c index b961e47..b961e47 100644 --- a/lib/libavb/avb_hashtree_descriptor.c +++ b/lib/avb/libavb/avb_hashtree_descriptor.c diff --git a/lib/libavb/avb_hashtree_descriptor.h b/lib/avb/libavb/avb_hashtree_descriptor.h index a5aafbf..a5aafbf 100644 --- a/lib/libavb/avb_hashtree_descriptor.h +++ b/lib/avb/libavb/avb_hashtree_descriptor.h diff --git a/lib/libavb/avb_kernel_cmdline_descriptor.c b/lib/avb/libavb/avb_kernel_cmdline_descriptor.c index 24b2978..24b2978 100644 --- a/lib/libavb/avb_kernel_cmdline_descriptor.c +++ b/lib/avb/libavb/avb_kernel_cmdline_descriptor.c diff --git a/lib/libavb/avb_kernel_cmdline_descriptor.h b/lib/avb/libavb/avb_kernel_cmdline_descriptor.h index 0eece7d..0eece7d 100644 --- a/lib/libavb/avb_kernel_cmdline_descriptor.h +++ b/lib/avb/libavb/avb_kernel_cmdline_descriptor.h diff --git a/lib/libavb/avb_ops.h b/lib/avb/libavb/avb_ops.h index 98ac907..30309c5 100644 --- a/lib/libavb/avb_ops.h +++ b/lib/avb/libavb/avb_ops.h @@ -110,28 +110,6 @@ struct AvbOps { 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 (*read_ab_metadata)(AvbOps* 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 (*write_ab_metadata)(AvbOps* 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 diff --git a/lib/libavb/avb_property_descriptor.c b/lib/avb/libavb/avb_property_descriptor.c index 03d8315..03d8315 100644 --- a/lib/libavb/avb_property_descriptor.c +++ b/lib/avb/libavb/avb_property_descriptor.c diff --git a/lib/libavb/avb_property_descriptor.h b/lib/avb/libavb/avb_property_descriptor.h index 2ad1c2e..2ad1c2e 100644 --- a/lib/libavb/avb_property_descriptor.h +++ b/lib/avb/libavb/avb_property_descriptor.h diff --git a/lib/libavb/avb_rsa.c b/lib/avb/libavb/avb_rsa.c index 8a2b8b4..8a2b8b4 100644 --- a/lib/libavb/avb_rsa.c +++ b/lib/avb/libavb/avb_rsa.c diff --git a/lib/libavb/avb_rsa.h b/lib/avb/libavb/avb_rsa.h index e82102b..e82102b 100644 --- a/lib/libavb/avb_rsa.h +++ b/lib/avb/libavb/avb_rsa.h diff --git a/lib/libavb/avb_sha.h b/lib/avb/libavb/avb_sha.h index b925bd2..b925bd2 100644 --- a/lib/libavb/avb_sha.h +++ b/lib/avb/libavb/avb_sha.h diff --git a/lib/libavb/avb_sha256.c b/lib/avb/libavb/avb_sha256.c index b1748eb..b1748eb 100644 --- a/lib/libavb/avb_sha256.c +++ b/lib/avb/libavb/avb_sha256.c diff --git a/lib/libavb/avb_sha512.c b/lib/avb/libavb/avb_sha512.c index f2f0ec4..f2f0ec4 100644 --- a/lib/libavb/avb_sha512.c +++ b/lib/avb/libavb/avb_sha512.c diff --git a/lib/libavb/avb_slot_verify.c b/lib/avb/libavb/avb_slot_verify.c index 57477d2..57477d2 100644 --- a/lib/libavb/avb_slot_verify.c +++ b/lib/avb/libavb/avb_slot_verify.c diff --git a/lib/libavb/avb_slot_verify.h b/lib/avb/libavb/avb_slot_verify.h index 87a6798..d644a44 100644 --- a/lib/libavb/avb_slot_verify.h +++ b/lib/avb/libavb/avb_slot_verify.h @@ -55,7 +55,7 @@ typedef enum { /* Get a textual representation of |result|. */ const char* avb_slot_verify_result_to_string(AvbSlotVerifyResult result); -/* Maximum number of rollback index slots number supported. */ +/* Maximum number of rollback index locations supported. */ #define AVB_MAX_NUMBER_OF_ROLLBACK_INDEX_SLOTS 4 /* AvbPartitionData contains data loaded from partitions when using @@ -95,8 +95,13 @@ typedef struct { * |vbmeta_size| bytes. You can use this data with * e.g. avb_descriptor_get_all(). * - * Rollback indexes for the slot are stored in the |rollback_indexes| - * field. + * Rollback indexes for the verified slot are stored in the + * |rollback_indexes| field. Note that avb_slot_verify() will NEVER + * modify stored_rollback_index[n] locations e.g. it will never use + * the write_rollback_index() AvbOps operation. Instead it is the job + * of the caller of avb_slot_verify() to do this based on e.g. A/B + * policy and other factors. See libavb_ab/avb_ab_flow.c for an + * example of how to do this. * * The |cmdline| field is a NUL-terminated string in UTF-8 resulting * from concatenating all |AvbKernelCmdlineDescriptor| and then diff --git a/lib/libavb/avb_sysdeps.h b/lib/avb/libavb/avb_sysdeps.h index 7fe9d06..7fe9d06 100644 --- a/lib/libavb/avb_sysdeps.h +++ b/lib/avb/libavb/avb_sysdeps.h diff --git a/lib/libavb/avb_sysdeps_uboot.c b/lib/avb/libavb/avb_sysdeps_uboot.c index be5c1d2..be5c1d2 100644 --- a/lib/libavb/avb_sysdeps_uboot.c +++ b/lib/avb/libavb/avb_sysdeps_uboot.c diff --git a/lib/libavb/avb_util.c b/lib/avb/libavb/avb_util.c index 435e556..435e556 100644 --- a/lib/libavb/avb_util.c +++ b/lib/avb/libavb/avb_util.c diff --git a/lib/libavb/avb_util.h b/lib/avb/libavb/avb_util.h index d53be97..d53be97 100644 --- a/lib/libavb/avb_util.h +++ b/lib/avb/libavb/avb_util.h diff --git a/lib/libavb/avb_vbmeta_image.c b/lib/avb/libavb/avb_vbmeta_image.c index 23607ed..23607ed 100644 --- a/lib/libavb/avb_vbmeta_image.c +++ b/lib/avb/libavb/avb_vbmeta_image.c diff --git a/lib/libavb/avb_vbmeta_image.h b/lib/avb/libavb/avb_vbmeta_image.h index 25d3689..25d3689 100644 --- a/lib/libavb/avb_vbmeta_image.h +++ b/lib/avb/libavb/avb_vbmeta_image.h diff --git a/include/libavb.h b/lib/avb/libavb/libavb.h index d025f32..b74307c 100644 --- a/include/libavb.h +++ b/lib/avb/libavb/libavb.h @@ -31,22 +31,19 @@ */ #define AVB_INSIDE_LIBAVB_H -#include "../lib/libavb/avb_ab_flow.h" -#include "../lib/libavb/avb_chain_partition_descriptor.h" -#include "../lib/libavb/avb_crypto.h" -#include "../lib/libavb/avb_descriptor.h" -#include "../lib/libavb/avb_footer.h" -#include "../lib/libavb/avb_hash_descriptor.h" -#include "../lib/libavb/avb_hashtree_descriptor.h" -#include "../lib/libavb/avb_kernel_cmdline_descriptor.h" -#include "../lib/libavb/avb_ops.h" -#include "../lib/libavb/avb_property_descriptor.h" -#include "../lib/libavb/avb_slot_verify.h" -#include "../lib/libavb/avb_sysdeps.h" -#include "../lib/libavb/avb_util.h" -#include "../lib/libavb/avb_vbmeta_image.h" +#include "avb_chain_partition_descriptor.h" +#include "avb_crypto.h" +#include "avb_descriptor.h" +#include "avb_footer.h" +#include "avb_hash_descriptor.h" +#include "avb_hashtree_descriptor.h" +#include "avb_kernel_cmdline_descriptor.h" +#include "avb_ops.h" +#include "avb_property_descriptor.h" +#include "avb_slot_verify.h" +#include "avb_sysdeps.h" +#include "avb_util.h" +#include "avb_vbmeta_image.h" #undef AVB_INSIDE_LIBAVB_H -#include "../lib/libavb/fsl/fsl_avb.h" - #endif /* LIBAVB_H_ */ diff --git a/lib/avb/libavb_ab/Makefile b/lib/avb/libavb_ab/Makefile new file mode 100644 index 0000000..f22d0ed --- /dev/null +++ b/lib/avb/libavb_ab/Makefile @@ -0,0 +1,2 @@ +ccflags-y += -DAVB_COMPILATION +obj-y += avb_ab_flow.o diff --git a/lib/avb/libavb_ab/avb_ab_flow.c b/lib/avb/libavb_ab/avb_ab_flow.c new file mode 100644 index 0000000..da8e4ea --- /dev/null +++ b/lib/avb/libavb_ab/avb_ab_flow.c @@ -0,0 +1,431 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include "avb_ab_flow.h" + +bool avb_ab_data_verify_and_byteswap(const AvbABData* src, AvbABData* dest) { + /* Ensure magic is correct. */ + if (avb_safe_memcmp(src->magic, AVB_AB_MAGIC, AVB_AB_MAGIC_LEN) != 0) { + avb_error("Magic is incorrect.\n"); + return false; + } + + avb_memcpy(dest, src, sizeof(AvbABData)); + dest->crc32 = avb_be32toh(dest->crc32); + + /* Ensure we don't attempt to access any fields if the major version + * is not supported. + */ + if (dest->version_major > AVB_AB_MAJOR_VERSION) { + avb_error("No support for given major version.\n"); + return false; + } + + /* Bail if CRC32 doesn't match. */ + if (dest->crc32 != + avb_crc32((const uint8_t*)dest, sizeof(AvbABData) - sizeof(uint32_t))) { + avb_error("CRC32 does not match.\n"); + return false; + } + + return true; +} + +void avb_ab_data_update_crc_and_byteswap(const AvbABData* src, + AvbABData* dest) { + avb_memcpy(dest, src, sizeof(AvbABData)); + dest->crc32 = avb_htobe32( + avb_crc32((const uint8_t*)dest, sizeof(AvbABData) - sizeof(uint32_t))); +} + +void avb_ab_data_init(AvbABData* data) { + avb_memset(data, '\0', sizeof(AvbABData)); + avb_memcpy(data->magic, AVB_AB_MAGIC, AVB_AB_MAGIC_LEN); + data->version_major = AVB_AB_MAJOR_VERSION; + data->version_minor = AVB_AB_MINOR_VERSION; + data->slots[0].priority = AVB_AB_MAX_PRIORITY; + data->slots[0].tries_remaining = AVB_AB_MAX_TRIES_REMAINING; + data->slots[0].successful_boot = 0; + data->slots[1].priority = AVB_AB_MAX_PRIORITY - 1; + data->slots[1].tries_remaining = AVB_AB_MAX_TRIES_REMAINING; + data->slots[1].successful_boot = 0; +} + +/* The AvbABData struct is stored 2048 bytes into the 'misc' partition + * following the 'struct bootloader_message' field. The struct is + * compatible with the guidelines in bootable/recovery/bootloader.h - + * e.g. it is stored in the |slot_suffix| field, starts with a + * NUL-byte, and is 32 bytes long. + */ +#define AB_METADATA_MISC_PARTITION_OFFSET 2048 + +AvbIOResult avb_ab_data_read(AvbABOps* ab_ops, AvbABData* data) { + AvbOps* ops = &(ab_ops->ops); + AvbABData serialized; + AvbIOResult io_ret; + size_t num_bytes_read; + + io_ret = + ops->read_from_partition(ops, "misc", AB_METADATA_MISC_PARTITION_OFFSET, + sizeof(AvbABData), &serialized, &num_bytes_read); + if (io_ret == AVB_IO_RESULT_ERROR_OOM) { + return AVB_IO_RESULT_ERROR_OOM; + } else if (io_ret != AVB_IO_RESULT_OK || + num_bytes_read != sizeof(AvbABData)) { + avb_error("Error reading A/B metadata.\n"); + return AVB_IO_RESULT_ERROR_IO; + } + + if (!avb_ab_data_verify_and_byteswap(&serialized, data)) { + avb_error( + "Error validating A/B metadata from disk. " + "Resetting and writing new A/B metadata to disk.\n"); + avb_ab_data_init(data); + return avb_ab_data_write(ab_ops, data); + } + + return AVB_IO_RESULT_OK; +} + +AvbIOResult avb_ab_data_write(AvbABOps* ab_ops, const AvbABData* data) { + AvbOps* ops = &(ab_ops->ops); + AvbABData serialized; + AvbIOResult io_ret; + + avb_ab_data_update_crc_and_byteswap(data, &serialized); + io_ret = + ops->write_to_partition(ops, "misc", AB_METADATA_MISC_PARTITION_OFFSET, + sizeof(AvbABData), &serialized); + if (io_ret == AVB_IO_RESULT_ERROR_OOM) { + return AVB_IO_RESULT_ERROR_OOM; + } else if (io_ret != AVB_IO_RESULT_OK) { + avb_error("Error writing A/B metadata.\n"); + return AVB_IO_RESULT_ERROR_IO; + } + return AVB_IO_RESULT_OK; +} + +static bool slot_is_bootable(AvbABSlotData* slot) { + return slot->priority > 0 && + (slot->successful_boot || (slot->tries_remaining > 0)); +} + +static void slot_set_unbootable(AvbABSlotData* slot) { + slot->priority = 0; + slot->tries_remaining = 0; + slot->successful_boot = 0; +} + +/* Ensure all unbootable and/or illegal states are marked as the + * canonical 'unbootable' state, e.g. priority=0, tries_remaining=0, + * and successful_boot=0. + */ +static void slot_normalize(AvbABSlotData* slot) { + if (slot->priority > 0) { + if (slot->tries_remaining == 0 && !slot->successful_boot) { + /* We've exhausted all tries -> unbootable. */ + slot_set_unbootable(slot); + } + if (slot->tries_remaining > 0 && slot->successful_boot) { + /* Illegal state - avb_ab_mark_slot_successful() will clear + * tries_remaining when setting successful_boot. + */ + slot_set_unbootable(slot); + } + } else { + slot_set_unbootable(slot); + } +} + +static const char* slot_suffixes[2] = {"_a", "_b"}; + +/* Helper function to load metadata - returns AVB_IO_RESULT_OK on + * success, error code otherwise. + */ +static AvbIOResult load_metadata(AvbABOps* ab_ops, AvbABData* ab_data, + AvbABData* ab_data_orig) { + AvbIOResult io_ret; + + io_ret = ab_ops->read_ab_metadata(ab_ops, ab_data); + if (io_ret != AVB_IO_RESULT_OK) { + avb_error("I/O error while loading A/B metadata.\n"); + return io_ret; + } + *ab_data_orig = *ab_data; + + /* Ensure data is normalized, e.g. illegal states will be marked as + * unbootable and all unbootable states are represented with + * (priority=0, tries_remaining=0, successful_boot=0). + */ + slot_normalize(&ab_data->slots[0]); + slot_normalize(&ab_data->slots[1]); + return AVB_IO_RESULT_OK; +} + +/* Writes A/B metadata to disk only if it has changed - returns + * AVB_IO_RESULT_OK on success, error code otherwise. + */ +static AvbIOResult save_metadata_if_changed(AvbABOps* ab_ops, + AvbABData* ab_data, + AvbABData* ab_data_orig) { + if (avb_safe_memcmp(ab_data, ab_data_orig, sizeof(AvbABData)) != 0) { + avb_debug("Writing A/B metadata to disk.\n"); + return ab_ops->write_ab_metadata(ab_ops, ab_data); + } + return AVB_IO_RESULT_OK; +} + +AvbABFlowResult avb_ab_flow(AvbABOps* ab_ops, + const char* const* requested_partitions, + AvbSlotVerifyData** out_data) { + AvbOps* ops = &(ab_ops->ops); + AvbSlotVerifyData* slot_data[2] = {NULL, NULL}; + AvbSlotVerifyData* data = NULL; + AvbABFlowResult ret; + AvbABData ab_data, ab_data_orig; + size_t slot_index_to_boot, n; + AvbIOResult io_ret; + + io_ret = load_metadata(ab_ops, &ab_data, &ab_data_orig); + if (io_ret == AVB_IO_RESULT_ERROR_OOM) { + ret = AVB_AB_FLOW_RESULT_ERROR_OOM; + goto out; + } else if (io_ret != AVB_IO_RESULT_OK) { + ret = AVB_AB_FLOW_RESULT_ERROR_IO; + goto out; + } + + /* Validate all bootable slots. */ + for (n = 0; n < 2; n++) { + if (slot_is_bootable(&ab_data.slots[n])) { + AvbSlotVerifyResult verify_result; + verify_result = avb_slot_verify(ops, requested_partitions, + slot_suffixes[n], &slot_data[n]); + if (verify_result != AVB_SLOT_VERIFY_RESULT_OK) { + if (verify_result == AVB_SLOT_VERIFY_RESULT_ERROR_OOM) { + ret = AVB_AB_FLOW_RESULT_ERROR_OOM; + goto out; + } + if (verify_result == AVB_SLOT_VERIFY_RESULT_ERROR_IO) { + ret = AVB_AB_FLOW_RESULT_ERROR_IO; + goto out; + } + avb_errorv("Error verifying slot ", slot_suffixes[n], " with result ", + avb_slot_verify_result_to_string(verify_result), + " - setting unbootable.\n", NULL); + slot_set_unbootable(&ab_data.slots[n]); + } + } + } + + if (slot_is_bootable(&ab_data.slots[0]) && + slot_is_bootable(&ab_data.slots[1])) { + if (ab_data.slots[1].priority > ab_data.slots[0].priority) { + slot_index_to_boot = 1; + } else { + slot_index_to_boot = 0; + } + } else if (slot_is_bootable(&ab_data.slots[0])) { + slot_index_to_boot = 0; + } else if (slot_is_bootable(&ab_data.slots[1])) { + slot_index_to_boot = 1; + } else { + /* No bootable slots! */ + avb_error("No bootable slots found.\n"); + ret = AVB_AB_FLOW_RESULT_ERROR_NO_BOOTABLE_SLOTS; + goto out; + } + + /* Update stored rollback index such that the stored rollback index + * is the largest value supporting all currently bootable slots. Do + * this for every rollback index slot. + */ + for (n = 0; n < AVB_MAX_NUMBER_OF_ROLLBACK_INDEX_SLOTS; n++) { + uint64_t rollback_index_value = 0; + + if (slot_data[0] != NULL && slot_data[1] != NULL) { + uint64_t a_rollback_index = slot_data[0]->rollback_indexes[n]; + uint64_t b_rollback_index = slot_data[1]->rollback_indexes[n]; + rollback_index_value = + (a_rollback_index < b_rollback_index ? a_rollback_index + : b_rollback_index); + } else if (slot_data[0] != NULL) { + rollback_index_value = slot_data[0]->rollback_indexes[n]; + } else if (slot_data[1] != NULL) { + rollback_index_value = slot_data[1]->rollback_indexes[n]; + } + + if (rollback_index_value != 0) { + uint64_t current_rollback_index_value; + io_ret = ops->read_rollback_index(ops, n, ¤t_rollback_index_value); + if (io_ret == AVB_IO_RESULT_ERROR_OOM) { + ret = AVB_AB_FLOW_RESULT_ERROR_OOM; + goto out; + } else if (io_ret != AVB_IO_RESULT_OK) { + avb_error("Error getting rollback index for slot.\n"); + ret = AVB_AB_FLOW_RESULT_ERROR_IO; + goto out; + } + if (current_rollback_index_value != rollback_index_value) { + io_ret = ops->write_rollback_index(ops, n, rollback_index_value); + if (io_ret == AVB_IO_RESULT_ERROR_OOM) { + ret = AVB_AB_FLOW_RESULT_ERROR_OOM; + goto out; + } else if (io_ret != AVB_IO_RESULT_OK) { + avb_error("Error setting stored rollback index.\n"); + ret = AVB_AB_FLOW_RESULT_ERROR_IO; + goto out; + } + } + } + } + + /* Finally, select this slot. */ + avb_assert(slot_data[slot_index_to_boot] != NULL); + data = slot_data[slot_index_to_boot]; + slot_data[slot_index_to_boot] = NULL; + ret = AVB_AB_FLOW_RESULT_OK; + + /* ... and decrement tries remaining, if applicable. */ + if (!ab_data.slots[slot_index_to_boot].successful_boot && + ab_data.slots[slot_index_to_boot].tries_remaining > 0) { + ab_data.slots[slot_index_to_boot].tries_remaining -= 1; + } + +out: + io_ret = save_metadata_if_changed(ab_ops, &ab_data, &ab_data_orig); + if (io_ret != AVB_IO_RESULT_OK) { + if (io_ret == AVB_IO_RESULT_ERROR_OOM) { + ret = AVB_AB_FLOW_RESULT_ERROR_OOM; + } else { + ret = AVB_AB_FLOW_RESULT_ERROR_IO; + } + if (data != NULL) { + avb_slot_verify_data_free(data); + data = NULL; + } + } + + for (n = 0; n < 2; n++) { + if (slot_data[n] != NULL) { + avb_slot_verify_data_free(slot_data[n]); + } + } + + if (out_data != NULL) { + *out_data = data; + } else { + if (data != NULL) { + avb_slot_verify_data_free(data); + } + } + + return ret; +} + +AvbIOResult avb_ab_mark_slot_active(AvbABOps* ab_ops, + unsigned int slot_number) { + AvbABData ab_data, ab_data_orig; + unsigned int other_slot_number; + AvbIOResult ret; + + avb_assert(slot_number < 2); + + ret = load_metadata(ab_ops, &ab_data, &ab_data_orig); + if (ret != AVB_IO_RESULT_OK) { + goto out; + } + + /* Make requested slot top priority, unsuccessful, and with max tries. */ + ab_data.slots[slot_number].priority = AVB_AB_MAX_PRIORITY; + ab_data.slots[slot_number].tries_remaining = AVB_AB_MAX_TRIES_REMAINING; + ab_data.slots[slot_number].successful_boot = 0; + + /* Ensure other slot doesn't have as high a priority. */ + other_slot_number = 1 - slot_number; + if (ab_data.slots[other_slot_number].priority == AVB_AB_MAX_PRIORITY) { + ab_data.slots[other_slot_number].priority = AVB_AB_MAX_PRIORITY - 1; + } + + ret = AVB_IO_RESULT_OK; + +out: + if (ret == AVB_IO_RESULT_OK) { + ret = save_metadata_if_changed(ab_ops, &ab_data, &ab_data_orig); + } + return ret; +} + +AvbIOResult avb_ab_mark_slot_unbootable(AvbABOps* ab_ops, + unsigned int slot_number) { + AvbABData ab_data, ab_data_orig; + AvbIOResult ret; + + avb_assert(slot_number < 2); + + ret = load_metadata(ab_ops, &ab_data, &ab_data_orig); + if (ret != AVB_IO_RESULT_OK) { + goto out; + } + + slot_set_unbootable(&ab_data.slots[slot_number]); + + ret = AVB_IO_RESULT_OK; + +out: + if (ret == AVB_IO_RESULT_OK) { + ret = save_metadata_if_changed(ab_ops, &ab_data, &ab_data_orig); + } + return ret; +} + +AvbIOResult avb_ab_mark_slot_successful(AvbABOps* ab_ops, + unsigned int slot_number) { + AvbABData ab_data, ab_data_orig; + AvbIOResult ret; + + avb_assert(slot_number < 2); + + ret = load_metadata(ab_ops, &ab_data, &ab_data_orig); + if (ret != AVB_IO_RESULT_OK) { + goto out; + } + + if (!slot_is_bootable(&ab_data.slots[slot_number])) { + avb_error("Cannot mark unbootable slot as successful.\n"); + ret = AVB_IO_RESULT_OK; + goto out; + } + + ab_data.slots[slot_number].tries_remaining = 0; + ab_data.slots[slot_number].successful_boot = 1; + + ret = AVB_IO_RESULT_OK; + +out: + if (ret == AVB_IO_RESULT_OK) { + ret = save_metadata_if_changed(ab_ops, &ab_data, &ab_data_orig); + } + return ret; +} diff --git a/lib/avb/libavb_ab/avb_ab_flow.h b/lib/avb/libavb_ab/avb_ab_flow.h new file mode 100644 index 0000000..21f680a93 --- /dev/null +++ b/lib/avb/libavb_ab/avb_ab_flow.h @@ -0,0 +1,226 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#if !defined(AVB_INSIDE_LIBAVB_AB_H) && !defined(AVB_COMPILATION) +#error "Never include this file directly, include libavb/libavb_ab.h instead." +#endif + +#ifndef AVB_AB_FLOW_H_ +#define AVB_AB_FLOW_H_ + +#include "avb_ab_ops.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* Magic for the A/B struct when serialized. */ +#define AVB_AB_MAGIC "\0AB0" +#define AVB_AB_MAGIC_LEN 4 + +/* Versioning for the on-disk A/B metadata - keep in sync with avbtool. */ +#define AVB_AB_MAJOR_VERSION 1 +#define AVB_AB_MINOR_VERSION 0 + +/* Size of AvbABData struct. */ +#define AVB_AB_DATA_SIZE 32 + +/* Maximum values for slot data */ +#define AVB_AB_MAX_PRIORITY 15 +#define AVB_AB_MAX_TRIES_REMAINING 7 + +/* Struct used for recording per-slot metadata. + * + * When serialized, data is stored in network byte-order. + */ +typedef struct AvbABSlotData { + /* Slot priority. Valid values range from 0 to AVB_AB_MAX_PRIORITY, + * both inclusive with 1 being the lowest and AVB_AB_MAX_PRIORITY + * being the highest. The special value 0 is used to indicate the + * slot is unbootable. + */ + uint8_t priority; + + /* Number of times left attempting to boot this slot ranging from 0 + * to AVB_AB_MAX_TRIES_REMAINING. + */ + uint8_t tries_remaining; + + /* Non-zero if this slot has booted successfully, 0 otherwise. */ + uint8_t successful_boot; + + /* Reserved for future use. */ + uint8_t reserved[1]; +} AVB_ATTR_PACKED AvbABSlotData; + +/* Struct used for recording A/B metadata. + * + * When serialized, data is stored in network byte-order. + */ +typedef struct AvbABData { + /* Magic number used for identification - see AVB_AB_MAGIC. */ + uint8_t magic[AVB_AB_MAGIC_LEN]; + + /* Version of on-disk struct - see AVB_AB_{MAJOR,MINOR}_VERSION. */ + uint8_t version_major; + uint8_t version_minor; + + /* Padding to ensure |slots| field start eight bytes in. */ + uint8_t reserved1[2]; + + /* Per-slot metadata. */ + AvbABSlotData slots[2]; + + /* Reserved for future use. */ + uint8_t reserved2[12]; + + /* CRC32 of all 28 bytes preceding this field. */ + uint32_t crc32; +} AVB_ATTR_PACKED AvbABData; + +/* Copies |src| to |dest|, byte-swapping fields in the + * process. Returns false if the data is invalid (e.g. wrong magic, + * wrong CRC32 etc.), true otherwise. + */ +bool avb_ab_data_verify_and_byteswap(const AvbABData* src, AvbABData* dest); + +/* Copies |src| to |dest|, byte-swapping fields in the process. Also + * updates the |crc32| field in |dest|. + */ +void avb_ab_data_update_crc_and_byteswap(const AvbABData* src, AvbABData* dest); + +/* Initializes |data| such that it has two slots and both slots have + * maximum tries remaining. The CRC is not set. + */ +void avb_ab_data_init(AvbABData* data); + +/* Reads A/B metadata from the 'misc' partition using |ops|. Returned + * data is properly byteswapped. Returns AVB_IO_RESULT_OK on + * success, error code otherwise. + * + * If the data read from disk is invalid (e.g. wrong magic or CRC + * checksum failure), the metadata will be reset using + * avb_ab_data_init() and then written to disk. + */ +AvbIOResult avb_ab_data_read(AvbABOps* ab_ops, AvbABData* data); + +/* Writes A/B metadata to the 'misc' partition using |ops|. This will + * byteswap and update the CRC as needed. Returns AVB_IO_RESULT_OK on + * success, error code otherwise. + */ +AvbIOResult avb_ab_data_write(AvbABOps* ab_ops, const AvbABData* data); + +/* Return codes used in avb_ab_flow(), see that function for + * documentation of each value. + */ +typedef enum { + AVB_AB_FLOW_RESULT_OK, + AVB_AB_FLOW_RESULT_ERROR_OOM, + AVB_AB_FLOW_RESULT_ERROR_IO, + AVB_AB_FLOW_RESULT_ERROR_NO_BOOTABLE_SLOTS +} AvbABFlowResult; + +/* High-level function to select a slot to boot. The following + * algorithm is used: + * + * 1. A/B metadata is loaded and validated using the + * read_ab_metadata() operation. Typically this means it's read from + * the 'misc' partition and if it's invalid then it's reset using + * avb_ab_data_init() and this reset metadata is returned. + * + * 2. All bootable slots listed in the A/B metadata are verified using + * avb_slot_verify(). If a slot fails verification, it will be marked + * as unbootable in the A/B metadata and the metadata will be saved to + * disk before returning. + * + * 3. If there are no bootable slots, the value + * AVB_AB_FLOW_RESULT_ERROR_NO_BOOTABLE_SLOTS is returned. + * + * 4. For each bootable slot, the Stored Rollback Indexes are updated + * such that for each rollback index slot, the Stored Rollback Index + * is the largest number smaller than or equal to the Rollback Index + * of each slot. + * + * 5. The bootable slot with the highest priority is selected and + * returned in |out_data|. If this slot is already marked as + * successful, the A/B metadata is not modified. However, if the slot + * is not marked as bootable its |tries_remaining| count is + * decremented and the A/B metadata is saved to disk before returning. + * In either case the value AVB_AB_FLOW_RESULT_OK is returning. + * + * The partitions to load is given in |requested_partitions| as a + * NULL-terminated array of NUL-terminated strings. Typically the + * |requested_partitions| array only contains a single item for the + * boot partition, 'boot'. + * + * If an I/O operation - such as loading/saving metadata or checking + * rollback indexes - fail, the value AVB_AB_FLOW_RESULT_ERROR_IO is + * returned. + * + * If memory allocation fails, AVB_AB_FLOW_RESULT_ERROR_OOM is + * returned. + * + * Reasonable behavior for handling AVB_AB_FLOW_RESULT_ERROR_NO_BOOTABLE_SLOTS + * is to initiate device recovery (which is device-dependent). + */ +AvbABFlowResult avb_ab_flow(AvbABOps* ab_ops, + const char* const* requested_partitions, + AvbSlotVerifyData** out_data); + +/* Marks the slot with the given slot number as active. Returns + * AVB_IO_RESULT_OK on success, error code otherwise. + * + * This function is typically used by the OS updater when completing + * an update. It can also used by the firmware for implementing the + * "set_active" command. + */ +AvbIOResult avb_ab_mark_slot_active(AvbABOps* ab_ops, unsigned int slot_number); + +/* Marks the slot with the given slot number as unbootable. Returns + * AVB_IO_RESULT_OK on success, error code otherwise. + * + * This function is typically used by the OS updater before writing to + * a slot. + */ +AvbIOResult avb_ab_mark_slot_unbootable(AvbABOps* ab_ops, + unsigned int slot_number); + +/* Marks the slot with the given slot number as having booted + * successfully. Returns AVB_IO_RESULT_OK on success, error code + * otherwise. + * + * Calling this on an unbootable slot is an error - AVB_IO_RESULT_OK + * will be returned yet the function will have no side-effects. + * + * This function is typically used by the OS updater after having + * confirmed that the slot works as intended. + */ +AvbIOResult avb_ab_mark_slot_successful(AvbABOps* ab_ops, + unsigned int slot_number); + +#ifdef __cplusplus +} +#endif + +#endif /* AVB_AB_FLOW_H_ */ diff --git a/lib/avb/libavb_ab/avb_ab_ops.h b/lib/avb/libavb_ab/avb_ab_ops.h new file mode 100644 index 0000000..d3f6c01 --- /dev/null +++ b/lib/avb/libavb_ab/avb_ab_ops.h @@ -0,0 +1,78 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#if !defined(AVB_INSIDE_LIBAVB_AB_H) && !defined(AVB_COMPILATION) +#error "Never include this file directly, include libavb/libavb_ab.h instead." +#endif + +#ifndef AVB_AB_OPS_H_ +#define AVB_AB_OPS_H_ + +#include "../libavb/libavb.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct AvbABOps; +typedef struct AvbABOps AvbABOps; + +struct AvbABData; + +/* High-level operations/functions/methods for A/B that are platform + * dependent. This struct extends the AvbOps struct from libavb. + */ +struct AvbABOps { + /* Operations from libavb. */ + AvbOps ops; + + /* 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 (*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 (*write_ab_metadata)(AvbABOps* ab_ops, + const struct AvbABData* data); +}; + +#ifdef __cplusplus +} +#endif + +#endif /* AVB_AB_OPS_H_ */ |