[Feature]add MT2731_MP2_MR2_SVN388 baseline version

Change-Id: Ief04314834b31e27effab435d3ca8ba33b499059
diff --git a/src/devtools/mrdump/mrdump_tool_source/Android.mk b/src/devtools/mrdump/mrdump_tool_source/Android.mk
new file mode 100644
index 0000000..f0eec8b
--- /dev/null
+++ b/src/devtools/mrdump/mrdump_tool_source/Android.mk
@@ -0,0 +1,21 @@
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES := \
+	mrdump_log.c \
+	mrdump_common.c \
+	mrdump_status.c \
+	mrdump_support_fiemap.c \
+	mrdump_support_ext4.c \
+	mrdump_support_f2fs.c \
+	mrdump_support_mpart.c \
+	mrdump_tool.c
+
+LOCAL_CFLAGS += -D__ANDROID__
+
+LOCAL_MODULE := mrdump_tool
+LOCAL_PROPRIETARY_MODULE := true
+LOCAL_MODULE_OWNER := mtk
+LOCAL_MODULE_TAGS := optional
+LOCAL_SHARED_LIBRARIES := libcutils libz liblog
+include $(MTK_EXECUTABLE)
diff --git a/src/devtools/mrdump/mrdump_tool_source/mrdump_common.c b/src/devtools/mrdump/mrdump_tool_source/mrdump_common.c
new file mode 100644
index 0000000..39c50af
--- /dev/null
+++ b/src/devtools/mrdump/mrdump_tool_source/mrdump_common.c
@@ -0,0 +1,205 @@
+/* uint64_t ...*/
+#include <inttypes.h>
+#include <stdbool.h>
+
+/* struct stat, open */
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+/* fsync(), close() */
+#include <unistd.h>
+
+/* strerror */
+#include <string.h>
+/* errno */
+#include <errno.h>
+
+/* statfs() and statvfs() */
+#include <sys/statfs.h>
+#include <sys/statvfs.h>
+#include <sys/vfs.h>
+
+/* ioctl, BLKGETSIZE64 */
+#include <linux/fs.h>
+#include <sys/ioctl.h>
+
+#ifdef __ANDROID__
+/* Property */
+#include <cutils/properties.h>
+#include <sys/system_properties.h>
+#elif defined(__YOCTO_OS__)
+#include <stdio.h>
+#endif
+
+/* mrdump related */
+#include "mrdump_log.h"
+#include "mrdump_common.h"
+#include "mrdump_support_ext4.h"
+#include "mrdump_support_f2fs.h"
+#include "mrdump_status_private.h"
+
+void mrdump_close(int fd)
+{
+    fsync(fd);
+    close(fd);
+}
+
+int mrdump_file_is_exist(const char *path)
+{
+    struct stat s;
+    if (!path)
+        return 0;
+    if (stat(path, &s) != 0)
+        return 0;
+    return 1;
+}
+
+int mrdump_get_data_os(void)
+{
+    if (mount_as_ext4(MRDUMP_EXT4_MOUNT_POINT))
+        return MRDUMP_DATA_FS_EXT4;
+
+    if (mount_as_f2fs(MRDUMP_EXT4_MOUNT_POINT))
+        return MRDUMP_DATA_FS_F2FS;
+
+    MD_LOGI("%s: unknown os\n", __func__);
+    return MRDUMP_DATA_FS_NONE;
+}
+
+uint64_t mrdump_get_partition_free_size(const char *mountp)
+{
+    struct statvfs vfs;
+    uint64_t psize;
+
+    if(statvfs(mountp, &vfs) == 0) {
+        psize = (uint64_t) vfs.f_frsize * (uint64_t) vfs.f_bfree;
+        MD_LOGD("%s: size of %s: %" PRId64 " bytes.\n", __func__, mountp, psize);
+        return psize;
+    }
+
+    MD_LOGE("%s: statvfs of %s got failed(%d), %s\n", __func__, mountp, errno, strerror(errno));
+    return 0;
+}
+
+uint64_t mrdump_get_partition_size(char *fullpath)
+{
+    int fd = open(fullpath, O_RDONLY);
+    if (0 > fd) {
+        MD_LOGE("%s: open fullpath failed. (%s)\n", __func__, fullpath);
+        return 0;
+    }
+
+    uint64_t psize;
+    int ret = ioctl(fd, BLKGETSIZE64, &psize);
+    if (0 > ret) {
+        MD_LOGE("%s: ioctl BLKGETSIZE64 failed. (%s)\n", __func__, fullpath);
+        mrdump_close(fd);
+        return 0;
+    }
+
+    mrdump_close(fd);
+
+    return psize;
+}
+
+static char *mrdump_get_device_node_from_fstab(const char *fstab, const char *mountp)
+{
+#ifdef __ANDROID_
+    int ret;
+    FILE *fp;
+    char c, myline[1024];
+    char *delim="\x09\x20";
+    char *DeviceNode, *MountPoint;
+
+    DeviceNode = NULL;
+    fp = fopen(fstab, "r");
+    if(fp == NULL)
+        return NULL;
+
+    while(!feof(fp)) {
+
+        // getline
+        ret = fscanf(fp, "%[^\n]", myline);
+
+        // strtok strings
+        if(ret > 0) {
+            if(myline[0] == '/') {
+                DeviceNode = strtok(myline, delim);
+                MountPoint = strtok(NULL, delim);
+                if(MountPoint != NULL) {
+                    if(!strcmp(MountPoint, mountp)) {
+                        fclose(fp);
+                        return strdup(DeviceNode);
+                    }
+                }
+            }
+        }
+
+        /* clear newline character */
+        ret = fscanf(fp, "%c", &c);
+        if (ret != 1) {
+            MD_LOGE("%s: not EOL.", __func__);
+            fclose(fp);
+            return NULL;
+        }
+    }
+    fclose(fp);
+    return NULL;
+#elif defined(__YOCTO_OS__)
+#endif
+}
+
+#ifdef __ANDROID_
+static const char *fstab_path_prefix[] = {
+    "/vendor/etc/fstab",
+    "/fstab",
+    NULL
+};
+#elif defined(__YOCTO_OS__)
+static const char expdb_dev[] = "/dev/disk/by-partlabel/expdb";
+static const char preallocate_dev[] = "/dev/disk/by-partlabel/log";
+#endif
+
+char *mrdump_get_device_node(const char *mountp)
+{
+#ifdef __ANDROID_
+    int i;
+    char *DeviceNode = NULL;
+    char fstab_filename[PROPERTY_VALUE_MAX];
+
+    /* get hardware parts */
+    char propbuf[PROPERTY_VALUE_MAX];
+    if(property_get("ro.hardware", propbuf, NULL) == 0)
+        property_get("ro.board.platform", propbuf, "");
+
+    for(i = 0; fstab_path_prefix[i] != NULL; i++) {
+        snprintf(fstab_filename, sizeof(fstab_filename), "%s.%s", fstab_path_prefix[i], propbuf);
+        if(mrdump_file_is_exist(fstab_filename))
+            DeviceNode =  mrdump_get_device_node_from_fstab(fstab_filename, mountp);
+        if(DeviceNode)
+            return DeviceNode;
+    }
+
+    /* search for path: /fstab */
+    DeviceNode =  mrdump_get_device_node_from_fstab("/fstab", mountp);
+    char fstab_filename[PATH_MAX];
+
+    for (i = 0; fstab_path_prefix[i] != NULL; i++) {
+        snprintf(fstab_filename, sizeof(fstab_filename), "%s", fstab_path_prefix[i]);
+        if(mrdump_file_is_exist(fstab_filename))
+            DeviceNode =  mrdump_get_device_node_from_fstab(fstab_filename, mountp);
+        if(DeviceNode)
+            return DeviceNode;
+    }
+    return DeviceNode;
+#elif defined(__YOCTO_OS__)
+    if (!strncmp(mountp, MRDUMP_EXPDB_NAME, sizeof(MRDUMP_EXPDB_NAME)))
+	return strdup(expdb_dev);
+
+    if (!strncmp(mountp, MRDUMP_EXT4_MOUNT_POINT, sizeof(MRDUMP_EXT4_MOUNT_POINT)))
+        return strdup(preallocate_dev);
+
+    return NULL;
+#endif
+}
diff --git a/src/devtools/mrdump/mrdump_tool_source/mrdump_common.h b/src/devtools/mrdump/mrdump_tool_source/mrdump_common.h
new file mode 100644
index 0000000..7a53b0f
--- /dev/null
+++ b/src/devtools/mrdump/mrdump_tool_source/mrdump_common.h
@@ -0,0 +1,31 @@
+#pragma once
+
+#ifdef __YOCTO_OS__
+#include <stdint.h>
+// typedef unsigned long long int uint64_t;
+#define strlcpy strncpy
+#endif
+
+/* variables definition */
+#define MRDUMP_DATA_FS_NONE    0
+#define MRDUMP_DATA_FS_EXT4    1
+#define MRDUMP_DATA_FS_F2FS    2
+#define MRDUMP_1K              1024
+#define MRDUMP_1M              (MRDUMP_1K * MRDUMP_1K)
+
+/* mrdump related */
+#define MRDUMP_DATA_PARTITION  "/dev/block/platform/bootdevice/by-name/userdata"
+#define MRDUMP_REST_BLOCKS     1024
+#define MRDUMP_REST_SPACE      (MRDUMP_1M * MRDUMP_REST_BLOCKS)
+
+/* mrdump flow control */
+#define MRDUMP_MAX_BW_REQ      100
+#define MRDUMP_MAX_BANDWIDTH   (MRDUMP_1M * MRDUMP_MAX_BW_REQ)
+
+/* Function Prototypes */
+void mrdump_close(int fd);
+int mrdump_file_is_exist(const char *path);
+int mrdump_get_data_os(void);
+uint64_t mrdump_get_partition_free_size(const char *mountp);
+uint64_t mrdump_get_partition_size(char *fullpath);
+char *mrdump_get_device_node(const char *mountp);
diff --git a/src/devtools/mrdump/mrdump_tool_source/mrdump_defaults.c b/src/devtools/mrdump/mrdump_tool_source/mrdump_defaults.c
new file mode 100644
index 0000000..e92d8db
--- /dev/null
+++ b/src/devtools/mrdump/mrdump_tool_source/mrdump_defaults.c
@@ -0,0 +1,13 @@
+#include <string.h>
+
+const char* sysenv_get(const char *name) {
+    if (!strncmp(name, "mrdump_allocate_size", sizeof("mrdump_allocate_size")))
+        return ("fullmem");
+    if (!strncmp(name, "mrdump_output", sizeof("mrdump_output")))
+        return ("internal-storage");
+    return NULL;
+}
+
+int sysenv_set(const char *name, const char *value) {
+    return 0;
+}
diff --git a/src/devtools/mrdump/mrdump_tool_source/mrdump_defaults.h b/src/devtools/mrdump/mrdump_tool_source/mrdump_defaults.h
new file mode 100644
index 0000000..2e93b26
--- /dev/null
+++ b/src/devtools/mrdump/mrdump_tool_source/mrdump_defaults.h
@@ -0,0 +1,2 @@
+extern const char* sysenv_get(const char *name);
+extern int sysenv_set(const char *name, const char *value);
diff --git a/src/devtools/mrdump/mrdump_tool_source/mrdump_log.c b/src/devtools/mrdump/mrdump_tool_source/mrdump_log.c
new file mode 100644
index 0000000..3f3972b
--- /dev/null
+++ b/src/devtools/mrdump/mrdump_tool_source/mrdump_log.c
@@ -0,0 +1,71 @@
+/* vprintf, vsnprintf */
+#include <stdio.h>
+
+/* exit(), atoi() */
+#include <stdlib.h>
+
+#ifdef __YOCTO_OS__
+#include <stdarg.h>
+#endif
+
+/* mrdump related */
+#include "mrdump_log.h"
+
+
+static int mdlog_level = LOG_INFO;
+static int mdlog_write_syslog = 1;
+
+void mdlog_init(int level, int write_syslog)
+{
+    mdlog_level = level;
+    mdlog_write_syslog = write_syslog;
+    openlog("mrdump_tool", 0, 0);
+}
+
+void mdlog_printf(int log_prio, const char *fmt, ...)
+{
+    va_list ap;
+
+    if (log_prio > mdlog_level) {
+        return;
+    }
+
+    va_start(ap, fmt);
+    if (mdlog_write_syslog) {
+        vsyslog(log_prio, fmt, ap);
+    }
+    else {
+        char prefix;
+        if (log_prio <= LOG_ERR) {
+            prefix = 'E';
+        } else if (log_prio == LOG_WARNING) {
+            prefix = 'W';
+        } else if (log_prio <= LOG_INFO) {
+            prefix = 'I';
+        } else {
+            prefix = 'D';
+        }
+        putc(prefix, stderr);
+        putc(':', stderr);
+        vfprintf(stderr, fmt, ap);
+    }
+    va_end(ap);
+}
+
+void error(const char *msg, ...)
+{
+    va_list ap;
+    char msgbuf[128];
+
+    va_start(ap, msg);
+    if (mdlog_write_syslog) {
+        vsyslog(LOG_ERR, msg, ap);
+    }
+    else {
+        vsnprintf(msgbuf, sizeof(msgbuf), msg, ap);
+        fprintf(stderr, "Error: %s", msgbuf);
+    }
+    va_end(ap);
+
+    exit(2);
+}
diff --git a/src/devtools/mrdump/mrdump_tool_source/mrdump_log.h b/src/devtools/mrdump/mrdump_tool_source/mrdump_log.h
new file mode 100644
index 0000000..b8bee70
--- /dev/null
+++ b/src/devtools/mrdump/mrdump_tool_source/mrdump_log.h
@@ -0,0 +1,26 @@
+#pragma once
+
+#include <syslog.h>
+
+void mdlog_init(int level, int write_syslog);
+
+void mdlog_printf(int log_prio, const char *fmt, ...);
+
+void error(const char *msg, ...) __attribute__((noreturn));
+
+/* LOG macro support */
+#define DEBUG_BY_CONSOLE
+#include <stdio.h>
+#if defined(DEBUG_BY_CONSOLE)
+#define MD_LOGV(...) printf(__VA_ARGS__)
+#define MD_LOGD(...) printf(__VA_ARGS__)
+#define MD_LOGI(...) printf(__VA_ARGS__)
+#define MD_LOGW(...) printf(__VA_ARGS__)
+#define MD_LOGE(...) printf(__VA_ARGS__)
+#else
+#define MD_LOGV(...) mdlog_printf(LOG_DEBUG, __VA_ARGS__)
+#define MD_LOGD(...) mdlog_printf(LOG_DEBUG, __VA_ARGS__)
+#define MD_LOGI(...) mdlog_printf(LOG_INFO, __VA_ARGS__)
+#define MD_LOGW(...) mdlog_printf(LOG_WARNING, __VA_ARGS__)
+#define MD_LOGE(...) mdlog_printf(LOG_ERR, __VA_ARGS__)
+#endif
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;
+}
diff --git a/src/devtools/mrdump/mrdump_tool_source/mrdump_status.h b/src/devtools/mrdump/mrdump_tool_source/mrdump_status.h
new file mode 100644
index 0000000..8212626
--- /dev/null
+++ b/src/devtools/mrdump/mrdump_tool_source/mrdump_status.h
@@ -0,0 +1,40 @@
+#if !defined(__MRDUMP_H__)
+#define __MRDUMP_H__
+
+#include <stdbool.h>
+#include <stdint.h>
+
+typedef enum {
+    MRDUMP_STATUS_NONE,
+    MRDUMP_STATUS_FAILED,
+    MRDUMP_STATUS_OK,
+} MRDUMP_STATUS;
+
+typedef enum {
+    MRDUMP_OUTPUT_NULL,
+    MRDUMP_OUTPUT_USB,
+    MRDUMP_OUTPUT_DATA_FS,
+    MRDUMP_OUTPUT_UNUSED, /* VFAT */
+    MRDUMP_OUTPUT_PARTITION,
+} MRDUMP_OUTPUT;
+
+#define MRDUMP_OUTPUT_EXT4_DATA MRDUMP_OUTPUT_DATA_FS
+#define MRDUMP_OUTPUT_PARTITION_DATA MRDUMP_OUTPUT_PARTITION
+
+struct mrdump_status_result {
+    uint32_t struct_size;
+
+    MRDUMP_STATUS status;
+    MRDUMP_OUTPUT output;
+    char mode[32];
+
+    char status_line[128];
+    char log_buf[2048];
+};
+
+/* public api */
+int mrdump_is_supported(void);
+bool mrdump_status_clear(void);
+bool mrdump_status_get(struct mrdump_status_result *result);
+
+#endif
diff --git a/src/devtools/mrdump/mrdump_tool_source/mrdump_status_private.h b/src/devtools/mrdump/mrdump_tool_source/mrdump_status_private.h
new file mode 100644
index 0000000..00651cd
--- /dev/null
+++ b/src/devtools/mrdump/mrdump_tool_source/mrdump_status_private.h
@@ -0,0 +1,26 @@
+#if !defined(__MRDUMP_USER_PRIVATE_H__)
+#define __MRDUMP_USER_PRIVATE_H__
+
+#include <stdbool.h>
+#include <stdint.h>
+
+/* DRAM KLOG at MRDUMP area of expdb, offset from bottom = 3145728 - 16384 = 3129344 */
+#define MRDUMP_OFFSET 3145728
+#define MRDUMP_EXPDB_NAME "/expdb"
+#define MRDUMP_KVER "/sys/module/mrdump/version"
+#define MRDUMP_LVER "/sys/module/mrdump/parameters/lk"
+#define MRDUMP_SIG "MRDUMP08"
+
+struct __attribute__((__packed__)) mrdump_cblock_result {
+    char sig[9];
+    char status[128];
+    char log_buf[2048];
+};
+
+struct partinfo {
+    int fd;
+    uint64_t size;
+    uint32_t blksize;
+};
+
+#endif
diff --git a/src/devtools/mrdump/mrdump_tool_source/mrdump_support_ext4.c b/src/devtools/mrdump/mrdump_tool_source/mrdump_support_ext4.c
new file mode 100644
index 0000000..1d00e94
--- /dev/null
+++ b/src/devtools/mrdump/mrdump_tool_source/mrdump_support_ext4.c
@@ -0,0 +1,1399 @@
+/* print */
+#include <stdio.h>
+
+/* uint64_t ...*/
+#include <inttypes.h>
+#include <stdbool.h>
+
+/* __u32 */
+#include <linux/types.h>
+
+/* struct stat, open */
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <fcntl.h>
+
+/* malloc */
+#include <stdlib.h>
+
+/* strerror */
+#include <string.h>
+/* errno */
+#include <errno.h>
+
+/* figetbsz */
+#include <linux/fs.h>
+#include <sys/ioctl.h>
+
+/* statfs() and statvfs() */
+#include <sys/statfs.h>
+#include <sys/statvfs.h>
+#include <sys/vfs.h>
+
+/* crc32, Z_NULL */
+#include <zlib.h>
+
+/* syscall, __NR_fallocate */
+#include <sys/syscall.h>
+
+/* time */
+#include <time.h>
+
+/* sysenv */
+#include "mrdump_defaults.h"
+
+/* mrdump related */
+#include "mrdump_log.h"
+#include "mrdump_common.h"
+#include "mrdump_status.h"
+#include "mrdump_support_fiemap.h"
+#include "mrdump_support_ext4.h"
+#include "mrdump_support_f2fs.h"
+#include "mrdump_support_mpart.h"
+
+/* add for block verification */
+static uint64_t lba_marker_time;
+static struct marked_block_data bdata;
+
+struct palloc_file {
+    int fd;
+    int blksize;
+    int lbaooo;
+};
+
+static struct palloc_file *palloc_file_open(const char *allocfile)
+{
+    struct stat statinfo;
+
+    struct palloc_file *pfile = malloc(sizeof(struct palloc_file));
+    pfile->fd = -1;
+    pfile->blksize = 0;
+    pfile->lbaooo = 0;
+
+    /////////////////////////////////////////////////////
+    // open file handle
+    pfile->fd = open(allocfile, O_RDONLY);
+    if(0 > pfile->fd) {
+        MD_LOGE("%s: file(%s) marker open failed(%d), %s\n", __func__, allocfile, errno, strerror(errno));
+        return NULL;
+    }
+    // Get file statinfo
+    if(0 > fstat(pfile->fd, &statinfo)) {
+        MD_LOGE("%s: marker stat failed(%d), %s\n", __func__, errno, strerror(errno));
+        goto cleanup;
+    }
+
+    if(0 > ioctl(pfile->fd, FIGETBSZ, &pfile->blksize)) {
+        MD_LOGE("%s: FIGETGSZ failed(%d), %s", __func__, errno, strerror(errno));
+        goto cleanup;
+    }
+
+    pfile->lbaooo = mrdump_fiemap_get_entry_lba(pfile->fd, pfile->blksize, 0);
+    if (pfile->lbaooo < 0) {
+        MD_LOGE("%s: get lba failed", __func__);
+        goto cleanup;
+    }
+    return pfile;
+
+  cleanup:
+    mrdump_close(pfile->fd);
+    pfile->fd = -1;
+    pfile->blksize = 0;
+    pfile->lbaooo = 0;
+    return NULL;
+}
+
+void palloc_file_close(struct palloc_file *pfile)
+{
+    mrdump_close(pfile->fd);
+    free(pfile);
+}
+
+static int fop_file_write_string(const char *path, const char *content, ...)
+{
+    int ret_val = 0;
+
+    int fd = open(path, O_WRONLY);
+    if (fd >= 0) {
+        char content_buf[1024];
+        va_list ap;
+
+        va_start(ap, content);
+        int n = vsnprintf(content_buf, sizeof(content_buf), content, ap);
+        va_end(ap);
+        int val = write(fd, content_buf, n);
+        if (val != n) {
+            if (val < 0) {
+                ret_val = -errno;
+            }
+            else {
+                ret_val = -EIO;
+            }
+        }
+        mrdump_close(fd);
+        if (ret_val == 0) {
+            ret_val = n;
+        }
+    }
+    else {
+        ret_val = -errno;
+    }
+    return ret_val;
+}
+
+////////////////////////////////////////////
+// common function (static in this file)  //
+////////////////////////////////////////////
+static bool ext4_setup_attr(char const *allocfile, bool enabled)
+{
+    int fd;
+    unsigned int myflags;
+
+    if(allocfile == NULL) {
+        allocfile = MRDUMP_EXT4_ALLOCATE_FILE;
+    }
+
+    fd = open(allocfile, O_RDONLY);
+    if(0 > fd) {
+        MD_LOGE("%s: open allocfile failed(%d), %s\n", __func__, errno, strerror(errno));
+        return false;
+    }
+
+    if(0 > ioctl(fd, FS_IOC_GETFLAGS, &myflags)) {
+        MD_LOGE("%s: FS_IOC_GETFLAGS failed(%d), %s\n", __func__, errno, strerror(errno));
+        return false;
+    }
+
+    if (enabled) {
+        myflags |= (FS_SECRM_FL | FS_IMMUTABLE_FL);
+    }
+    else {
+        myflags &= ~(FS_SECRM_FL | FS_IMMUTABLE_FL);
+    }
+    if(0 > ioctl(fd, FS_IOC_SETFLAGS, &myflags)) {
+        MD_LOGE("%s: FS_IOC_SETFLAGS failed(%d), %s\n", __func__, errno, strerror(errno));
+        return false;
+    }
+
+    mrdump_close(fd);
+    return true;
+}
+
+static off64_t ext4_block_lseek(int fd, unsigned lba, int blksize)
+{
+    unsigned long long location = (unsigned long long) lba * (unsigned long long) blksize;
+    return lseek64(fd, location, SEEK_SET);
+}
+
+static int ext4_open_device_node(const char *mountp)
+{
+    char *devicenode = mrdump_get_device_node(mountp);
+    if(devicenode == NULL) {
+        MD_LOGE("%s: Get devicenode return null\n", __func__);
+        return -1;
+    }
+    int fd = open(devicenode, O_RDWR);
+    if(0 > fd) {
+        MD_LOGE("%s: open devicenode failed(%d), %s\n", __func__, errno, strerror(errno));
+        free(devicenode);
+        return -1;
+    }
+    free(devicenode);
+    return fd;
+}
+
+bool mount_as_ext4(const char *mountp)
+{
+    struct statfs fs;
+    if(statfs(mountp, &fs) == 0) {
+        /*
+         * bionic header didn't define EXT4_SUPER_MAGIC
+         * use EXT3_SUPER_MAGIC instead
+         */
+        if(fs.f_type == EXT3_SUPER_MAGIC)
+            return true;
+        return false;
+    }
+    MD_LOGE("%s: %s statfs error.\n", __func__, mountp);
+    return false;
+}
+
+static int check_a_data_block(int myfds, int mybs, uint32_t lba)
+{
+    unsigned long long offset = (unsigned long long)lba * (unsigned long long)mybs;
+    struct marked_block_data output_data;
+    unsigned int mycrc = crc32(0, Z_NULL, 0);
+    mycrc = crc32(mycrc, (void *)&bdata, (mybs-4));
+    bdata.crc = mycrc;
+    bdata.lba = lba;
+
+    if(0 > pread64(myfds, (void *)&output_data, mybs, offset)) {
+        MD_LOGE("%s: write block error!(%d), %s", __func__, errno, strerror(errno));
+        return -1;
+    };
+
+    // check lba
+    if (bdata.lba != output_data.lba) {
+        MD_LOGE("Read BlockData LBA failed (c:%u, v:%u)\n", bdata.lba, output_data.lba);
+        return -1;
+    }
+    // check timestamp
+    if (bdata.timestamp != output_data.timestamp) {
+        MD_LOGE("Read BlockData timestamp failed (c:%u, v:%u)\n", bdata.timestamp, output_data.timestamp);
+        return -1;
+    }
+    // check crc
+    if (bdata.crc != output_data.crc) {
+        MD_LOGE("Read BlockData crc32 failed (c:%u, v:%u)\n", bdata.crc, output_data.crc);
+        return -1;
+    }
+
+    return 0;
+}
+
+static int format_a_data_block(int myfds, int mybs, uint32_t lba)
+{
+    unsigned long long offset = (unsigned long long)lba * (unsigned long long)mybs;
+
+    bdata.lba = lba;
+    // (no change) bdata.timestamp = lba_marker_time;
+    unsigned int mycrc = crc32(0, Z_NULL, 0);
+    mycrc = crc32(mycrc, (void *)&bdata, (mybs-4));
+    bdata.crc = mycrc;
+
+    if(0 > pwrite64(myfds, (void *)&bdata, mybs, offset)) {
+        MD_LOGE("%s: write block error!(%d), %s", __func__, errno, strerror(errno));
+        return -1;
+    };
+
+    return 0;
+}
+
+static int ext4_get_next_bidx(int myfd, unsigned int *pBlock, unsigned int bbidx, unsigned int bs, unsigned int moves)
+{
+    unsigned int rlba, mycrc;
+
+    if(bbidx > MRDUMP_EXT4_LBA_PER_BLOCK)
+        return -1;
+
+    if(bbidx == MRDUMP_EXT4_LBA_PER_BLOCK) {
+        rlba = pBlock[bbidx];
+        // seek to location
+        if(-1 == ext4_block_lseek(myfd, rlba, bs)) {
+            MD_LOGE("%s: lseek64 location failed(%d), %s", __func__, errno, strerror(errno));
+            return -1;
+        }
+        // read to pBlock
+        if(0 > read(myfd, pBlock, bs)) {
+            MD_LOGE("%s: read lbaooo error!(%d), %s", __func__, errno, strerror(errno));
+            return -1;
+        }
+        // check crc32
+        mycrc = crc32(0, Z_NULL, 0);
+        mycrc = crc32(mycrc, (void *)pBlock, (bs-4));
+        if(mycrc != pBlock[1023]) {
+            MD_LOGE("%s: crc32 error!(%d), %s", __func__, errno, strerror(errno));
+            return -1;
+        }
+        bbidx = 0;
+    } else {
+        bbidx+=moves;
+    }
+    return bbidx;
+}
+
+static unsigned int ext4_num_to_join(unsigned int *pBlock, unsigned int bbidx)
+{
+    unsigned int i, j;
+    for(i=0, j=0; i<MRDUMP_EXT4_MAX_CONTINUE; i++) {
+        if((pBlock[bbidx+i] - pBlock[bbidx]) == i) {
+            j++;
+            continue;
+        }
+        break;
+    }
+    return j;
+}
+
+static int construct_a_block(int myfds, int mybs, int myloop, int myoffset, struct fiemap_info *mapinfo, unsigned int rows)
+{
+    unsigned int i, lba, num, mycrc;
+    unsigned int block[1024]; // assume max BLOCKSIZE=4096, int(4byte) for addressing
+
+    // Zero blocks
+    memset(block, 0, sizeof(block));
+
+    // number of address per block
+    // 1024 = Normal_LBA[1022] + Next_LBA + crc32
+    num = (mybs+sizeof(int)-1) / sizeof(int);
+
+    // Indexing by 0. --> (i-1)
+    // i     = 1~MRDUMP_EXT4_LBA_PER_BLOCK(1022)
+    // index = 0~1021
+    i = 1;
+    while(i < (num - 1)) {
+        lba = myoffset + (i-1);
+        lba = mrdump_fiemap_get_lba_of_block(mapinfo, rows, lba);
+        if(0 > lba) {
+            MD_LOGE("%s: mrdump_fiemap_get_lba_of_block(1021) failed(%d), %s", __func__, errno, strerror(errno));
+            return -1;
+        }
+        block[(i-1)] = lba;
+        i++;
+    }
+
+    /* coverity: to avoid while(i < (num - 1)) taking false branch */
+    if (i < 2) {
+        MD_LOGE("%s: number of address per block should be more than 2\n", __func__);
+        return -1;
+    }
+
+    // i     = 1023
+    // index = MRDUMP_EXT4_LBA_PER_BLOCK(1022)
+    if (block[(i-2)] == 0) {
+        // End of File
+        block[(i-1)] = 0;
+    } else {
+        // lba = (myloop+1); --> Need ++ For InfoLBA[EXT4_LBA_INFO_NUM];
+        // block starts from 2nd Block
+        lba = myloop + 2;
+        lba = mrdump_fiemap_get_lba_of_block(mapinfo, rows, lba);
+        if(0 > lba) {
+            MD_LOGE("%s: mrdump_fiemap_get_lba_of_block(1022) failed(%d), %s", __func__, errno, strerror(errno));
+            return -1;
+        }
+        block[(i-1)] = lba;
+    }
+
+    // i     = 1023: crc32
+    // index = 1023: (NO block[i+1] now...)
+    // PS: index = 1023 now... i takes no changes.
+    mycrc = crc32(0, Z_NULL, 0);
+    mycrc = crc32(mycrc, (void *)block, (mybs-4));
+    block[i] = mycrc;
+
+    // Prepare to write onto the Blocks in the front ...
+    //
+    // the address (LBA) where to write on.
+    // lba = myloop; --> Need ++ For InfoLBA[EXT4_LBA_INFO_NUM];
+    lba = myloop+1;
+    lba = mrdump_fiemap_get_lba_of_block(mapinfo, rows, lba);
+    if(0 > lba) {
+        MD_LOGE("%s: mrdump_fiemap_get_lba_of_block(write) failed(%d), %s", __func__, errno, strerror(errno));
+        return -1;
+    }
+    // Write block onto location;
+    if (-1 == ext4_block_lseek(myfds, lba, mybs)) {
+        MD_LOGE("%s: lseek64 location failed(%d), %s", __func__, errno, strerror(errno));
+        return -1;
+    }
+    if(0 > write(myfds, (void *)block, sizeof(block))) {
+        MD_LOGE("%s: write block error!(%d), %s", __func__, errno, strerror(errno));
+        return -1;
+    }
+
+    // return the new offset
+    // i = 1023
+    if (block[(i-1)] == 0) {
+        myoffset = 0;
+    } else {
+        myoffset = myoffset + (i - 1);
+    }
+
+    return (int)myoffset;
+}
+
+static void mrdump_dump_pafile_info(const uint8_t lba[MRDUMP_PAF_TOTAL_SIZE])
+{
+    uint32_t version = *(uint32_t *)(lba);
+    uint32_t info_lba = *(uint32_t *)(lba + MRDUMP_PAF_INFO_LBA);
+    uint32_t addr_lba = *(uint32_t *)(lba + MRDUMP_PAF_ADDR_LBA);
+    uint64_t filesize = *(uint64_t *)(lba + MRDUMP_PAF_ALLOCSIZE);
+    uint64_t coredump_size = *(uint64_t *)(lba + MRDUMP_PAF_COREDUMPSIZE);
+    uint64_t timestamp = *(uint64_t *)(lba + MRDUMP_PAF_TIMESTAMP);
+    uint32_t crcval = *(uint64_t *)(lba + MRDUMP_PAF_CRC32);
+
+
+    MD_LOGD("PAFILE-INFO version %u info-lba %u addr-lba %u file-size %llu coredump-size %llu timestamp %llx crc %x\n",
+            version, info_lba, addr_lba, filesize, coredump_size, timestamp, crcval);
+}
+
+/* lba format
+ *  0: version      (2 bytes)
+ *  2:reserved      (2 bytes)
+ *  4:info lba      (4 bytes)
+ *  8:addr lba      (4 bytes)
+ * 12:allocate size (8 bytes)
+ * 20:coredump size (8 bytes)
+ * 28:timestamp     (8 bytes)
+ * 36:CRC32         (4 bytes)
+ */
+static bool fs_lba_mark_header(const struct palloc_file *pfile)
+{
+    int num_blocks, rsv_blocks;
+    struct stat statinfo;
+    unsigned int mycrc, block;
+    uint8_t InfoLBA[MRDUMP_PAF_TOTAL_SIZE], *pinfo;
+
+    // Get file statinfo
+    if(0 > fstat(pfile->fd, &statinfo)) {
+        MD_LOGE("%s: marker stat failed(%d), %s\n", __func__, errno, strerror(errno));
+        return false;
+    }
+    // Get Blocksize and counting blocks
+    uint64_t blksize = pfile->blksize;
+
+    // Counting blocks
+    num_blocks = (statinfo.st_size + blksize - 1) / blksize;
+
+    /////////////////////////////////////////////////////
+    // Zero InfoLBA ...
+    memset(InfoLBA, 0, sizeof(InfoLBA));
+    pinfo = &InfoLBA[0];
+
+    /* Setup pafile info version */
+    *(uint16_t *)pinfo = MRDUMP_PAF_VERSION;
+
+    /* Flags */
+    *(uint16_t *)(pinfo + 2) = 0;
+
+    // Get info LBA
+    block = mrdump_fiemap_get_entry_lba(pfile->fd, blksize, 0);
+    *(uint32_t *)(pinfo + MRDUMP_PAF_INFO_LBA) = block;
+
+    // Get 2nd LBA
+    if(2 > mrdump_fiemap_get_entry_tot(pfile->fd, blksize, 0))
+        *(uint32_t *)(pinfo + MRDUMP_PAF_ADDR_LBA) = mrdump_fiemap_get_entry_lba(pfile->fd, blksize, 1);
+    else
+        *(uint32_t *)(pinfo + MRDUMP_PAF_ADDR_LBA) = block + 1;
+
+    // Reserved space for Header and Tailer
+    rsv_blocks = num_blocks/MRDUMP_EXT4_LBA_PER_BLOCK;   // Header
+    rsv_blocks+= 2;                 // Tailer
+    *(uint64_t *)(pinfo + MRDUMP_PAF_ALLOCSIZE) = (num_blocks - rsv_blocks) * blksize;
+
+    // Set core dump size to zero
+    *(uint64_t *)(pinfo + MRDUMP_PAF_COREDUMPSIZE) = 0UL;
+
+    // Set timestamp to lba_marker_time
+    *(uint64_t *)(pinfo + MRDUMP_PAF_TIMESTAMP) = lba_marker_time;
+
+    // check crc32 of InfoLBA
+    mycrc = crc32(0, Z_NULL, 0);
+    mycrc = crc32(mycrc, (void *)InfoLBA, MRDUMP_LBA_DATAONLY);
+    *(uint32_t *)(pinfo + MRDUMP_PAF_CRC32) = mycrc;
+
+    int fd = ext4_open_device_node(MRDUMP_EXT4_MOUNT_POINT);
+    if (fd < 0) {
+        return false;
+    }
+    // Save InfoLBA First
+    if(-1 == ext4_block_lseek(fd, block, blksize)) {
+        MD_LOGE("%s: marker header lseek64 InfoLBA failed(%d), %s\n", __func__, errno, strerror(errno));
+        mrdump_close(fd);
+        return false;
+    }
+    if(0 > write(fd, (void *)InfoLBA, (sizeof(InfoLBA)))) {
+        MD_LOGE("%s: marker header write InfoLBA error!(%d), %s\n", __func__, errno, strerror(errno));
+        mrdump_close(fd);
+        return false;
+    }
+
+    mrdump_close(fd);
+    return true;
+}
+
+static bool fs_lba_mark_body(const struct palloc_file *pfile)
+{
+    int             fds;
+    int             i, blksize, num_blocks, loop, offset;
+    struct stat     statinfo;
+
+    // Get file statinfo
+    if(0 > fstat(pfile->fd, &statinfo)) {
+        MD_LOGE("%s: marker stat failed(%d), %s\n", __func__, errno, strerror(errno));
+        return false;
+    }
+    // Get Blocksize and counting blocks
+    blksize = pfile->blksize;
+    num_blocks = (statinfo.st_size + blksize - 1) / blksize;
+
+    /////////////////////////////////////////////////////
+    // begin to record (2-layer block writing)
+    char *devicenode = mrdump_get_device_node(MRDUMP_EXT4_MOUNT_POINT);
+    if(devicenode == NULL) {
+        MD_LOGE("%s: get devicenode failed(%d), %s\n", __func__, errno, strerror(errno));
+        return false;
+    } else {
+        fds = open(devicenode, O_RDWR);
+        if(0 > fds) {
+            free(devicenode);
+            MD_LOGE("%s: open devicenode failed(%d), %s\n", __func__, errno, strerror(errno));
+            return false;
+        }
+    }
+    free(devicenode);
+
+    // for performance, we must finish fiemap here... but not in the loop
+    unsigned int my_num = mrdump_fiemap_total_entries(pfile->fd);
+    if(my_num == 0) {
+        MD_LOGE("%s: mrdump_fiemap_total_entries error!(%d), %s\n", __func__, errno, strerror(errno));
+        mrdump_close(fds);
+        return false;
+    }
+
+#ifdef MRDUMP_DEBUG
+    MD_LOGI("%s: my_num=(%06u)\n", __func__, my_num);
+#endif
+
+    struct fiemap_info *myinfo = malloc(my_num * sizeof(struct fiemap_info));
+    if(!mrdump_fiemap_get_entries(pfile->fd, blksize, myinfo, my_num)) {
+        MD_LOGE("%s: mrdump_fiemap_get_entries error!(%d), %s\n", __func__, errno, strerror(errno));
+        mrdump_close(fds);
+        return false;
+    }
+
+#ifdef MRDUMP_DEBUG
+    for(i=0; i<(int)my_num; i++) {
+        MD_LOGI("%s: i=%03d, LBA=%06u, TOT=%06u\n", __func__, i, myinfo[i].lba, myinfo[i].tot);
+    }
+#endif
+
+    // go
+    loop = (blksize / sizeof(unsigned int)) - 2;
+    loop = (num_blocks + loop - 1) / loop;
+#ifdef MRDUMP_DEBUG
+    MD_LOGI("%s: num_blocks=%d, my_num=%u\n", __func__, num_blocks, my_num);
+#endif
+    offset = loop + 1;
+    for(i=0; i<loop; i++) {
+        offset = construct_a_block(fds, blksize, i, offset, myinfo, my_num);
+        if (offset == -1) {
+            MD_LOGE("%s: marker construct block error!(%d), %s\n", __func__, errno, strerror(errno));
+            mrdump_close(fds);
+            free(myinfo);
+            return false;
+        }
+    }
+    mrdump_close(fds);
+    free(myinfo);
+    return true;
+}
+
+static bool ext4_fallocate(const char *allocfile, uint64_t allocsize)
+{
+    int fd;
+
+    if((allocfile == NULL) || (allocsize == 0)) {
+        MD_LOGE("%s: allocfile is NULL or allocsize = %" PRIu64 "\n", __func__, allocsize);
+        return false;
+    }
+
+    while(!mrdump_file_is_exist(AE_DUMPSYS_DATA_PATH)) {
+        MD_LOGI("%s: wait until %s ready.\n", __func__, AE_DUMPSYS_DATA_PATH);
+        sleep(1);
+    }
+
+    if(mount_as_f2fs(MRDUMP_EXT4_MOUNT_POINT)) {
+
+        allocsize = ((allocsize + F2FS_MAPSIZE - 1) / F2FS_MAPSIZE) * F2FS_MAPSIZE;
+        if(!f2fs_fallocate(allocfile, allocsize)) {
+            MD_LOGE("%s: f2fs_fallocate failed (allocfile=%s, allocsize=%" PRIu64 ")\n", __func__, allocfile, allocsize);
+            return false;
+        }
+
+        fd = open(allocfile, O_RDONLY);
+        if(0 > fd) {
+            MD_LOGE("%s: open fd failed.\n", __func__);
+            return false;
+        }
+
+        unsigned int val = 1234;
+        if(0 > ioctl(fd, F2FS_IOC_GET_PIN_FILE , &val)) {
+            MD_LOGE("%s: F2FS_IOC_GET_PIN_FILE(%u) failed(%d), %s\n", __func__, val, errno, strerror(errno));
+        }
+        MD_LOGI("%s: file(%s:%" PRIu64 ") Skip GC (%u times)\n", __func__, allocfile, allocsize, val);
+
+        mrdump_close(fd);
+
+    } else {
+
+        fd = open(allocfile, O_RDWR | O_CREAT, 0400);
+        if(0 > fd) {
+            MD_LOGE("%s: open allocfile failed(%d), %s\n", __func__, errno, strerror(errno));
+            return false;
+        }
+
+#if (!__LP64__)
+        uint32_t low = allocsize & 0xffffffff;
+        uint32_t high = allocsize >> 32;
+
+        if(0 > syscall(__NR_fallocate, fd, 0, 0, 0, low, high)) {
+            MD_LOGE("%s: fallocate32 failed(allocfile=%s, allocsize=%" PRIu64 ")\n", __func__, allocfile, allocsize);
+            mrdump_close(fd);
+            unlink(allocfile);
+            return false;
+        }
+#else
+        if(0 > syscall(__NR_fallocate, fd, 0, 0, allocsize)) {
+            MD_LOGE("%s: fallocate64 failed(allocfile=%s, allocsize=%" PRIu64 ")\n", __func__, allocfile, allocsize);
+            mrdump_close(fd);
+            unlink(allocfile);
+            return false;
+        }
+#endif
+        mrdump_close(fd);
+    }
+
+    return true;
+}
+
+static bool palloc_file_remove(const char *allocfile)
+{
+    /* Ignore attribute setting failed */
+    fop_file_write_string(MRDUMP_EXT4_PARA_LBAOOO, "0");
+
+    if (mrdump_file_is_exist(allocfile)) {
+        ext4_setup_attr(allocfile, false);
+        if (unlink(allocfile) != 0) {
+            MD_LOGE("%s: Cannot unlink %s(%d), %s\n", __func__, allocfile, errno, strerror(errno));
+            return false;
+        }
+    }
+    return true;
+}
+
+static bool mrdump_read_pafile_info(const struct palloc_file *pfile, int device_fd,
+                                    struct mrdump_pafile_info *info)
+{
+    memset(info, 0, sizeof(struct mrdump_pafile_info));
+
+    uint8_t block0[MRDUMP_PAF_TOTAL_SIZE];
+    memset(block0, 0, sizeof(block0));
+
+    if (-1 == ext4_block_lseek(device_fd, pfile->lbaooo, pfile->blksize)) {
+        MD_LOGE("%s: lseek64 InfoLBA failed(%d), %s\n", __func__, errno, strerror(errno));
+        return false;
+    }
+
+    if (0 > read(device_fd, block0, sizeof(block0))) {
+        MD_LOGE("%s: read InfoLBA error (%d), %s\n", __func__, errno, strerror(errno));
+        return false;
+    }
+
+    uint8_t *bufp = &block0[0];
+    unsigned int crcval = crc32(0, Z_NULL, 0);
+    crcval = crc32(crcval, (void *)block0, MRDUMP_LBA_DATAONLY);
+    if (crcval != *(uint32_t *)&block0[MRDUMP_PAF_CRC32]) {
+        MD_LOGE("%s: LBA info CRC error (c:%08x, v:%08x)\n", __func__, crcval,
+                *(uint32_t *)&block0[MRDUMP_PAF_CRC32]);
+        return false;
+    }
+
+    uint16_t version = *(uint16_t *)&block0[0];
+    if (version != MRDUMP_PAF_VERSION) {
+        MD_LOGE("%s: LBA version mismatch (c:%d, v:%d)\n", __func__, MRDUMP_PAF_VERSION, version);
+        mrdump_dump_pafile_info(block0);
+        return false;
+    }
+    info->info_lba = *(uint32_t *)(bufp + MRDUMP_PAF_INFO_LBA);
+    info->addr_lba = *(uint32_t *)(bufp + MRDUMP_PAF_ADDR_LBA);
+    info->filesize = *(uint64_t *)(bufp + MRDUMP_PAF_ALLOCSIZE);
+    info->coredump_size = *(uint64_t *)(bufp + MRDUMP_PAF_COREDUMPSIZE);
+    info->timestamp = *(uint64_t *)(bufp + MRDUMP_PAF_TIMESTAMP);
+    return true;
+}
+
+static bool mark_data_block(const struct palloc_file *pfile)
+{
+    int             fds, fdd; /* fd of src and dst */
+    int             i, j, blksize, num_blocks, loop;
+    struct stat     statinfo;
+    unsigned int    lba, BlockLBA[1024];
+
+    // Get file statinfo
+    if(0 > fstat(pfile->fd, &statinfo)) {
+        MD_LOGE("%s: marker stat failed(%d), %s\n", __func__, errno, strerror(errno));
+        return false;
+    }
+    // Get Blocksize and counting blocks
+    blksize = pfile->blksize;
+    num_blocks = (statinfo.st_size + blksize - 1) / blksize;
+
+    /////////////////////////////////////////////////////
+    // begin to record (2-layer block writing)
+    char *devicenode = mrdump_get_device_node(MRDUMP_EXT4_MOUNT_POINT);
+    if(devicenode == NULL) {
+        MD_LOGE("%s: get devicenode failed(%d), %s\n", __func__, errno, strerror(errno));
+        return false;
+    } else {
+        fds = open(devicenode, O_RDONLY);
+        if(0 > fds) {
+            free(devicenode);
+            MD_LOGE("%s: open devicenode failed(%d), %s\n", __func__, errno, strerror(errno));
+            return false;
+        }
+        fdd = open(devicenode, O_WRONLY);
+        if(0 > fdd) {
+            mrdump_close(fds);
+            free(devicenode);
+            MD_LOGE("%s: open devicenode failed(%d), %s\n", __func__, errno, strerror(errno));
+            return false;
+        }
+    }
+    free(devicenode);
+
+    // Check each Block (Now: InfoLBA + Address Block)
+    // 1. InfoLBA blocks
+    struct mrdump_pafile_info info;
+    if (!mrdump_read_pafile_info(pfile, fds, &info)) {
+        mrdump_close(fds);
+        mrdump_close(fdd);
+        return false;
+    }
+
+    // go for Address Area
+    bool stop_here = false;
+    lba = (unsigned int)info.addr_lba;
+    bdata.timestamp = info.timestamp;
+    loop = (blksize / sizeof(unsigned int)) - 2;    // 1022
+    loop = (num_blocks + loop - 1) / loop;          // num of blocks which Address Area really occupied
+
+    for(i=0; i<loop; i++) {
+#ifdef MRDUMMP_DEBUG
+        MD_LOGE("%s: i(%03d) loop(%03d)\n", __func__, i, loop);
+#endif
+        if(-1 == ext4_block_lseek(fds, lba, blksize)) {
+            MD_LOGE("%s: bdata lseek64 BlockLBA failed(%d), %s\n", __func__, errno, strerror(errno));
+            mrdump_close(fds);
+            mrdump_close(fdd);
+            return false;
+        }
+        if(0 > read(fds, (void *)BlockLBA, blksize)) {
+            MD_LOGE("%s: bdata read BlockLBA error!(%d), %s\n", __func__, errno, strerror(errno));
+            mrdump_close(fds);
+            mrdump_close(fdd);
+            return false;
+        }
+
+        for(j=0; j<MRDUMP_EXT4_LBA_PER_BLOCK; j++) {
+            lba = BlockLBA[j];
+
+            if(lba == 0)
+                stop_here = true;
+
+            if(format_a_data_block(fdd, blksize, lba) < 0) {
+                MD_LOGE("%s: format_data_block error! j=%d (%d), %s\n", __func__, j, errno, strerror(errno));
+                mrdump_close(fds);
+                mrdump_close(fdd);
+                return false;
+            }
+        }
+        lba = BlockLBA[j];
+
+        if(stop_here)
+            break;
+    }
+    mrdump_close(fds);
+    mrdump_close(fdd);
+    return true;
+}
+
+static bool fs_lba_maker(const struct palloc_file *pfile, bool need_to_reinit)
+{
+#ifdef MRDUMP_DEBUG
+    MD_LOGI("%s start... need_to_reinit=(%d)\n", __func__, need_to_reinit);
+#endif
+
+    if (pfile == NULL)
+        MD_LOGE("%s pfile is null.\n", __func__);
+    else
+        MD_LOGE("%s pfile is not null.\n", __func__);
+
+    if (need_to_reinit) {
+        lba_marker_time = (uint64_t)time(NULL);
+        MD_LOGI("%s: lba_marker_time(%llx)\n", __func__, lba_marker_time);
+
+        if (!fs_lba_mark_header(pfile)) {
+            MD_LOGE("%s: mark header failed(%d), %s\n", __func__, errno, strerror(errno));
+            return false;
+        }
+
+        if (!fs_lba_mark_body(pfile)) {
+            MD_LOGE("%s: mark body failed(%d), %s\n", __func__, errno, strerror(errno));
+            return false;
+        }
+    }
+
+    if (MRDUMP_DATA_FS_F2FS == mrdump_get_data_os()) {
+        if(!mark_data_block(pfile)) {
+            MD_LOGE("%s: mark data block failed(%d), %s\n", __func__, errno, strerror(errno));
+            return false;
+        }
+    }
+
+    sync();
+#ifdef MRDUMP_DEBUG
+    MD_LOGI("%s end...\n", __func__);
+#endif
+    return true;
+}
+
+static struct palloc_file *ext4_new_fallocfile(const char *allocfile, uint64_t allocsize)
+{
+    uint64_t psize = mrdump_get_partition_free_size(MRDUMP_EXT4_MOUNT_POINT);
+    if (psize < (allocsize + MRDUMP_REST_SPACE)) {
+        MD_LOGE("Error: Partition %s has no enough free space(%" PRIu64 "MB), allocate size %" PRIu64 "MB\n",
+                MRDUMP_EXT4_MOUNT_POINT, psize / (1024 * 1024), allocsize / (1024 * 1024));
+        return NULL;
+    }
+
+    if (!ext4_fallocate(allocfile, allocsize)) {
+        MD_LOGE("%s: new fallocate failed(%d), %s\n", __func__, errno, strerror(errno));
+        return NULL;
+    }
+
+    if (!ext4_setup_attr(allocfile, true)) {
+        MD_LOGE("%s: ext4_setup_attr failed(%d), %s\n", __func__, errno, strerror(errno));
+        return NULL;
+    }
+
+    struct palloc_file *pfile = palloc_file_open(allocfile);
+    if (pfile == NULL) {
+        MD_LOGE("%s: palloc_file_open failed(%d), %s\n", __func__, errno, strerror(errno));
+        return NULL;
+    }
+
+    if (!fs_lba_maker(pfile, true)) {
+        palloc_file_close(pfile);
+        MD_LOGE("%s: lba marker failed(%d), %s\n", __func__, errno, strerror(errno));
+        return NULL;
+    }
+
+    // sync when finish lba_marker in new_fallocate.
+    sync();
+
+    return pfile;
+}
+
+static int ext4_bdata_is_ok(const struct palloc_file *pfile)
+{
+    int fds, num_blocks, j;
+    struct stat statinfo;
+    unsigned int mycrc, BlockLBA[1024];
+    unsigned int i;
+    bool stop_here = false;
+
+    // Get file statinfo
+    if(0 > fstat(pfile->fd, &statinfo)) {
+        MD_LOGE("%s: bdata stat failed(%d), %s\n", __func__, errno, strerror(errno));
+        return BDATA_STATE_FILE_ACCESS_ERROR;
+    }
+
+    // Counting blocks
+    num_blocks = (statinfo.st_size + statinfo.st_blksize - 1) / statinfo.st_blksize;
+    num_blocks = (num_blocks + MRDUMP_EXT4_LBA_PER_BLOCK - 1) / MRDUMP_EXT4_LBA_PER_BLOCK;
+
+    // open
+    char *devicenode = mrdump_get_device_node(MRDUMP_EXT4_MOUNT_POINT);
+    if(devicenode == NULL) {
+        MD_LOGE("%s: get devicenode failed(%d), %s\n", __func__, errno, strerror(errno));
+        return BDATA_STATE_FILE_ACCESS_ERROR;
+    } else {
+        fds = open(devicenode, O_RDWR);
+        if(0 > fds) {
+            free(devicenode);
+            MD_LOGE("%s: open devicenode failed(%d), %s\n", __func__, errno, strerror(errno));
+            return BDATA_STATE_FILE_ACCESS_ERROR;
+        }
+    }
+    free(devicenode);
+
+    // Check each Block (Now: InfoLBA + Address Block)
+    // 1. InfoLBA blocks
+    struct mrdump_pafile_info info;
+    if (!mrdump_read_pafile_info(pfile, fds, &info)) {
+        mrdump_close(fds);
+        return BDATA_STATE_BLOCK_HEADER_ERROR;
+    }
+
+    //get timestamp
+    bdata.timestamp = info.timestamp;
+
+    // for performance, we must finish fiemap here... but not in the loop
+    unsigned int my_num = mrdump_fiemap_total_entries(pfile->fd);
+    if(my_num == 0) {
+        MD_LOGE("%s: mrdump_fiemap_total_entries error!(%d), %s\n", __func__, errno, strerror(errno));
+        mrdump_close(fds);
+        return BDATA_STATE_BLOCK_HEADER_ERROR;
+    }
+    struct fiemap_info *myinfo = malloc(my_num * sizeof(struct fiemap_info));
+    if(!mrdump_fiemap_get_entries(pfile->fd, pfile->blksize, myinfo, my_num)) {
+        MD_LOGE("%s: mrdump_fiemap_get_entries error!(%d), %s\n", __func__, errno, strerror(errno));
+        mrdump_close(fds);
+        return BDATA_STATE_BLOCK_HEADER_ERROR;
+    }
+
+    // 2. Address Block sector wait until patch in lk
+
+    if (mount_as_ext4(MRDUMP_EXT4_MOUNT_POINT) && info.coredump_size == ULLONG_MAX) {
+        MD_LOGE("coredump size is incorrect\n");
+        return BDATA_STATE_BLOCK_DATA_ERROR;
+    }
+    for (i=1; i<(unsigned int)num_blocks; i++) {
+        unsigned int lba = (unsigned int)mrdump_fiemap_get_lba_of_block(myinfo, my_num, i);
+        if(-1 == ext4_block_lseek(fds, lba, pfile->blksize)) {
+            MD_LOGE("%s: bdata lseek64 BlockLBA failed(%d), %s\n", __func__, errno, strerror(errno));
+            free(myinfo);
+            mrdump_close(fds);
+            return BDATA_STATE_BLOCK_HEADER_ERROR;
+        }
+        if(0 > read(fds, (void *)BlockLBA, pfile->blksize)) {
+            MD_LOGE("%s: bdata read BlockLBA error!(%d), %s\n", __func__, errno, strerror(errno));
+            free(myinfo);
+            mrdump_close(fds);
+            return BDATA_STATE_BLOCK_HEADER_ERROR;
+        }
+        mycrc = crc32(0, Z_NULL, 0);
+        mycrc = crc32(mycrc, (void *)BlockLBA, (pfile->blksize-4));
+        if (mycrc != BlockLBA[1023]) {
+            MD_LOGE("%s: bdata BlockLBA %d CRC error(%08x, %08x)\n", __func__, i, mycrc, BlockLBA[1023]);
+            free(myinfo);
+            mrdump_close(fds);
+            return BDATA_STATE_BLOCK_HEADER_ERROR;
+        }
+    }
+    // data block vaildation for F2FS
+    if (mount_as_f2fs(MRDUMP_EXT4_MOUNT_POINT) && info.coredump_size == ULLONG_MAX) {
+        for(i=1; i<(unsigned int)num_blocks; i++) {
+            unsigned int lba = (unsigned int)mrdump_fiemap_get_lba_of_block(myinfo, my_num, i);
+            if(-1 == ext4_block_lseek(fds, lba, pfile->blksize)) {
+                MD_LOGE("%s: bdata lseek64 BlockLBA failed(%d), %s\n", __func__, errno, strerror(errno));
+                mrdump_close(fds);
+                return BDATA_STATE_BLOCK_DATA_ERROR;
+            }
+            if(0 > read(fds, (void *)BlockLBA, pfile->blksize)) {
+                MD_LOGE("%s: bdata read BlockLBA error!(%d), %s\n", __func__, errno, strerror(errno));
+                mrdump_close(fds);
+                return BDATA_STATE_BLOCK_DATA_ERROR;
+            }
+
+            for(j=0; j<MRDUMP_EXT4_LBA_PER_BLOCK; j++) {
+                lba = BlockLBA[j];
+
+                if(lba == 0)
+                    stop_here = true;
+
+                if(check_a_data_block(fds, pfile->blksize, lba) < 0) {
+                    MD_LOGE("%s: format_data_block error! j=%d \n", __func__, j);
+                    mrdump_close(fds);
+                    return BDATA_STATE_BLOCK_DATA_ERROR;
+                }
+            }
+            lba = BlockLBA[j];
+
+            if(stop_here)
+                break;
+        }
+    }
+
+    mrdump_close(fds);
+    free(myinfo);
+    return BDATA_STATE_CHECK_PASS;
+}
+
+////////////////////////////////////////////
+// export function (extern of other files)//
+////////////////////////////////////////////
+
+bool mrdump_file_get_info(const char *allocfile, struct mrdump_pafile_info *info)
+{
+    struct palloc_file *pfile = palloc_file_open(allocfile);
+    if (pfile == NULL) {
+        return false;
+    }
+    int device_fd = ext4_open_device_node(MRDUMP_EXT4_MOUNT_POINT);
+    if (device_fd < 0) {
+        palloc_file_close(pfile);
+        return false;
+    }
+    bool retval = mrdump_read_pafile_info(pfile, device_fd, info);
+    palloc_file_close(pfile);
+    mrdump_close(device_fd);
+    return retval;
+}
+
+static uint64_t ext4_default_filesize(int memsize)
+{
+    int ret = 0;
+    FILE *fp;
+    char c, myline[1024];
+    char *delim="\x09\x20";
+    uint64_t MySize;
+
+    fp = fopen("/proc/meminfo", "r");
+    if(fp == NULL)
+        return ret;
+
+    while(!feof(fp)) {
+
+        // getline
+        ret = fscanf(fp, "%[^\n]", myline);
+
+        // strtok strings
+        MySize = 0;
+        if(ret > 0) {
+            char *mystr = strtok(myline, delim);
+            if(mystr != NULL) {
+                if(!strcmp(mystr, "MemTotal:")) {
+                    mystr = strtok(NULL, delim);
+                    if(mystr != NULL) {
+                        MySize = atol(mystr);
+                    }
+                    break;
+                }
+            }
+        }
+
+        /* clear newline character */
+        ret = fscanf(fp, "%c", &c);
+        if (ret != 1) {
+            MD_LOGE("%s: not EOL.", __func__);
+            fclose(fp);
+            break;
+        }
+    }
+    fclose(fp);
+
+    // Count proper MySize about half size of MemTotal;
+    ret = ((MySize*1000) + (1000*1000) - 1)/(1000000);
+    if(memsize == DEFAULT_HALFMEM)
+        ret/= 2;
+    MySize = (uint64_t)ret*1024*1024;
+
+    return (MySize);
+}
+
+uint64_t mrdump_file_default_filesize(void)
+{
+    uint64_t fsize = 0;
+    int  f_mem = USERDEFINED_MEM;
+    const char *mrdump_allocate_size = sysenv_get("mrdump_allocate_size");
+
+printf("mrdump_allocate_size = %s\n", mrdump_allocate_size);
+    if ((mrdump_allocate_size == NULL) || !strncmp(mrdump_allocate_size, "fullmem", 7)) {
+        fsize = ext4_default_filesize(DEFAULT_FULLMEM);
+        f_mem = DEFAULT_FULLMEM;
+    }
+    else if ((!strncmp(mrdump_allocate_size, "0", 1))) {
+        fsize = 0;
+        f_mem = DEFAULT_DISABLE;
+    }
+    else if (!strncmp(mrdump_allocate_size, "halfmem", 7)) {
+        fsize = ext4_default_filesize(DEFAULT_HALFMEM);
+        f_mem = DEFAULT_HALFMEM;
+    }
+    // nnn or others
+    else if(f_mem == USERDEFINED_MEM) {
+        int value = atoi(mrdump_allocate_size);
+        if(value > 0) {
+            fsize = (uint64_t)value*1024*1024;
+        }
+        else {
+            fsize = 0;
+        }
+    }
+
+    return fsize;
+}
+
+////////////////////////////////////////////
+// User API                                  //
+////////////////////////////////////////////
+static bool mrdump_ext4_reinit_allocfile(const char *allocfile, uint64_t realsize, bool reset)
+{
+    int check_state = 0;
+
+    /* pre-allocate only in internal-storage:ext4 */
+    const char *output_dev = sysenv_get("mrdump_output");
+    MD_LOGI("%s: output-dev(%s)\n", __func__, output_dev);
+    if  ((output_dev != NULL) && (strcmp(output_dev, "internal-storage") != 0)) {
+        palloc_file_remove(allocfile);
+        return false;
+    }
+
+    if (realsize > 0) {
+        struct palloc_file *pfile = NULL;
+        if (!mrdump_file_is_exist(allocfile)) {
+            pfile = ext4_new_fallocfile(allocfile, realsize);
+            if (pfile == NULL) {
+                MD_LOGE("%s: fallocate failed at new creation.\n", __func__);
+                return false;
+            }
+        } else {
+            pfile = palloc_file_open(allocfile);
+            if (pfile == NULL) {
+                MD_LOGE("%s: palloc_file_open failed.\n", __func__);
+                goto cleanup;
+            }
+
+            // existed allocate
+            // Check Block Data validity
+            check_state = ext4_bdata_is_ok(pfile);
+            if ((check_state == BDATA_STATE_FILE_ACCESS_ERROR) || (check_state == BDATA_STATE_BLOCK_HEADER_ERROR)) {
+                MD_LOGI("%s: Address Blocks checked: incorrect.\n", __func__);
+                palloc_file_close(pfile);
+                palloc_file_remove(allocfile);
+                pfile = ext4_new_fallocfile(allocfile, realsize);
+                if (pfile == NULL) {
+                    MD_LOGE("%s: Address Blocks not correct, re-fallocate.\n", __func__);
+                    return false;
+                }
+            } else if (check_state == BDATA_STATE_BLOCK_DATA_ERROR) {
+                MD_LOGE("BlockData Verification failed\n");
+                if (!fs_lba_maker(pfile, true)) {
+                    MD_LOGE("%s: lba marker failed, removing pre-allocate-file.\n", __func__);
+                    palloc_file_close(pfile);
+                    goto cleanup;
+                }
+            } else {
+                MD_LOGI("%s: Address Blocks checked: correct.\n", __func__);
+                if (reset) {
+                    if (!fs_lba_maker(pfile, true)) {
+                        MD_LOGE("%s: lba marker failed, removing pre-allocate-file.\n", __func__);
+                        palloc_file_close(pfile);
+                        goto cleanup;
+                    }
+                }
+            }
+        }
+
+        int retval = fop_file_write_string(MRDUMP_EXT4_PARA_LBAOOO, "%u\n", (unsigned int) pfile->lbaooo);
+        if (retval < 0) {
+            MD_LOGE("%s: write %s failed(%d), %s\n", __func__, MRDUMP_EXT4_PARA_LBAOOO,
+                    -retval, strerror(-retval));
+            palloc_file_close(pfile);
+            goto cleanup;
+        }
+        palloc_file_close(pfile);
+        MD_LOGI("%s: LBAOOO ready\n", __func__);
+        return true;
+    }
+    MD_LOGI("Allocate size %llx set to zero, remove preallocate file\n", realsize);
+  cleanup:
+    palloc_file_remove(allocfile);
+    return false;
+}
+
+bool mrdump_file_fetch_zip_coredump(const char *outfile)
+{
+    struct mrdump_pafile_info lbainfo;
+    unsigned int       blknum;
+    unsigned int       rlba, bidx, BlockLBA[1024];
+    unsigned int       len, mylen;
+    unsigned char      MyData[MRDUMP_EXT4_EXSPACE];
+    int       fpRead, fpWrite, ret;
+
+    // outfile
+    if(outfile == NULL) {
+        MD_LOGE("%s: outfile is NULL! (%d), %s\n", __func__, errno, strerror(errno));
+        return false;
+    }
+
+    struct palloc_file *pfile = palloc_file_open(MRDUMP_EXT4_ALLOCATE_FILE);
+    if (pfile == 0) {
+        return false;
+    }
+
+    fpRead = ext4_open_device_node(MRDUMP_EXT4_MOUNT_POINT);
+    if (fpRead < -1) {
+        goto cleanup0;
+    }
+
+    if (!mrdump_read_pafile_info(pfile, fpRead, &lbainfo)) {
+        mrdump_close(fpRead);
+        goto cleanup0;
+    }
+    if (lbainfo.coredump_size == 0) {
+        MD_LOGI("Ramdump size is 0, no data to dump\n");
+        mrdump_close(fpRead);
+        goto cleanup0;
+    }
+
+    // Write handle
+    fpWrite = open(outfile, O_RDWR | O_CREAT | O_TRUNC, 0600);
+    if(0 > fpWrite) {
+        MD_LOGE("%s: open Write handle open failed(%d), %s\n", __func__, errno, strerror(errno));
+        mrdump_close(fpRead);
+        goto cleanup0;
+    }
+
+    // Init BlockLBA
+    rlba = lbainfo.addr_lba;
+    if(-1 == ext4_block_lseek(fpRead, rlba, pfile->blksize)) {
+        MD_LOGE("%s: lseek64 Init BlockLBA failed(%d), %s\n", __func__, errno, strerror(errno));
+        mrdump_close(fpRead);
+        mrdump_close(fpWrite);
+        unlink(outfile);
+        goto cleanup0;
+    }
+    if(0 > read(fpRead, BlockLBA, sizeof(BlockLBA))) {
+        MD_LOGE("%s: fetch read BlockLBA error!(%d), %s\n", __func__, errno, strerror(errno));
+        mrdump_close(fpRead);
+        mrdump_close(fpWrite);
+        unlink(outfile);
+        goto cleanup0;
+    }
+
+    // Fetching data
+    bidx    = 0;
+    rlba    =  BlockLBA[bidx];
+
+    uint64_t delaylen = 0;
+    uint64_t coresize = lbainfo.coredump_size;
+    while(coresize > 0) {
+
+        // counting coutinue datas...
+        blknum = ext4_num_to_join((unsigned int *)BlockLBA, bidx);
+        len = blknum * pfile->blksize;
+        if(coresize < len) {
+            mylen = coresize;
+        } else {
+            mylen = len;
+        }
+
+        // Reading data to MyData
+        if(-1 == ext4_block_lseek(fpRead, rlba, pfile->blksize)) {
+            MD_LOGE("%s: lseek64 Read MyData failed(%d), %s", __func__, errno, strerror(errno));
+            mrdump_close(fpRead);
+            mrdump_close(fpWrite);
+            unlink(outfile);
+            goto cleanup0;
+        }
+        if(0 > read(fpRead, MyData, mylen)) {
+            MD_LOGE("%s: fetch MyData error!(%d), %s", __func__, errno, strerror(errno));
+            mrdump_close(fpRead);
+            mrdump_close(fpWrite);
+            unlink(outfile);
+            goto cleanup0;
+        }
+        if(0 > write(fpWrite, MyData, mylen)) {
+            MD_LOGE("%s: fetch MyData error!(%d), %s", __func__, errno, strerror(errno));
+            mrdump_close(fpRead);
+            mrdump_close(fpWrite);
+            unlink(outfile);
+            goto cleanup0;
+        }
+
+        ret = ext4_get_next_bidx(fpRead, (unsigned int *)BlockLBA, bidx, pfile->blksize, blknum);
+        if(ret < 0){
+            MD_LOGE("%s: fpRead failed to get next block idx(%d), %s", __func__, errno, strerror(errno));
+            mrdump_close(fpRead);
+            mrdump_close(fpWrite);
+            unlink(outfile);
+            goto cleanup0;
+        }
+        bidx = (unsigned int)ret;
+
+        if(bidx > MRDUMP_EXT4_LBA_PER_BLOCK) {
+            mrdump_close(fpRead);
+            mrdump_close(fpWrite);
+            unlink(outfile);
+            goto cleanup0;
+        }
+        if(bidx == MRDUMP_EXT4_LBA_PER_BLOCK) {
+            ret = ext4_get_next_bidx(fpRead, (unsigned int *)BlockLBA, bidx, pfile->blksize, blknum);
+            if(ret < 0) {
+                MD_LOGE("%s: bidx(1022) failed to get next block idx(%d), %s", __func__, errno, strerror(errno));
+                mrdump_close(fpRead);
+                mrdump_close(fpWrite);
+                unlink(outfile);
+                goto cleanup0;
+            }
+            bidx = (unsigned int)ret;
+        }
+        rlba = BlockLBA[bidx];
+        coresize -= mylen;
+
+        /* flow control */
+        delaylen += mylen;
+        if (delaylen >= MRDUMP_MAX_BANDWIDTH) {
+            delaylen = 0;
+            fdatasync(fpWrite);
+            sleep(1);
+        }
+    }
+
+    mrdump_close(fpRead);
+    mrdump_close(fpWrite);
+
+    MD_LOGI("Ramdump write to %s size %" PRId64 "\n", outfile, lbainfo.coredump_size);
+    return true;
+
+  cleanup0:
+    palloc_file_close(pfile);
+    return false;
+}
+
+void mrdump_file_set_maxsize(int mrdump_size)
+{
+    palloc_file_remove(MRDUMP_EXT4_ALLOCATE_FILE);
+
+    char s[64];
+    uint64_t fsize = 0;
+
+    if(mrdump_size < 0)
+        mrdump_size = 0;
+
+    switch(mrdump_size) {
+    case DEFAULT_DISABLE:
+        sysenv_set("mrdump_allocate_size", "0");
+        fsize = 0;
+        break;
+    case DEFAULT_HALFMEM:
+        sysenv_set("mrdump_allocate_size", "halfmem");
+        fsize = mrdump_file_default_filesize();
+        break;
+    case DEFAULT_FULLMEM:
+        sysenv_set("mrdump_allocate_size", "fullmem");
+        fsize = mrdump_file_default_filesize();
+        break;
+    default:
+        snprintf(s, sizeof(s), "%d", mrdump_size);
+        sysenv_set("mrdump_allocate_size", s);
+        fsize = (uint64_t)mrdump_size*1024*1024;
+        break;
+    }
+
+    if (mrdump_ext4_reinit_allocfile(MRDUMP_EXT4_ALLOCATE_FILE, fsize, true)) {
+        printf("set MT-RAMDUMP allocated file size => %" PRIu64 " MB].\n", (fsize/1024/1024));
+    }
+}
+
+/* System startup setup
+ * Sanity check
+ * 1. Check if /data partition filesystem is supported
+ * 2. Check if lk/kernel MT-RAMDUMP support is enabled
+ * 3. Check if mrdump file size is set to non-zero
+ * If above condition is failed, remove pre-allocated file and disable MRDUMP.
+ * Try to pre-allocated file
+ * 1. If file doesn't exist, create a new file
+ * 2. If file exist and header/body corrupted, re-create a new file
+ */
+void mrdump_file_setup(bool reset)
+{
+    /* check if mount as ext4 partition or f2fs */
+    if(MRDUMP_DATA_FS_NONE == mrdump_get_data_os()) {
+        MD_LOGE("Unsupport file system type.");
+        return;
+    }
+
+    if (!mrdump_is_supported()) {
+        MD_LOGE("MRDUMP is not supported\n");
+        palloc_file_remove(MRDUMP_EXT4_ALLOCATE_FILE);
+        return;
+    }
+
+    mrdump_ext4_reinit_allocfile(MRDUMP_EXT4_ALLOCATE_FILE, mrdump_file_default_filesize(), reset);
+}
diff --git a/src/devtools/mrdump/mrdump_tool_source/mrdump_support_ext4.h b/src/devtools/mrdump/mrdump_tool_source/mrdump_support_ext4.h
new file mode 100644
index 0000000..eb05c11
--- /dev/null
+++ b/src/devtools/mrdump/mrdump_tool_source/mrdump_support_ext4.h
@@ -0,0 +1,80 @@
+#pragma once
+
+/* debug on/off */
+#define MRDUMP_DEBUG
+
+/* for statfs */
+#define EXT3_SUPER_MAGIC 0xEF53
+
+/* Variables defined */
+#define AE_DUMPSYS_DATA_PATH        "/log/mtklog"
+#define MRDUMP_EXT4_NEW_FILE        true
+#define MRDUMP_EXT4_OLD_FILE        false
+#define MRDUMP_EXT4_PARA_LBAOOO     "/sys/module/mrdump/parameters/lbaooo"
+#define MRDUMP_EXT4_PROC_MOUNTS     "/proc/self/mounts"
+//#define MRDUMP_EXT4_MOUNT_POINT     "/data"
+#define MRDUMP_EXT4_MOUNT_POINT     "/log"
+#define MRDUMP_EXT4_ALLOCATE_FILE   AE_DUMPSYS_DATA_PATH"/mrdump_preallocated"
+#define MRDUMP_EXT4_MIN_ALLOCATE    256
+#define MRDUMP_EXT4_BLKSIZE         4096
+#define MRDUMP_EXT4_MAX_CONTINUE    64
+#define MRDUMP_EXT4_EXSPACE         (MRDUMP_EXT4_BLKSIZE*MRDUMP_EXT4_MAX_CONTINUE)
+#define MRDUMP_EXT4_LBA_PER_BLOCK   1022
+
+/*
+ * v1: support allocate size > 4G
+ * v2: support timestamp
+ */
+#define MRDUMP_PAF_VERSION 0x0002
+
+#define MRDUMP_PAF_INFO_LBA      4
+#define MRDUMP_PAF_ADDR_LBA      8
+#define MRDUMP_PAF_ALLOCSIZE    12
+#define MRDUMP_PAF_COREDUMPSIZE 20
+#define MRDUMP_PAF_TIMESTAMP    28
+#define MRDUMP_PAF_CRC32        36
+#define MRDUMP_LBA_DATAONLY     MRDUMP_PAF_CRC32
+#define MRDUMP_PAF_TOTAL_SIZE   40
+
+typedef enum {
+    DEFAULT_DISABLE,
+    DEFAULT_HALFMEM,
+    DEFAULT_FULLMEM,
+    USERDEFINED_MEM
+} MRDUMP_DEFAULT_SIZE;
+
+typedef enum {
+    BDATA_STATE_CHECK_PASS,
+    BDATA_STATE_FILE_ACCESS_ERROR,
+    BDATA_STATE_BLOCK_HEADER_ERROR,
+    BDATA_STATE_BLOCK_DATA_ERROR,
+} MRDUMP_BDATA_STATE;
+
+/* for chattr */
+#define FS_IOC_GETFLAGS                 _IOR('f', 1, long)
+#define FS_IOC_SETFLAGS                 _IOW('f', 2, long)
+#define FS_SECRM_FL                     0x00000001 /* Secure deletion */
+#define FS_IMMUTABLE_FL                 0x00000010 /* Immutable file */
+
+struct mrdump_pafile_info {
+    uint32_t info_lba;
+    uint32_t addr_lba;
+    uint64_t filesize;
+    uint64_t coredump_size;
+    uint64_t timestamp;
+};
+
+struct __attribute__((__packed__)) marked_block_data {
+    uint32_t lba;
+    uint64_t zero_padding[510];
+    uint64_t timestamp;
+    uint32_t crc;
+};
+
+/* Function Prototypes */
+void mrdump_file_set_maxsize(int mrdump_size);
+void mrdump_file_setup(bool reset);
+bool mrdump_file_get_info(const char *allocfile, struct mrdump_pafile_info *info);
+uint64_t mrdump_file_default_filesize(void);
+bool mrdump_file_fetch_zip_coredump(const char *outfile);
+bool mount_as_ext4(const char *mountp);
diff --git a/src/devtools/mrdump/mrdump_tool_source/mrdump_support_f2fs.c b/src/devtools/mrdump/mrdump_tool_source/mrdump_support_f2fs.c
new file mode 100644
index 0000000..dbeb418
--- /dev/null
+++ b/src/devtools/mrdump/mrdump_tool_source/mrdump_support_f2fs.c
@@ -0,0 +1,94 @@
+/* uint64_t ...*/
+#include <inttypes.h>
+#include <stdbool.h>
+
+/* statfs() */
+#include <sys/statfs.h>
+
+/* mmap, munmap */
+#include <sys/mman.h>
+
+/* fsync(), close(), write(), unlink() */
+#include <unistd.h>
+
+/* __u32 */
+#include <linux/types.h>
+
+/* ioctl */
+//#include <linux/fs.h>
+#include <sys/ioctl.h>
+
+/* struct stat, open */
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+/* strerror */
+#include <string.h>
+/* errno */
+#include <errno.h>
+
+/* mrdump related */
+#include "mrdump_log.h"
+#include "mrdump_common.h"
+#include "mrdump_support_f2fs.h"
+
+bool mount_as_f2fs(const char *mountp)
+{
+    struct statfs fs;
+    if(statfs(mountp, &fs) == 0) {
+        if(fs.f_type == F2FS_SUPER_MAGIC)
+            return true;
+
+        return false;
+    }
+    MD_LOGE("%s: %s statfs error.\n", __func__, mountp);
+    return false;
+}
+
+bool f2fs_fallocate(const char *allocfile, uint64_t allocsize)
+{
+    int i;
+    int zQ = (allocsize + F2FS_MAPSIZE - 1) / F2FS_MAPSIZE;
+    unsigned int val;
+
+    if((allocfile == NULL) || (allocsize == 0)) {
+        MD_LOGE("%s: allocfile is NULL or allocsize = %" PRIu64 "\n", __func__, allocsize);
+        return false;
+    }
+
+    void *ZeroPage = mmap(NULL, F2FS_MAPSIZE, PROT_READ, MAP_ANONYMOUS | MAP_SHARED, -1, 0);
+    if(ZeroPage == NULL) {
+        MD_LOGE("%s: ZeroPage map failed.\n", __func__);
+        return false;
+    }
+
+    int fd = open(allocfile, O_RDWR | O_CREAT, 0400);
+    if(0 > fd) {
+        MD_LOGE("%s: open fd failed.\n", __func__);
+        munmap(ZeroPage, F2FS_MAPSIZE);
+        return false;
+    }
+
+    for(i=0; i<zQ; i++) {
+        if(0 >= write(fd,ZeroPage, F2FS_MAPSIZE)) {
+            MD_LOGE("%s: ZeroPage write failed\n", __func__);
+            close(fd);
+            unlink(allocfile);
+            munmap(ZeroPage, F2FS_MAPSIZE);
+            return false;
+        }
+    }
+
+    fsync(fd);
+
+    val = 31337;
+    if(0 > ioctl(fd, F2FS_IOC_SET_PIN_FILE, &val)) {
+        MD_LOGE("%s: F2FS_IOC_SET_PIN_FILE(%u) failed(%d), %s\n", __func__, val, errno, strerror(errno));
+    }
+
+    close(fd);
+    munmap(ZeroPage, F2FS_MAPSIZE);
+
+    return true;
+}
diff --git a/src/devtools/mrdump/mrdump_tool_source/mrdump_support_f2fs.h b/src/devtools/mrdump/mrdump_tool_source/mrdump_support_f2fs.h
new file mode 100644
index 0000000..8408201
--- /dev/null
+++ b/src/devtools/mrdump/mrdump_tool_source/mrdump_support_f2fs.h
@@ -0,0 +1,14 @@
+#pragma once
+
+/* Map size for ZeroPage */
+#define F2FS_SUPER_MAGIC 0xF2F52010
+#define F2FS_MAPSIZE (1024*1024*8)
+
+/* for IOCTL */
+#define F2FS_IOCTL_MAGIC        0xf5
+#define F2FS_IOC_SET_PIN_FILE   _IOW(F2FS_IOCTL_MAGIC, 13, __u32)
+#define F2FS_IOC_GET_PIN_FILE   _IOR(F2FS_IOCTL_MAGIC, 14, __u32)
+
+/* Function Prototypes */
+bool mount_as_f2fs(const char *mountp);
+bool f2fs_fallocate(const char *allocfile, uint64_t allocsize);
diff --git a/src/devtools/mrdump/mrdump_tool_source/mrdump_support_fiemap.c b/src/devtools/mrdump/mrdump_tool_source/mrdump_support_fiemap.c
new file mode 100644
index 0000000..9481947
--- /dev/null
+++ b/src/devtools/mrdump/mrdump_tool_source/mrdump_support_fiemap.c
@@ -0,0 +1,194 @@
+/* printf */
+#include <stdio.h>
+
+/* uint64_t ...*/
+#include <inttypes.h>
+#include <stdbool.h>
+
+/* malloc */
+#include <stdlib.h>
+
+/* ioctl, fibmap, fiemap */
+#include <linux/fs.h>
+#include <sys/ioctl.h>
+#include <linux/fiemap.h>
+
+/* strerror */
+#include <string.h>
+/* errno */
+#include <errno.h>
+
+/* mrdump related */
+#include "mrdump_log.h"
+#include "mrdump_common.h"
+#include "mrdump_support_fiemap.h"
+
+static unsigned int fiemap_total_entries(int fd)
+{
+    int is_last, rows = 0;
+
+    // Preparing for fiemap work
+    struct fiemap *fiemap = (struct fiemap *)malloc(sizeof(struct fiemap) + sizeof(struct fiemap_extent));
+    unsigned long long lstart = 0;             // logical input mapping star
+#if (__LP64__)
+    unsigned long long llength = ~0ULL;        // logical input mapping length
+#else
+    unsigned long long llength = 0xFFFFFFFF;
+#endif
+
+    fiemap->fm_start = lstart;
+    fiemap->fm_length = llength;
+    fiemap->fm_flags = 0;
+    fiemap->fm_extent_count = 1;
+    fiemap->fm_mapped_extents = 0;   // output only
+
+    do {
+        if(0 > ioctl(fd, FS_IOC_FIEMAP, (unsigned long)fiemap)) {
+            MD_LOGE("%s: FIEMAP ioctl failed!(%d), %s\n", __func__, errno, strerror(errno));
+            return 0;
+        }
+
+        if(fiemap->fm_mapped_extents == 0) {
+            MD_LOGE("%s: FIEMAP: fm_mapped_extents = 0(%d), %s\n", __func__, errno, strerror(errno));
+            return 0;
+        }
+
+        // check if the last extent
+        is_last = fiemap->fm_extents[0].fe_flags & FIEMAP_EXTENT_LAST;
+
+        // Set up the next call arguments
+        if(!is_last) {
+            unsigned long long foo = fiemap->fm_extents[0].fe_logical + fiemap->fm_extents[0].fe_length;
+            fiemap->fm_start = foo;
+            fiemap->fm_length = lstart + llength - foo;
+            fiemap->fm_flags = 0;
+            fiemap->fm_extent_count = 1;
+        }
+
+        rows++;
+
+    } while(!is_last);
+
+    free(fiemap);
+    return rows;
+
+}
+
+static bool fiemap_get_entries(int fd, unsigned int blksize, struct fiemap_info *mapinfo, unsigned int rows)
+{
+    struct fiemap_info *myinfo = mapinfo;
+
+    // Preparing for fiemap work
+    struct fiemap *fiemap = (struct fiemap *)malloc(sizeof(struct fiemap) + sizeof(struct fiemap_extent));
+    unsigned long long lstart = 0;             // logical input mapping star
+#if (__LP64__)
+    unsigned long long llength = ~0ULL;        // logical input mapping length
+#else
+    unsigned long long llength = 0xFFFFFFFF;
+#endif
+
+    fiemap->fm_start = lstart;
+    fiemap->fm_length = llength;
+    fiemap->fm_flags = 0;
+    fiemap->fm_extent_count = 1;
+    fiemap->fm_mapped_extents = 0;   // output only
+
+    unsigned int i, is_last;
+    for(i=0; i<rows; i++)
+    {
+        if(0 > ioctl(fd, FS_IOC_FIEMAP, (unsigned long)fiemap)) {
+            printf("%s: FIEMAP ioctl failed!(%d), %s\n", __func__, errno, strerror(errno));
+            return false;
+        }
+
+        // check if the last extent
+        is_last = fiemap->fm_extents[0].fe_flags & FIEMAP_EXTENT_LAST;
+
+        // basic parameters
+        myinfo->lba = (unsigned int)(fiemap->fm_extents[0].fe_physical/blksize);
+        myinfo->tot = (unsigned int)(fiemap->fm_extents[0].fe_length / blksize);
+
+        // Set up the next call arguments
+        if(!is_last) {
+
+            unsigned long long foo = fiemap->fm_extents[0].fe_logical + fiemap->fm_extents[0].fe_length;
+            fiemap->fm_start = foo;
+            fiemap->fm_length = lstart + llength - foo;
+            fiemap->fm_flags = 0;
+            fiemap->fm_extent_count = 1;
+        }
+        myinfo++;
+    }
+    free(fiemap);
+    return true;
+}
+
+static int fiemap_get_entry_lba(int fd, unsigned int blksize, unsigned int rows)
+{
+    unsigned int lba = 0, num = (unsigned int)fiemap_total_entries(fd);
+    if(num > 0) {
+        struct fiemap_info *myinfo = malloc(num * sizeof(struct fiemap_info));
+        if(fiemap_get_entries(fd, blksize, myinfo, num)) {
+            lba = myinfo[rows].lba;
+            free(myinfo);
+            return (int)lba;
+        }
+        free(myinfo);
+    }
+    return -1;
+}
+
+static int fiemap_get_entry_tot(int fd, unsigned int blksize, unsigned int rows)
+{
+    unsigned int tot = 0, num = (unsigned int)fiemap_total_entries(fd);
+    if(num > 0) {
+        struct fiemap_info *myinfo = malloc(num * sizeof(struct fiemap_info));
+        if(fiemap_get_entries(fd, blksize, myinfo, num)) {
+            tot = myinfo[rows].tot;
+            free(myinfo);
+            return (int)tot;
+        }
+        free(myinfo);
+    }
+    return -1;
+}
+
+static unsigned int fiemap_get_lba_of_block(struct fiemap_info *myinfo, unsigned int rows, unsigned int block)
+{
+    unsigned int i, lba = 0, tot = 0;
+    for(i=0; i<rows; i++) {
+        tot = myinfo[i].tot;
+        if(block < tot) {
+            lba = myinfo[i].lba + block;
+            break;
+        } else {
+            block = block - tot;
+        }
+    }
+    return lba;
+}
+
+unsigned int mrdump_fiemap_total_entries(int fd)
+{
+    return fiemap_total_entries(fd);
+}
+
+bool mrdump_fiemap_get_entries(int fd, unsigned int blksize, struct fiemap_info *mapinfo, unsigned int rows)
+{
+    return fiemap_get_entries(fd, blksize, mapinfo, rows);
+}
+
+unsigned int mrdump_fiemap_get_lba_of_block(struct fiemap_info *myinfo, unsigned int num, unsigned int block)
+{
+    return fiemap_get_lba_of_block(myinfo, num, block);
+}
+
+int mrdump_fiemap_get_entry_tot(int fd, unsigned int blksize, unsigned int rows)
+{
+    return fiemap_get_entry_tot(fd, blksize, rows);
+}
+
+int mrdump_fiemap_get_entry_lba(int fd, unsigned int blksize, unsigned int rows)
+{
+    return fiemap_get_entry_lba(fd, blksize, rows);
+}
diff --git a/src/devtools/mrdump/mrdump_tool_source/mrdump_support_fiemap.h b/src/devtools/mrdump/mrdump_tool_source/mrdump_support_fiemap.h
new file mode 100644
index 0000000..f703a13
--- /dev/null
+++ b/src/devtools/mrdump/mrdump_tool_source/mrdump_support_fiemap.h
@@ -0,0 +1,13 @@
+#pragma once
+
+struct fiemap_info {
+    __u32 lba;
+    __u32 tot;
+};
+
+/* Function Prototypes */
+unsigned int mrdump_fiemap_total_entries(int fd);
+bool mrdump_fiemap_get_entries(int fd, unsigned int blksize, struct fiemap_info *mapinfo, unsigned int rows);
+unsigned int mrdump_fiemap_get_lba_of_block(struct fiemap_info *myinfo, unsigned int num, unsigned int block);
+int mrdump_fiemap_get_entry_tot(int fd, unsigned int blksize, unsigned int rows);
+int mrdump_fiemap_get_entry_lba(int fd, unsigned int blksize, unsigned int rows);
diff --git a/src/devtools/mrdump/mrdump_tool_source/mrdump_support_mpart.c b/src/devtools/mrdump/mrdump_tool_source/mrdump_support_mpart.c
new file mode 100644
index 0000000..924e00c
--- /dev/null
+++ b/src/devtools/mrdump/mrdump_tool_source/mrdump_support_mpart.c
@@ -0,0 +1,281 @@
+/* strlcpy */
+#include <stdio.h>
+
+/* uint64_t ...*/
+#include <inttypes.h>
+#include <stdbool.h>
+
+/* struct stat, lstat, open, execl */
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <fcntl.h>
+
+/* malloc */
+#include <stdlib.h>
+
+/* strlen */
+#include <string.h>
+
+/* strerror */
+#include <string.h>
+/* errno */
+#include <errno.h>
+
+/* bzero */
+#include <strings.h>
+
+/* ctime */
+#include <time.h>
+
+/* crc32, Z_NULL */
+#include <zlib.h>
+
+/* mrdump related */
+#include "mrdump_log.h"
+#include "mrdump_common.h"
+#include "mrdump_support_mpart.h"
+#include "mrdump_support_ext4.h"
+
+/* remember to free the fullpath when it is no longer required. */
+static char *get_partition_fullpath(char *linkfile)
+{
+    struct stat sa;
+    if (lstat(linkfile, &sa) == -1) {
+        MD_LOGE("%s: no mrdump partition.\n", __func__);
+        return NULL;
+    }
+
+    char *fullpath = malloc(sa.st_size + 1);
+    if (fullpath == NULL) {
+        MD_LOGE("%s: insufficient memory\n");
+        return NULL;
+    }
+
+    ssize_t r = readlink(linkfile, fullpath, sa.st_size + 1);
+    if (r == -1) {
+        MD_LOGE("%s: lstat\n");
+        return NULL;
+    }
+    if (r > sa.st_size) {
+        MD_LOGE("%s: symlink increased in size "
+                    "between lstat() and readlink()\n");
+        return NULL;
+    }
+    fullpath[r] = '\0';
+
+    return fullpath;
+}
+
+/* remember to free the pname when it is no longer required. */
+static char *get_partition_name(char *fullpath)
+{
+    char *pfile = fullpath;
+    if (!pfile) {
+        MD_LOGE("%s: no such full path\n", __func__);
+        return NULL;
+    }
+    int len = strlen(pfile);
+
+    char *pname = malloc(len);
+    if (pname == NULL) {
+        MD_LOGE("%s: malloc failed\n", __func__);
+        return NULL;
+    }
+
+    char *delim="\x2f";
+    char *p = strtok(pfile, delim);
+    while (p) {
+        p = strtok(NULL, delim);
+        if (p) {
+            bzero(pname, len);
+            strlcpy(pname, p, len);
+        }
+    }
+
+    return pname;
+}
+
+int mrdump_check_partition(void)
+{
+    /* get real path from symbolic file */
+    char *fullpath = get_partition_fullpath(MRDUMP_MPART_PARTITION);
+    if (!fullpath) {
+        MD_LOGE("%s: no such fullpath\n", __func__);
+        return 0;
+    }
+
+    /* get device node name */
+    char *realpath= strdup(fullpath);
+    char *pname = get_partition_name(realpath);
+    if (!pname) {
+        MD_LOGE("%s: cannot get the partition name\n", __func__);
+        return 0;
+    }
+    free(realpath);
+
+    /* get partition size */
+    uint64_t psize = mrdump_get_partition_size(fullpath);
+
+    /* get stat */
+    struct stat sb;
+    if (stat(fullpath, &sb) == -1) {
+        MD_LOGE("%s: no mrdump partition.\n", __func__);
+        return 0;
+    }
+
+    /* parition informations, reference to EXAMPLE of manpage STAT(2) */
+    MD_LOGI("PARTNAME:                  mrdump\n");
+    MD_LOGI("LINK:                      %s\n", MRDUMP_MPART_PARTITION);
+    MD_LOGI("Partition size:            %llu bytes\n", psize);
+    MD_LOGI("DEVNAME:                   %s\n", pname);
+    MD_LOGI("FILE:                      %s\n", fullpath);
+    MD_LOGI("File type:                 ");
+    switch (sb.st_mode & S_IFMT) {
+        case S_IFBLK:  MD_LOGI("block device\n");            break;
+        case S_IFCHR:  MD_LOGI("character device\n");        break;
+        case S_IFDIR:  MD_LOGI("directory\n");               break;
+        case S_IFIFO:  MD_LOGI("FIFO/pipe\n");               break;
+        case S_IFLNK:  MD_LOGI("symlink\n");                 break;
+        case S_IFREG:  MD_LOGI("regular file\n");            break;
+        case S_IFSOCK: MD_LOGI("socket\n");                  break;
+        default:       MD_LOGI("unknown?\n");                break;
+    }
+    MD_LOGI("Ownership:                 UID=%ld   GID=%ld\n",
+            (long) sb.st_uid, (long) sb.st_gid);
+    MD_LOGI("I-node number:             %ld\n", (long) sb.st_ino);
+    MD_LOGI("Mode:                      %lo (octal)\n", (unsigned long) sb.st_mode);
+    MD_LOGI("Link count:                %ld\n", (long) sb.st_nlink);
+    MD_LOGI("Last status change:        %s\n", ctime(&sb.st_ctime));
+    MD_LOGI("Last file access:          %s\n", ctime(&sb.st_atime));
+    MD_LOGI("Last file modification:    %s\n", ctime(&sb.st_mtime));
+
+    /* remember to free fullpath and pname */
+    free(fullpath);
+    free(pname);
+
+    return 1;
+}
+
+static bool mrdump_read_pafile_info(int device_fd,
+                                    struct mrdump_pafile_info *info)
+{
+    memset(info, 0, sizeof(struct mrdump_pafile_info));
+
+    uint8_t block0[MRDUMP_PAF_TOTAL_SIZE];
+    memset(block0, 0, sizeof(block0));
+
+    if (0 > read(device_fd, block0, sizeof(block0))) {
+        MD_LOGE("%s: read InfoLBA error (%d), %s\n", __func__, errno, strerror(errno));
+        return false;
+    }
+
+    uint8_t *bufp = &block0[0];
+    unsigned int crcval = crc32(0, Z_NULL, 0);
+    crcval = crc32(crcval, (void *)block0, MRDUMP_LBA_DATAONLY);
+    if (crcval != *(uint32_t *)&block0[MRDUMP_PAF_CRC32]) {
+        MD_LOGE("%s: LBA info CRC error (c:%08x, v:%08x)\n", __func__, crcval,
+                *(uint32_t *)&block0[MRDUMP_PAF_CRC32]);
+        return false;
+    }
+
+    info->coredump_size = *(uint64_t *)(bufp + MRDUMP_PAF_COREDUMPSIZE);
+    return true;
+}
+
+bool mrdump_file_fetch_zip_coredump_partition(const char *outfile)
+{
+    struct mrdump_pafile_info lbainfo;
+    unsigned int       read_len, mylen;
+    unsigned char      MyData[MRDUMP_PARTITION_EXSPACE];
+    int                fpRead, fpWrite;
+
+    // outfile
+    if(outfile == NULL) {
+        MD_LOGE("%s: outfile is NULL! (%d), %s\n", __func__, errno, strerror(errno));
+        return false;
+    }
+
+    fpRead = open(MRDUMP_MPART_PARTITION, O_RDWR);
+    if (fpRead < 0) {
+        MD_LOGE("mrdump partition %s open failed (%d), %s\n",
+                MRDUMP_MPART_PARTITION, errno, strerror(errno));
+        return false;
+    }
+
+    if (!mrdump_read_pafile_info(fpRead, &lbainfo)) {
+        mrdump_close(fpRead);
+        return false;
+    }
+
+    if (lbainfo.coredump_size == 0) {
+        MD_LOGI("mrdump partition have 0 size dump, no data to dump\n");
+        mrdump_close(fpRead);
+        return false;
+    }
+
+    // Write handle
+    fpWrite = open(outfile, O_RDWR | O_CREAT | O_TRUNC, 0600);
+    if(0 > fpWrite) {
+        MD_LOGE("%s: open Write handle open failed(%d), %s\n", __func__, errno, strerror(errno));
+        mrdump_close(fpRead);
+        goto cleanup0;
+    }
+
+    uint64_t delaylen = 0;
+    uint64_t coresize = lbainfo.coredump_size;
+
+    if (lseek64(fpRead, BLK_SIZE, SEEK_SET) == (off64_t) -1) {
+        MD_LOGE("%s: lseek64 Read MyData failed(%d), %s", __func__, errno, strerror(errno));
+        mrdump_close(fpRead);
+        mrdump_close(fpWrite);
+        unlink(outfile);
+        goto cleanup0;
+    }
+
+    while(coresize > 0) {
+
+        // counting coutinue datas...
+        read_len = MAX_READ_BLK * BLK_SIZE;
+
+        if(coresize < read_len) {
+            mylen = coresize;
+        } else {
+            mylen = read_len;
+        }
+
+        if(0 > read(fpRead, MyData, mylen)) {
+            MD_LOGE("%s: fetch MyData error!(%d), %s", __func__, errno, strerror(errno));
+            mrdump_close(fpRead);
+            mrdump_close(fpWrite);
+            unlink(outfile);
+            goto cleanup0;
+        }
+        if(0 > write(fpWrite, MyData, mylen)) {
+            MD_LOGE("%s: fetch MyData error!(%d), %s", __func__, errno, strerror(errno));
+            mrdump_close(fpRead);
+            mrdump_close(fpWrite);
+            unlink(outfile);
+            goto cleanup0;
+        }
+
+        coresize -= mylen;
+
+        /* flow control */
+        delaylen += mylen;
+        if (delaylen >= MRDUMP_MAX_BANDWIDTH) {
+            delaylen = 0;
+            fdatasync(fpWrite);
+            sleep(1);
+        }
+    }
+
+    mrdump_close(fpRead);
+    mrdump_close(fpWrite);
+
+    MD_LOGI("Ramdump write to %s size %" PRId64 "\n", outfile, lbainfo.coredump_size);
+    return true;
+
+  cleanup0:
+    return false;
+}
diff --git a/src/devtools/mrdump/mrdump_tool_source/mrdump_support_mpart.h b/src/devtools/mrdump/mrdump_tool_source/mrdump_support_mpart.h
new file mode 100644
index 0000000..fb791f0
--- /dev/null
+++ b/src/devtools/mrdump/mrdump_tool_source/mrdump_support_mpart.h
@@ -0,0 +1,12 @@
+#pragma once
+
+/* for DPART(Dedicated Partition) solution */
+#define MRDUMP_MPART_PARTITION "/dev/block/platform/bootdevice/by-name/mrdump"
+#define MRDUMP_MPART_START_OFFSET 4096
+#define MAX_READ_BLK 64
+#define BLK_SIZE 4096
+#define MRDUMP_PARTITION_EXSPACE MAX_READ_BLK*BLK_SIZE
+
+/* functions */
+int mrdump_check_partition(void);
+bool mrdump_file_fetch_zip_coredump_partition(const char *outfile);
diff --git a/src/devtools/mrdump/mrdump_tool_source/mrdump_tool.c b/src/devtools/mrdump/mrdump_tool_source/mrdump_tool.c
new file mode 100644
index 0000000..085aabe
--- /dev/null
+++ b/src/devtools/mrdump/mrdump_tool_source/mrdump_tool.c
@@ -0,0 +1,405 @@
+/* uint64_t ...*/
+#include <inttypes.h>
+#include <stdbool.h>
+
+/* vprintf, vsnprintf */
+#include <stdio.h>
+
+/* exit(), atoi() */
+#include <stdlib.h>
+
+/* getopt, optind */
+#include <unistd.h>
+
+/* sysenv */
+#include "mrdump_defaults.h"
+
+/* strcmp */
+#include <string.h>
+
+#include <getopt.h>
+/* mrdump related */
+#include "mrdump_log.h"
+#include "mrdump_common.h"
+#include "mrdump_status.h"
+#include "mrdump_support_ext4.h"
+#include "mrdump_support_mpart.h"
+
+static void usage(const char *prog) __attribute__((noreturn));
+static void usage(const char *prog)
+{
+    printf("Usage\n"
+        "\t%1$s is-supported\n\n"
+        "\t%1$s status-get\n"
+        "\t%1$s status-log\n"
+        "\t%1$s status-clear\n\n"
+        "\t%1$s file-setup\n"
+        "\t%1$s file-allocate n\n"
+        "\t\tn is 0(disable file output) 1(halfmem) 2(fullmem) >256\n"
+        "\t%1$s file-extract-core [-r] filename\n"
+        "\t\t-r\tre-init pre-allocated file\n"
+        "\t%1$s file-info\n\n"
+        "\t%1$s mem-size-set n\n"
+        "\t\tn is between 64 ~ 16384(m), 0 is output total-mem-size\n\n"
+        "\t%1$s output-set output\n"
+        "\t\tsetting mrdump output device\n"
+        "\t\t  none\n"
+        "\t\t  null\n"
+        "\t\t  usb\n"
+        "\t\t  partition: mrdump partition\n"
+        "\t\t  internal-storage: ext4, f2fs\n"
+        "\t%1$s output-get\n"
+        "\t\tgetting mrdump output device\n",
+        prog);
+    exit(1);
+}
+
+static void dump_status_ok(const struct mrdump_status_result *result)
+{
+    printf("Ok\n");
+    printf("\tMode: %s\n\tOutput: ", result->mode);
+
+    switch (result->output) {
+    case MRDUMP_OUTPUT_NULL:
+        printf("null\n");
+        break;
+    case MRDUMP_OUTPUT_USB:
+        printf("usb\n");
+        break;
+    case MRDUMP_OUTPUT_DATA_FS:
+        printf("ext4/data partition\n");
+        break;
+    case MRDUMP_OUTPUT_PARTITION:
+        printf("dynamic mrdump partition\n");
+        break;
+    default:
+        printf("not supported\n");
+        break;
+    }
+}
+
+static int file_setup_command(int argc, char * __attribute__((unused)) argv[])
+{
+    if (!mrdump_is_supported()) {
+        error("file-setup not allowed in this mode.\n");
+    }
+    if (argc != 1) {
+        error("Invalid file-setup command argument\n");
+    }
+    mrdump_file_setup(false);
+    return 0;
+}
+
+static void file_allocate_command(int argc, char *argv[])
+{
+    if (!mrdump_is_supported()) {
+        error("file-allocate not allowed in this mode.\n");
+    }
+    if (argc != 2) {
+        error("Invaid file-allocate command argument\n");
+    }
+    int size_m = atoi(argv[1]);
+
+    if (size_m < 0)
+        size_m = 0;
+
+    if ((size_m <= 2) || (size_m >= MRDUMP_EXT4_MIN_ALLOCATE)) {
+        // enable condition: only 0, 1, 2, >256
+        mrdump_file_set_maxsize(size_m);
+    }
+    else {
+        error("Invalid dump size %d\n", size_m);
+    }
+}
+
+static int file_extract_core_command(int argc, char *argv[])
+{
+    int opt;
+    bool reinit = false;
+
+    while ((opt = getopt(argc, argv, "r")) != -1) {
+        switch (opt) {
+        case 'r':
+            reinit = true;
+            break;
+        default:
+            error("Invalid file-extract-core parameter\n");
+        }
+    }
+    if (optind >= argc) {
+        error("Expected filename after options\n");
+    }
+
+    const char *fn = argv[optind];
+    const char *output_dev = sysenv_get("mrdump_output");
+
+    MD_LOGI("%s: mrdump_output= %s\n",__func__, output_dev);
+
+    if (output_dev) {
+        if (!strncmp(output_dev, "partition", 9)) {
+            MD_LOGI("%s: partition solution\n",__func__);
+            if (mrdump_file_fetch_zip_coredump_partition(fn)) {
+                return 0;
+            }
+        }
+        else if (!strncmp(output_dev, "internal-storage", 21)) {
+            MD_LOGI("%s: ext4 solution\n",__func__);
+            if (mrdump_file_fetch_zip_coredump(fn)) {
+                mrdump_file_setup(reinit);
+                return 0;
+            }
+        }
+    }
+
+    error("Fetching Coredump data failed\n");
+}
+
+static int file_info_command(int argc, char * __attribute__((unused)) argv[])
+{
+    if (argc != 1) {
+        error("Invalid file-info command argument\n");
+    }
+
+    struct mrdump_pafile_info info;
+    if (mrdump_file_get_info(MRDUMP_EXT4_ALLOCATE_FILE, &info)) {
+        printf("\tInfo LBA :      %" PRIu32 "\n"
+               "\tAddress LBA :   %" PRIu32 "\n"
+               "\tFile Size :     %" PRIu64 "\n"
+               "\tCoredump Size : %" PRIu64 "\n"
+               "\tTimestamp :     %" PRIx64 "\n",
+               info.info_lba, info.addr_lba,
+               info.filesize, info.coredump_size,
+               info.timestamp
+              );
+        return 0;
+    }
+    else {
+        error("Cannot get pre-allocate file info\n");
+    }
+}
+
+static void mem_size_set_command(int argc, char *argv[])
+{
+    char msize[5];
+
+    if (argc != 2) {
+        error("Invaid mem-size-set command argument\n");
+    }
+
+    int size_m = atoi(argv[1]);
+    if ((size_m == 0) || ((size_m >= 64) && (size_m <= 16 * 1024))) {
+        if (size_m != 0) {
+            snprintf(msize, sizeof(msize), "%d", size_m);
+            if (sysenv_set("mrdump_mem_size", msize) == 0) {
+                MD_LOGI("mem-size-set done.\n");
+            }
+        }
+        else {
+            if (sysenv_set("mrdump_mem_size", "") == 0) {
+                MD_LOGI("total-mem-size done.\n");
+            }
+            else {
+                error("failed to set memory dump size, plz try again later.\n");
+            }
+        }
+    }
+    else {
+        error("Invalid memory dump size\n");
+    }
+}
+
+static void output_set_command(int argc, char *argv[])
+{
+    if(argc < 2) {
+        error("Invalid output device, valid input [none, null, usb, partition, internal-storage]\n");
+    }
+    else {
+        const char *output_dev = argv[1];
+        int need_reboot = 0;
+        const char *prev_output_dev = sysenv_get("mrdump_output");
+
+        if (strcmp(prev_output_dev, "partition") == 0) {
+            if (mrdump_check_partition()) {
+                need_reboot = 1;
+            }
+        }
+        if (strcmp(output_dev, "partition") == 0) {
+            if (!mrdump_check_partition()) {
+                error("mrdump partition doesn't exist, cannot dump to partition.\n");
+            }
+            need_reboot = 1;
+        }
+        else if (strcmp(output_dev, "none") &&
+                 strcmp(output_dev, "null") &&
+                 strcmp(output_dev, "usb") &&
+                 strcmp(output_dev, "internal-storage")) {
+            error("Unknown output %s\n", output_dev);
+        }
+
+        if (sysenv_set("mrdump_output", output_dev) == 0) {
+            MD_LOGI("mrdump_output = %s\n", output_dev);
+        }
+        else {
+            error("output-set failed.(%s)\n", output_dev);
+        }
+
+        if (strcmp(output_dev, "internal-storage") == 0) {
+            mrdump_file_set_maxsize(DEFAULT_FULLMEM);
+        }
+        else {
+            mrdump_file_set_maxsize(DEFAULT_DISABLE);
+        }
+
+        if (need_reboot) {
+            if (0 > execl("/system/bin/reboot", "reboot", NULL, NULL))
+                error("%s: failed to reboot into LK for partition resize.\n", __func__);
+        }
+    }
+}
+
+static void status_get_command(int __attribute((unused)) argc,
+                               char * __attribute ((unused)) argv[])
+{
+    struct mrdump_status_result result;
+    if (mrdump_status_get(&result)) {
+        printf("MT-RAMDUMP\n\tStatus:");
+        switch (result.status) {
+        case MRDUMP_STATUS_NONE:
+            printf("None\n");
+            break;
+        case MRDUMP_STATUS_FAILED:
+            printf("Failed\n");
+            break;
+        case MRDUMP_STATUS_OK:
+            dump_status_ok(&result);
+            break;
+        }
+    }
+    else {
+        error("MT-RAMDUMP get status failed\n");
+    }
+}
+
+static int parse_log_level(const char *log_level)
+{
+    if (strcmp(log_level, "debug") == 0)
+        return LOG_DEBUG;
+    else if (strcmp(log_level, "info") == 0)
+        return LOG_INFO;
+    else if (strcmp(log_level, "warn") == 0)
+        return LOG_WARNING;
+    else if (strcmp(log_level, "error") == 0)
+        return LOG_ERR;
+    return LOG_WARNING;
+}
+
+int main(int argc, char *argv[])
+{
+    int log_level = LOG_WARNING;
+    int log_syslog = 0;
+
+    static struct option long_options[]= {
+        {"help", no_argument, 0, 0},
+        {"log-level", required_argument, 0, 0},
+        {"log-syslog", no_argument, 0, 0},
+        {0, 0, 0, 0},
+    };
+
+    while (1) {
+        int option_index, c;
+        c = getopt_long(argc, argv, "+", long_options, &option_index);
+        if (c == -1)
+            break;
+
+        switch (c) {
+        case 0:
+            if (strcmp(long_options[option_index].name, "log-level") == 0) {
+                log_level = parse_log_level(optarg);
+            }
+            else if (strcmp(long_options[option_index].name, "log-syslog") == 0) {
+                log_syslog = 1;
+            }
+            else if (strcmp(long_options[option_index].name, "help") == 0) {
+                usage(argv[0]);
+            }
+            break;
+
+        default:
+            usage(argv[0]);
+        }
+    }
+
+    mdlog_init(log_level, log_syslog);
+
+    const int command_argc = argc - optind;
+    if (command_argc < 1) {
+        error("No command given\n");
+    }
+    const char *command = argv[optind];
+    char **command_argv = &argv[optind];
+
+    if (strcmp(command, "is-supported") == 0) {
+        if (mrdump_is_supported()) {
+            printf("MT-RAMDUMP support ok\n");
+        }
+        else {
+            printf("MT-RAMDUMP not support\n");
+        }
+    }
+    else if (strcmp(command, "status-get") == 0) {
+        status_get_command(command_argc, command_argv);
+    }
+    else if (strcmp(command, "status-log") == 0) {
+        struct mrdump_status_result result;
+        bool res = mrdump_status_get(&result);
+
+        printf("=>status line:\n%s\n=>log:\n%s\n", result.status_line, result.log_buf);
+        if (!res) {
+            error("MT-RAMDUMP get status failed\n");
+        }
+    }
+    else if (strcmp(command, "status-clear") == 0) {
+        if (!mrdump_is_supported()) {
+            error("MT-RAMDUMP not support\n");
+        }
+        if (!mrdump_status_clear()) {
+            error("MT-RAMDUMP Status clear failed\n");
+        }
+    }
+    else if (strcmp(command, "file-setup") == 0) {
+        file_setup_command(command_argc, command_argv);
+    }
+    else if (strcmp(command, "file-allocate") == 0) {
+        file_allocate_command(command_argc, command_argv);
+    }
+    else if (strcmp(command, "file-extract-core") == 0) {
+        file_extract_core_command(command_argc, command_argv);
+    }
+    else if (strcmp(command, "file-info") == 0) {
+        file_info_command(command_argc, command_argv);
+    }
+    else if (strcmp(command, "mem-size-set") == 0) {
+        mem_size_set_command(command_argc, command_argv);
+    }
+    else if (strcmp(command, "output-set") == 0) {
+        output_set_command(command_argc, command_argv);
+    }
+    else if (strcmp(command, "partition") == 0) {
+        /* ignored "-Wunused-result" */
+        if (1 == mrdump_check_partition()) {;}
+    }
+    else if (strcmp(command, "output-get") == 0) {
+        const char *output_dev = sysenv_get("mrdump_output");
+        if (!output_dev) {
+            printf("default\n");
+        }
+        else {
+            printf("%s\n", output_dev);
+        }
+    }
+    else {
+        error("Unknown command %s\n", command);
+    }
+
+    return 0;
+}