[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