[Feature]add MT2731_MP2_MR2_SVN388 baseline version

Change-Id: Ief04314834b31e27effab435d3ca8ba33b499059
diff --git a/src/bsp/lk/lib/upgrade_app_ctrl/include/lib/upgrade_app_ctrl.h b/src/bsp/lk/lib/upgrade_app_ctrl/include/lib/upgrade_app_ctrl.h
new file mode 100644
index 0000000..d39fe0a
--- /dev/null
+++ b/src/bsp/lk/lib/upgrade_app_ctrl/include/lib/upgrade_app_ctrl.h
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2020 MediaTek Inc.
+ *
+ * Use of this source code is governed by MIT-style
+ * license that can be found in the LICENSE file or at
+ * https://opensource.org/licenses/MIT
+ */
+
+#pragma once
+
+#include <stdint.h>
+
+#define UPG_SUCCEED   2
+
+#define BOOTCTRL_SUFFIX_A      "_a"
+#define BOOTCTRL_SUFFIX_B      "_b"
+
+
+/* upgrade_app boot control API */
+
+/**
+* get_suffix() returns the current slot' suffix.
+*/
+const char *get_suffix(void);
diff --git a/src/bsp/lk/lib/upgrade_app_ctrl/rules.mk b/src/bsp/lk/lib/upgrade_app_ctrl/rules.mk
new file mode 100644
index 0000000..33c1053
--- /dev/null
+++ b/src/bsp/lk/lib/upgrade_app_ctrl/rules.mk
@@ -0,0 +1,10 @@
+LOCAL_DIR := $(GET_LOCAL_DIR)
+MODULE := $(LOCAL_DIR)
+
+
+MODULE_SRCS += \
+    $(LOCAL_DIR)/upgrade_app_ctrl_api.c
+
+MODULE_DEPS += lib/mempool lib/bio
+
+include make/module.mk
diff --git a/src/bsp/lk/lib/upgrade_app_ctrl/upgrade_app_ctrl_api.c b/src/bsp/lk/lib/upgrade_app_ctrl/upgrade_app_ctrl_api.c
new file mode 100644
index 0000000..a2d9559
--- /dev/null
+++ b/src/bsp/lk/lib/upgrade_app_ctrl/upgrade_app_ctrl_api.c
@@ -0,0 +1,189 @@
+/*
+ * Copyright (c) 2020 MediaTek Inc.
+ *
+ * Use of this source code is governed by MIT-style
+ * license that can be found in the LICENSE file or at
+ * https://opensource.org/licenses/MIT
+ */
+#include <assert.h>
+#include <errno.h>
+#include <lib/bio.h>
+#include <lib/mempool.h>
+#include <lib/upgrade_app_ctrl.h>
+#include <platform.h>
+#include <string.h>
+#include <trace.h>
+
+#define BOOTCTR_PARTITION "misc"
+#define LOCAL_TRACE 0
+
+typedef struct boot_flag boot_flag;
+struct boot_flag {
+    int lastboot;    //0:last boot from system A, 1:last boot from system B
+    int usea;        //0:upgrade A failed or not upgrade, 2:upgrade A success
+    int useb;        //0:upgrade B failed or not upgrade, 2:upgrade B success
+    int current;     //0:current boot from system A, 1:current boot from system B
+};
+
+/**
+* set the cuurent_boot flag
+* last_flag: last_boot flag
+* current_flag: current_boot flag
+* part_name: partition name of storing boot flags
+*
+* return: 0-success, -1 failed
+*/
+static u32 set_currently_boot_flag(int last_flag, int current_flag, const char *part_name)
+{
+    int ret = -1;
+    long len = 0;
+    size_t bdev_erase_size;
+    char *buf = NULL;
+    boot_flag set_flag;
+
+    struct bdev *bdev_MISC = bio_open_by_label(part_name);
+    if (bdev_MISC == NULL) {
+        LTRACEF_LEVEL(CRITICAL, "open partition %s failed! %d \n",
+                      part_name, __LINE__);
+        goto err;
+    }
+    ASSERT(bdev_MISC->geometry != NULL);
+    bdev_erase_size = (size_t)bdev_MISC->geometry->erase_size;
+    LTRACEF("bdev_erase_size is %d. \n", bdev_erase_size);
+
+    buf = mempool_alloc(bdev_erase_size, MEMPOOL_ANY);
+    if (buf == NULL) {
+        LTRACEF_LEVEL(CRITICAL, "malloc buffer failed! %d \n", __LINE__);
+        goto err;
+    }
+    len = bio_read(bdev_MISC, buf, 0, bdev_erase_size);
+    if (len < 0) {
+        LTRACEF_LEVEL(CRITICAL, "bio_read error: %d\n", len);
+        goto err;
+    }
+
+    /* dump flag for debug */
+    LTRACEF("current boot flag is %d\n", current_flag);
+    /* set currently flag to buf */
+    set_flag.lastboot = last_flag;
+    set_flag.current = current_flag;
+    set_flag.usea = -1;
+    LTRACEF("last_flag boot flag is %d\n", last_flag);
+    set_flag.useb = -1;
+    memcpy(buf, (void *)&set_flag, sizeof(boot_flag));
+
+    // earse the partition
+    len = bio_erase(bdev_MISC, 0, bdev_erase_size);
+    if (len < 0) {
+        LTRACEF_LEVEL(CRITICAL, "bio_erase error: %d\n", len);
+        goto err;
+    }
+    /* write buf to offset 0 */
+    len = bio_write(bdev_MISC, (char *)buf, 0, bdev_erase_size);
+    if (len <=  0) {
+        LTRACEF_LEVEL(CRITICAL, "bio write fail, return : %d,  error: %s \n",
+                      len, strerror(errno));
+        LTRACEF_LEVEL(CRITICAL, "buf: %s\n", buf);
+        goto err;
+    }
+    LTRACEF("set flag: lastboot = %d, use A = %d, use B = %d, current = %d\n",
+            set_flag.lastboot, set_flag.usea, set_flag.useb, set_flag.current);
+    ret = 0;
+err:
+    if (buf) {
+        mempool_free(buf);
+    }
+    if (bdev_MISC) {
+        bio_close(bdev_MISC);
+    }
+    return ret;
+}
+
+/**
+* check boot flags to decide boot from system A or system B
+* part_name: partition name of storing boot flags
+*
+* return: 0-choose system A to boot, 1-choose system B to boot
+*/
+static u32 check_boot_partition(const char *part_name)
+{
+    int ret = 0;
+    boot_flag flag;
+    int boot = 0;
+
+    struct bdev *bdev_MISC = bio_open_by_label(part_name);
+    int len = -1;
+    char *buf = NULL;
+
+    if (!bdev_MISC) {
+        LTRACEF_LEVEL(CRITICAL, "failed to open MISC\n");
+        goto err;
+    }
+
+    /* read partition */
+    buf = mempool_alloc(sizeof(boot_flag), MEMPOOL_ANY);
+    if (buf == NULL) {
+        LTRACEF_LEVEL(CRITICAL, "malloc buffer failed! %d \n", __LINE__);
+        goto err;
+    }
+    len = bio_read(bdev_MISC, buf, 0, sizeof(boot_flag));
+    memcpy(&flag, (void *)buf, sizeof(boot_flag));
+    if (len < 0) {
+        LTRACEF_LEVEL(CRITICAL, "read %s: boot flag read error. LINE: %d\n",
+                      part_name, __LINE__);
+        goto err;
+    }
+
+    /* dump flag for debug */
+    LTRACEF("lastboot = %d, use A = %d, use B = %d, current = %d\n",
+            flag.lastboot, flag.usea, flag.useb, flag.current);
+
+    /* make decision */
+    if (flag.lastboot == 0) {
+        if (flag.useb == UPG_SUCCEED) {
+            boot = 1;
+            LTRACEF_LEVEL(ALWAYS, "***last succeed boot from A system,upgrade B succeed***\n");
+        } else {
+            boot = 0;
+            LTRACEF_LEVEL(ALWAYS, "***last succeed boot from A system,upgrade B failed or no upgrade B***\n");
+        }
+    } else if (flag.lastboot == 1) {
+        if (flag.usea == UPG_SUCCEED) {
+            boot = 0;
+            LTRACEF_LEVEL(ALWAYS, "***last succeed boot from B system,upgrade A succeed***\n");
+        } else {
+            boot = 1;
+            LTRACEF_LEVEL(ALWAYS, "***last succeed boot from B system,upgrade A failed or no upgrade A***\n");
+        }
+    } else {
+        LTRACEF_LEVEL(ALWAYS, "boot flag is not match, use default boot partition\n");
+        boot = 0;
+    }
+
+    if ((flag.current != boot) || (flag.usea == UPG_SUCCEED) ||
+        (flag.useb == UPG_SUCCEED)) {
+        ret = set_currently_boot_flag(flag.lastboot, boot, part_name);
+        if (ret != 0)
+            LTRACEF_LEVEL(CRITICAL, "set flags fail. LINE: %d\n", __LINE__);
+    }
+
+err:
+    if (buf) {
+        mempool_free(buf);
+    }
+    if (bdev_MISC) {
+        bio_close(bdev_MISC);
+    }
+    return boot;
+}
+
+const char *get_suffix(void)
+{
+    u32 boot_part;
+    LTRACEF("Enter AB upgrade_app flow\n");
+    boot_part = check_boot_partition(BOOTCTR_PARTITION);
+    LTRACEF_LEVEL(ALWAYS, "boot_part=%u, suffix=%c\n",
+                  boot_part, (boot_part == 1) ? 'B' : 'A');
+    return (boot_part == 1) ? BOOTCTRL_SUFFIX_B : BOOTCTRL_SUFFIX_A;
+}
+