[Feature]add MT2731_MP2_MR2_SVN388 baseline version

Change-Id: Ief04314834b31e27effab435d3ca8ba33b499059
diff --git a/src/devtools/mrdump/mrdump_tool_source/mrdump_status.c b/src/devtools/mrdump/mrdump_tool_source/mrdump_status.c
new file mode 100644
index 0000000..edc4a2e
--- /dev/null
+++ b/src/devtools/mrdump/mrdump_tool_source/mrdump_status.c
@@ -0,0 +1,265 @@
+/* printf */
+#include <stdio.h>
+
+/* open */
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+/* read */
+#include <unistd.h>
+
+/* free */
+#include <stdlib.h>
+
+/* ioctl */
+#include <sys/ioctl.h>
+
+/* lseek64 */
+#ifndef _LARGEFILE64_SOURCE
+#define _LARGEFILE64_SOURCE
+#endif
+#include <sys/types.h>
+#include <unistd.h>
+
+/* bzero */
+#include <strings.h>
+
+/* strlen, memset, strncpy, strtok... */
+#include <string.h>
+
+/* errno */
+#include <errno.h>
+
+/* BLKGETSIZE64 */
+#include <linux/fs.h>
+
+/* mrdump related */
+#include "mrdump_log.h"
+#include "mrdump_common.h"
+#include "mrdump_status.h"
+#include "mrdump_status_private.h"
+
+#ifdef __YOCTO_OS__
+#define strlcpy strncpy
+#endif
+
+static int file_read_string(const char* path, char *content, int len)
+{
+    if (len <= 0) {
+        return -2;
+    }
+
+    int fd = open(path, O_RDONLY);
+    if (fd < 0) {
+        return -1;
+    }
+
+    /* Preserved NULL byte */
+    len--;
+    int size = 0;
+    do {
+        int ret = read(fd, content + size, len - size);
+        if (ret <= 0)
+            break;
+        size = size + ret;
+    } while (size < len);
+    content[size] = 0;
+
+    close(fd);
+    return size;
+}
+
+static int expdb_open(struct partinfo *partinfo)
+{
+    uint64_t part_size;
+    uint32_t part_blksize;
+
+    memset(partinfo, 0, sizeof(struct partinfo));
+
+    char *pp = mrdump_get_device_node(MRDUMP_EXPDB_NAME);
+    if (pp == NULL) {
+        MD_LOGE("%s: No expdb partition found", __func__);
+        return -1;
+    }
+
+    int fd = open(pp, O_RDWR);
+    if (fd < 0) {
+        MD_LOGE("%s: open expdb failed(%d)", __func__, errno);
+        free(pp);
+        return -1;
+    }
+    free(pp);
+
+    if (ioctl(fd, BLKGETSIZE64, &part_size) < 0) {
+        MD_LOGE("%s, get expdb partition size fail(%d)", __func__, errno);
+        close(fd);
+        return -1;
+    }
+
+    if (ioctl(fd, BLKSSZGET, &part_blksize) < 0) {
+        MD_LOGE("%s, get sector size fail(%d)", __func__, errno);
+        close(fd);
+        return -1;
+    }
+
+    partinfo->fd = fd;
+    partinfo->size = part_size;
+    partinfo->blksize = part_blksize;
+
+    return 0;
+}
+
+int mrdump_is_supported(void)
+{
+    char kversion[16], lversion[16];
+    int klen, llen;
+
+    bzero(kversion, sizeof(kversion));
+    bzero(lversion, sizeof(lversion));
+
+    if (file_read_string(MRDUMP_KVER, kversion, sizeof(kversion)) < 0) {
+        MD_LOGE("%s: cannot get kernel version\n", __func__);
+        return 0;
+    }
+
+    klen = strlen(kversion);
+    if (klen == 0) {
+        MD_LOGE("%s: null kernel version\n", __func__);
+        return 0;
+    }
+
+    if (file_read_string(MRDUMP_LVER, lversion, sizeof(lversion)) < 0) {
+        MD_LOGE("%s: cannot get lk version\n", __func__);
+        return 0;
+    }
+
+    llen = strlen(lversion);
+    if (llen == 0) {
+        MD_LOGE("%s: null lk version\n", __func__);
+        return 0;
+    }
+
+    if ((klen != llen) || (strncmp(kversion, lversion, klen) != 0)) {
+        MD_LOGE("%s: kernel and lk version mismatched.\n", __func__);
+        return 0;
+    }
+
+    MD_LOGI("%s: true\n", __func__);
+    return 1;
+}
+
+bool mrdump_status_clear(void)
+{
+    struct partinfo partinfo;
+
+    if (expdb_open(&partinfo) >= 0) {
+	if (lseek64(partinfo.fd, partinfo.size - MRDUMP_OFFSET, SEEK_SET) < 0) {
+	    MD_LOGE("%s: Can't seek part fd %d\n", __func__, partinfo.fd);
+	    close(partinfo.fd);
+	    return false;
+	}
+
+	struct mrdump_cblock_result cblock_result;
+	if (read(partinfo.fd, &cblock_result, sizeof(struct mrdump_cblock_result)) != sizeof(struct mrdump_cblock_result)) {
+	    MD_LOGE("%s: Can't read part fd %d\n", __func__, partinfo.fd);
+	    close(partinfo.fd);
+	    return false;
+	}
+	memset(cblock_result.status, 0, sizeof(cblock_result.status));
+	strncpy(cblock_result.status, "CLEAR", 5);
+
+	if (lseek64(partinfo.fd, partinfo.size - MRDUMP_OFFSET, SEEK_SET) < 0) {
+	    MD_LOGE("%s: Can't seek part fd %d\n", __func__, partinfo.fd);
+	    close(partinfo.fd);
+	    return false;
+	}
+	if (write(partinfo.fd, &cblock_result, sizeof(struct mrdump_cblock_result)) != sizeof(struct mrdump_cblock_result)) {
+	    MD_LOGE("%s: Can't write part fd %d\n", __func__, partinfo.fd);
+	    close(partinfo.fd);
+	    return false;
+	}
+	close(partinfo.fd);
+	return true;
+    }
+    return false;
+}
+
+bool mrdump_status_get(struct mrdump_status_result *result)
+{
+    memset(result, 0, sizeof(struct mrdump_status_result));
+    result->struct_size = sizeof(struct mrdump_status_result);
+
+    struct partinfo partinfo;
+    if (expdb_open(&partinfo) >= 0) {
+	if (lseek64(partinfo.fd, partinfo.size - MRDUMP_OFFSET, SEEK_SET) < 0) {
+	    MD_LOGE("%s: Can't seek part fd %d\n", __func__, partinfo.fd);
+	    close(partinfo.fd);
+	    return false;
+	}
+
+	struct mrdump_cblock_result cblock_result;
+	if (read(partinfo.fd, &cblock_result, sizeof(struct mrdump_cblock_result)) != sizeof(struct mrdump_cblock_result)) {
+	    MD_LOGE("%s: Can't read part fd %d\n", __func__, partinfo.fd);
+	    close(partinfo.fd);
+	    return false;
+	}
+	close(partinfo.fd);
+
+	if (strcmp(cblock_result.sig, MRDUMP_SIG) != 0) {
+	    MD_LOGE("%s: Signature mismatched (result: %s)\n", __func__, cblock_result.sig);
+	    return false;
+	}
+	/* Copy/parsing status line */
+	strncpy(result->status_line, cblock_result.status, sizeof(cblock_result.status));
+	result->status_line[sizeof(result->status_line) - 1] = 0;
+
+	char *saveptr;
+	cblock_result.status[sizeof(cblock_result.status) - 1] = 0;
+	char *strval = strtok_r(cblock_result.status, "\n", &saveptr);
+	if (strval != NULL) {
+	    if (strcmp(strval, "OK") == 0) {
+		result->status = MRDUMP_STATUS_OK;
+		result->output = MRDUMP_OUTPUT_NULL;
+
+		do {
+		    strval = strtok_r(NULL, "\n", &saveptr);
+		    if (strval != NULL) {
+                        if (strncmp(strval, "OUTPUT:", 7) == 0) {
+			    if (strcmp(strval + 7, "EXT4_DATA") == 0) {
+				result->output = MRDUMP_OUTPUT_DATA_FS;
+			    }
+			    else if (strcmp(strval + 7, "PARTITION_DATA") == 0) {
+				result->output = MRDUMP_OUTPUT_PARTITION;
+			    }
+			    else {
+				return false;
+			    }
+			}
+			else if (strncmp(strval, "MODE:", 5) == 0) {
+			    strlcpy(result->mode, strval + 5, sizeof(result->mode));
+			}
+		    }
+		} while (strval != NULL);
+	    }
+	    else if (strcmp(strval, "NONE") == 0) {
+		result->status = MRDUMP_STATUS_NONE;
+	    }
+	    else if (strcmp(strval, "CLEAR") == 0) {
+		result->status = MRDUMP_STATUS_NONE;
+	    }
+	    else {
+		result->status = MRDUMP_STATUS_FAILED;
+	    }
+	}
+	else {
+	    MD_LOGE("%s: status parsing error \"%s\"\n", __func__, cblock_result.status);
+	    return false;
+	}
+
+	strncpy(result->log_buf, cblock_result.log_buf, sizeof(cblock_result.log_buf));
+	result->log_buf[sizeof(result->log_buf) - 1] = 0;
+	return true;
+    }
+    return false;
+}