[Feature]add MT2731_MP2_MR2_SVN388 baseline version

Change-Id: Ief04314834b31e27effab435d3ca8ba33b499059
diff --git a/src/bsp/lk/lib/aee/kdump_usb.c b/src/bsp/lk/lib/aee/kdump_usb.c
new file mode 100644
index 0000000..d2a6b9a
--- /dev/null
+++ b/src/bsp/lk/lib/aee/kdump_usb.c
@@ -0,0 +1,265 @@
+/*
+ * Copyright (c) 2018 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.
+ */
+
+#if !defined(__KDUMP_USB_C__)
+#define __KDUMP_USB_C__
+
+#include <mrdump.h>
+#include <malloc.h>
+#include <printf.h>
+#include <string.h>
+#include <sys/types.h>
+#include "aee.h"
+#include "kdump.h"
+
+/*
+ * USB Connectivity
+ * Note: for usb transmission
+ *   QMU mode : MAX packet length: 63x1024 = 64512 byte. -> GPD_BUF_SIZE_ALIGN
+ *   ZLP issue: EXSPACE should not be multiple size of 512 byte.
+ */
+#define EXSPACE      64256
+#define MAX_RSP_SIZE 64
+#define CON_TIMEOUT  5000
+
+/* Flow control */
+#define USB_RTS      "_RTS"
+#define USB_CTS      "_CTS"
+#define USB_FIN      "_FIN"
+#define USBDONE      "DONE"
+
+/*
+ * Need to align 64 bytes to meet cache line length
+ * 1. cmd[MAX_RSP_SIZE]
+ * 2. data[EXSPACE]
+ */
+struct mrdump_usb_handle {
+    char cmd[MAX_RSP_SIZE];
+    uint8_t data[EXSPACE];
+    unsigned int zipsize;
+    int idx;
+};
+
+/* flow control of usb connection */
+static bool usb_data_transfer(struct mrdump_usb_handle *handle, int length)
+{
+    int len;
+
+    /* send RTS */
+    memset(handle->cmd, 0, MAX_RSP_SIZE);
+    len = snprintf(handle->cmd, MAX_RSP_SIZE, "%s", USB_RTS);
+    len = usb_write_with_timeout(handle->cmd, strlen(handle->cmd), CON_TIMEOUT);
+    if (len > 0) {
+
+        /* receive CTS */
+        memset(handle->cmd, 0, MAX_RSP_SIZE);
+        len = usb_read_with_timeout(handle->cmd, MAX_RSP_SIZE, CON_TIMEOUT);
+        if ((len == (int)strlen(USB_CTS))&&
+                (!strncmp(handle->cmd, USB_CTS, strlen(USB_CTS)))) {
+
+            /* send DATA */
+            len = usb_write_with_timeout(handle->data, length, CON_TIMEOUT);
+            if (len > 0) {
+
+                /* get FIN */
+                memset(handle->cmd, 0, sizeof(handle->cmd));
+                len = usb_read_with_timeout(handle->cmd, sizeof(handle->cmd), CON_TIMEOUT);
+                if ((len == (int)strlen(USB_FIN)) &&
+                        (!strncmp(handle->cmd, USB_FIN, strlen(USB_FIN)))) {
+                    return true;
+                } else {
+                    voprintf_error("%s: failed to get FIN.cmd<%p,%d><%x,%x,%x,%x>\n", __func__,
+                                   handle->cmd, len, handle->cmd[0], handle->cmd[1], handle->cmd[2], handle->cmd[3]);
+                }
+
+            } else {
+                voprintf_error("%s: send DATA error.\n", __func__);
+            }
+        } else {
+            voprintf_error("%s: Not CTS after RTS.cmd<%p,%d><%x,%x,%x,%x>\n", __func__,
+                           handle->cmd, len, handle->cmd[0], handle->cmd[1], handle->cmd[2], handle->cmd[3]);
+        }
+    } else {
+        voprintf_error("%s: send RTS error.\n", __func__);
+    }
+    return false;
+}
+
+/* store data in pool (EXSPACE) and write when pool is full */
+static int do_store_or_write(struct mrdump_usb_handle *handle, uint8_t *buf, uint32_t length)
+{
+    int total;
+    unsigned int leftspace, mylen, reval;
+
+
+    /* count for leftspace */
+    total = EXSPACE;
+    leftspace = total - handle->idx;
+
+    /* check length */
+    if (length > leftspace) {
+        mylen = leftspace;
+        reval = length - leftspace;
+    } else {
+        mylen = length;
+        reval = 0;
+    }
+
+    /* store */
+    while (mylen > 0) {
+        handle->data[handle->idx] = *buf;
+        handle->idx++;
+        buf++;
+        mylen--;
+    }
+
+    /* write */
+    if (handle->idx == total) {
+        if (!usb_data_transfer(handle, handle->idx)) {
+            voprintf_error("%s: connection failed.(error idx: %d)\n",
+                           __func__, handle->idx);
+            return -1;
+        }
+        handle->idx = 0;
+    }
+
+    return reval;
+}
+
+static int usb_write_cb(void *opaque_handle, void *buf, int size)
+{
+    unsigned int    len, moves;
+    int             ret = 0;
+    uint8_t         *ptr;
+
+    struct mrdump_usb_handle *handle = opaque_handle;
+
+    handle->zipsize += size;
+
+    /* EOF, write the left Data in handle data buffer... */
+    if ((buf == NULL) && (size == 0)) {
+
+        /* MUST: a delay for the last transmission */
+        mdelay(10);
+
+        if (!usb_data_transfer(handle, handle->idx)) {
+            voprintf_error("%s: connection failed.(error idx: %d)\n",
+                           __func__, handle->idx);
+            return -1;
+        }
+
+        /* send "MRDUMP ZLP" */
+        memset((void *)handle->data, 0, sizeof(handle->data));
+        size = snprintf((char *)handle->data, sizeof(handle->data), "%s_%s",
+                        MRDUMP_GO_DUMP, USBDONE);
+        if (0 > usb_write_with_timeout(handle->data, strlen((char *)handle->data),
+                                       CON_TIMEOUT)) {
+            voprintf_error(" USB Dump: Write MRDUMP ZLP failed.\n");
+            return -1;
+        }
+
+        return 0;
+    }
+
+    /* buf should not be NULL if not EOF */
+    if (buf == NULL)
+        return -1;
+
+    /* process of Store and write */
+    len = size;
+    ptr = (uint8_t *)buf;
+    while (1) {
+        ret = do_store_or_write(handle, ptr, len);
+        if (ret < 0) {
+            voprintf_error(" USB Dump: store and write failed.\n");
+            return -1;
+        } else if (ret == 0) {
+            break;
+        } else {
+            moves = len - ret;
+            ptr += moves;
+            len = ret;
+        }
+    }
+
+    return size;
+}
+
+int kdump_usb_output(const struct mrdump_control_block *mrdump_cb,
+                     const struct kzip_addlist *memlist)
+{
+    int i;
+    struct kzip_addlist expdb_file[2];
+    char *expdb_filename;
+    unsigned int expdb_offset, expdb_filesize;
+    voprintf_info("Output by USB\n");
+
+    struct mrdump_usb_handle *handle = memalign(64, sizeof(struct mrdump_usb_handle));
+    if (handle == NULL) {
+        voprintf_error("No enough memory.");
+        return -1;
+    }
+    memset(handle, 0, sizeof(struct mrdump_usb_handle));
+
+    mdelay(100);
+    bool ok = true;
+    mtk_wdt_restart();
+    struct kzip_file *zf = kzip_open(handle, usb_write_cb);
+    if (zf != NULL) {
+        /* add SYS_COREDUMP */
+        if (!kzip_add_file(zf, memlist, "SYS_COREDUMP"))
+            ok = false;
+
+        /* add file on expdb */
+        for (i = 0; i < IPANIC_NR_SECTIONS; i++) {
+            if (kedump_get_data_info(i, &expdb_filename, &expdb_offset, &expdb_filesize) == 0) {
+                expdb_file[0].address = expdb_offset;
+                expdb_file[0].size = expdb_filesize;
+                expdb_file[0].type = EXPDB_FILE;
+                expdb_file[1].address = 0;
+                expdb_file[1].size = 0;
+                expdb_file[1].type = MEM_NO_MAP;
+                if (!kzip_add_file(zf, expdb_file, expdb_filename))
+                    ok = false;
+            }
+        }
+
+        /* close zipfile */
+        kzip_close(zf);
+        usb_write_cb(handle, NULL, 0); /* really write the last part */
+        zf = NULL;
+    } else {
+        ok = false;
+    }
+    free(handle);
+
+    mtk_wdt_restart();
+    if (ok) {
+        mrdump_status_ok("OUTPUT:%s\nMODE:%s\n", "USB DUMP",
+                         mrdump_mode2string(mrdump_cb->crash_record.reboot_mode));
+    }
+
+    return ok ? 0 : -1;
+}
+
+#endif