[Feature]add MT2731_MP2_MR2_SVN388 baseline version
Change-Id: Ief04314834b31e27effab435d3ca8ba33b499059
diff --git a/src/bsp/lk/lib/bootctrl/bootctrl_api.c b/src/bsp/lk/lib/bootctrl/bootctrl_api.c
new file mode 100644
index 0000000..3129b1a
--- /dev/null
+++ b/src/bsp/lk/lib/bootctrl/bootctrl_api.c
@@ -0,0 +1,411 @@
+/*
+ * 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 <assert.h>
+#include <endian.h>
+#include <errno.h>
+#include <lib/bio.h>
+#include <lib/bootctrl.h>
+#include <lib/bootctrl_plat.h>
+#include <lib/cksum.h>
+#include <lib/mempool.h>
+#include <libavb_ab/libavb_ab.h>
+#include <platform.h>
+#include <string.h>
+#include <trace.h>
+
+#define BOOTCTR_PARTITION "misc"
+#define MOD "bootctrl"
+#define SLOT_COUNT 2
+#define LOCAL_TRACE 0
+/******************************************************************************
+ * DEBUG
+ ******************************************************************************/
+static AvbABData metadata_saved;
+static int metadata_read = 0;
+
+const char *get_suffix(void)
+{
+ const char *suffix[] = {BOOTCTRL_SUFFIX_A, BOOTCTRL_SUFFIX_B};
+ int slot = get_current_slot();
+ if (slot < 0 || slot >= SLOT_COUNT)
+ return NULL;
+ return suffix[slot];
+}
+
+static int read_write_partition_info(AvbABData *bctrl ,int mode)
+{
+ int ret = -1;
+ bdev_t *bdev;
+ size_t bdev_erase_size;
+ size_t total_erase_size;
+ ssize_t read_bytes;
+ ssize_t write_bytes;
+ void *metadata_info_buf = NULL;
+ uint32_t crc32val;
+
+ bdev = bio_open_by_label(BOOTCTR_PARTITION);
+ if (!bdev) {
+ LTRACEF("Partition [%s] is not exist.\n", BOOTCTR_PARTITION);
+ return ret;
+ }
+
+ ASSERT(bdev->geometry != NULL);
+ bdev_erase_size = (size_t)bdev->geometry->erase_size;
+ LTRACEF("bdev_erase_size is %d. \n", bdev_erase_size);
+ switch (mode) {
+ case READ_PARTITION:
+ if ((metadata_read) && (!memcmp(metadata_saved.magic ,AVB_AB_MAGIC,
+ AVB_AB_MAGIC_LEN))) {
+ memcpy(bctrl, &metadata_saved, sizeof(AvbABData));
+ } else {
+ read_bytes = bio_read(bdev, (void *)bctrl,
+ OFFSETOF_METADATA_INFO, sizeof(AvbABData));
+ if (-1 == read_bytes) {
+ LTRACEF("bio_read error %ld\n", read_bytes);
+ goto out;
+ }
+ memcpy(&metadata_saved,bctrl,sizeof(AvbABData));
+ metadata_read = 1;
+ }
+ break;
+ case WRITE_PARTITION:
+ crc32val = (uint32_t)crc32(0UL, (const uint8_t *)bctrl,
+ sizeof(AvbABData) - sizeof(uint32_t));
+ bctrl->crc32 = ntohl(crc32val);
+
+ total_erase_size = bdev_erase_size *
+ ((OFFSETOF_METADATA_INFO + sizeof(AvbABData)) / bdev_erase_size + 1);
+
+ // allocate buffer for the partition
+ metadata_info_buf = mempool_alloc(total_erase_size, MEMPOOL_ANY);
+ if (!metadata_info_buf) {
+ LTRACEF("mempool alloc error. \n");
+ goto out;
+ }
+
+ // read the partition data
+ read_bytes = bio_read(bdev, (void *)metadata_info_buf,
+ 0, total_erase_size);
+ if (-1 == read_bytes) {
+ LTRACEF("bio_read error: %zd\n", read_bytes);
+ goto out;
+ }
+
+ // update the content in partition_buf
+ memcpy(metadata_info_buf + OFFSETOF_METADATA_INFO, bctrl, sizeof(AvbABData));
+
+ // earse the partition
+ write_bytes = bio_erase(bdev, 0, total_erase_size);
+ if (write_bytes < 0) {
+ LTRACEF("bio_erase error: %zd\n", write_bytes);
+ goto out;
+ }
+
+ // write the partition
+ write_bytes = bio_write(bdev, (void *)metadata_info_buf,
+ 0, total_erase_size);
+ if ((size_t)write_bytes != total_erase_size) {
+ LTRACEF("bio_write error: %zd\n", write_bytes);
+ goto out;
+ }
+
+ metadata_read = 0; //force to read from partition after successful blkdev_write()E
+ break;
+ default:
+ break;
+ }
+ ret = 0;
+out:
+ bio_close(bdev);
+ if (metadata_info_buf != NULL) {
+ mempool_free(metadata_info_buf);
+ }
+ return ret;
+}
+
+int ab_metadata_init(int slot)
+{
+ int slot1 = 0;
+ int ret = -1 ;
+ AvbABSlotData *slotp;
+
+ AvbABData metadata;
+
+ if (slot < 0 || slot >= SLOT_COUNT) {
+ return -1;
+ }
+
+ ret = read_write_partition_info(&metadata, READ_PARTITION);
+ if (ret < 0) {
+ return -1;
+ }
+
+ memcpy(metadata.magic ,AVB_AB_MAGIC, AVB_AB_MAGIC_LEN);
+
+ /* Set highest priority and reset retry count */
+ slotp = &metadata.slots[slot];
+ slotp->successful_boot = 0;
+ slotp->priority = AVB_AB_MAX_PRIORITY;
+ slotp->tries_remaining = AVB_AB_MAX_TRIES_REMAINING;
+ slotp->efuse_write = 0;
+ slotp->bl_ver = 0;
+
+ /* Re-set arg to another slot */
+ slot1 = (slot == 0) ? 1 : 0;
+ slotp = &metadata.slots[slot1];
+ slotp->successful_boot = 0;
+ slotp->priority = AVB_AB_MAX_PRIORITY - 1;
+ slotp->tries_remaining = AVB_AB_MAX_TRIES_REMAINING;
+ slotp->efuse_write = 0;
+ slotp->bl_ver = 0;
+
+ ret = read_write_partition_info(&metadata, WRITE_PARTITION);
+ if (ret < 0) {
+ return -1;
+ }
+ return 0;
+}
+
+int get_current_slot(void)
+{
+ int slot = 0, ret = -1;
+
+ AvbABData metadata;
+
+ ret = read_write_partition_info(&metadata, READ_PARTITION);
+ if (ret < 0) {
+ return -1;
+ }
+
+ if (memcmp(metadata.magic , AVB_AB_MAGIC, AVB_AB_MAGIC_LEN) != 0) {
+ LTRACEF("booctrl magic not match init default value\n");
+ ab_metadata_init(0);
+ plat_ab_set_active_bootdev(0);
+ return slot;
+ }
+ slot = (metadata.slots[0].priority >= metadata.slots[1].priority) ? 0 : 1;
+
+ return slot;
+}
+
+
+int rollback_slot(int slot)
+{
+ int slot1,ret = -1;
+ AvbABSlotData *slotp;
+ AvbABData metadata;
+
+ ret = read_write_partition_info(&metadata, READ_PARTITION);
+ if (ret < 0) {
+ return -1;
+ }
+
+ /* Set highest priority and reset retry count */
+ slotp = &metadata.slots[slot];
+ slotp->priority = AVB_AB_MAX_PRIORITY;
+
+ /* Ensure other slot doesn't have as high a priority. */
+ slot1 = (slot == 0) ? 1 : 0;
+ slotp = &metadata.slots[slot1];
+ if (slotp->priority == AVB_AB_MAX_PRIORITY)
+ slotp->priority = AVB_AB_MAX_PRIORITY - 1;
+
+ ret = read_write_partition_info(&metadata, WRITE_PARTITION);
+ if (ret < 0) {
+ return -1;
+ }
+
+ return 0;
+}
+
+uint8_t get_retry_count(int slot)
+{
+ int ret = -1;
+ AvbABSlotData *slotp;
+ AvbABData metadata;
+
+ if (slot < 0 || slot >= SLOT_COUNT) {
+ return ret;
+ }
+
+ ret = read_write_partition_info(&metadata, READ_PARTITION);
+ if (ret < 0) {
+ return -1;
+ }
+
+ slotp = &metadata.slots[slot];
+ return slotp->tries_remaining;
+}
+
+int reduce_retry_count(int slot)
+{
+ int ret = -1;
+ AvbABSlotData *slotp;
+ AvbABData metadata;
+
+ if (slot < 0 || slot >= SLOT_COUNT) {
+ return -1;
+ }
+
+ ret = read_write_partition_info(&metadata, READ_PARTITION);
+ if (ret < 0) {
+ return -1;
+ }
+
+ slotp = &metadata.slots[slot];
+ if (slotp->tries_remaining > 0)
+ slotp->tries_remaining--;
+
+ ret = read_write_partition_info(&metadata, WRITE_PARTITION);
+ if (ret < 0) {
+ return -1;
+ }
+
+ return 0;
+}
+
+int check_valid_slot(void)
+{
+ int ret = -1;
+ AvbABData metadata;
+
+ ret = read_write_partition_info(&metadata, READ_PARTITION);
+
+ if (ret < 0) {
+ return -1;
+ }
+
+ if (memcmp(metadata.magic , AVB_AB_MAGIC, AVB_AB_MAGIC_LEN) != 0) {
+ LTRACEF("booctrl magic not match init default value\n");
+ ab_metadata_init(0);
+ return 0;
+ }
+
+ if ((metadata.slots[0].priority > 0) || (metadata.slots[1].priority > 0))
+ return 0;
+
+ return -1;
+}
+
+int mark_slot_invalid(int slot)
+{
+ int ret = -1;
+ AvbABSlotData *slotp;
+ AvbABData metadata;
+
+ if (slot < 0 || slot >= SLOT_COUNT) {
+ return -1;
+ }
+
+ ret = read_write_partition_info(&metadata, READ_PARTITION);
+ if (ret < 0) {
+ return -1;
+ }
+
+ slotp = &metadata.slots[slot];
+ slotp->successful_boot = 0;
+ slotp->priority = 0;
+
+ ret = read_write_partition_info(&metadata, WRITE_PARTITION);
+ if (ret < 0) {
+ return -1;
+ }
+
+ return 0;
+}
+
+int get_bootup_status(int slot)
+{
+ int ret = -1;
+ AvbABSlotData *slotp;
+ AvbABData metadata;
+
+ if (slot < 0 || slot >= SLOT_COUNT) {
+ return -1;
+ }
+
+ ret = read_write_partition_info(&metadata, READ_PARTITION);
+ if (ret < 0) {
+ return -1;
+ }
+
+ slotp = &metadata.slots[slot];
+ return slotp->successful_boot;
+}
+
+static void check_update_anti_rollback_bl_ver(int slot)
+{
+ int ret = -1;
+ AvbABSlotData *slotp;
+ AvbABData metadata;
+
+ ret = read_write_partition_info(&metadata, READ_PARTITION);
+ if (ret < 0) {
+ return;
+ }
+ slotp = &metadata.slots[slot];
+ if (slotp->efuse_write) {
+ ret = plat_write_lk_antirollback_version(slotp->bl_ver);
+ if (ret) {
+ LTRACEF("efuse write bl ver %d fail: %d\n",slotp->bl_ver,ret);
+ }
+ slotp->efuse_write = 0;
+ read_write_partition_info(&metadata, WRITE_PARTITION);
+ }
+}
+
+int check_ab_boot(void)
+{
+ int ret, slot,next_slot;
+
+ if (check_valid_slot() != 0){
+ ab_metadata_init(0);
+ plat_ab_set_active_bootdev(0);
+ }
+
+ slot = get_current_slot();
+ if (get_bootup_status(slot) == 1) {
+ check_update_anti_rollback_bl_ver(slot);
+ return 0;
+ }
+
+ if (get_retry_count(slot) > 0) {
+ reduce_retry_count(slot);
+ return 0;
+ }
+
+ mark_slot_invalid(slot);
+
+ if (check_valid_slot() == -1)
+ return -EIO;
+ next_slot = (slot == 0) ? 1 : 0;
+ ret = plat_ab_set_active_bootdev(next_slot);
+
+ /* report the bad slot error code when set new active bootdev ok */
+ if (ret == 0)
+ return -EBADSLT;
+
+ /* otherwise, report the error code we encounter */
+ return ret;
+}
+
diff --git a/src/bsp/lk/lib/bootctrl/bootctrl_plat.c b/src/bsp/lk/lib/bootctrl/bootctrl_plat.c
new file mode 100644
index 0000000..7557cd2
--- /dev/null
+++ b/src/bsp/lk/lib/bootctrl/bootctrl_plat.c
@@ -0,0 +1,34 @@
+/*
+ * 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 <errno.h>
+
+/* plat_ab_set_active_bootdev() - set active boot device in ab boot flow */
+__WEAK int plat_ab_set_active_bootdev(int slot)
+{
+ return -ENOTSUP;
+}
+
+__WEAK int plat_write_lk_antirollback_version(int version)
+{
+ return 0;
+}
diff --git a/src/bsp/lk/lib/bootctrl/include/lib/bootctrl.h b/src/bsp/lk/lib/bootctrl/include/lib/bootctrl.h
new file mode 100644
index 0000000..dd9d88c
--- /dev/null
+++ b/src/bsp/lk/lib/bootctrl/include/lib/bootctrl.h
@@ -0,0 +1,136 @@
+/*
+ * Copyright (c) 2016 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.
+ */
+
+#ifndef _BOOTCTRL_H_
+#define _BOOTCTRL_H_
+
+#include <stdint.h>
+
+/* struct boot_ctrl occupies the slot_suffix field of
+ * struct bootloader_message */
+
+#define OFFSETOF_METADATA_INFO 2048
+
+#define BOOTCTRL_MAGIC 0x19191100
+#define BOOTCTRL_SUFFIX_A "_a"
+#define BOOTCTRL_SUFFIX_B "_b"
+#define BOOTCTRL_SUFFIX_MAXLEN 2
+
+#define BOOT_CONTROL_VERSION 1
+#define READ_PARTITION 0
+#define WRITE_PARTITION 1
+
+typedef struct slot_metadata {
+ uint8_t priority : 3;
+ uint8_t retry_count : 3;
+ uint8_t successful_boot : 1;
+ uint8_t normal_boot : 1;
+} slot_metadata_t;
+typedef struct boot_ctrl {
+ /* Magic for identification */
+ uint32_t magic;
+
+ /* Version of struct. */
+ uint8_t version;
+
+ /* Information about each slot. */
+ slot_metadata_t slot_info[2];
+
+ uint8_t recovery_retry_count;
+} boot_ctrl_t;
+
+
+typedef enum {
+ BOOT_PART_NONE = 0,
+ BOOT_PART_A,
+ BOOT_PART_B
+} boot_part_t;
+
+#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
+/* bootctrl API */
+/**
+* get_suffix() returns the current slot' suffix.
+*/
+const char *get_suffix(void);
+/**
+* get_current_slot() returns the current slot used by partitions.
+*/
+int get_current_slot(void);
+/**
+* ab_metadata_init() init two slot information and marks the slot passed in
+* parameter as the active boot slot.
+* Returns whether the command succeeded.
+*/
+int ab_metadata_init(int slot);
+/**
+* get_retry_count() get the slot's boot retry count. if retry count < 0,
+* should switch to next slot.
+* Returns the retry count.
+*/
+uint8_t get_retry_count(int slot);
+/**
+* reduce_retry_count() reduce the slot's boot retry count.
+*/
+int reduce_retry_count(int slot);
+/**
+* check_valid_slot() check whether valid slot exist for boot.
+* Returns whether the command succeeded.
+*/
+int check_valid_slot(void);
+/**
+* mark_slot_invalid() mark the slot as invalid.
+* Returns whether the command succeeded.
+*/
+int mark_slot_invalid(int slot);
+/**
+* get_bootup_status() get whether the slot have been successfully booted.
+* Returns whether the command succeeded.
+*/
+int get_bootup_status(int slot);
+
+/**
+ * check_ab_boot() - check ab boot status
+ *
+ * check ab boot status, and reduce retry count on current slot if necessary.
+ * If the retry count reaches zero, bootctrl will switch the active slot to
+ * the other slot.
+ *
+ * returns:
+ * 0: success
+ * -EBADSLT: current boot slot marked as invalid, and set new boot slot done
+ * -ENOTSUP: ab boot device not supported
+ */
+int check_ab_boot(void);
+#endif /* _BOOTCTRL_H_ */
diff --git a/src/bsp/lk/lib/bootctrl/include/lib/bootctrl_plat.h b/src/bsp/lk/lib/bootctrl/include/lib/bootctrl_plat.h
new file mode 100644
index 0000000..05140c4
--- /dev/null
+++ b/src/bsp/lk/lib/bootctrl/include/lib/bootctrl_plat.h
@@ -0,0 +1,56 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+/*
+ * plat_ab_set_active_bootdev() - set active boot device in ab boot flow
+ *
+ * this function is used to set the active boot device, aka slot in ab boot
+ * concept. The slot concept should be defined by the actual platform.
+ * For platforms that support ab boot device concept should override this
+ * function.
+ *
+ * @slot: the slot # to be set as active boot device
+ *
+ * returns:
+ * 0: success
+ * -ENOTSUP: function not supported
+ * others: failure
+ */
+__WEAK int plat_ab_set_active_bootdev(int slot);
+
+
+/*
+ * plat_write_lk_antirollback_version() - write lk version to efuse for lk anti rollback
+ *
+ * this function is used to write the current lk version to efuse for lk anti
+ * rollback function
+ *
+ * @version: the lk version to be set to efuse
+ *
+ * returns:
+ * 0: success
+ * others: failure
+ */
+__WEAK int plat_write_lk_antirollback_version(int version);
diff --git a/src/bsp/lk/lib/bootctrl/rules.mk b/src/bsp/lk/lib/bootctrl/rules.mk
new file mode 100644
index 0000000..41063e0
--- /dev/null
+++ b/src/bsp/lk/lib/bootctrl/rules.mk
@@ -0,0 +1,12 @@
+LOCAL_DIR := $(GET_LOCAL_DIR)
+MODULE := $(LOCAL_DIR)
+
+MODULE_INCLUDES += $(MODULE_BUILDDIR)/../../../include lib
+
+MODULE_SRCS += \
+ $(LOCAL_DIR)/bootctrl_api.c \
+ $(LOCAL_DIR)/bootctrl_plat.c
+
+MODULE_DEPS += lib/cksum
+
+include make/module.mk