[Feature]add MT2731_MP2_MR2_SVN388 baseline version
Change-Id: Ief04314834b31e27effab435d3ca8ba33b499059
diff --git a/src/bsp/lk/app/blxboot/avb.c b/src/bsp/lk/app/blxboot/avb.c
new file mode 100644
index 0000000..fbeea72
--- /dev/null
+++ b/src/bsp/lk/app/blxboot/avb.c
@@ -0,0 +1,406 @@
+/*
+ * Copyright (c) 2019 MediaTek Inc.
+ *
+ * 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 <lib/bio.h>
+#include <lib/dl_commands.h>
+/* VERIFIED BOOT 2 */
+#include <libavb/libavb.h>
+#include <libavb_ab/libavb_ab.h>
+
+#include <platform/mmc_rpmb.h>
+#include <sys/types.h>
+#include <string.h>
+
+#include "blxboot_ab.h"
+
+static AvbIOResult mt_read_from_partition(AvbOps *ops,
+ const char *partition,
+ int64_t offset,
+ size_t num_bytes,
+ void *buffer,
+ size_t *out_num_read)
+{
+ bdev_t *bdev;
+ off_t part_size;
+ size_t read_bytes;
+
+ bdev = bio_open_by_label(partition) ? : bio_open(partition);
+ if (!bdev) {
+ dprintf(CRITICAL, "Partition [%s] is not exist.\n", partition);
+ return AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION;
+ }
+
+ part_size = bdev->total_size;
+
+ if (offset < 0) {
+ if (-offset > part_size) {
+ bio_close(bdev);
+ return AVB_IO_RESULT_ERROR_RANGE_OUTSIDE_PARTITION;
+ }
+
+ offset += part_size;
+ }
+
+ if (offset+num_bytes > (uint64_t)part_size) {
+ bio_close(bdev);
+ return AVB_IO_RESULT_ERROR_RANGE_OUTSIDE_PARTITION;
+ }
+
+ read_bytes = bio_read(bdev, buffer, offset, num_bytes);
+
+ if (out_num_read != NULL)
+ *out_num_read = read_bytes;
+
+ bio_close(bdev);
+ return AVB_IO_RESULT_OK;
+}
+
+static AvbIOResult mt_write_to_partition(AvbOps *ops,
+ const char *partition,
+ int64_t offset,
+ size_t num_bytes,
+ const void *buffer)
+{
+ bdev_t *bdev;
+ off_t part_size;
+ size_t write_bytes;
+
+ bdev = bio_open_by_label(partition) ? : bio_open(partition);
+ if (!bdev) {
+ dprintf(CRITICAL, "Partition [%s] is not exist.\n", partition);
+ return AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION;
+ }
+
+ part_size = bdev->total_size;
+
+ if (offset < 0) {
+ if (-offset > part_size) {
+ bio_close(bdev);
+ return AVB_IO_RESULT_ERROR_RANGE_OUTSIDE_PARTITION;
+ }
+
+ offset += part_size;
+ }
+
+ if (offset+num_bytes > (uint64_t)part_size) {
+ bio_close(bdev);
+ return AVB_IO_RESULT_ERROR_RANGE_OUTSIDE_PARTITION;
+ }
+
+ write_bytes = bio_write(bdev, buffer,offset, num_bytes);
+
+ if (write_bytes != num_bytes) {
+ bio_close(bdev);
+ return AVB_IO_RESULT_ERROR_IO;
+ }
+
+ bio_close(bdev);
+ return AVB_IO_RESULT_OK;
+}
+
+#ifdef AVB_ENABLE_ANTIROLLBACK
+typedef struct {
+ uint64_t rollback_indexes[AVB_MAX_NUMBER_OF_ROLLBACK_INDEX_LOCATIONS];
+} rollback_indexes_t;
+#define VERIDX_IN_PRMB 0
+/*antirollback index is stored in rpmb region block 1*/
+static AvbIOResult mt_read_rollback_index(AvbOps *ops,
+ size_t rollback_index_location,
+ uint64_t *out_rollback_index)
+{
+ int ret=0;
+ unsigned char blk[256] = {0};
+ ret = mmc_rpmb_block_read(VERIDX_IN_PRMB,blk);
+ if (ret != 0 ) {
+ *out_rollback_index = 0;
+ return AVB_IO_RESULT_OK;
+ }
+ rollback_indexes_t *indexes = (rollback_indexes_t *)blk;
+ *out_rollback_index=indexes->rollback_indexes[rollback_index_location];
+#if 0
+ dprintf(CRITICAL, "indexes read: %08llx %08llx %08llx %08llx\n",
+ indexes->rollback_indexes[0], indexes->rollback_indexes[1],
+ indexes->rollback_indexes[2], indexes->rollback_indexes[3]);
+#endif
+ return AVB_IO_RESULT_OK;
+}
+
+static AvbIOResult mt_write_rollback_index(AvbOps *ops,
+ size_t rollback_index_location,
+ uint64_t rollback_index)
+{
+ int ret=0;
+ unsigned char blk[256] = {0};
+ ret = mmc_rpmb_block_read(VERIDX_IN_PRMB,blk);
+ if (ret != 0 ) {
+ return AVB_IO_RESULT_ERROR_IO;
+ }
+ rollback_indexes_t *indexes = (rollback_indexes_t *)blk;
+ indexes->rollback_indexes[rollback_index_location] = rollback_index;
+#if 0
+ dprintf(CRITICAL, "indexes write: %08llx %08llx %08llx %08llx\n",
+ indexes->rollback_indexes[0], indexes->rollback_indexes[1],
+ indexes->rollback_indexes[2], indexes->rollback_indexes[3]);
+#endif
+ ret = mmc_rpmb_block_write(VERIDX_IN_PRMB,(unsigned char *)indexes);
+ if (ret != 0 ) {
+ return AVB_IO_RESULT_ERROR_IO;
+ }
+ return AVB_IO_RESULT_OK;
+}
+#else
+static AvbIOResult mt_read_rollback_index(AvbOps *ops,
+ size_t rollback_index_location,
+ uint64_t *out_rollback_index)
+{
+ *out_rollback_index = 0;
+ return AVB_IO_RESULT_OK;
+}
+
+static AvbIOResult mt_write_rollback_index(AvbOps *ops,
+ size_t rollback_index_location,
+ uint64_t rollback_index)
+{
+ return AVB_IO_RESULT_OK;
+}
+#endif
+
+#define INDEX_RPMB_UNLOCK 1
+#define AVB_DEVICE_UNLOCK 0x5a
+static AvbIOResult mt_read_is_device_unlocked(AvbOps *ops, bool *out_is_unlocked)
+{
+ if (out_is_unlocked != NULL) {
+ *out_is_unlocked = false;
+ }
+
+#if defined(AVB_ENABLE_ANTIROLLBACK) || defined(AVB_ENABLE_DEVICE_STATE_CHANGE)
+ unsigned char blk[256]= {0};
+ int ret = -1;
+
+ ret=mmc_rpmb_block_read(INDEX_RPMB_UNLOCK,&blk[0]);
+ if (ret != 0) {
+ dprintf(CRITICAL, "mmc_rpmb_block_read fail %d.\n", ret);
+ return AVB_IO_RESULT_ERROR_IO;
+ }
+
+ if (blk[0] == AVB_DEVICE_UNLOCK)
+ *out_is_unlocked = true;
+#endif
+
+ dprintf(CRITICAL, "mt_read_is_device_unlocked return: %d.\n", *out_is_unlocked);
+
+ return AVB_IO_RESULT_OK;
+}
+
+static AvbIOResult mt_get_unique_node_for_partition(AvbOps *ops,
+ const char *partition,
+ char *guid_buf,
+ size_t guid_buf_size)
+{
+
+ strlcpy(guid_buf, "/dev/ubiblock0_0", guid_buf_size);
+ return AVB_IO_RESULT_OK;
+
+}
+static AvbIOResult mt_get_unique_guid_for_partition(AvbOps *ops,
+ const char *partition,
+ char *guid_buf,
+ size_t guid_buf_size)
+{
+ bdev_t *bdev;
+
+ bdev = bio_open_by_label(partition) ? : bio_open(partition);
+ if (!bdev) {
+ dprintf(CRITICAL, "Partition [%s] is not exist.\n", partition);
+ return AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION;
+ }
+
+ strlcpy(guid_buf, bdev->unique_uuid, guid_buf_size);
+ bio_close(bdev);
+ return AVB_IO_RESULT_OK;
+}
+
+#include <libfdt.h>
+#include <image.h>
+extern const unsigned char blob[];
+static const unsigned char *get_pubkey_in_blob(void)
+{
+ int sig_node;
+ int noffset;
+ const void *sig_blob=&blob[0];
+ sig_node = fdt_subnode_offset(sig_blob, 0, FDT_SIG_NODE);
+ for (noffset = fdt_first_subnode(sig_blob, sig_node);
+ noffset >= 0;
+ noffset = fdt_next_subnode(sig_blob, noffset)) {
+ return (const unsigned char *)fdt_getprop(sig_blob, noffset, BLOB_MOD_NODE, NULL);
+ }
+ return NULL;
+}
+
+static AvbIOResult mt_validate_vbmeta_public_key(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)
+{
+ unsigned char *pubkey_in_blob;
+ unsigned char *pubkey_in_footer;
+ AvbRSAPublicKeyHeader *header;
+
+ header = (AvbRSAPublicKeyHeader *)public_key_data;
+ pubkey_in_blob = (unsigned char *)get_pubkey_in_blob();
+ if (!pubkey_in_blob) {
+ avb_error("Public key is NULL in blob\n");
+ return AVB_IO_RESULT_ERROR_NO_SUCH_VALUE;
+ }
+ pubkey_in_footer = (unsigned char *)(public_key_data+sizeof(AvbRSAPublicKeyHeader));
+ if (memcmp(pubkey_in_blob,pubkey_in_footer,avb_be32toh(header->key_num_bits)/32)==0) {
+ *out_is_trusted = true;
+ } else {
+ *out_is_trusted = false;
+ }
+
+ return AVB_IO_RESULT_OK;
+}
+
+static AvbOps avbops;
+
+static AvbABOps avbabops = {
+ .ops = &avbops,
+
+ .read_ab_metadata = avb_ab_data_read,
+ .write_ab_metadata = avb_ab_data_write,
+};
+
+static AvbIOResult mt_get_size_of_partition(AvbOps *ops,
+ const char *partition,
+ uint64_t *out_size_num_bytes)
+{
+ bdev_t *bdev;
+
+ bdev = bio_open_by_label(partition) ? : bio_open(partition);
+ *out_size_num_bytes = (uint64_t)bdev->total_size;
+ return AVB_IO_RESULT_OK;
+}
+
+static AvbOps avbops = {
+ .ab_ops = &avbabops,
+
+ .read_from_partition = mt_read_from_partition,
+ .write_to_partition = mt_write_to_partition,
+ .validate_vbmeta_public_key = mt_validate_vbmeta_public_key,
+ .read_rollback_index = mt_read_rollback_index,
+ .write_rollback_index = mt_write_rollback_index,
+ .read_is_device_unlocked = mt_read_is_device_unlocked,
+ .get_size_of_partition = mt_get_size_of_partition,
+#ifdef BOOT_DEV_NAND
+ .get_unique_guid_for_partition = mt_get_unique_node_for_partition,
+#else
+ .get_unique_guid_for_partition = mt_get_unique_guid_for_partition,
+#endif
+};
+
+bool is_device_unlocked(void)
+{
+ AvbIOResult io_ret;
+ bool is_device_unlocked;
+ io_ret = avbops.read_is_device_unlocked(&avbops, &is_device_unlocked);
+ if (io_ret != AVB_IO_RESULT_OK) {
+ //any error treat as locked
+ return false;
+ }
+ return is_device_unlocked;
+}
+
+void *get_partition_data(const char *part_name, AvbSlotVerifyData *verifyData)
+{
+ size_t i=0;
+
+ if ((part_name == NULL) || (verifyData == NULL))
+ return NULL;
+
+ for (; i<verifyData->num_loaded_partitions; i++) {
+ if (avb_strcmp(part_name,verifyData->loaded_partitions[i].partition_name)==0) {
+ return verifyData->loaded_partitions[i].data;
+ }
+ }
+ return NULL;
+}
+
+AvbSlotVerifyResult avb_update_rollback_indexes(AvbOps *ops,AvbSlotVerifyData *verifyData)
+{
+ size_t n = 0;
+ AvbIOResult io_ret;
+ AvbSlotVerifyResult ret = AVB_SLOT_VERIFY_RESULT_OK;
+ /* 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 location.
+ */
+ for (n = 0; n < AVB_MAX_NUMBER_OF_ROLLBACK_INDEX_LOCATIONS; n++) {
+ uint64_t rollback_index_value = 0;
+
+ rollback_index_value = verifyData->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_SLOT_VERIFY_RESULT_ERROR_OOM;
+ goto out;
+ } else if (io_ret != AVB_IO_RESULT_OK) {
+ avb_error("Error getting rollback index for slot.\n");
+ ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
+ 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_SLOT_VERIFY_RESULT_ERROR_OOM;
+ goto out;
+ } else if (io_ret != AVB_IO_RESULT_OK) {
+ avb_error("Error setting stored rollback index.\n");
+ ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
+ goto out;
+ }
+ }
+ }
+ }
+out:
+ return ret;
+}
+
+AvbSlotVerifyResult android_verified_boot_2_0(const char *part_name,
+ AvbSlotVerifyData **verifyData)
+{
+ AvbSlotVerifyResult verify_result;
+ const char *requested_partitions[] = { part_name, NULL };
+ const char *ab_suffix = get_suffix() ? : "";
+
+ verify_result = avb_slot_verify(&avbops,requested_partitions,ab_suffix,is_device_unlocked(),AVB_HASHTREE_ERROR_MODE_RESTART,verifyData);
+ dprintf(CRITICAL, "avb boot verification result is %s\n",avb_slot_verify_result_to_string(verify_result));
+ if (verify_result == AVB_SLOT_VERIFY_RESULT_OK) {
+ verify_result = avb_update_rollback_indexes(&avbops,*verifyData);
+ dprintf(CRITICAL, "avb boot rollback indexes result is %s\n",avb_slot_verify_result_to_string(verify_result));
+ }
+ return verify_result;
+}
+