[Feature]add MT2731_MP2_MR2_SVN388 baseline version

Change-Id: Ief04314834b31e27effab435d3ca8ba33b499059
diff --git a/src/bsp/lk/lib/aee/KEDump.c b/src/bsp/lk/lib/aee/KEDump.c
new file mode 100644
index 0000000..1f1fa60
--- /dev/null
+++ b/src/bsp/lk/lib/aee/KEDump.c
@@ -0,0 +1,887 @@
+/*
+ * Copyright (c) 2018 MediaTek Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include <arch/mmu.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <lib/bio.h>
+#include <lib/cksum.h>
+#include <lib/mempool.h>
+#include <lib/partition.h>
+#include <platform/mt_reg_base.h>
+#include <platform/mtk_bio_ioctl.h>
+#include <platform/mtk_wdt.h>
+#include <boot_args.h>
+#include "KEHeader.h"
+#include "elf.h"
+#include "ram_console.h"
+
+#ifdef MTK_3LEVEL_PAGETABLE
+
+#include <target.h>
+#endif
+#ifdef MTK_MRDUMP_SRAM_CB
+#include <platform/mtk_mrdump.h>
+#endif
+#include <err.h>
+#include <boot_mode.h>
+
+extern BOOT_ARGUMENT *g_boot_arg;
+extern void arch_clean_cache_range(addr_t start, size_t len);
+enum {
+    AEE_LKDUMP_CLEAR = 0,
+    AEE_LKDUMP_RAMCONSOLE_RAW,
+    AEE_LKDUMP_PSTORE_RAW,
+    AEE_LKDUMP_KEDUMP_CRC,
+    AEE_LKDUMP_MINI_RDUMP,
+    AEE_LKDUMP_PROC_CUR_TSK,    //5
+    AEE_LKDUMP_KERNEL_LOG_RAW,
+    AEE_LKDUMP_DISP_DEBUG_RAW,
+    AEE_LKDUMP_DFD20,
+    AEE_LKDUMP_LAST_DRAM,
+    AEE_LKDUMP_LAST_CPU_BUS,    //10
+    AEE_LKDUMP_LAST_SPM_DATA,
+    AEE_LKDUMP_LAST_SPM_SRAM_DATA,
+    AEE_LKDUMP_ATF_LAST,
+    AEE_LKDUMP_ATF_CRASH,
+    AEE_LKDUMP_ATF_RAW,
+    AEE_LKDUMP_ATF_RDUMP,   //16
+    AEE_LKDUMP_CPU_HVFS_RAW,
+    AEE_LKDUMP_SSPM_COREDUMP,
+    AEE_LKDUMP_SSPM_DATA,
+    AEE_LKDUMP_SSPM_XFILE,
+    AEE_LKDUMP_SSPM_LAST_LOG,   //21
+    AEE_LKDUMP_PLLK_LAST_LOG,
+    AEE_LKDUMP_MCDI_DATA,
+    AEE_LKDUMP_SCP_COREDUMP,
+    AEE_LKDUMP_ZAEE_LOG,
+    AEE_LKDUMP_HEADER,      //26
+    AEE_LKDUMP_UNKNOWN
+};
+
+enum {
+    AEE_PLAT_DFD20,
+    AEE_PLAT_DRAM,
+    AEE_PLAT_CPU_BUS,
+    AEE_PLAT_SPM_DATA,
+    AEE_PLAT_SPM_SRAM_DATA,
+    AEE_PLAT_ATF_LAST_LOG,
+    AEE_PLAT_ATF_CRASH_REPORT,
+    AEE_PLAT_ATF_RAW_LOG,
+    AEE_PLAT_ATF_RDUMP_LOG,
+    AEE_PLAT_HVFS,
+#ifdef MTK_TINYSYS_SSPM_SUPPORT
+    AEE_PLAT_SSPM_COREDUMP,
+    AEE_PLAT_SSPM_DATA,
+    AEE_PLAT_SSPM_XFILE,
+    AEE_PLAT_SSPM_LAST_LOG,
+#endif
+    AEE_PLAT_PLLK_LAST_LOG,
+    AEE_PLAT_LOG_DUR_LKDUMP,
+    AEE_PLAT_MCDI_DATA,
+    AEE_PLAT_SCP_COREDUMP,
+    AEE_PLAT_DEBUG_NUM
+};
+
+/* db filename and max size */
+struct aee_db_file_info {
+    char filename[32];
+    unsigned int filesize;
+    unsigned int step;
+};
+
+static struct aee_db_file_info adfi[AEE_PLAT_DEBUG_NUM] = {
+    [AEE_PLAT_DFD20]          = { "DFD20.dfd",              0x40000, AEE_LKDUMP_DFD20},         /* 256 KB */
+    [AEE_PLAT_DRAM]           = { "SYS_LAST_DRAM",          0x2400,  AEE_LKDUMP_LAST_DRAM},       /*   9 KB */
+    [AEE_PLAT_CPU_BUS]        = { "SYS_LAST_CPU_BUS",       0x10000, AEE_LKDUMP_LAST_CPU_BUS}, /*  64 KB */
+    [AEE_PLAT_SPM_DATA]       = { "SYS_LAST_SPM_DATA",      0x1000,  AEE_LKDUMP_LAST_SPM_DATA}, /*  4 KB */
+    [AEE_PLAT_SPM_SRAM_DATA]  = { "SYS_LAST_SPM_SRAM_DATA", 0x1000,  AEE_LKDUMP_LAST_SPM_SRAM_DATA}, /*  4 KB */
+    [AEE_PLAT_ATF_LAST_LOG]   = { "SYS_ATF_LAST",           0x20000, AEE_LKDUMP_ATF_LAST}, /* 128KB */
+    [AEE_PLAT_ATF_CRASH_REPORT] = { "SYS_ATF_CRASH",        0x30000, AEE_LKDUMP_ATF_CRASH}, /* 64KB+128KB */
+    [AEE_PLAT_ATF_RAW_LOG]    = { "SYS_ATF_RAW_LOG",        0x60000, AEE_LKDUMP_ATF_RAW}, /* 384 KB */
+    [AEE_PLAT_ATF_RDUMP_LOG]  = { "SYS_ATF_RDUMP",          0x80000, AEE_LKDUMP_ATF_RDUMP }, /* 512KB */
+    [AEE_PLAT_HVFS]           = { "SYS_CPUHVFS_RAW",        0x3000,  AEE_LKDUMP_CPU_HVFS_RAW}, /* 12 KB */
+#ifdef MTK_TINYSYS_SSPM_SUPPORT
+    [AEE_PLAT_SSPM_COREDUMP]  = { "SYS_SSPM_COREDUMP",      0x40080, AEE_LKDUMP_SSPM_COREDUMP}, /* 256KB + 128Byte */
+    [AEE_PLAT_SSPM_DATA]      = { "SYS_SSPM_DATA",          0x400,   AEE_LKDUMP_SSPM_DATA}, /* 1KB */
+    [AEE_PLAT_SSPM_XFILE]     = { "SYS_SSPM_XFILE",         0xA0000, AEE_LKDUMP_SSPM_XFILE}, /* 640KB */
+    [AEE_PLAT_SSPM_LAST_LOG]  = { "SYS_SSPM_LAST_LOG",      0x400,   AEE_LKDUMP_SSPM_LAST_LOG}, /* 1KB */
+#endif
+    [AEE_PLAT_PLLK_LAST_LOG]  = { "SYS_PLLK_LAST_LOG",      0x40000, AEE_LKDUMP_PLLK_LAST_LOG}, /* 256KB */
+    [AEE_PLAT_LOG_DUR_LKDUMP] = { "SYS_LOG_DUR_LKDUMP",     0x40000, AEE_PLAT_LOG_DUR_LKDUMP}, /* 256KB */
+    [AEE_PLAT_MCDI_DATA]      = { "SYS_MCDI_DATA",          0x800,   AEE_LKDUMP_MCDI_DATA}, /* 2KB, size will modified by plat. */
+#ifdef MTK_TINYSYS_SCP_SUPPORT
+    [AEE_PLAT_SCP_COREDUMP]   = { "SYS_SCP_DUMP.gz",        0xA0000, AEE_LKDUMP_SCP_COREDUMP} /* 640KB */
+#endif
+};
+
+struct aee_db_file_info *get_file_info(void)
+{
+    return adfi;
+}
+
+#define EXPDB_RESERVED_OTHER    (3 * 1024 * 1024) //reserved expdb for control block and pl/lk log
+#define BIO_ERASE_ALIGN 0x40000
+#define MEM_EXPDB_SIZE  0x300000
+static char *mem_expdb;
+
+static bdev_t *bdev;
+
+struct elfhdr {
+    void *start;
+    unsigned int e_machine;
+    unsigned int e_phoff;
+    unsigned int e_phnum;
+};
+
+struct kedump_crc {
+    unsigned int ram_console_crc;
+    unsigned int pstore_crc;
+};
+
+static struct kedump_crc kc;
+
+int check_ram_console_is_abnormal_boot(void)
+{
+    return ram_console_is_abnormal_boot();
+}
+
+static unsigned int last_dump_step;
+
+#define elf_note    elf32_note
+#define PHDR_PTR(ehdr, phdr, mem)       \
+    (ehdr->e_machine == EM_ARM ? ((struct elf32_phdr*)phdr)->mem : ((struct elf64_phdr*)phdr)->mem)
+
+#define PHDR_TYPE(ehdr, phdr) PHDR_PTR(ehdr, phdr, p_type)
+#define PHDR_VADDR(ehdr, phdr) PHDR_PTR(ehdr, phdr, p_vaddr)
+#define PHDR_ADDR(ehdr, phdr) PHDR_PTR(ehdr, phdr, p_paddr)
+#define PHDR_SIZE(ehdr, phdr) PHDR_PTR(ehdr, phdr, p_filesz)
+#define PHDR_OFF(ehdr, phdr) PHDR_PTR(ehdr, phdr, p_offset)
+#define PHDR_INDEX(ehdr, i)         \
+    (ehdr->e_machine == EM_ARM ? ehdr->start + ehdr->e_phoff + sizeof(struct elf32_phdr) * i :    \
+    ehdr->start + ehdr->e_phoff + sizeof(struct elf64_phdr) *i)
+
+#ifndef ALIGN
+#define ALIGN(x, a) (((x) + ((a) -1)) & ~((a) -1))
+#endif
+
+static unsigned int calculate_crc32(void *data, unsigned int len)
+{
+    unsigned int crc_value = 0;
+
+    crc_value = crc32(0L, data, len);
+    LOG("kedump: crc = 0x%x\n", crc_value);
+    return crc_value;
+}
+
+static struct elfhdr *kedump_elf_hdr(void)
+{
+    char *ei;
+    static struct elfhdr kehdr;
+    static struct elfhdr *ehdr = (void *)-1;
+    if (ehdr != (void *)-1)
+        return ehdr;
+    ehdr = NULL;
+
+    kehdr.start = PA_TO_VA((paddr_t)KE_RESERVED_MEM_ADDR);
+    LOG("kedump: KEHeader %p\n", kehdr.start);
+    if (kehdr.start) {
+        ei = (char *)kehdr.start; //elf_hdr.e_ident
+        LOG("kedump: read header 0x%p[0x%x%x%x%x]\n", ei, ei[0], ei[1], ei[2], ei[3]);
+        /* valid elf header */
+        if (ei[0] == 0x7f && ei[1] == 'E' && ei[2] == 'L' && ei[3] == 'F') {
+            kehdr.e_machine = ((struct elf32_hdr *)(kehdr.start))->e_machine;
+            if (kehdr.e_machine == EM_ARM) {
+                kehdr.e_phnum = ((struct elf32_hdr *)(kehdr.start))->e_phnum;
+                kehdr.e_phoff = ((struct elf32_hdr *)(kehdr.start))->e_phoff;
+                ehdr = &kehdr;
+            } else if (kehdr.e_machine == EM_AARCH64) {
+                kehdr.e_phnum = ((struct elf64_hdr *)(kehdr.start))->e_phnum;
+                kehdr.e_phoff = ((struct elf64_hdr *)(kehdr.start))->e_phoff;
+                ehdr = &kehdr;
+            }
+        }
+        if (ehdr == NULL)
+            LOG("kedump: invalid header[0x%x%x%x%x]\n", ei[0], ei[1], ei[2], ei[3]);
+    }
+    LOG("kedump: mach[0x%x], phnum[0x%x], phoff[0x%x]\n", kehdr.e_machine, kehdr.e_phnum,
+        kehdr.e_phoff);
+    return ehdr;
+}
+
+static int kedump_dev_open(void)
+{
+    bdev = bio_open_by_label(AEE_IPANIC_PLABLE);
+    if (!bdev) {
+        bdev = bio_open(AEE_IPANIC_PLABLE);
+        if (!bdev) {
+            LOG("kedump: no %s partition\n", AEE_IPANIC_PLABLE);
+            return -1;
+        }
+    }
+
+    if (bdev->total_size < EXPDB_RESERVED_OTHER) {
+        LOG("kedump: partition size(%llx) is lesser then reserved!(%llx)\n", bdev->total_size,
+            (unsigned long long)EXPDB_RESERVED_OTHER);
+        return -1;
+    }
+
+closebdev:
+    bio_close(bdev);
+
+    return 0;
+}
+
+static unsigned long long mem_expdb_write(void *data, unsigned long long offset, unsigned long sz)
+{
+    if ((offset + sz) > MEM_EXPDB_SIZE) {
+        LOG("kedump: mem_expdb_write overflow!\n");
+        return 0;
+    }
+
+    memcpy(mem_expdb + offset, data, sz);
+    return sz;
+}
+
+#define TRUNK 0x8000
+static unsigned long long kedump_dev_write(unsigned long long offset, uint64_t data, unsigned long sz)
+{
+    unsigned long long size_wrote = 0;
+    uint8_t *memsrc = (uint8_t *)data;
+    unsigned long rest = sz;
+    unsigned int ret = 0;
+    unsigned long long mini_size = bdev->total_size - EXPDB_RESERVED_OTHER;
+    LOG("kedump: offset:0x%llx, data:0x%llx, size:0x%lx\n", offset, data, sz);
+
+    if (offset >= mini_size || sz > (mini_size - offset)) {
+        LOG("kedump: kedump_dev_write overflow\n");
+        return 0;
+    }
+    while (rest > 0) {
+        unsigned long write_sz;
+        if (rest <= TRUNK) {
+            write_sz = rest;
+        } else {
+            write_sz = TRUNK;
+        }
+        LOG("kedump: offset:0x%llx, memsrc:0x%lx, write_sz:0x%lx\n", offset, (size_t)memsrc, write_sz);
+
+        ret = mem_expdb_write(memsrc, offset, write_sz);
+        if (ret <= 0) {
+            LOG("kedump: mem_expdb_write fail\n");
+            break;
+        }
+
+        size_wrote += ret;
+        offset += write_sz;
+        rest -= write_sz;
+        memsrc += write_sz;
+    }
+    if ((long long)size_wrote <= 0) {
+        LOG("kedump: write failed(%llx), %lx@%llx -> %llx\n", size_wrote, sz, data, offset);
+        size_wrote = 0;
+    }
+
+    LOG("kedump: kedump_dev_write done\n");
+    return size_wrote;
+}
+
+static unsigned long long offset_plat_debug = 0;
+static unsigned long length_plat_debug = 0;
+static unsigned long long kedump_plat_write (void *data, unsigned long sz)
+{
+    unsigned long long datasize = 0;
+
+    datasize = kedump_dev_write(offset_plat_debug, (uint64_t)data, sz);
+    offset_plat_debug += datasize;
+    length_plat_debug += sz;
+
+    return datasize;
+}
+
+static void kedump_dev_close(void)
+{
+    return;
+}
+
+/* the min offset reserved for the header's size. */
+static unsigned long kedump_mrdump_header_size (struct elfhdr *ehdr)
+{
+    void *phdr = PHDR_INDEX(ehdr, 1);
+    return ALIGN(PHDR_OFF(ehdr, phdr) + PHDR_SIZE(ehdr, phdr), PAGE_SIZE);
+}
+
+static unsigned int kedump_mini_rdump(struct elfhdr *ehdr, unsigned long long offset)
+{
+    void *phdr;
+    unsigned long long addr;
+    void *vaddr;
+    unsigned long size;
+    unsigned int i;
+    unsigned int total = 0;
+    unsigned long elfoff = kedump_mrdump_header_size(ehdr);
+    unsigned long sz_header = elfoff;
+
+    for (i = 0; i < ehdr->e_phnum; i++) {
+        phdr = PHDR_INDEX(ehdr, i);
+        if (PHDR_SIZE(ehdr, phdr) != 0 || PHDR_TYPE(ehdr, phdr) != 0)
+            LOGD("kedump: PT[%d] %x@%llx -> %x(%x)\n", PHDR_TYPE(ehdr, phdr), PHDR_SIZE(ehdr, phdr),
+                 PHDR_ADDR(ehdr, phdr), elfoff, (unsigned int)PHDR_OFF(ehdr, phdr));
+        if (PHDR_TYPE(ehdr, phdr) != PT_LOAD)
+            continue;
+        addr = PHDR_ADDR(ehdr, phdr);
+
+#ifdef MTK_MRDUMP_SRAM_CB
+        if ((addr < DRAM_BASE_PHY) && ((addr < MRDUMP_CB_ADDR) ||
+            (addr > (MRDUMP_CB_ADDR + MRDUMP_CB_SIZE)))) {
+            LOG("kedump: skip dump non-allow PA:%llx, VA:%llx\n", addr, PHDR_VADDR(ehdr, phdr));
+            continue;
+        }
+#else
+        if (addr < DRAM_BASE_PHY) {
+            LOG("kedump: skip dump non-dram PA:%llx, VA:%llx\n", addr, PHDR_VADDR(ehdr, phdr));
+            continue;
+        }
+#endif
+        size = PHDR_SIZE(ehdr, phdr);
+        if (size == 0 || elfoff == 0)
+            LOG("kedump: dump addr 0x%llx, size 0x%lx\n", addr, size);
+        if (ehdr->e_machine == EM_ARM)
+            ((struct elf32_phdr *)phdr)->p_offset = elfoff;
+        else
+            ((struct elf64_phdr *)phdr)->p_offset = elfoff;
+        if (size != 0 && elfoff != 0) {
+            vaddr = PA_TO_VA((paddr_t)addr);
+            total += kedump_dev_write(offset + elfoff, (uint64_t)vaddr, size);
+        }
+        elfoff += size;
+    }
+    total += kedump_dev_write(offset, (uint64_t)(ehdr->start), sz_header);
+    return total;
+}
+
+static unsigned int kedump_misc(unsigned long long addr, unsigned int start, unsigned int size,
+    unsigned long long offset)
+{
+    unsigned int total;
+    LOG("kedump: misc data %x@%llx+%x\n", size, addr, start);
+    if (start >= size)
+        start = start % size;
+    total = kedump_dev_write(offset, (uint64_t)(addr + start), size - start);
+    if (start)
+        total += kedump_dev_write(offset + total, (uint64_t)addr, start);
+    return total;
+}
+
+static unsigned int kedump_misc32(struct mrdump_mini_misc_data32 *data, unsigned long long offset)
+{
+    if (data != NULL) {
+        unsigned int addr = data->paddr;
+        unsigned int start = 0;
+        void *vaddr;
+        vaddr = PA_TO_VA((paddr_t)addr);
+
+        start = data->start ? *(unsigned int *)(unsigned long)(PA_TO_VA(data->start)) : 0;
+
+        unsigned int size = data->size;
+        return kedump_misc((uint64_t)vaddr, start, size, offset);
+    } else
+        return 0;
+}
+
+static unsigned int kedump_misc64(struct mrdump_mini_misc_data64 *data, unsigned long long offset)
+{
+    if (data != NULL) {
+        unsigned long long addr = (unsigned long long)data->paddr;
+        unsigned int start = 0;
+        void *vaddr;
+        vaddr = PA_TO_VA((paddr_t)addr);
+        start = data->start ? *(unsigned int *)(unsigned long)(PA_TO_VA((paddr_t)data->start)) : 0;
+        unsigned int size = (unsigned int)data->size;
+        return kedump_misc((uint64_t)vaddr, start, size, offset);
+    } else
+        return 0;
+}
+
+struct ipanic_header panic_header;
+static unsigned long long header_off;
+static void kedump_add2hdr(unsigned int offset, unsigned int size, unsigned datasize,
+    const char *name)
+{
+    struct ipanic_data_header *pdata;
+    int i;
+    for (i = 0; i < IPANIC_NR_SECTIONS; i++) {
+        pdata = &panic_header.data_hdr[i];
+        if (pdata->valid == 0)
+            break;
+    }
+    LOG("kedump add: %s[%d] %x/%x@%x\n", name, i, datasize, size, offset);
+    if (i < IPANIC_NR_SECTIONS) {
+        pdata->offset = offset;
+        pdata->total = size;
+        pdata->used = datasize;
+        strlcpy((char *)pdata->name, name, sizeof(pdata->name));
+        pdata->valid = 1;
+    }
+    header_off += kedump_dev_write(header_off, (uint64_t)(pdata), sizeof(struct ipanic_data_header));
+}
+
+static int kedump_kernel_info(unsigned long long *offset)
+{
+    struct elfhdr *ehdr;
+    unsigned long sz_misc;
+    void *phdr_misc;
+    struct elf_note *misc, *miscs;
+    char *m_name;
+    void *m_data;
+    char name[32];
+    unsigned int size, datasize;
+    unsigned int i;
+    unsigned int start_tmp;
+
+    ehdr = kedump_elf_hdr();
+    if (0 == ehdr)
+        return -1;
+    ram_console_set_dump_step(AEE_LKDUMP_MINI_RDUMP);
+    datasize = kedump_mini_rdump(ehdr, *offset);
+    size = datasize;
+    kedump_add2hdr(*offset, size, datasize, "SYS_MINI_RDUMP");
+    *offset += datasize;
+    phdr_misc = PHDR_INDEX(ehdr, 1);
+    miscs = (struct elf_note *)(ehdr->start + PHDR_OFF(ehdr, phdr_misc));
+    LOGD("kedump: misc[%p] %llx@%llx\n", phdr_misc, PHDR_SIZE(ehdr, phdr_misc),
+         PHDR_OFF(ehdr, phdr_misc));
+    sz_misc = sizeof(struct elf_note) + miscs->n_namesz + miscs->n_descsz;
+    LOGD("kedump: miscs[%p], size %x\n", miscs, sz_misc);
+    for (i = 0; i < (PHDR_SIZE(ehdr, phdr_misc)) / sz_misc; i++) {
+        char klog_first[16];
+        memset(klog_first, 0x0, sizeof(klog_first));
+        misc = (struct elf_note *)((void *)miscs + sz_misc * i);
+        m_name = (char *)misc + sizeof(struct elf_note);
+        if (m_name[0] == 'N' && m_name[1] == 'A' && m_name[2] == '\0')
+            break;
+        m_data = (void *)misc + sizeof(struct elf_note) + misc->n_namesz;
+        if (misc->n_descsz == sizeof(struct mrdump_mini_misc_data32)) {
+            if (strcmp(m_name, "_KERNEL_LOG_") == 0) {
+                start_tmp = ((struct mrdump_mini_misc_data32 *)m_data)->start;
+                sprintf(klog_first, "_%u", start_tmp ? *(unsigned int *)
+                        (PA_TO_VA((paddr_t)start_tmp)) : 0);
+                ((struct mrdump_mini_misc_data32 *)m_data)->start = 0;
+            }
+            datasize = kedump_misc32((struct mrdump_mini_misc_data32 *)m_data, *offset);
+            size = ((struct mrdump_mini_misc_data32 *)m_data)->size;
+        } else {
+            if (strcmp(m_name, "_KERNEL_LOG_") == 0) {
+                start_tmp = ((struct mrdump_mini_misc_data64 *)m_data)->start;
+                sprintf(klog_first, "_%u", start_tmp ? *(unsigned int *)
+                        (PA_TO_VA((paddr_t)start_tmp)) : 0);
+                ((struct mrdump_mini_misc_data64 *)m_data)->start = 0;
+            }
+            datasize = kedump_misc64((struct mrdump_mini_misc_data64 *)m_data, *offset);
+            size = ((struct mrdump_mini_misc_data64 *)m_data)->size;
+        }
+        /* [SYS_]MISC[_RAW] */
+        if (m_name[0] == '_')
+            strlcpy (name, "SYS", sizeof(name));
+        else
+            name[0] = 0;
+        strlcat (name, m_name, sizeof(name));
+        if (m_name[strlen(m_name)-1] == '_')
+            strlcat (name,  "RAW", sizeof(name));
+        if (klog_first[0] != 0)
+            strlcat(name, klog_first, sizeof(name));
+        kedump_add2hdr(*offset, size, datasize, name);
+        *offset += datasize;
+    }
+    return 0;
+}
+
+static int kedump_ram_console(unsigned long long *offset)
+{
+    unsigned long sz_misc, addr_misc;
+    unsigned int datasize;
+
+    /* ram_console raw log */
+    ram_console_set_dump_step(AEE_LKDUMP_RAMCONSOLE_RAW);
+    ram_console_addr_size(&addr_misc, &sz_misc);
+    if (addr_misc && sz_misc) {
+        datasize = kedump_misc((unsigned long long)addr_misc, 0, (unsigned int)sz_misc, *offset);
+        kc.ram_console_crc = calculate_crc32((void *)addr_misc, sz_misc);
+        kedump_add2hdr(*offset, (unsigned long long)sz_misc, datasize, "SYS_RAMCONSOLE_RAW");
+        *offset += datasize;
+    }
+#ifdef MTK_PMIC_FULL_RESET
+    /* pstore raw log*/
+    ram_console_set_dump_step(AEE_LKDUMP_PSTORE_RAW);
+    datasize = kedump_misc((unsigned long long)PA_TO_VA((paddr_t)PSTORE_ADDR), 0,
+                           (unsigned int)PSTORE_SIZE, *offset);
+    kc.pstore_crc = calculate_crc32((void *)PA_TO_VA((paddr_t)PSTORE_ADDR), PSTORE_SIZE);
+    kedump_add2hdr(*offset, (unsigned int)PSTORE_SIZE, datasize, "SYS_PSTORE_RAW");
+    *offset += datasize;
+#endif
+    /* save crc data*/
+    ram_console_set_dump_step(AEE_LKDUMP_KEDUMP_CRC);
+    datasize = kedump_dev_write(*offset, (uint64_t)(&kc), sizeof(struct kedump_crc));
+    kedump_add2hdr(*offset, sizeof(struct kedump_crc), datasize, "KEDUMP_CRC");
+    *offset += datasize;
+    return 0;
+}
+
+#if 0
+static int kedump_platform_debug(unsigned long long *offset)
+{
+    /* platform debug */
+    int len = 0;
+    unsigned int datasize;
+    unsigned int i;
+
+    for (i=0; i<AEE_PLAT_DEBUG_NUM; i++) {
+        offset_plat_debug = *offset;
+        length_plat_debug = 0;
+        ram_console_set_dump_step(adfi[i].step);
+        datasize = kedump_plat_savelog(i, offset_plat_debug, &len, kedump_plat_write);
+        if ((datasize > 0) && (datasize <= adfi[i].filesize)) {
+            kedump_add2hdr(*offset, length_plat_debug, datasize, adfi[i].filename);
+            *offset += datasize;
+        }
+    }
+    return 0;
+}
+#endif
+
+static int kedump_to_expdb(void)
+{
+    unsigned long long offset;
+    unsigned int datasize;
+    ssize_t ret;
+    bool f_rewrite;
+
+    if (kedump_dev_open() != 0)
+        return -1;
+
+    last_dump_step = ram_console_get_dump_step();
+    if (last_dump_step != AEE_LKDUMP_CLEAR) {
+        LOG("kedump: last lk dump is not finished at step %u\n", last_dump_step);
+        //return 0;
+    }
+
+    mem_expdb = mempool_alloc(MEM_EXPDB_SIZE, MEMPOOL_ANY);
+    if (mem_expdb == NULL) {
+        LOG("kedump: mem_expdb malloc fail!\n");
+        return -1;
+    }
+    LOG("kedump: mem_expdb malloc success %p size is 0x%x\n", mem_expdb, MEM_EXPDB_SIZE);
+    memset(mem_expdb, 0x0, MEM_EXPDB_SIZE);
+
+    //write header firstly
+    panic_header.magic = AEE_IPANIC_MAGIC;
+    panic_header.version = AEE_IPANIC_PHDR_VERSION;
+    panic_header.size = sizeof(panic_header);
+    panic_header.blksize = bdev->block_size;
+    panic_header.partsize = bdev->total_size - EXPDB_RESERVED_OTHER;
+    LOG("kedump: expdb write panic header panic_header addr:0x%llx\n", (uint64_t)(&panic_header));
+    kedump_dev_write(0, (uint64_t)(&panic_header), sizeof(panic_header));
+    header_off = sizeof(panic_header) - sizeof(struct ipanic_data_header) * IPANIC_NR_SECTIONS;
+    LOG("kedump: block size:0x%zx\n", bdev->block_size);
+
+    /* reserve space in expdb for panic header */
+    offset = ALIGN(sizeof(panic_header), bdev->block_size);
+
+    kedump_ram_console(&offset);
+    kedump_kernel_info(&offset);
+//  kedump_platform_debug(&offset);
+
+    /* save KEdump flow logs */
+    datasize = kedump_dev_write(offset, (uint64_t)logbuf, SZLOG);
+    kedump_add2hdr(offset, SZLOG, datasize, "ZAEE_LOG");
+    offset += datasize;
+
+    offset = ALIGN(offset, BIO_ERASE_ALIGN);
+    LOG("kedump: total offset is:0x%llx after align:0x%x\n", offset, BIO_ERASE_ALIGN);
+    if (offset > MEM_EXPDB_SIZE) {
+        LOG("kedump: total offset 0x%llx over MEM_EXPDB_SIZE\n", offset);
+        mempool_free((void *)mem_expdb);
+        return -1;
+    }
+
+    if (bio_ioctl(bdev, BIO_IOCTL_QUERY_CAP_REWRITABLE, &f_rewrite) != NO_ERROR) {
+        f_rewrite = false;
+    }
+
+    if (!f_rewrite) {
+        ret = bio_erase(bdev, 0, offset);
+        if (ret < 0) {
+            LOG("kedump: bio_erase mem_expdb 0x%llx fail\n", offset);
+            mempool_free((void *)mem_expdb);
+            return -1;
+        }
+    }
+
+    ret = bio_write(bdev, mem_expdb, 0, offset);
+    if (ret != offset) {
+       LOG("kedump: bio_write mem_expdb 0x%llx but only write 0x%zd\n", offset, ret);
+    }
+
+    mempool_free((void *)mem_expdb);
+
+    ram_console_set_dump_step(AEE_LKDUMP_CLEAR);
+    return 0;
+}
+
+/*
+ * kedump_restore_mem() - read ram console data from expdb
+ *
+ * this function is used to store ram console data from
+ * expdb to PSTORE reserved memory.
+ *
+ * returns:
+ *     -1: device not supported
+ */
+int kedump_restore_mem(void)
+{
+    int i;
+    unsigned int crc;
+    struct ipanic_header iheader;
+    struct kedump_crc saved_crc = {0, 0};
+    unsigned long sz_misc = 0, addr_misc = 0;
+    unsigned char *temp_ram_console = NULL;
+#ifdef MTK_PMIC_FULL_RESET
+    unsigned char *temp_pstore = NULL;
+#endif
+
+#ifdef MTK_PMIC_FULL_RESET
+    if (ram_console_reboot_by_cold_reset()) {
+        LOG("kedump: last is full pmic reset!\n");
+    } else {
+        LOG("kedump: last is not full pmic reset!\n");
+    }
+#endif
+
+    if (kedump_dev_open() != 0)
+        return -1;
+    bio_read(bdev, (unsigned char *)&iheader, 0, sizeof(struct ipanic_header));
+    if (iheader.magic == AEE_IPANIC_MAGIC && iheader.version >= AEE_IPANIC_PHDR_VERSION) {
+        LOG("kedump: found content in expdb\n");
+        for (i = IPANIC_NR_SECTIONS - 1; i >= 0; i--) {
+            if (strncmp((const char *)iheader.data_hdr[i].name, "KEDUMP_CRC",
+                sizeof("KEDUMP_CRC") - 1) == 0) {
+                LOG("kedump: read %s from offset 0x%x size 0x%x\n", iheader.data_hdr[i].name,
+                    iheader.data_hdr[i].offset, iheader.data_hdr[i].used);
+                bio_read(bdev, (uchar *)(&saved_crc), iheader.data_hdr[i].offset,
+                    iheader.data_hdr[i].used);
+            }
+            if (strncmp((const char *)iheader.data_hdr[i].name, "SYS_RAMCONSOLE_RAW",
+                sizeof("SYS_RAMCONSOLE_RAW") - 1) == 0) {
+                ram_console_addr_size(&addr_misc, &sz_misc);
+                if (addr_misc && sz_misc) {
+                    temp_ram_console = mempool_alloc(sz_misc, MEMPOOL_ANY);
+                    if (!temp_ram_console) {
+                        LOG("kedump: temp_ram_console alloc fail\n");
+                    } else {
+                        LOG("kedump: read %s from offset 0x%x size 0x%x\n", iheader.data_hdr[i].name,
+                            iheader.data_hdr[i].offset, iheader.data_hdr[i].used);
+                        memset(temp_ram_console, 0x0, sz_misc);
+                        bio_read(bdev, temp_ram_console, iheader.data_hdr[i].offset,
+                            iheader.data_hdr[i].used);
+                        crc = calculate_crc32(temp_ram_console, sz_misc);
+                        if (crc != saved_crc.ram_console_crc) {
+                            LOG("kedump: temp ram_console crc fail\n");
+                            mempool_free(temp_ram_console);
+                            temp_ram_console = NULL;
+                        }
+                    }
+                } else {
+                    LOG("kedump: ram_console not init\n");
+                }
+            }
+#ifdef MTK_PMIC_FULL_RESET
+            else if (strncmp((const char *)iheader.data_hdr[i].name, "SYS_PSTORE_RAW",
+                sizeof("SYS_PSTORE_RAW") - 1) == 0) {
+                temp_pstore = mempool_alloc(PSTORE_SIZE, MEMPOOL_ANY);
+                if (!temp_pstore) {
+                    LOG("kedump: temp_pstore alloc fail\n");
+                } else {
+                    LOG("kedump: read %s from offset 0x%x size 0x%x\n", iheader.data_hdr[i].name,
+                        iheader.data_hdr[i].offset, iheader.data_hdr[i].used);
+                    memset(temp_pstore, 0x0, PSTORE_SIZE);
+                    bio_read(bdev, temp_pstore, iheader.data_hdr[i].offset,
+                        iheader.data_hdr[i].used);
+                    crc = calculate_crc32(temp_pstore, PSTORE_SIZE);
+                    if (crc != saved_crc.pstore_crc) {
+                        LOG("kedump: pstore crc fail\n");
+                        mempool_free(temp_pstore);
+                        temp_pstore = NULL;
+                    }
+                }
+            }
+#endif
+        }
+
+        if (ram_console_should_restore(temp_ram_console)) {
+            LOG("kedump: ram_console_should_restore\n");
+            memcpy((uchar *)addr_misc, temp_ram_console, sz_misc);
+#ifdef MTK_PMIC_FULL_RESET
+            if (temp_pstore)
+                memcpy((uchar *)paddr_to_kvaddr((paddr_t)PSTORE_ADDR), temp_pstore, PSTORE_SIZE);
+#endif
+            ram_console_set_dump_step(AEE_LKDUMP_CLEAR);
+            ram_console_is_abnormal_boot();
+        }
+
+        if (temp_ram_console)
+            mempool_free(temp_ram_console);
+#ifdef MTK_PMIC_FULL_RESET
+        if (temp_pstore)
+            mempool_free(temp_pstore);
+#endif
+    }
+    return 0;
+}
+
+static int kedump_avail(void)
+{
+    void *flag = PA_TO_VA((paddr_t)KE_RESERVED_MEM_ADDR);
+
+    if (((char *)flag)[0] == 0x81 && ((char *)flag)[1] == 'E' &&
+        ((char *)flag)[2] == 'L' && ((char *)flag)[3] == 'F') {
+        LOG("kedump: already dumped in lk\n");
+        return -1;
+    }
+
+    if (((char *)flag)[0] == 0x0 && ((char *)flag)[1] == 'E' &&
+        ((char *)flag)[2] == 'L' && ((char *)flag)[3] == 'F') {
+        LOG("kedump: already dumped in kernel\n");
+        return -1;
+    }
+    return 0;
+}
+
+int kedump_get_data_info(int index, char **name, u32 *offset, u32 *size)
+{
+    struct ipanic_header iheader;
+    struct ipanic_data_header *pdata;
+
+    if (bdev == NULL ) {
+        if (kedump_dev_open() != 0)
+            return -1;
+    }
+
+    bio_read(bdev, (unsigned char *)&iheader, 0, sizeof(struct ipanic_header));
+    if (iheader.magic != AEE_IPANIC_MAGIC || iheader.version < AEE_IPANIC_PHDR_VERSION)
+        return -2;
+
+    if (index < 0 || index >= IPANIC_NR_SECTIONS) {
+        LOG("kedump: invalid index number:%d\n", index);
+        return -3;
+    }
+
+    if (name == NULL || offset == NULL || size == NULL) {
+        LOG("kedump: invalid argument number:%d\n", index);
+        return -4;
+    }
+
+    pdata = &iheader.data_hdr[index];
+    if (pdata->valid == 0)
+        return -5;
+
+    *name = (char *)pdata->name;
+    *offset = pdata->offset;
+    *size = pdata->used;
+
+    return 0;
+}
+
+static int kedump_done(void)
+{
+    void *flag = PA_TO_VA((paddr_t)KE_RESERVED_MEM_ADDR);
+
+    ((char *)flag)[0] = 0x81;
+    ((char *)flag)[1] = 'E';
+    ((char *)flag)[2] = 'L';
+    ((char *)flag)[3] = 'F';
+    arch_clean_cache_range((vaddr_t)flag, sizeof(struct elfhdr));
+
+    return 0;
+}
+
+/* in case that platform didn't support smart_reset_check() */
+const char *smart_reset_check(void) __attribute__((weak));
+const char *smart_reset_check(void)
+{
+    return NULL;
+}
+
+/* in case that platform didn't support mtk_wdt_get_last_stage() */
+const char *mtk_wdt_get_last_stage(void) __attribute__((weak));
+const char *mtk_wdt_get_last_stage(void)
+{
+    return NULL;
+}
+
+/* Dump KE infomation to expdb */
+/*  1: has expception, 0: has no exception */
+int kedump_mini(void)
+{
+    const char *status;
+
+    status = smart_reset_check();
+    if (status != NULL)
+        LOG("kedump: smart_reset_check %s\n", status);
+
+    status = mtk_wdt_get_last_stage();
+    if (status != NULL)
+        LOG("kedump: mtk_wdt_get_last_stage %s\n", status);
+
+    LOG("kedump mini start\n");
+
+#if 0
+    if (lkdump_debug_init())
+        LOG("kedump: lkdump debug init ok\n");
+    else
+        LOG("kedump: lkdump debug not ready\n");
+#endif
+
+    if (g_boot_arg) {
+        if (!g_boot_arg->ddr_reserve_enable)
+            LOG("kedump: ddr reserve mode disabled\n");
+        else
+            LOG("kedump: ddr reserve mode enabled\n");
+        if (!g_boot_arg->ddr_reserve_success)
+            LOG("kedump: ddr reserve mode failed\n");
+    } else {
+        LOG("kedump: skip due to null boot arg pointer error\n");
+        return 0;
+    }
+
+    LOG("kedump avail\n");
+    if (kedump_avail())
+        return 0;
+
+    LOG("kedump to expdb\n");
+    kedump_to_expdb();
+
+    kedump_done();
+    LOG("kedump mini done\n");
+    return 1;
+}
diff --git a/src/bsp/lk/lib/aee/dump_joint.c b/src/bsp/lk/lib/aee/dump_joint.c
new file mode 100644
index 0000000..72d0ae9
--- /dev/null
+++ b/src/bsp/lk/lib/aee/dump_joint.c
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2018 MediaTek Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#include <boot_args.h>
+#include <env.h>
+#include <mrdump.h>
+#include <platform/mtk_wdt.h>
+#include <platform/mt_reg_base.h>
+#include <string.h>
+
+extern BOOT_ARGUMENT *g_boot_arg;
+
+static int mrdump_check(void)
+{
+    if (mrdump_detection()) {
+        extern int mrdump_run2(void) __attribute__((weak));
+        mrdump_run2();
+        return 1;
+    }
+    return 0;
+}
+
+void do_check_kedump(void)
+{
+    extern int kedump_mini(void) __attribute__((weak));
+    if (kedump_mini) {
+        if (kedump_mini()) {
+            mrdump_check();
+            mrdump_reboot();
+        }
+    }
+}
+
+void do_check_mrdump(void)
+{
+    extern int kedump_init(void) __attribute((weak));
+    if (kedump_init) {
+        if (kedump_init())
+            do_check_kedump();
+    }
+}
+
+u64 physical_memory_size(void)
+{
+    return g_boot_arg->dram_size;
+}
+
diff --git a/src/bsp/lk/lib/aee/env.c b/src/bsp/lk/lib/aee/env.c
new file mode 100644
index 0000000..ebe73a2
--- /dev/null
+++ b/src/bsp/lk/lib/aee/env.c
@@ -0,0 +1,346 @@
+/*
+ * Copyright (c) 2018 MediaTek Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include <env.h>
+#include <errno.h>
+#include <lib/bio.h>
+#include <lib/mempool.h>
+#include <malloc.h>
+#include <printf.h>
+#include <stdint.h>
+#include <string.h>
+#include <sys/types.h>
+#define ENV_PART "para"
+
+#define MODULE_NAME "LK_ENV"
+env_t g_env;
+static int env_valid;
+static char *env_buffer;
+static char env_get_char(int index);
+static char *env_get_addr(int index);
+static int envmatch(uchar *s1, int i2);
+static int write_env_area(char *env_buf);
+static int read_env_area(char *env_buf);
+
+#ifndef min
+#define min(x, y)   (x < y ? x : y)
+#endif
+
+void env_init(void)
+{
+    int ret, i;
+    env_buffer = (char *)mempool_alloc(CFG_ENV_SIZE, MEMPOOL_ANY);
+    memset(env_buffer, 0x00, CFG_ENV_SIZE);
+    g_env.env_data = env_buffer + CFG_ENV_DATA_OFFSET;
+    ret = read_env_area(env_buffer);
+    int checksum = 0;
+    if (ret < 0) {
+        printf("[%s]read_env_area fail, ret = %x\n", MODULE_NAME, ret);
+        env_valid = 0;
+        goto end;
+    }
+
+    memcpy(g_env.sig, env_buffer, sizeof(g_env.sig));
+    memcpy(g_env.sig_1, env_buffer + CFG_ENV_SIG_1_OFFSET, sizeof(g_env.sig_1));
+
+    if (!strcmp(g_env.sig, ENV_SIG) && !strcmp(g_env.sig_1, ENV_SIG)) {
+        g_env.checksum = *((int *)env_buffer + CFG_ENV_CHECKSUM_OFFSET / 4);
+        for (i = 0; i < (int)(CFG_ENV_DATA_SIZE); i++) {
+            checksum += g_env.env_data[i];
+        }
+        if (checksum != g_env.checksum) {
+            printf("[%s]checksum mismatch s %d d %d!\n", MODULE_NAME, g_env.checksum, checksum);
+            env_valid = 0;
+            goto end;
+        } else {
+            printf("[%s]ENV initialize sucess\n", MODULE_NAME);
+            env_valid = 1;
+        }
+
+    } else {
+        printf("[%s]ENV SIG Wrong\n", MODULE_NAME);
+        env_valid = 0;
+        goto end;
+    }
+end:
+    if (!env_valid) {
+        memset(env_buffer, 0x00, CFG_ENV_SIZE);
+    }
+
+}
+
+char *get_env(char *name)
+{
+    int i, nxt;
+    printf("[%s]get_env %s\n", MODULE_NAME, name);
+    if (!env_valid)
+        return NULL;
+
+    for (i = 0; env_get_char(i) != '\0'; i = nxt + 1) {
+        int val;
+
+        for (nxt = i; env_get_char(nxt) != '\0'; ++nxt) {
+            if (nxt >= CFG_ENV_SIZE) {
+                return (NULL);
+            }
+        }
+        if ((val = envmatch((uchar *) name, i)) < 0)
+            continue;
+        return ((char *)env_get_addr(val));
+    }
+
+    return (NULL);
+}
+
+static char env_get_char(int index)
+{
+    return *(g_env.env_data + index);
+}
+
+static char *env_get_addr(int index)
+{
+    return (g_env.env_data + index);
+
+}
+
+static int envmatch(uchar *s1, int i2)
+{
+
+    while (*s1 == env_get_char(i2++))
+        if (*s1++ == '=')
+            return (i2);
+    if (*s1 == '\0' && env_get_char(i2 - 1) == '=')
+        return (i2);
+    return (-1);
+}
+
+int set_env(char *name, char *value)
+{
+    int len, oldval;
+    uchar *env, *nxt = NULL;
+
+    int ret;
+
+    uchar *env_data = (uchar *) g_env.env_data;
+
+    printf("[%s]set_env %s %s\n", MODULE_NAME, name, value);
+
+    oldval = -1;
+
+    if (!env_valid) {
+        env = env_data;
+        goto add;
+    }
+
+    for (env = env_data; *env; env = nxt + 1) {
+        for (nxt = env; *nxt; ++nxt);
+        if ((oldval = envmatch((uchar *) name, env - env_data)) >= 0)
+            break;
+    }
+
+    if (oldval > 0) {
+        if (*++nxt == '\0') {
+            if (env > env_data) {
+                env--;
+            } else {
+                *env = '\0';
+            }
+        } else {
+            for (;;) {
+                *env = *nxt++;
+                if ((*env == '\0') && (*nxt == '\0'))
+                    break;
+                ++env;
+            }
+        }
+        *++env = '\0';
+    }
+
+    for (env = env_data; *env || *(env + 1); ++env);
+    if (env > env_data)
+        ++env;
+
+add:
+    /*
+     * Overflow when:
+     * "name" + "=" + "val" +"\0\0"  > ENV_SIZE - (env-env_data)
+     */
+    len = strlen(name) + 2;
+    /* add '=' for first arg, ' ' for all others */
+    len += strlen(value) + 1;
+
+    if (len > (&env_data[CFG_ENV_DATA_SIZE] - env)) {
+        printf("## Error: environment overflow, \"%s\" deleted\n", name);
+        return -1;
+    }
+    while ((*env = *name++) != '\0')
+        env++;
+
+    *env = '=';
+
+    while ((*++env = *value++) != '\0');
+
+    /* end is marked with double '\0' */
+    *++env = '\0';
+    memset(env, 0x00, CFG_ENV_DATA_SIZE - (env - env_data));
+    ret = write_env_area(env_buffer);
+    if (ret < 0) {
+        printf("[%s]write env fail\n", MODULE_NAME);
+        memset(env_buffer, 0x00, CFG_ENV_SIZE);
+        return -1;
+    }
+    env_valid = 1;
+    return 0;
+
+}
+
+void print_env()
+{
+    int i, nxt;
+    uchar *env = (uchar *) g_env.env_data;
+    if (!env_valid) {
+        printf("[%s]no valid env\n", MODULE_NAME);
+        return;
+    }
+    printf("[%s]env:\n", MODULE_NAME);
+    for (i = 0; env_get_char(i) != '\0'; i = nxt + 1) {
+        for (nxt = i; env_get_char(nxt) != '\0'; ++nxt) {
+            if (nxt >= (int)(CFG_ENV_DATA_SIZE)) {
+                return;
+            }
+        }
+        printf("%s\n", env + i);
+    }
+}
+
+static int write_env_area(char *env_buf)
+{
+#if 0 //nelson
+    part_t *part;
+    part_dev_t *dev;
+    size_t count;
+    long len;
+    int i, checksum = 0;
+    unsigned long long start_addr;
+
+    dev = mt_part_get_device();
+    if (!dev) {
+        return -ENODEV;
+    }
+
+    part = mt_part_get_partition(ENV_PART);
+    if (!part) {
+        return -ENOENT;
+    }
+
+    start_addr = (u64) part->start_sect * dev->blkdev->blksz;
+
+    count = min(sizeof(ENV_SIG), sizeof(g_env.sig));
+    memcpy(env_buf, ENV_SIG, count);
+    memcpy(env_buf + CFG_ENV_SIG_1_OFFSET, ENV_SIG, count);
+
+    for (i = 0; i < (int)CFG_ENV_DATA_SIZE; i++) {
+        checksum += *(env_buf + CFG_ENV_DATA_OFFSET + i);
+    }
+    printf("checksum %d\n", checksum);
+
+    *((int *)env_buf + CFG_ENV_CHECKSUM_OFFSET / 4) = checksum;
+
+    len = dev->write(dev, (uchar *) env_buf, start_addr + CFG_ENV_OFFSET, CFG_ENV_SIZE, part->part_id);
+    if (len < 0) {
+        return -EIO;
+    }
+#else
+    size_t count;
+    long len;
+    int i, checksum = 0;
+
+    bdev_t *bdev;
+
+    bdev = bio_open_by_label(ENV_PART);
+    if (!bdev) {
+        return -ENODEV;
+    }
+
+    count = min(sizeof(ENV_SIG), sizeof(g_env.sig));
+    memcpy(env_buf, ENV_SIG, count);
+    memcpy(env_buf + CFG_ENV_SIG_1_OFFSET, ENV_SIG, count);
+
+    for (i = 0; i < (int)CFG_ENV_DATA_SIZE; i++) {
+        checksum += *(env_buf + CFG_ENV_DATA_OFFSET + i);
+    }
+    dprintf(CRITICAL, "checksum %d\n", checksum);
+
+    *((int *)env_buf + CFG_ENV_CHECKSUM_OFFSET / 4) = checksum;
+    len = bio_write(bdev, (uchar *) env_buf, CFG_ENV_OFFSET, CFG_ENV_SIZE);
+    if (len < 0) {
+        return -EIO;
+    }
+
+#endif
+    return 0;
+
+}
+
+static int read_env_area(char *env_buf)
+{
+#if 0 //nelson
+    part_t *part;
+    part_dev_t *dev;
+    long len;
+    unsigned long long start_addr;
+
+    dev = mt_part_get_device();
+    if (!dev) {
+        return -ENODEV;
+    }
+
+    part = mt_part_get_partition(ENV_PART);
+    if (!part) {
+        return -ENOENT;
+    }
+
+    start_addr = (u64) part->start_sect * dev->blkdev->blksz;
+
+    len = dev->read(dev, start_addr + CFG_ENV_OFFSET, (uchar *) env_buf, CFG_ENV_SIZE, part->part_id);
+    if (len < 0) {
+        return -EIO;
+    }
+#else
+
+    long len;
+    bdev_t *bdev;
+
+    bdev = bio_open_by_label(ENV_PART);
+    if (!bdev) {
+        return -ENODEV;
+    }
+
+    len = bio_read(bdev, (uchar *) env_buf, CFG_ENV_OFFSET, CFG_ENV_SIZE);
+    if (len < 0) {
+        return -EIO;
+    }
+
+#endif
+    return 0;
+}
diff --git a/src/bsp/lk/lib/aee/include/KEHeader.h b/src/bsp/lk/lib/aee/include/KEHeader.h
new file mode 100644
index 0000000..b61f8e5
--- /dev/null
+++ b/src/bsp/lk/lib/aee/include/KEHeader.h
@@ -0,0 +1,140 @@
+/*
+ * Copyright (c) 2018 MediaTek Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include <sys/types.h>
+
+#define AEE_IPANIC_PLABLE "expdb"
+
+
+#define AEE_IPANIC_MAGIC 0xaee0dead
+#define AEE_IPANIC_PHDR_VERSION     0x10
+#define IPANIC_NR_SECTIONS              64
+#if (AEE_IPANIC_PHDR_VERSION >= 0x10)
+#define IPANIC_USERSPACE_READ           1
+#endif
+
+/***************************************************************/
+/* #define MRDUMP_MINI_NR_SECTION       40         */
+/* #define MRDUMP_MINI_SECTION_SIZE     (32 * 1024)            */
+/* #define MRDUMP_MINI_NR_MISC      20             */
+/***************************************************************/
+
+struct mrdump_mini_misc_data32 {
+    unsigned int vaddr;
+    unsigned int paddr;
+    unsigned int start;
+    unsigned int size;
+};
+
+struct mrdump_mini_misc_data64 {
+    unsigned long long vaddr;
+    unsigned long long paddr;
+    unsigned long long start;
+    unsigned long long size;
+};
+
+/**********************************************/
+/* struct mrdump_mini_elf_misc {          */
+/*         struct elf_note note;          */
+/*         char name[16];             */
+/*         struct mrdump_mini_misc_data data; */
+/* };                         */
+/**********************************************/
+
+/**********************************************************/
+/* struct mrdump_mini_elf_header {            */
+/*         struct elfhdr ehdr;                */
+/*         struct elf_phdr phdrs[MRDUMP_MINI_NR_SECTION]; */
+/*         struct {                   */
+/*                 struct elf_note note;          */
+/*                 char name[12];             */
+/*                 struct elf_prpsinfo data;          */
+/*         } psinfo;                      */
+/*         struct {                   */
+/*                 struct elf_note note;          */
+/*                 char name[12];             */
+/*                 struct elf_prstatus data;          */
+/*         } prstatus[3];                 */
+/*         struct {                   */
+/*                 struct elf_note note;          */
+/*                 char name[20];             */
+/*                 struct mrdump_mini_misc_data data;     */
+/*         } misc[MRDUMP_MINI_NR_MISC];           */
+/* };                             */
+/**********************************************************/
+
+//#define PAGE_SIZE 4096
+/***********************************************************************************************************/
+/* #define MRDUMP_MINI_HEADER_SIZE  ALIGN(sizeof(struct mrdump_mini_elf_header), PAGE_SIZE)        */
+/* #define MRDUMP_MINI_DATA_SIZE        (MRDUMP_MINI_NR_SECTION * MRDUMP_MINI_SECTION_SIZE)        */
+/* #define MRDUMP_MINI_BUF_SIZE         (MRDUMP_MINI_HEADER_SIZE + MRDUMP_MINI_DATA_SIZE)      */
+/***********************************************************************************************************/
+
+// ipanic partation
+struct ipanic_data_header {
+    u32 type;       /* data type(0-31) */
+    u32 valid;      /* set to 1 when dump succeded */
+    u32 offset;     /* offset in EXPDB partition */
+    u32 used;       /* valid data size */
+    u32 total;      /* allocated partition size */
+    u32 encrypt;    /* data encrypted */
+    u32 raw;        /* raw data or plain text */
+    u32 compact;    /* data and header in same block, to save space */
+    u8 name[32];
+};
+
+struct ipanic_header {
+    u32 magic;
+    u32 version;    /* ipanic version */
+    u32 size;       /* ipanic_header size */
+    u32 datas;      /* bitmap of data sections dumped */
+    u32 dhblk;      /* data header blk size, 0 if no dup data headers */
+    u32 blksize;
+    u32 partsize;   /* expdb partition totoal size */
+    u32 bufsize;
+    u64 buf;
+    struct ipanic_data_header data_hdr[IPANIC_NR_SECTIONS];
+};
+
+#define IPANIC_MMPROFILE_LIMIT          0x220000
+
+typedef enum {
+    IPANIC_DT_HEADER = 0 ,
+    IPANIC_DT_KERNEL_LOG = 1 ,
+    IPANIC_DT_WDT_LOG ,
+    IPANIC_DT_WQ_LOG ,
+    IPANIC_DT_CURRENT_TSK = 6 ,
+    IPANIC_DT_OOPS_LOG ,
+    IPANIC_DT_MINI_RDUMP = 8 ,
+    IPANIC_DT_MMPROFILE ,
+    IPANIC_DT_MAIN_LOG ,
+    IPANIC_DT_SYSTEM_LOG ,
+    IPANIC_DT_EVENTS_LOG ,
+    IPANIC_DT_RADIO_LOG ,
+    IPANIC_DT_LAST_LOG ,
+    IPANIC_DT_RAM_DUMP = 28 ,
+    IPANIC_DT_SHUTDOWN_LOG = 30 ,
+    IPANIC_DT_RESERVED31 = 31 ,
+} IPANIC_DT;
+
+int kedump_get_data_info(int index, char **name, u32 *offset, u32 *size);
diff --git a/src/bsp/lk/lib/aee/include/aee.h b/src/bsp/lk/lib/aee/include/aee.h
new file mode 100644
index 0000000..f9c164f
--- /dev/null
+++ b/src/bsp/lk/lib/aee/include/aee.h
@@ -0,0 +1,108 @@
+/*
+ * Copyright (c) 2018 MediaTek Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#if !defined (__AEE_H__)
+#define __AEE_H__
+
+#include <mrdump.h>
+#include <stdbool.h>
+#include <stdarg.h>
+#include <stdint.h>
+#include <sys/types.h>
+#include "KEHeader.h"
+
+typedef enum {
+    AEE_MODE_MTK_ENG = 1,
+    AEE_MODE_MTK_USER,
+    AEE_MODE_CUSTOMER_ENG,
+    AEE_MODE_CUSTOMER_USER
+} AEE_MODE;
+
+typedef enum {
+    AEE_REBOOT_MODE_NORMAL = 0,
+    AEE_REBOOT_MODE_KERNEL_OOPS,
+    AEE_REBOOT_MODE_KERNEL_PANIC,
+    AEE_REBOOT_MODE_NESTED_EXCEPTION,
+    AEE_REBOOT_MODE_WDT,
+    AEE_REBOOT_MODE_EXCEPTION_KDUMP,
+    AEE_REBOOT_MODE_MRDUMP_KEY,
+    AEE_REBOOT_MODE_GZ_KE,
+    AEE_REBOOT_MODE_GZ_WDT,
+    AEE_REBOOT_MODE_HANG_DETECT,
+} AEE_REBOOT_MODE;
+
+enum {
+    REBOOT_REASON_REBOOT = 0,
+    REBOOT_REASON_WATCHDOG,
+    REBOOT_REASON_KERNEL_PANIC,
+    REBOOT_REASON_2S_REBOOT,
+    REBOOT_REASON_DM_VERITY_CORRUPTION
+};
+
+#define IPANIC_OOPS_HEADER_PROCESS_NAME_LENGTH 256
+#define IPANIC_OOPS_HEADER_BACKTRACE_LENGTH 3840
+
+struct ipanic_oops_header {
+    char process_path[IPANIC_OOPS_HEADER_PROCESS_NAME_LENGTH];
+    char backtrace[IPANIC_OOPS_HEADER_BACKTRACE_LENGTH];
+};
+
+extern uint32_t g_aee_mode;
+
+const char *mrdump_mode2string(uint8_t mode);
+
+struct mrdump_control_block *aee_mrdump_get_params(void);
+struct mrdump_control_block *mrdump_cb_addr(void);
+int mrdump_cb_size(void);
+
+void aee_mrdump_flush_cblock(struct mrdump_control_block *bufp);
+
+void voprintf(char type, const char *msg, va_list ap);
+void voprintf_verbose(const char *msg, ...);
+void voprintf_debug(const char *msg, ...);
+void voprintf_info(const char *msg, ...);
+void voprintf_warning(const char *msg, ...);
+void voprintf_error(const char *msg, ...);
+void vo_show_progress(int sizeM);
+
+void mrdump_status_none(const char *fmt, ...);
+void mrdump_status_ok(const char *fmt, ...);
+void mrdump_status_error(const char *fmt, ...);
+
+struct aee_timer {
+    unsigned int acc_ms;
+
+    unsigned int start_ms;
+};
+
+void aee_timer_init(struct aee_timer *t);
+void aee_timer_start(struct aee_timer *t);
+void aee_timer_stop(struct aee_timer *t);
+
+/* FIXME: move to platform/mtk_wdt.h */
+extern void mtk_wdt_restart(void);
+extern ulong get_timer_masked (void);
+extern uint32_t memory_size(void);
+bool ram_console_reboot_by_mrdump_key(void)__attribute__((weak));
+
+#endif
diff --git a/src/bsp/lk/lib/aee/include/dev/aee_platform_debug.h b/src/bsp/lk/lib/aee/include/dev/aee_platform_debug.h
new file mode 100644
index 0000000..99ff07c
--- /dev/null
+++ b/src/bsp/lk/lib/aee/include/dev/aee_platform_debug.h
@@ -0,0 +1,108 @@
+/*
+ * Copyright (c) 2018 MediaTek Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#if !defined(__AEE_PLATFORM_DEBUG_H__)
+#define __AEE_PLATFORM_DEBUG_H__
+
+#include <boot_args.h>
+#include <sys/types.h>
+
+typedef unsigned long long u64;
+typedef unsigned long long (*CALLBACK)(void *data, unsigned long sz);
+
+/* extern global variable */
+extern BOOT_ARGUMENT *g_boot_arg;
+
+enum {
+	AEE_PLAT_DFD20,
+	AEE_PLAT_DRAM,
+	AEE_PLAT_CPU_BUS,
+	AEE_PLAT_SPM_DATA,
+	AEE_PLAT_SPM_SRAM_DATA,
+	AEE_PLAT_ATF_LAST_LOG,
+	AEE_PLAT_ATF_CRASH_REPORT,
+	AEE_PLAT_ATF_RAW_LOG,
+	AEE_PLAT_ATF_RDUMP_LOG,
+	AEE_PLAT_HVFS,
+#ifdef MTK_TINYSYS_SSPM_SUPPORT
+	AEE_PLAT_SSPM_COREDUMP,
+	AEE_PLAT_SSPM_DATA,
+	AEE_PLAT_SSPM_XFILE,
+	AEE_PLAT_SSPM_LAST_LOG,
+#endif
+	AEE_PLAT_PLLK_LAST_LOG,
+	AEE_PLAT_LOG_DUR_LKDUMP,
+	AEE_PLAT_MCDI_DATA,
+	AEE_PLAT_SCP_COREDUMP,
+	AEE_PLAT_DEBUG_NUM
+};
+
+/* function pointers */
+extern unsigned int (* plat_dfd20_get)(u64 offset, int *len, CALLBACK dev_write);
+extern unsigned int (* plat_dram_get)(u64 offset, int *len, CALLBACK dev_write);
+extern unsigned int (* plat_cpu_bus_get)(u64 offset, int *len, CALLBACK dev_write);
+extern unsigned int (* plat_spm_data_get)(u64 offset, int *len, CALLBACK dev_write);
+extern unsigned int (* plat_spm_sram_data_get)(u64 offset, int *len, CALLBACK dev_write);
+extern unsigned int (* plat_hvfs_get)(u64 offset, int *len, CALLBACK dev_write);
+#ifdef MTK_TINYSYS_SSPM_SUPPORT
+extern unsigned int (* plat_sspm_coredump_get)(u64 offset, int *len, CALLBACK dev_write);
+extern unsigned int (* plat_sspm_data_get)(u64 offset, int *len, CALLBACK dev_write);
+extern unsigned int (* plat_sspm_xfile_get)(u64 offset, int *len, CALLBACK dev_write);
+extern unsigned int (* plat_sspm_log_get)(u64 offset, int *len, CALLBACK dev_write);
+#endif
+extern unsigned int (* plat_pllk_last_log_get)(u64 offset, int *len, CALLBACK dev_write);
+extern unsigned int (* plat_dur_lkdump_get)(u64 offset, int *len, CALLBACK dev_write);
+extern unsigned int (* plat_mcdi_get)(u64 offset, int *len, CALLBACK dev_write);
+#ifdef MTK_TINYSYS_SCP_SUPPORT
+extern unsigned int (* plat_scp_coredump_get)(u64 offset, int *len, CALLBACK dev_write);
+#endif
+
+/* DRAM KLOG at MRDUMP area of expdb, offset from bottom = 3145728 - 16384 = 3129344 */
+#define MRDUMP_EXPDB_BOTTOM_OFFSET 2097152
+#define MRDUMP_EXPDB_DRAM_KLOG_OFFSET 3129344
+
+/* common api */
+unsigned int kedump_plat_savelog(int condition, u64 offset, int *len, CALLBACK dev_write);
+
+extern void arch_clean_cache_range(addr_t start, size_t len);
+//extern part_dev_t *mt_part_get_device(void);
+
+/* common interface for platform */
+void mrdump_write_log(u64 offset_dst, void *data, int len);
+void mrdump_read_log(void *data, int len, u64 offset);
+
+int lkdump_debug_init(void);
+/* common interface from platform */
+int platform_debug_init(void);
+void platform_lastpc_postinit(void);
+
+extern struct aee_db_file_info* get_file_info(void);
+
+/* db filename and max size */
+struct aee_db_file_info {
+        char filename[32];
+        unsigned int filesize;
+        unsigned int step;
+};
+
+#endif /* __AEE_PLATFORM_DEBUG_H__ */
+
diff --git a/src/bsp/lk/lib/aee/include/elf.h b/src/bsp/lk/lib/aee/include/elf.h
new file mode 100644
index 0000000..d76bd7f
--- /dev/null
+++ b/src/bsp/lk/lib/aee/include/elf.h
@@ -0,0 +1,225 @@
+/*
+ * Copyright (c) 2018 MediaTek Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/****************************************************************************
+ ****************************************************************************
+ ***
+ ***   This header was automatically generated from a Linux kernel header
+ ***   of the same name, to make information necessary for userspace to
+ ***   call into the kernel available to libc.  It contains only constants,
+ ***   structures, and macros generated from the original header, and thus,
+ ***   contains no copyrightable information.
+ ***
+ ***   To edit the content of this header, modify the corresponding
+ ***   source file (e.g. under external/kernel-headers/original/) then
+ ***   run bionic/libc/kernel/tools/update_all.py
+ ***
+ ***   Any manual change here will be lost the next time this script will
+ ***   be run. You've been warned!
+ ***
+ ****************************************************************************
+ ****************************************************************************/
+#ifndef _UAPI_LINUX_ELF_H
+#define _UAPI_LINUX_ELF_H
+
+typedef short   __s16;
+typedef int __s32;
+typedef long long __s64;
+typedef unsigned short  __u16;
+typedef unsigned int    __u32;
+typedef unsigned long long __u64;
+
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+typedef __u32 Elf32_Addr;
+typedef __u16 Elf32_Half;
+typedef __u32 Elf32_Off;
+typedef __s32 Elf32_Sword;
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+typedef __u32 Elf32_Word;
+typedef __u64 Elf64_Addr;
+typedef __u16 Elf64_Half;
+typedef __s16 Elf64_SHalf;
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+typedef __u64 Elf64_Off;
+typedef __s32 Elf64_Sword;
+typedef __u32 Elf64_Word;
+typedef __u64 Elf64_Xword;
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+typedef __s64 Elf64_Sxword;
+#define PT_NULL 0
+#define PT_LOAD 1
+#define PT_DYNAMIC 2
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#define PT_INTERP 3
+#define PT_NOTE 4
+#define PT_SHLIB 5
+#define PT_PHDR 6
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#define PT_TLS 7
+
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#define ET_NONE 0
+#define ET_REL 1
+#define ET_EXEC 2
+#define ET_DYN 3
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#define ET_CORE 4
+#define ET_LOPROC 0xff00
+#define ET_HIPROC 0xffff
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+
+
+#define EI_NIDENT 16
+
+typedef struct elf32_hdr {
+    /* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+    unsigned char e_ident[EI_NIDENT];
+    Elf32_Half e_type;
+    Elf32_Half e_machine;
+    Elf32_Word e_version;
+    /* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+    Elf32_Addr e_entry;
+    Elf32_Off e_phoff;
+    Elf32_Off e_shoff;
+    Elf32_Word e_flags;
+    /* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+    Elf32_Half e_ehsize;
+    Elf32_Half e_phentsize;
+    Elf32_Half e_phnum;
+    Elf32_Half e_shentsize;
+    /* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+    Elf32_Half e_shnum;
+    Elf32_Half e_shstrndx;
+} Elf32_Ehdr;
+typedef struct elf64_hdr {
+    /* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+    unsigned char e_ident[EI_NIDENT];
+    Elf64_Half e_type;
+    Elf64_Half e_machine;
+    Elf64_Word e_version;
+    /* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+    Elf64_Addr e_entry;
+    Elf64_Off e_phoff;
+    Elf64_Off e_shoff;
+    Elf64_Word e_flags;
+    /* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+    Elf64_Half e_ehsize;
+    Elf64_Half e_phentsize;
+    Elf64_Half e_phnum;
+    Elf64_Half e_shentsize;
+    /* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+    Elf64_Half e_shnum;
+    Elf64_Half e_shstrndx;
+} Elf64_Ehdr;
+#define PF_R 0x4
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#define PF_W 0x2
+#define PF_X 0x1
+typedef struct elf32_phdr {
+    Elf32_Word p_type;
+    /* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+    Elf32_Off p_offset;
+    Elf32_Addr p_vaddr;
+    Elf32_Addr p_paddr;
+    Elf32_Word p_filesz;
+    /* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+    Elf32_Word p_memsz;
+    Elf32_Word p_flags;
+    Elf32_Word p_align;
+} Elf32_Phdr;
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+typedef struct elf64_phdr {
+    Elf64_Word p_type;
+    Elf64_Word p_flags;
+    Elf64_Off p_offset;
+    /* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+    Elf64_Addr p_vaddr;
+    Elf64_Addr p_paddr;
+    Elf64_Xword p_filesz;
+    Elf64_Xword p_memsz;
+    /* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+    Elf64_Xword p_align;
+} Elf64_Phdr;
+
+#define EI_MAG0 0
+#define EI_MAG1 1
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#define EI_MAG2 2
+#define EI_MAG3 3
+#define EI_CLASS 4
+#define EI_DATA 5
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#define EI_VERSION 6
+#define EI_OSABI 7
+#define EI_PAD 8
+#define ELFMAG0 0x7f
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#define ELFMAG1 'E'
+#define ELFMAG2 'L'
+#define ELFMAG3 'F'
+#define ELFMAG "\177ELF"
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#define SELFMAG 4
+#define ELFCLASSNONE 0
+#define ELFCLASS32 1
+#define ELFCLASS64 2
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#define ELFCLASSNUM 3
+#define ELFDATANONE 0
+#define ELFDATA2LSB 1
+#define ELFDATA2MSB 2
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#define EV_NONE 0
+#define EV_CURRENT 1
+#define EV_NUM 2
+#define ELFOSABI_NONE 0
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#define ELFOSABI_LINUX 3
+#ifndef ELF_OSABI
+#define ELF_OSABI ELFOSABI_NONE
+#endif
+
+#define NT_PRSTATUS 1
+#define NT_PRFPREG 2
+#define NT_PRPSINFO 3
+#define NT_TASKSTRUCT 4
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#define NT_AUXV 6
+
+/* Note header in a PT_NOTE section */
+typedef struct elf32_note {
+    Elf32_Word n_namesz;
+    /* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+    Elf32_Word n_descsz;
+    Elf32_Word n_type;
+} Elf32_Nhdr;
+typedef struct elf64_note {
+    /* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+    Elf64_Word n_namesz;
+    Elf64_Word n_descsz;
+    Elf64_Word n_type;
+} Elf64_Nhdr;
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#define EM_AARCH64      183
+#define EM_ARM          40
+#endif
diff --git a/src/bsp/lk/lib/aee/include/emi_info_v1.h b/src/bsp/lk/lib/aee/include/emi_info_v1.h
new file mode 100644
index 0000000..f300fa9
--- /dev/null
+++ b/src/bsp/lk/lib/aee/include/emi_info_v1.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2018 MediaTek Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef __EMI_INFO_H__
+#define __EMI_INFO_H__
+
+#include <mt_emi_mpu.h>
+
+typedef struct {
+    unsigned int dram_type;
+    unsigned int ch_num;
+    unsigned int rk_num;
+    unsigned long long rank_size[MAX_RK];
+} emi_info_t;
+
+#endif
diff --git a/src/bsp/lk/lib/aee/include/env.h b/src/bsp/lk/lib/aee/include/env.h
new file mode 100644
index 0000000..73f57b6
--- /dev/null
+++ b/src/bsp/lk/lib/aee/include/env.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2018 MediaTek Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef __ENV_H__
+#define __ENV_H__
+
+#ifdef MTK_COMBO_NAND_SUPPORT
+extern unsigned int mtk_nand_erasesize(void);
+#define CFG_ENV_SIZE    0x8000 //(32KB)
+#define CFG_ENV_OFFSET  mtk_nand_erasesize()
+#else
+#define CFG_ENV_SIZE 0x4000 //(16KB)
+#define CFG_ENV_OFFSET 0x20000 //(128KB)
+#endif
+
+#define CFG_ENV_DATA_SIZE (CFG_ENV_SIZE-sizeof(g_env.checksum)-sizeof(g_env.sig)-sizeof(g_env.sig_1))
+#define CFG_ENV_DATA_OFFSET (sizeof(g_env.sig))
+#define CFG_ENV_SIG_1_OFFSET (CFG_ENV_SIZE - sizeof(g_env.checksum)-sizeof(g_env.sig_1))
+#define CFG_ENV_CHECKSUM_OFFSET (CFG_ENV_SIZE - sizeof(g_env.checksum))
+
+#define ENV_SIG "ENV_v1"
+
+typedef struct env_struct {
+    char sig[8]; // "ENV_v1"
+    char *env_data;
+    char sig_1[8];  //"ENV_v1"
+    int checksum; // checksum for env_data
+} env_t;
+
+extern void env_init(void);
+extern char *get_env(char *name);
+extern int set_env(char *name,char *value);
+extern void print_env(void);
+#endif
diff --git a/src/bsp/lk/lib/aee/include/kdump.h b/src/bsp/lk/lib/aee/include/kdump.h
new file mode 100644
index 0000000..43d346f
--- /dev/null
+++ b/src/bsp/lk/lib/aee/include/kdump.h
@@ -0,0 +1,266 @@
+/*
+ * Copyright (c) 2018 MediaTek Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#if !defined(__KDUMP_H__)
+#define __KDUMP_H__
+
+#include <compiler.h>
+#include <libfdt.h>
+#include <mrdump.h>
+#include <platform/mt_reg_base.h>
+#include <stdint.h>
+
+#ifdef MTK_MRDUMP_SRAM_CB
+#include <platform/mtk_mrdump.h>
+#endif
+
+#define MRDUMP_DEV_UNKNOWN 0
+#define MRDUMP_DEV_NONE 1
+#define MRDUMP_DEV_NULL 2
+#define MRDUMP_DEV_ISTORAGE_EXT4 3
+#define MRDUMP_DEV_ISTORAGE_VFAT 4
+#define MRDUMP_DEV_USB 5
+
+#define MRDUMP_GO_DUMP "MRDUMP08"
+
+/* for dts */
+#ifdef CFG_DTB_EARLY_LOADER_SUPPORT
+
+struct mrdump_reserve_args {
+    uint32_t hi_addr;
+    uint32_t lo_addr;
+    uint32_t hi_size;
+    uint32_t lo_size;
+};
+
+#endif
+
+/*
+ * for ext4 and f2fs, InfoLBA (header), version 2
+ * 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
+
+#define KZIP_ENTRY_MAX 30
+#define LOCALHEADERMAGIC 0x04034b50UL
+#define CENTRALHEADERMAGIC 0x02014b50UL
+#define ZIP64ENDOFCENTRALDIRMAGIC 0x06064b50UL
+#define ZIP64ENDOFCENTRALDIRLOCATORMAGIC 0x07064b50UL
+#define ENDOFCENTRALDIRMAGIC 0x06054b50UL
+
+#define KDUMP_CORE_HEADER_SIZE 2 * 4096
+
+struct kzip_entry {
+    char *filename;
+    int level;
+    uint64_t localheader_offset;
+    uint64_t comp_size;
+    uint64_t uncomp_size;
+    uint32_t crc32;
+};
+
+struct kzip_file {
+    uint32_t reported_size;
+    uint32_t wdk_kick_size;
+    uint64_t current_size;
+
+    uint32_t entries_num;
+    struct kzip_entry zentries[KZIP_ENTRY_MAX];
+    void *handle;
+
+    int (*write_cb)(void *handle, void *buf, int size);
+};
+
+#define MEM_NO_MAP 0
+#define MEM_DO_MAP 1
+#define EXPDB_FILE 2
+struct kzip_addlist {
+    uint64_t address;
+    uint64_t size;
+    int type;
+};
+
+#define MRDUMP_CPU_MAX 12
+
+#define MRDUMP_ENABLE_COOKIE 0x590d2ba3
+
+typedef uint32_t arm32_gregset_t[18];
+typedef uint64_t arm64_gregset_t[34];
+
+struct arm32_ctrl_regs {
+    uint32_t sctlr;
+    uint64_t ttbcr;
+    uint64_t ttbr0;
+    uint64_t ttbr1;
+};
+
+struct arm64_ctrl_regs {
+    uint32_t sctlr_el1;
+    uint32_t sctlr_el2;
+    uint32_t sctlr_el3;
+
+    uint64_t tcr_el1;
+    uint64_t tcr_el2;
+    uint64_t tcr_el3;
+
+    uint64_t ttbr0_el1;
+    uint64_t ttbr0_el2;
+    uint64_t ttbr0_el3;
+
+    uint64_t ttbr1_el1;
+
+    uint64_t sp_el[4];
+};
+
+struct mrdump_crash_record {
+    int reboot_mode;
+
+    char msg[128];
+
+    uint32_t fault_cpu;
+
+    union {
+        arm32_gregset_t arm32_regs;
+        arm64_gregset_t arm64_regs;
+    } cpu_regs[MRDUMP_CPU_MAX];
+
+    union {
+        struct arm32_ctrl_regs arm32_creg;
+        struct arm64_ctrl_regs arm64_creg;
+    } cpu_creg[MRDUMP_CPU_MAX];
+};
+
+struct mrdump_ksyms_param {
+    char     tag[4];
+    uint32_t flag;
+    uint32_t crc;
+    uint64_t start_addr;
+    uint32_t size;
+    uint32_t addresses_off;
+    uint32_t num_syms_off;
+    uint32_t names_off;
+    uint32_t markers_off;
+    uint32_t token_table_off;
+    uint32_t token_index_off;
+} __attribute__((packed));
+
+struct mrdump_machdesc {
+    uint32_t nr_cpus;
+
+    uint64_t page_offset;
+    uint64_t high_memory;
+
+    uint64_t kimage_vaddr;
+    uint64_t dram_start;
+    uint64_t dram_end;
+    uint64_t kimage_stext;
+    uint64_t kimage_etext;
+    uint64_t kimage_stext_real;
+    uint64_t kimage_voffset;
+    uint64_t kimage_sdata;
+    uint64_t kimage_edata;
+
+    uint64_t vmalloc_start;
+    uint64_t vmalloc_end;
+
+    uint64_t modules_start;
+    uint64_t modules_end;
+
+    uint64_t phys_offset;
+    uint64_t master_page_table;
+
+    uint64_t memmap;
+
+    uint64_t dfdmem_pa;  // Reserved for DFD 3.0+
+
+    struct mrdump_ksyms_param kallsyms;
+};
+
+struct __attribute__((__packed__)) mrdump_cblock_result {
+    char sig[9];
+    char status[128];
+    char log_buf[2048];
+};
+
+struct mrdump_control_block {
+    char sig[8];
+
+    struct mrdump_machdesc machdesc;
+    uint32_t machdesc_crc;
+
+    uint32_t enabled;
+    uint32_t output_fs_lbaooo;
+
+    struct mrdump_crash_record crash_record;
+};
+
+struct kzip_file *kzip_open(void *handle, int (*write_cb)(void *handle, void *p, int size));
+bool kzip_add_file(struct kzip_file *zf, const struct kzip_addlist *addlist, const char *zfilename);
+bool kzip_close(struct kzip_file *zf);
+
+struct mrdump_dev;
+
+struct mrdump_dev *mrdump_dev_emmc_vfat(void);
+struct mrdump_dev *mrdump_dev_emmc_ext4(void);
+struct mrdump_dev *mrdump_dev_sdcard(void);
+
+int kdump_null_output(const struct mrdump_control_block *kparams,
+    const struct kzip_addlist *memlist);
+int mrdump_ext4_output(const struct mrdump_control_block *mrdump_cb,
+    const struct kzip_addlist *memlist, struct mrdump_dev *mrdump_dev);
+int mrdump_vfat_output(const struct mrdump_control_block *mrdump_cb,
+    const struct kzip_addlist *memlist, struct mrdump_dev *mrdump_dev);
+int kdump_usb_output(const struct mrdump_control_block *mrdump_cb,
+    const struct kzip_addlist *memlist);
+
+void kdump_core_header_init(const struct mrdump_control_block *kparams,
+    const struct kzip_addlist *memlist);
+void kdump_core32_header_init(const struct mrdump_control_block *kparams,
+    const struct kzip_addlist *memlist);
+void kdump_core64_header_init(const struct mrdump_control_block *kparams,
+    const struct kzip_addlist *memlist);
+
+void mrdump_setup_cblock(void);
+void mrdump_setup_version(void);
+void mrdump_setup_boot_reason(void);
+
+extern u64 physical_memory_size(void);
+extern void mtk_wdt_disable(void);
+extern void mtk_wdt_init(void);
+extern void mrdump_read_expdb(void *data, int len, u64 offset_src);
+
+#ifdef MTK_3LEVEL_PAGETABLE
+vaddr_t scratch_addr(void);
+#endif
+
+#endif
diff --git a/src/bsp/lk/lib/aee/include/kdump_sdhc.h b/src/bsp/lk/lib/aee/include/kdump_sdhc.h
new file mode 100644
index 0000000..8a28943
--- /dev/null
+++ b/src/bsp/lk/lib/aee/include/kdump_sdhc.h
@@ -0,0 +1,121 @@
+/*
+ * Copyright (c) 2018 MediaTek Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#if !defined(__KDUMP_SDHC_H__)
+#define __KDUMP_SDHC_H__
+
+#include <lib/bio.h>
+#include <stdbool.h>
+
+#define MaxFindFileClusNum 100
+
+typedef enum {
+    WRITE_FILE_DIRECT = 0,
+    FORMAT_BEF_WRITE = 1
+} FileWriteType;
+
+
+typedef enum FileSysType {
+    FAT_16 = 0,
+    FAT_32 = 1
+} FATType;
+
+typedef struct {
+    uint32_t   BPB_BytsPerSec;
+    uint32_t   BPB_SecPerClus;
+    uint32_t   BPB_RsvdSecCnt;
+    uint32_t   BPB_NumFATs;
+    uint32_t   BPB_FATSz;
+    uint32_t   BPB_RootEntCnt;
+    uint32_t   BPB_RootClus;
+    uint32_t   BPB_TotSec;
+    FATType FileSysType;
+    uint32_t   BootStartSec;
+    uint32_t   FATStartSec;
+    uint32_t   RootDirStartSec;
+    uint32_t   ClusStartSec;
+} FAT_Para;
+
+
+
+typedef struct {
+    uint8_t    name[11];            // file name
+    uint8_t    attr;                // file attribute bits (system, hidden, etc.)
+    uint8_t    NTflags;             // ???
+    uint8_t    createdTimeMsec;     // ??? (milliseconds needs 11 bits for 0-2000)
+    uint16_t    createdTime;         // time of file creation
+    uint16_t    createdDate;         // date of file creation
+    uint16_t    lastAccessDate;      // date of last file access
+    uint16_t    clusFirstHigh;       // high word of first cluster
+    uint16_t    time;                // time of last file change
+    uint16_t    date;                // date of last file change
+    uint16_t    clusFirst;           // low word of first cluster
+    uint32_t   size;                // file size in bytes
+} DirEntry;
+
+typedef struct {
+    uint8_t    seqNum;              // sequence number
+    uint8_t    name1[10];           // name characters (five UTF-16 characters)
+    uint8_t    attr;                // attributes (always 0x0F)
+    uint8_t    NTflags;             // reserved (alwyas 0x00)
+    uint8_t    checksum;            // checksum of DOS file name
+    uint8_t    name2[12];           // name characters (six UTF-16 characters)
+    uint16_t    clusFirst;           // word of first cluster (always 0x0000)
+    uint8_t    name3[4];            // name characters (2 UTF-16 characters)
+} LfnEntry;
+
+#define FAT_BUFSIZE 65536
+
+typedef struct {
+    uint8_t   FileBuffer[FAT_BUFSIZE];  // File cluster cache, assume maximum cluster size is 64KB
+    uint8_t   FATBuffer[512];       // FAT cache
+    uint32_t  BufferLen;            // data cached length in FileBuffer
+    uint32_t  TotalLen;         // File total length
+    uint32_t  PrevClusterNum;       // Prev cluster number
+    uint32_t  CurrClusterNum;       // Current cluster number
+    uint32_t  FATSector;            // Current FAT sector number
+    uint32_t  CheckSum;         // File write content checksum
+    bool DiskFull;
+} FileHandler;
+
+
+struct mrdump_dev {
+    const char *name;
+    void *handle;
+    bdev_t *bdev;
+
+    bool (*read)(struct mrdump_dev *dev, uint64_t sector_addr, uint8_t *pdBuf, int32_t blockLen);
+    bool (*write)(struct mrdump_dev *dev, uint64_t sector_addr, uint8_t *pdBuf, int32_t blockLen);
+};
+
+static inline int mrdump_dev_read(struct mrdump_dev *dev, uint32_t sector_addr, uint8_t *pdBuf, int32_t blockLen)
+{
+    return dev->read(dev, sector_addr, pdBuf, blockLen);
+}
+
+static inline int mrdump_dev_write(struct mrdump_dev *dev, uint32_t sector_addr, uint8_t *pdBuf, int32_t blockLen)
+{
+    return dev->write(dev, sector_addr, pdBuf, blockLen);
+}
+
+#endif
diff --git a/src/bsp/lk/lib/aee/include/mrdump.h b/src/bsp/lk/lib/aee/include/mrdump.h
new file mode 100644
index 0000000..f676197
--- /dev/null
+++ b/src/bsp/lk/lib/aee/include/mrdump.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2018 MediaTek Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#if !defined (__MRDUMP_H__)
+#define __MRDUMP_H__
+
+#include <sys/types.h>
+
+#define AEE_MRDUMP_LK_RSV_SIZE 0x100000
+#define AEE_MRDUMP_DDR_RSV_READY 0x9502
+
+void aee_reserve_memory(char *str, ...);
+int mrdump_detection(void);
+
+void mrdump_reboot(void);
+int mrdump_run2(void);
+
+int check_ram_console_is_abnormal_boot(void) __attribute__((weak));
+
+/* extern functions */
+int usb_write_with_timeout(void *buf, unsigned len, lk_time_t timeout);
+int usb_read_with_timeout(void *_buf, unsigned len, lk_time_t timeout);
+
+#endif
diff --git a/src/bsp/lk/lib/aee/include/mrdump_elf.h b/src/bsp/lk/lib/aee/include/mrdump_elf.h
new file mode 100644
index 0000000..8448fa0
--- /dev/null
+++ b/src/bsp/lk/lib/aee/include/mrdump_elf.h
@@ -0,0 +1,118 @@
+/*
+ * Copyright (c) 2018 MediaTek Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#if !defined(__KDUMP_ELF_H__)
+#define __KDUMP_ELF_H__
+
+#include <stdint.h>
+#include "mrdump_elf_common.h"
+
+#define ELF_ARM_NGREGS 18
+typedef uint32_t elf_arm_gregset_t[ELF_ARM_NGREGS];
+
+typedef struct elf32_hdr {
+    unsigned char e_ident[EI_NIDENT];
+    Elf32_Half e_type;
+    Elf32_Half e_machine;
+    Elf32_Word e_version;
+    Elf32_Addr e_entry;
+    Elf32_Off e_phoff;
+    Elf32_Off e_shoff;
+    Elf32_Word e_flags;
+    Elf32_Half e_ehsize;
+    Elf32_Half e_phentsize;
+    Elf32_Half e_phnum;
+    Elf32_Half e_shentsize;
+    Elf32_Half e_shnum;
+    Elf32_Half e_shstrndx;
+} Elf64_Ehdr;
+
+typedef struct elf32_phdr {
+    Elf32_Word p_type;
+    Elf32_Off p_offset;
+    Elf32_Addr p_vaddr;
+    Elf32_Addr p_paddr;
+    Elf32_Word p_filesz;
+    Elf32_Word p_memsz;
+    Elf32_Word p_flags;
+    Elf32_Word p_align;
+} Elf32_Phdr;
+
+typedef struct elf_note {
+    Elf32_Word   n_namesz;       /* Name size */
+    Elf32_Word   n_descsz;       /* Content size */
+    Elf32_Word   n_type;         /* Content type */
+} Elf_Nhdr;
+
+struct elf32_timeval {
+    int32_t tv_sec;
+    int32_t tv_usec;
+};
+
+struct elf_siginfo {
+    int32_t si_signo;
+    int32_t si_code;
+    int32_t si_errno;
+};
+
+struct elf32_arm_prstatus {
+    struct elf_siginfo pr_info;
+    short pr_cursig;
+    uint32_t pr_sigpend;
+    uint32_t pr_sighold;
+
+    int32_t pr_pid;
+    int32_t pr_ppid;
+    int32_t pr_pgrp;
+
+    int32_t pr_sid;
+    struct elf32_timeval pr_utime;
+    struct elf32_timeval pr_stime;
+    struct elf32_timeval pr_cutime;
+    struct elf32_timeval pr_cstime;
+
+    elf_arm_gregset_t pr_reg;
+
+    int32_t pr_fpvalid;
+};
+
+struct elf32_prpsinfo {
+    char pr_state;
+    char pr_sname;
+    char pr_zomb;
+    char pr_nice;
+    uint32_t pr_flag;
+
+    uint16_t pr_uid;
+    uint16_t pr_gid;
+
+    int32_t pr_pid;
+    int32_t pr_ppid;
+    int32_t pr_pgrp;
+    int32_t pr_sid;
+
+    char pr_fname[16];
+    char pr_psargs[ELF_PRARGSZ];
+};
+
+#endif /* __KDUMP_ELF_H__ */
diff --git a/src/bsp/lk/lib/aee/include/mrdump_elf64.h b/src/bsp/lk/lib/aee/include/mrdump_elf64.h
new file mode 100644
index 0000000..4ab22a6
--- /dev/null
+++ b/src/bsp/lk/lib/aee/include/mrdump_elf64.h
@@ -0,0 +1,118 @@
+/*
+ * Copyright (c) 2018 MediaTek Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#if !defined(__MRDUMP_ELF64_H__)
+#define __MRDUMP_ELF64_H__
+
+#include <stdint.h>
+#include "mrdump_elf_common.h"
+
+#define ELF_ARM64_NGREGS 34
+typedef uint64_t elf_arm64_gregset_t[ELF_ARM64_NGREGS];
+
+typedef struct elf64_hdr {
+    unsigned char e_ident[EI_NIDENT];
+    Elf64_Half e_type;
+    Elf64_Half e_machine;
+    Elf64_Word e_version;
+    Elf64_Addr e_entry;
+    Elf64_Off e_phoff;
+    Elf64_Off e_shoff;
+    Elf64_Word e_flags;
+    Elf64_Half e_ehsize;
+    Elf64_Half e_phentsize;
+    Elf64_Half e_phnum;
+    Elf64_Half e_shentsize;
+    Elf64_Half e_shnum;
+    Elf64_Half e_shstrndx;
+} Elf64_ehdr;
+
+typedef struct elf64_phdr {
+    Elf64_Word p_type;
+    Elf64_Word p_flags;
+    Elf64_Off p_offset;
+    Elf64_Addr p_vaddr;
+    Elf64_Addr p_paddr;
+    Elf64_Xword p_filesz;
+    Elf64_Xword p_memsz;
+    Elf64_Xword p_align;
+} Elf64_phdr;
+
+typedef struct elf64_note {
+    Elf64_Word    n_namesz;   /* Name size */
+    Elf64_Word    n_descsz;   /* Content size */
+    Elf64_Word    n_type;     /* Content type */
+} Elf64_nhdr;
+
+struct elf_timeval64 {
+    int64_t tv_sec;
+    int64_t tv_usec;
+};
+
+struct elf_siginfo {
+    int64_t si_signo;
+    int64_t si_code;
+    int64_t si_errno;
+};
+
+struct elf_arm64_prstatus64 {
+    struct elf_siginfo pr_info;
+    short pr_cursig;
+    uint64_t pr_sigpend;
+    uint64_t pr_sighold;
+
+    int32_t pr_pid;
+    int32_t pr_ppid;
+    int32_t pr_pgrp;
+
+    int32_t pr_sid;
+    struct elf_timeval64 pr_utime;
+    struct elf_timeval64 pr_stime;
+    struct elf_timeval64 pr_cutime;
+    struct elf_timeval64 pr_cstime;
+
+    elf_arm64_gregset_t pr_reg;
+
+    int64_t pr_fpvalid;
+};
+
+struct elf_prpsinfo64 {
+    char pr_state;
+    char pr_sname;
+    char pr_zomb;
+    char pr_nice;
+    uint64_t pr_flag;
+
+    uint32_t pr_uid;
+    uint32_t pr_gid;
+
+    int32_t pr_pid;
+    int32_t pr_ppid;
+    int32_t pr_pgrp;
+    int32_t pr_sid;
+
+    char pr_fname[16];
+    char pr_psargs[ELF_PRARGSZ];
+};
+
+#endif /* __MRDUMP_ELF64_H__ */
diff --git a/src/bsp/lk/lib/aee/include/mrdump_elf_common.h b/src/bsp/lk/lib/aee/include/mrdump_elf_common.h
new file mode 100644
index 0000000..10d9d23
--- /dev/null
+++ b/src/bsp/lk/lib/aee/include/mrdump_elf_common.h
@@ -0,0 +1,144 @@
+/*
+ * Copyright (c) 2018 MediaTek Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#if !defined(__MRDUMP_ELF_COMMON_H__)
+#define __MRDUMP_ELF_COMMON_H__
+
+#define ELFMAG      "\177ELF"
+#define SELFMAG     4
+
+#define CORE_STR "CORE"
+
+#ifndef ELF_CORE_EFLAGS
+#define ELF_CORE_EFLAGS 0
+#endif
+
+#define EI_NIDENT   16
+
+#define EI_CLASS    4
+#define EI_DATA     5
+#define EI_VERSION  6
+#define EI_OSABI    7
+#define EI_PAD      8
+
+#define EM_ARM 40
+#define EM_AARCH64 183
+
+#define ET_CORE 4
+
+#define PT_LOAD 1
+#define PT_NOTE 4
+
+#define ELFCLASS32 1
+#define ELFCLASS64 2
+
+#define NT_PRSTATUS 1
+#define NT_PRFPREG 2
+#define NT_PRPSINFO 3
+/* MRDUMP support note type */
+#define NT_MRDUMP_MACHDESC 0xAEE0
+#define NT_MRDUMP_CBLOCK 0xBEEF
+
+
+#define PF_R 0x4
+#define PF_W 0x2
+#define PF_X 0x1
+
+#define ELFOSABI_NONE 0
+
+#define EV_CURRENT 1
+
+#define ELFDATA2LSB 1
+
+#define ELF_PRARGSZ 80
+
+#define MRDUMP_TYPE_FULL_MEMORY 0
+#define MRDUMP_TYPE_KERNEL_1 1
+#define MRDUMP_TYPE_KERNEL_2 2
+
+#define MRDUMP_TYPE_MASK 0x3
+
+typedef uint32_t Elf32_Addr;
+typedef uint16_t Elf32_Half;
+typedef uint32_t Elf32_Off;
+typedef int32_t Elf32_Sword;
+typedef uint32_t Elf32_Word;
+
+typedef uint64_t Elf64_Addr;
+typedef uint16_t Elf64_Half;
+typedef uint64_t Elf64_Off;
+typedef uint32_t Elf64_Word;
+typedef uint64_t Elf64_Xword;
+
+static inline void mrdump_elf_setup_eident(unsigned char e_ident[EI_NIDENT], unsigned char elfclasz)
+{
+    dprintf(CRITICAL, "%s before memcpy\n", __func__);
+    memcpy(e_ident, ELFMAG, SELFMAG);
+    dprintf(CRITICAL, "%s after memcpy\n", __func__);
+    e_ident[EI_CLASS] = elfclasz;
+    e_ident[EI_DATA] = ELFDATA2LSB;
+    e_ident[EI_VERSION] = EV_CURRENT;
+    e_ident[EI_OSABI] = ELFOSABI_NONE;
+    memset(e_ident+EI_PAD, 0, EI_NIDENT-EI_PAD);
+}
+
+#define mrdump_elf_setup_elfhdr(elfp, machid, elfhdr_t, elfphdr_t, phdrcount)   \
+    elfp->e_type = ET_CORE;                     \
+    elfp->e_machine = machid;                   \
+    elfp->e_version = EV_CURRENT;                   \
+    elfp->e_entry = 0;                      \
+    elfp->e_phoff = sizeof(elfhdr_t);               \
+    elfp->e_shoff = 0;                      \
+    elfp->e_flags = ELF_CORE_EFLAGS;                \
+    elfp->e_ehsize = sizeof(elfhdr_t);              \
+    elfp->e_phentsize = sizeof(elfphdr_t);              \
+    elfp->e_phnum = phdrcount;                  \
+    elfp->e_shentsize = 0;                      \
+    elfp->e_shnum = 0;                      \
+    elfp->e_shstrndx = 0;                       \
+
+
+struct __attribute__((__packed__)) elf_mrdump_machdesc {
+    uint32_t flags;
+    uint32_t nr_cpus;
+
+    uint64_t phys_offset;
+    uint64_t total_memory;
+
+    uint64_t page_offset;
+    uint64_t high_memory;
+
+    uint64_t kimage_vaddr;
+
+    uint64_t modules_start;
+    uint64_t modules_end;
+
+    uint64_t vmalloc_start;
+    uint64_t vmalloc_end;
+
+    uint64_t master_page_table;
+
+    uint64_t dfdmem_pa;
+};
+
+#endif
diff --git a/src/bsp/lk/lib/aee/include/mt_emi_mpu.h b/src/bsp/lk/lib/aee/include/mt_emi_mpu.h
new file mode 100644
index 0000000..a91b13c
--- /dev/null
+++ b/src/bsp/lk/lib/aee/include/mt_emi_mpu.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2018 MediaTek Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef __MT_EMI_MPU_H__
+#define __MT_EMI_MPU_H__
+
+#define EMI_MPU_ALIGN_BITS  16
+#define EMI_MPU_DOMAIN_NUM  16
+#define EMI_MPU_REGION_NUM  32
+
+#define MAX_CH  2
+#define MAX_RK  2
+
+//#include <emi_mpu_v1.h>
+#include <emi_info_v1.h>
+
+#endif /* __MT_EMI_MPU_H__ */
diff --git a/src/bsp/lk/lib/aee/include/partition.h b/src/bsp/lk/lib/aee/include/partition.h
new file mode 100644
index 0000000..1760b68
--- /dev/null
+++ b/src/bsp/lk/lib/aee/include/partition.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2018 MediaTek Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef __PARTITION_H__
+#define __PARTITION_H__
+
+#include <platform/mmc_core.h>
+
+#define BIMG_HEADER_SZ              (0x800)
+#define MKIMG_HEADER_SZ             (0x200)
+
+#define PART_HDR_DATA_SIZE  512
+
+#define PART_KERNEL     "KERNEL"
+#define PART_ROOTFS     "ROOTFS"
+
+#define PART_MAGIC          0x58881688
+#define PART_EXT_MAGIC      0x58891689
+#define PART_MAX_COUNT      128
+#define PART_PRELOADER_SIZE (0x400)
+
+#define FRP_NAME        "frp"
+
+typedef union {
+    struct {
+        unsigned int magic;        /* partition magic */
+        unsigned int dsize;        /* partition data size */
+        char         name[32];     /* partition name */
+        unsigned int maddr;        /* partition memory address */
+        unsigned int mode;      /* maddr is counted from the beginning or end of RAM */
+        /* extension */
+        unsigned int ext_magic;    /* always EXT_MAGIC */
+        unsigned int hdr_size;     /* header size is 512 bytes currently, but may extend in the future */
+        unsigned int hdr_version;  /* see HDR_VERSION */
+        unsigned int img_type;     /* please refer to #define beginning with IMG_TYPE_ */
+        unsigned int img_list_end; /* end of image list? 0: this image is followed by another image 1: end */
+        unsigned int align_size;   /* image size alignment setting in bytes, 16 by default for AES encryption */
+        unsigned int dsize_extend; /* high word of image size for 64 bit address support */
+        unsigned int maddr_extend; /* high word of image load address in RAM for 64 bit address support */
+    } info;
+    unsigned char data[PART_HDR_DATA_SIZE];
+} part_hdr_t;
+#endif /* __PARTITION_H__ */
+
diff --git a/src/bsp/lk/lib/aee/include/plat_dbg_info.h b/src/bsp/lk/lib/aee/include/plat_dbg_info.h
new file mode 100644
index 0000000..5bb704a
--- /dev/null
+++ b/src/bsp/lk/lib/aee/include/plat_dbg_info.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2018 MediaTek Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef __PLAT_DBG_INFO_H__
+#define __PLAT_DBG_INFO_H__
+
+#define INFO_TYPE_MAX 3
+
+typedef struct {
+    unsigned int key;
+    unsigned int base;
+    unsigned int size;
+} dbg_info_in_bootargs;
+
+unsigned int get_dbg_info_base(unsigned int key);
+unsigned int get_dbg_info_size(unsigned int key);
+
+#endif
+
diff --git a/src/bsp/lk/lib/aee/include/ram_console.h b/src/bsp/lk/lib/aee/include/ram_console.h
new file mode 100644
index 0000000..689a434
--- /dev/null
+++ b/src/bsp/lk/lib/aee/include/ram_console.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2018 MediaTek Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef __RAM_CONSOLE_H__
+#define __RAM_CONSOLE_H__
+
+#include <kernel/vm.h>
+#include <platform/ram_console_def.h>
+#include <ram_console_common.h>
+
+#define SZLOG 8192
+char logbuf[SZLOG];
+int sLOG(const char *fmt, ...);
+
+#define LOG(fmt, ...)           \
+    do {    \
+        sLOG(fmt, ##__VA_ARGS__);       \
+        _dprintf(fmt, ##__VA_ARGS__); \
+    } while (0)
+
+#define LOGD(fmt, ...)              \
+    sLOG(fmt, ##__VA_ARGS__)
+
+#if WITH_KERNEL_VM
+    #define PA_TO_VA(pa) paddr_to_kvaddr(pa)
+#else
+    #define PA_TO_VA(pa) pa
+#endif
+
+#endif // #ifndef __RAM_CONSOLE_H__
diff --git a/src/bsp/lk/lib/aee/include/ram_console_common.h b/src/bsp/lk/lib/aee/include/ram_console_common.h
new file mode 100644
index 0000000..700701e
--- /dev/null
+++ b/src/bsp/lk/lib/aee/include/ram_console_common.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2018 MediaTek Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef __RAM_CONSOLE_COMMON_H__
+#define __RAM_CONSOLE_COMMON_H__
+
+enum AEE_EXP_TYPE_NUM {
+    AEE_EXP_TYPE_HWT = 1,
+    AEE_EXP_TYPE_KE = 2,
+    AEE_EXP_TYPE_NESTED_PANIC = 3,
+    AEE_EXP_TYPE_SMART_RESET = 4,
+    AEE_EXP_TYPE_HANG_DETECT = 5,
+    AEE_EXP_TYPE_LK_CRASH = 6,
+    AEE_EXP_TYPE_DM_VERITY_CORRUPTION = 7,
+};
+
+#define RAM_CONSOLE_EXP_TYPE_MAGIC 0xaeedead0
+#define RAM_CONSOLE_EXP_TYPE_DEC(exp_type) \
+    ((exp_type ^ RAM_CONSOLE_EXP_TYPE_MAGIC) < 16 ? exp_type ^ RAM_CONSOLE_EXP_TYPE_MAGIC : exp_type)
+
+void ram_console_init(void);
+int ram_console_get_wdt_status(unsigned int *);
+int ram_console_get_fiq_step(unsigned int *);
+int ram_console_get_exp_type(unsigned int *);
+int ram_console_set_exp_type(unsigned int exp_type);
+int ram_console_is_abnormal_boot(void);
+void ram_console_lk_save(unsigned int val, int index);
+void ram_console_reboot_reason_save(u32 rgu_status);
+void pl_ram_console_init(void);
+
+void ram_console_addr_size(unsigned long *addr, unsigned long *size);
+void ram_console_set_dump_step(unsigned int step);
+int ram_console_get_dump_step(void);
+bool ram_console_should_restore(unsigned char *ram_console_ptr);
+#ifdef MTK_PMIC_FULL_RESET
+bool ram_console_reboot_by_cold_reset(void);
+#endif
+#endif // #ifndef __RAM_CONSOLE_COMMON_H__
+
diff --git a/src/bsp/lk/lib/aee/kdump_aee.c b/src/bsp/lk/lib/aee/kdump_aee.c
new file mode 100644
index 0000000..3011e7b
--- /dev/null
+++ b/src/bsp/lk/lib/aee/kdump_aee.c
@@ -0,0 +1,39 @@
+/*

+ * Copyright (c) 2018 MediaTek Inc.

+ *

+ * Permission is hereby granted, free of charge, to any person obtaining

+ * a copy of this software and associated documentation files

+ * (the "Software"), to deal in the Software without restriction,

+ * including without limitation the rights to use, copy, modify, merge,

+ * publish, distribute, sublicense, and/or sell copies of the Software,

+ * and to permit persons to whom the Software is furnished to do so,

+ * subject to the following conditions:

+ *

+ * The above copyright notice and this permission notice shall be

+ * included in all copies or substantial portions of the Software.

+ *

+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,

+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF

+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.

+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY

+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,

+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE

+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

+ */

+

+#ifdef MTK_PMIC_FULL_RESET

+#include <platform/pmic.h>

+#else

+#include <platform/mtk_wdt.h>

+#endif

+

+void mrdump_reboot(void)

+{

+#ifdef MTK_PMIC_FULL_RESET

+    dprintf(ALWAYS, "[MINIDUMP]Ready for full pmic reset\n");

+    pmic_cold_reset();

+#else

+    dprintf(ALWAYS, "[MINIDUMP]Ready for reset\n");

+    mtk_arch_reset(1);

+#endif

+}

diff --git a/src/bsp/lk/lib/aee/kdump_ext4.c b/src/bsp/lk/lib/aee/kdump_ext4.c
new file mode 100644
index 0000000..3dc3c11
--- /dev/null
+++ b/src/bsp/lk/lib/aee/kdump_ext4.c
@@ -0,0 +1,408 @@
+/*
+ * Copyright (c) 2018 MediaTek Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include <lib/mempool.h>
+#include <lib/zlib.h>
+#include <malloc.h>
+#include <platform/mtk_wdt.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <string.h>
+
+#include "aee.h"
+#include "kdump.h"
+#include "kdump_sdhc.h"
+#include "lib/cksum.h"
+
+#define BLKSIZE         4096
+#define MAX_CONTINUE    16                      // only 1MB memory for lk
+#define EXSPACE         (BLKSIZE*MAX_CONTINUE)  // Expect continue space
+
+uint64_t lba_marker_time;
+struct __attribute__((__packed__)) marked_block_data {
+    uint32_t lba;
+    uint64_t zero_padding[510];
+    uint64_t timestamp;
+    uint32_t crc;
+} bdata;
+
+struct mrdump_lba_handle {
+    struct mrdump_dev *dumpdev;
+    uint64_t allocsize;
+    uint64_t filesize;
+    unsigned int wlba;
+    unsigned int rlba;
+    int bidx;
+    int midx;
+    unsigned int blknum;
+    unsigned int block_lba[1024];
+    uint8_t data[EXSPACE];
+};
+
+static uint64_t ext4_lba_to_block_offset(uint32_t lba)
+{
+    return (uint64_t)lba * (uint64_t)BLKSIZE;
+}
+
+#ifdef MTK_USERIMAGES_USE_F2FS
+static bool check_block_valid(const struct mrdump_lba_handle *handle, uint32_t lba)
+{
+    mtk_wdt_restart();
+    if (!handle->dumpdev->read(handle->dumpdev, ext4_lba_to_block_offset(lba), (uint8_t *)&bdata, BLKSIZE)) {
+        voprintf_error(" Read BlockData failed\n");
+        return false;
+    }
+
+    if (bdata.lba != lba) {
+        voprintf_error(" Read BlockData LBA failed (c:%08x, v:%08x)\n", bdata.lba, lba);
+        return false;
+    }
+
+    if (bdata.timestamp != lba_marker_time) {
+        voprintf_error(" Read BlockData timestamp failed (c:%016x, v:%016x)\n", bdata.timestamp, lba_marker_time);
+        return false;
+    }
+
+    unsigned int crcval = crc32(0, Z_NULL, 0);
+    crcval = crc32(crcval, (void *)&bdata, (BLKSIZE - 4));
+    if (bdata.crc != crcval) {
+        voprintf_error("%s: Get BlockData crc32 error (c:%08x, v:%08x)\n", __func__, crcval, bdata.crc);
+        return false;
+    }
+
+    return true;
+}
+#endif
+
+static int Get_Next_bidx(struct mrdump_lba_handle *handle, unsigned int moves)
+{
+    unsigned int mycrc;
+
+    if (handle->bidx == 1022) {
+        handle->rlba = handle->block_lba[handle->bidx];
+        if (!handle->dumpdev->read(handle->dumpdev, ext4_lba_to_block_offset(handle->rlba), (uint8_t *)handle->block_lba, BLKSIZE)) {
+            voprintf_error(" SDCard: Reading BlockLBA failed.\n");
+            return -1;
+        }
+        // check crc32
+        mycrc = crc32(0, Z_NULL, 0);
+        mycrc = crc32(mycrc, (void *)handle->block_lba, (BLKSIZE-4));
+        if (mycrc != handle->block_lba[1023]) {
+            voprintf_error(" Get next index crc32 error!\n");
+            return -1;
+        }
+        handle->bidx = 0;
+    } else {
+        handle->bidx+=moves;
+    }
+    return handle->bidx;
+}
+
+unsigned int Num_to_Join(const struct mrdump_lba_handle *handle, unsigned int idx)
+{
+    unsigned int i, j;
+    uint32_t lba;
+
+    for (i=0, j=0; i<MAX_CONTINUE; i++) {
+        lba = handle->block_lba[idx+i];
+        if ((lba - handle->block_lba[idx]) == i) {
+            mtk_wdt_restart();
+#ifdef MTK_USERIMAGES_USE_F2FS
+            if (!check_block_valid(handle, lba)) {
+                voprintf_error(" BlockData Verification failed\n");
+                return 0;
+            }
+#endif
+            j++;
+            continue;
+        }
+        break;
+    }
+    return j;
+}
+
+// Store data and write when buffer(handle's data) full
+// return left length to avoid recursive call. --> turn to for loop
+static int Do_Store_or_Write(struct mrdump_lba_handle *handle, uint8_t *buf, uint32_t Length)
+{
+    int total;
+    unsigned int leftspace, mylen, reval;
+
+    total = BLKSIZE * handle->blknum;
+    leftspace = total - handle->midx;
+
+    // Check Length
+    if (Length > leftspace) {
+        mylen = leftspace;
+        reval = Length - leftspace;
+    } else {
+        mylen = Length;
+        reval = 0;
+    }
+
+    // Store
+    while (mylen > 0) {
+        handle->data[handle->midx] = *buf;
+        handle->midx++;
+        buf++;
+        mylen--;
+    }
+
+    // Write
+    if (handle->midx == total) {
+        if (!handle->dumpdev->write(handle->dumpdev, ext4_lba_to_block_offset(handle->wlba), handle->data, total)) {
+            voprintf_error(" SDCard: Write dump data failed.\n");
+            return -1;
+        }
+        handle->bidx = Get_Next_bidx(handle, handle->blknum);
+        if (handle->bidx < 0) {
+            voprintf_error(" SDCard: Reading bidx failed.\n");
+            return -1;
+        }
+        if (handle->bidx == 1022) {
+            handle->bidx = Get_Next_bidx(handle, handle->blknum);
+            if (handle->bidx < 0) {
+                voprintf_error(" SDCard: Reading 1022 bidx failed.\n");
+                return -1;
+            }
+        }
+        handle->blknum = Num_to_Join(handle, handle->bidx);
+        if (handle->blknum == 0)
+            return -1;
+        handle->wlba = handle->block_lba[handle->bidx];
+        handle->midx = 0;
+    }
+    return reval;
+}
+
+static int lba_write_cb(void *opaque_handle, void *buf, int size)
+{
+    unsigned int    len, moves;
+    int             ret;
+    uint8_t         *Ptr;
+
+    struct mrdump_lba_handle *handle = opaque_handle;
+
+    if ((handle->filesize + size) > handle->allocsize) {
+        voprintf_error(" dump size > allocated size. file-size %lld allocate-size %lld\n", handle->filesize + size, handle->allocsize);
+        return -1;
+    }
+    handle->filesize += size;
+
+    // End of File, write the left Data in handle data buffer...
+    if ((buf == NULL) && (size == 0)) {
+        if (!handle->dumpdev->write(handle->dumpdev, ext4_lba_to_block_offset(handle->wlba), handle->data, handle->midx)) {
+            voprintf_error(" SDCard: Write dump data failed.\n");
+            return -1;
+        }
+        return 0;
+    }
+
+    // buf should not be NULL if not EOF
+    if (buf == NULL)
+        return -1;
+
+    // process of Store and write
+    len = size;
+    ret = len;
+    Ptr = (uint8_t *)buf;
+    while (1) {
+        ret = Do_Store_or_Write(handle, Ptr, len);
+        if (ret < 0) {
+            voprintf_error(" SDCard: Store and Write failed.\n");
+            return -1;
+        } else if (ret==0) {
+            break;
+        } else {
+            moves = len - ret;
+            Ptr  += moves;
+            len   = ret;
+        }
+    }
+    return size;
+}
+
+static inline uint16_t paf_version_extract(uint8_t pafinfo[MRDUMP_PAF_TOTAL_SIZE])
+{
+    return pafinfo[0] + (pafinfo[1] << 8);
+}
+
+static void dump_paf_info(uint8_t InfoLBA[MRDUMP_PAF_TOTAL_SIZE], const char *msg, ...)
+{
+    va_list ap;
+    va_start(ap, msg);
+    voprintf('E', msg, ap);
+    va_end(ap);
+
+    uint32_t paf_version = paf_version_extract(InfoLBA);
+    uint32_t paf_info_lba = *(uint32_t *)(InfoLBA + MRDUMP_PAF_INFO_LBA);
+    uint32_t paf_addr_lba = *(uint32_t *)(InfoLBA + MRDUMP_PAF_ADDR_LBA);
+    uint64_t paf_alloc_size = *(uint64_t *)(InfoLBA + MRDUMP_PAF_ALLOCSIZE);
+    uint64_t paf_coredump_size = *(uint64_t *)(InfoLBA + MRDUMP_PAF_COREDUMPSIZE);
+    uint64_t paf_timestamp = *(uint64_t *)(InfoLBA + MRDUMP_PAF_TIMESTAMP);
+    uint32_t paf_crc32 = *(uint32_t *)(InfoLBA + MRDUMP_PAF_CRC32);
+
+    voprintf_info(" pafile ver %u info-lba %u addr-lba %u alloc-size %llu coredump-size %llu timestamp %llx crc %x\n",
+                  paf_version, paf_info_lba, paf_addr_lba, paf_alloc_size, paf_coredump_size, paf_timestamp, paf_crc32);
+}
+
+int mrdump_ext4_output(const struct mrdump_control_block *mrdump_cb, const struct kzip_addlist *memlist, struct mrdump_dev *mrdump_dev)
+{
+    uint8_t InfoLBA[MRDUMP_PAF_TOTAL_SIZE];
+    unsigned int mycrc;
+
+    if (mrdump_dev == NULL) {
+        return -1;
+    }
+
+    voprintf_info("Output to EXT4 Partition %s\n", mrdump_dev->name);
+
+    // pre-work for ext4 LBA
+    bzero(InfoLBA, sizeof(InfoLBA));
+
+    // Error 1. InfoLBA starting address not available
+    if (mrdump_cb->output_fs_lbaooo == 0) {
+        voprintf_error(" Pre-Allocate has no LBA markers(lbaooo=%u). RAM-Dump stop!\n", mrdump_cb->output_fs_lbaooo);
+        return -1;
+    }
+    if (!mrdump_dev->read(mrdump_dev, ext4_lba_to_block_offset(mrdump_cb->output_fs_lbaooo), (uint8_t *)InfoLBA, sizeof(InfoLBA))) {
+        voprintf_error(" SDCard: Reading InfoLBA failed.\n");
+        return -1;
+    }
+
+    uint32_t paf_version = paf_version_extract(InfoLBA);
+    uint32_t paf_info_lba = *(uint32_t *)(InfoLBA + MRDUMP_PAF_INFO_LBA);
+    uint32_t paf_addr_lba = *(uint32_t *)(InfoLBA + MRDUMP_PAF_ADDR_LBA);
+    uint64_t paf_alloc_size = *(uint64_t *)(InfoLBA + MRDUMP_PAF_ALLOCSIZE);
+    uint64_t paf_coredump_size = *(uint64_t *)(InfoLBA + MRDUMP_PAF_COREDUMPSIZE);
+    uint64_t paf_timestamp = *(uint64_t *)(InfoLBA + MRDUMP_PAF_TIMESTAMP);
+    uint32_t paf_info_crc32 = *(uint32_t *)(InfoLBA + MRDUMP_PAF_CRC32);
+
+    if (paf_version != MRDUMP_PAF_VERSION) {
+        dump_paf_info(InfoLBA, " Unsupport PAF version %d (expected: %d)\n", paf_version, MRDUMP_PAF_VERSION);
+        return -1;
+    }
+    // Error 3. InfoLBA[EXT4_1ST_LBA] should be mrdump_cb->output_fs_lbaooo
+    if (mrdump_cb->output_fs_lbaooo != paf_info_lba) {
+        dump_paf_info(InfoLBA, " LBA Starting Address Error(LBA0=%u)! Abort!\n", paf_info_lba);
+        return -1;
+    }
+
+    // Error 4. EXT4_CORE_DUMP_SIZE is not zero --> want to hold 1st dump
+    if (paf_coredump_size != 0) {
+        dump_paf_info(InfoLBA, " CORE DUMP SIZE is not Zero! Abort!(coresize=%llu)\n", paf_coredump_size);
+        return -1;
+    }
+
+    // Error 5. EXT4_USER_FILESIZE is zero
+    if (paf_alloc_size == 0) {
+        dump_paf_info(InfoLBA, " Allocate file with zero size. Abort!(filesize=%llu)\n", paf_alloc_size);
+        return -1;
+    }
+
+    // get lba_marker_time as timestamp
+    lba_marker_time = paf_timestamp;
+
+    // Error 2. CRC not matched
+    mycrc = crc32(0L, Z_NULL, 0);
+    mycrc = crc32(mycrc, (const unsigned char *)InfoLBA, sizeof(InfoLBA) - 4);
+    if (mycrc != paf_info_crc32) {
+        dump_paf_info(InfoLBA, " InfoLBA CRC32 Error! Abort! (CRC1=0x%08x, CRC2=0x%08x)\n", mycrc, paf_info_crc32);
+        return -1;
+    }
+
+    //struct mrdump_lba_handle *handle = memalign(16, sizeof(struct mrdump_lba_handle));
+    /* return is auto align to CACHE_LINE: which is 64 */
+    struct mrdump_lba_handle *handle = mempool_alloc(sizeof(struct mrdump_lba_handle), MEMPOOL_ANY);
+    if ((handle == NULL) || (((unsigned long long)handle) & 0xf)) {
+        voprintf_error("No enough memory or alloc memory not align 16B\n");
+        return -1;
+    }
+    memset(handle, 0, sizeof(struct mrdump_lba_handle));
+    handle->dumpdev = mrdump_dev;
+    handle->rlba = mrdump_cb->output_fs_lbaooo;
+    handle->allocsize = paf_alloc_size;
+
+    // Starting Dumping Data
+    handle->rlba = paf_addr_lba;
+    if (!handle->dumpdev->read(handle->dumpdev, ext4_lba_to_block_offset(handle->rlba), (uint8_t *)handle->block_lba, BLKSIZE)) {
+        dump_paf_info(InfoLBA, " SDCard: Reading BlockLBA error.\n");
+        mempool_free(handle);
+        return -1;
+    }
+    handle->wlba = handle->block_lba[handle->midx];
+    handle->blknum = Num_to_Join(handle, handle->bidx);
+    if (handle->blknum == 0) {
+        voprintf_error("No continuous space.\n");
+        mempool_free(handle);
+        return -1;
+    }
+
+    voprintf_info(" Pre-Allocate starts at LBA: %u\n", paf_info_lba);
+    voprintf_info(" SYS_COREDUMP starts at LBA: %u\n", handle->wlba);
+
+    mtk_wdt_restart();
+
+    bool ok = true;
+    mtk_wdt_restart();
+
+    struct kzip_file *zf = kzip_open(handle, lba_write_cb);
+    if (zf != NULL) {
+        if (!kzip_add_file(zf, memlist, "SYS_COREDUMP")) {
+            ok = false;
+        }
+        mtk_wdt_restart();
+        kzip_close(zf);
+        lba_write_cb(handle, NULL, 0); /* really write onto emmc of the last part */
+        zf = NULL;
+    } else {
+        ok = false;
+    }
+
+    if (!ok) {
+        mempool_free(handle);
+        return -1;
+    }
+
+    voprintf_info(" SYS_COREDUMP ends at LBA: %u\n", handle->wlba);
+    voprintf_info(" Zip COREDUMP size is: %u\n", handle->filesize);
+
+    // Record File Size...
+    *(uint64_t *)(InfoLBA + MRDUMP_PAF_COREDUMPSIZE) = handle->filesize;
+
+    mycrc = crc32(0L, Z_NULL, 0);
+    *(uint32_t *)(InfoLBA + MRDUMP_PAF_CRC32) = crc32(mycrc, (const unsigned char *)InfoLBA, MRDUMP_LBA_DATAONLY);
+    if (!handle->dumpdev->write(handle->dumpdev, ext4_lba_to_block_offset(paf_info_lba), (uint8_t *)InfoLBA, sizeof(InfoLBA))) {
+        voprintf_error(" SDCard: Write InfoLBA error.\n");
+        mempool_free(handle);
+        return -1;
+    }
+    mempool_free(handle);
+
+    mtk_wdt_restart();
+    mrdump_status_ok("OUTPUT:%s\nMODE:%s\n", "EXT4_DATA", mrdump_mode2string(mrdump_cb->crash_record.reboot_mode));
+    return 0;
+}
+
diff --git a/src/bsp/lk/lib/aee/kdump_null.c b/src/bsp/lk/lib/aee/kdump_null.c
new file mode 100644
index 0000000..8fdc7ad
--- /dev/null
+++ b/src/bsp/lk/lib/aee/kdump_null.c
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2018 MediaTek Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include <malloc.h>
+#include <platform/mtk_wdt.h>
+#include <stdint.h>
+#include <string.h>
+
+#include "aee.h"
+#include "kdump.h"
+
+static int null_write_cb(void *handle, void *buf, int size)
+{
+    return size;
+}
+
+int kdump_null_output(const struct mrdump_control_block *mrdump_cb, const struct kzip_addlist *memlist)
+{
+    voprintf_info("Output to null\n");
+    mtk_wdt_restart();
+
+    bool ok = true;
+    mtk_wdt_restart();
+    struct kzip_file *zf = kzip_open(NULL, null_write_cb);
+    if (zf != NULL) {
+        if (!kzip_add_file(zf, memlist, "SYS_COREDUMP"))
+            ok = false;
+        kzip_close(zf);
+        zf = NULL;
+    } else {
+        ok = false;
+    }
+    mtk_wdt_restart();
+    if (ok) {
+        mrdump_status_ok("NULL-OUTPUT\n");
+    }
+    return ok ? 0 : -1;
+}
diff --git a/src/bsp/lk/lib/aee/kdump_sd.c b/src/bsp/lk/lib/aee/kdump_sd.c
new file mode 100644
index 0000000..1ae6ffe
--- /dev/null
+++ b/src/bsp/lk/lib/aee/kdump_sd.c
@@ -0,0 +1,897 @@
+/*
+ * Copyright (c) 2018 MediaTek Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include <malloc.h>
+#include <platform/mtk_wdt.h>
+#include <stdint.h>
+#include <string.h>
+
+#include "aee.h"
+#include "kdump.h"
+#include "kdump_sdhc.h"
+
+#define PAGE_SIZE 4096
+
+#define DEVICE_SECTOR_BYTES 512
+
+FAT_Para m_bFATInfo;
+uint32_t m_bLastFATPage;
+struct aee_timer total_time;
+static struct mrdump_dev *dumpdev;
+
+LfnEntry g_LfnEntry = {
+    0x41,                               // sequence number
+    {'C','\0','E','\0','D','\0','u','\0','m','\0'},                     // name characters (five UTF-16 characters)
+    0x0F,                               // attributes (always 0x0F)
+    0x00,                               // reserved (alwyas 0x00)
+    0xDF,                               // checksum of DOS file name
+    {'p','\0','.','\0','k','\0','d','\0','m','\0','p','\0'},            // name characters (six UTF-16 characters)
+    0x0000,                             // word of first cluster (always 0x0000)
+    {'\0','\0',0xFF,0xFF}
+};
+
+DirEntry g_DirEntry = {
+    {'C','E','D','U','M','P','~','1','K','D','M'},              // name
+    0x20,                           // attr
+    0x00,                           // NTflags
+    0x00,                           // createdTimeMsec
+    0x63E8,                         // createdTime
+    0x2E21,                         // createdDate
+    0x2E21,                         // lastAccessDate
+    0x0000,                         // clusFirstHigh
+    0x6490,                         // time
+    0x2E21,                         // date
+    0x0000,                         // clusFirst
+    0x00000000                      // size
+};
+
+unsigned int OALGetTickCount(void)
+{
+    return 0 ;
+}
+
+static unsigned char ToLower(unsigned char c)
+{
+    if ((c >= 'A') && (c <= 'Z'))
+        return c+ 'a' - 'A';
+    else
+        return c;
+}
+
+static bool Compare_sd(const uint8_t *a, const uint8_t *b, int length)
+{
+    while (length--) {
+        if (ToLower(*a++) != ToLower(*b++))
+            return false;
+    }
+    return true;
+}
+
+static uint32_t BytesToNum_sd(uint8_t *b, int bytes)
+{
+    uint32_t result = 0;
+    int i;
+
+    for (i = 0; i < bytes; i++) {
+        result |= b[i] << (i << 3);
+    }
+    return result;
+}
+
+static bool fatfs_dev_read(struct mrdump_dev *dev, uint64_t sector_addr, uint8_t *pdBuf, int32_t blockLen)
+{
+    return dev->read(dev, sector_addr * DEVICE_SECTOR_BYTES, pdBuf, blockLen * DEVICE_SECTOR_BYTES);
+}
+
+static bool fatfs_dev_write(struct mrdump_dev *dev, uint64_t sector_addr, uint8_t *pdBuf, int32_t blockLen)
+{
+    return dev->write(dev, sector_addr * DEVICE_SECTOR_BYTES, pdBuf, blockLen * DEVICE_SECTOR_BYTES);
+}
+
+static void fatfs_commit_fat_entry(FileHandler *pFileHandler, int fat_offset, uint32_t value)
+{
+    if (m_bFATInfo.FileSysType == FAT_32) {
+        pFileHandler->FATBuffer[fat_offset * 4] = (value) & 0xff;
+        pFileHandler->FATBuffer[fat_offset * 4 + 1] = (value >> 8) & 0xff;
+        pFileHandler->FATBuffer[fat_offset * 4 + 2] = (value >> 16) & 0xff;
+        pFileHandler->FATBuffer[fat_offset * 4 + 3] = (value >> 24) & 0xff;
+    } else {
+        pFileHandler->FATBuffer[fat_offset * 2] = (value) & 0xff;
+        pFileHandler->FATBuffer[fat_offset * 2 + 1] = (value >> 8) & 0xff;
+    }
+}
+
+uint32_t FindBootPartition_sd(uint8_t *SectorBuffer)
+{
+    uint32_t PartitionStart;
+    uint32_t PartitionTpye;
+    PartitionTpye = BytesToNum_sd(SectorBuffer + 0x1c2, 1);
+    PartitionStart = BytesToNum_sd(SectorBuffer + 0x1c6, 4);
+
+    voprintf_debug("SDCard: PartitionStart=0x%x ,PartitionTpye=0x%x\n", PartitionStart, PartitionTpye);
+    if (PartitionTpye == 5) {
+        if (!fatfs_dev_read(dumpdev, PartitionStart,SectorBuffer,1)) {
+            voprintf_debug("SDCard: can not find BootPosition! \n");
+            return 0;
+        }
+        PartitionStart += BytesToNum_sd(SectorBuffer + 0x1c6, 4);
+        voprintf_debug("SDCard: PartitionStart=0x%x\n", PartitionStart);
+    }
+    return PartitionStart;
+}
+
+bool ReadBootPartition_sd(uint8_t *SectorBuffer)
+{
+    m_bFATInfo.BPB_BytsPerSec = BytesToNum_sd(SectorBuffer+11, 2);
+    m_bFATInfo.BPB_SecPerClus = BytesToNum_sd(SectorBuffer+13, 1);
+    m_bFATInfo.BPB_RsvdSecCnt = BytesToNum_sd(SectorBuffer+14, 2);
+    m_bFATInfo.BPB_NumFATs = BytesToNum_sd(SectorBuffer+16, 1);
+    m_bFATInfo.BPB_FATSz = BytesToNum_sd(SectorBuffer+22, 2);
+    if (m_bFATInfo.BPB_FATSz) {
+        m_bFATInfo.FileSysType = FAT_16;
+        m_bFATInfo.BPB_RootEntCnt = BytesToNum_sd(SectorBuffer+17, 2);
+        m_bFATInfo.BPB_TotSec = BytesToNum_sd(SectorBuffer+19, 2);
+        m_bFATInfo.BPB_RootClus = 0;
+        voprintf_debug("SDCard: FilSysType = FAT16\n");
+    } else {
+        m_bFATInfo.FileSysType = FAT_32;
+        m_bFATInfo.BPB_TotSec = BytesToNum_sd(SectorBuffer+32, 4);
+        m_bFATInfo.BPB_FATSz = BytesToNum_sd(SectorBuffer+36, 4);
+        m_bFATInfo.BPB_RootEntCnt = 0;
+        m_bFATInfo.BPB_RootClus = BytesToNum_sd(SectorBuffer+44, 4);
+        voprintf_debug("SDCard: FilSysType = FAT32\n");
+    }
+
+    voprintf_debug("SDCard: BPB_BytsPerSec = 0x%04x\n", m_bFATInfo.BPB_BytsPerSec);
+    voprintf_debug("SDCard: BPB_SecPerClus = 0x%02x\n", m_bFATInfo.BPB_SecPerClus);
+    voprintf_debug("SDCard: BPB_RsvdSecCnt = 0x%04x\n", m_bFATInfo.BPB_RsvdSecCnt);
+    voprintf_debug("SDCard: BPB_NumFATs = 0x%02x\n", m_bFATInfo.BPB_NumFATs);
+    voprintf_debug("SDCard: BPB_FATSz = 0x%08x\n", m_bFATInfo.BPB_FATSz);
+    voprintf_debug("SDCard: BPB_RootClus = 0x%08x\n", m_bFATInfo.BPB_RootClus);
+    voprintf_debug("SDCard: BPB_TotSec = 0x%08x\n", m_bFATInfo.BPB_TotSec);
+
+    if ((PAGE_SIZE > m_bFATInfo.BPB_SecPerClus * m_bFATInfo.BPB_BytsPerSec) ||
+            ((m_bFATInfo.BPB_SecPerClus * m_bFATInfo.BPB_BytsPerSec) % PAGE_SIZE != 0)) {
+        voprintf_error("Can't support SDCard cluster bytes %d\n", m_bFATInfo.BPB_SecPerClus * m_bFATInfo.BPB_BytsPerSec);
+        return false;
+    }
+    return true;
+}
+
+static bool Block0_is_BootSector(uint8_t *Ptr)
+{
+    uint32_t BytesPerSec = 0;
+    uint32_t SecPerClus = 0;
+    uint32_t BPB_Media = 0;
+
+    BytesPerSec = BytesToNum_sd(Ptr + 11, 2);
+    if (!((BytesPerSec == 512)||(BytesPerSec == 1024)||(BytesPerSec == 2048)||(BytesPerSec == 4096))) {
+        voprintf_error("Unsupport sector size %d\n", BytesPerSec);
+        return false;
+    }
+    SecPerClus = BytesToNum_sd(Ptr + 13, 1);
+    if (!((SecPerClus == 1)||(SecPerClus == 2)||(SecPerClus == 4)||
+            (SecPerClus == 8)||(SecPerClus == 16)||(SecPerClus == 32)||
+            (SecPerClus == 64)||(SecPerClus == 128)) &&
+            (SecPerClus * BytesPerSec <= 0x10000)) {
+        voprintf_error("Unsupport cluster size %d\n", SecPerClus);
+        return false;
+    }
+    BPB_Media = BytesToNum_sd(Ptr + 21, 1);
+    if (!((BPB_Media == 0xF8)||(BPB_Media == 0xF0)||(BPB_Media == 0xF9)||
+            (BPB_Media == 0xFA)||(BPB_Media == 0xFB)||(BPB_Media == 0xFC)||
+            (BPB_Media == 0xFD)||(BPB_Media == 0xFE)||(BPB_Media == 0xFF))) {
+        voprintf_error("Unsupport media descriptor %d\n", BPB_Media);
+        return false;
+    }
+
+    return true;
+}
+
+bool GetBPBInfo_sd(uint8_t *Ptr)
+{
+    m_bFATInfo.BPB_BytsPerSec = 512;
+    m_bFATInfo.BootStartSec = 0;
+
+    //*pSectorPosition
+    if (!fatfs_dev_read(dumpdev, m_bFATInfo.BootStartSec, Ptr, 1)) {
+        voprintf_error("SDCard: can not find MBR\n");
+        return false;
+    }
+
+    // Add support block0 is bootPartition
+    if (Block0_is_BootSector(Ptr)) {
+        m_bFATInfo.BootStartSec = 0;
+    } else {
+        m_bFATInfo.BootStartSec  = FindBootPartition_sd(Ptr);
+        if (!fatfs_dev_read(dumpdev, m_bFATInfo.BootStartSec, Ptr, 1)) {
+            voprintf_error("SDCard: can't find BootPosition\n");
+            mrdump_status_error("SDCard: can't find BootPosition\n");
+            return false;
+        }
+        if (!Block0_is_BootSector(Ptr)) {
+            voprintf_error("SDCard: BPB sector dismatch FAT Spec\n");
+            mrdump_status_error("SDCard: BPB sector dismatch FAT Spec\n");
+            return false;
+        }
+    }
+    if (!ReadBootPartition_sd(Ptr)) {
+        voprintf_error("SDCard: can not Read BootPartition\n");
+        mrdump_status_error("SDCard: can not Read BootPartition\n");
+        return false;
+    }
+
+    m_bFATInfo.FATStartSec = m_bFATInfo.BootStartSec + m_bFATInfo.BPB_RsvdSecCnt;
+
+    if (m_bFATInfo.FileSysType == FAT_32) {
+        m_bFATInfo.ClusStartSec = m_bFATInfo.FATStartSec+(m_bFATInfo.BPB_NumFATs)*(m_bFATInfo.BPB_FATSz);
+        m_bFATInfo.RootDirStartSec = m_bFATInfo.ClusStartSec + (m_bFATInfo.BPB_RootClus-2)*(m_bFATInfo.BPB_SecPerClus);
+    } else {
+        m_bFATInfo.RootDirStartSec = m_bFATInfo.FATStartSec+(m_bFATInfo.BPB_NumFATs)*(m_bFATInfo.BPB_FATSz);
+        m_bFATInfo.ClusStartSec = m_bFATInfo.RootDirStartSec+32*m_bFATInfo.BPB_RootEntCnt/m_bFATInfo.BPB_BytsPerSec;
+    }
+
+    return true;
+}
+
+uint32_t FindFirstClusInFAT_sd(uint32_t StartClusNum, uint8_t *Ptr)
+{
+    uint32_t SectorNum;
+    uint32_t NextClusterPosition;
+    uint32_t BytsPerFAT;
+    uint32_t BytsPerAdd;
+    if (m_bFATInfo.FileSysType == FAT_32)
+        BytsPerAdd = 4;//FAT32
+    else
+        BytsPerAdd = 2;//FAT16
+
+    BytsPerFAT = m_bFATInfo.BPB_BytsPerSec/BytsPerAdd;
+
+    m_bLastFATPage = StartClusNum/BytsPerFAT;
+    SectorNum = m_bFATInfo.FATStartSec+m_bLastFATPage;
+#ifdef SD_DATA_PRINT
+    voprintf_verbose("SDCard: now FATSec = %d \n",SectorNum);
+#endif
+    if (!fatfs_dev_read(dumpdev, SectorNum, Ptr, 1)) {
+        voprintf_error("SDCard: can not FindFirstClusInFAT_sd\n");
+        // FIXME: this is not right, why return 0?
+        return 0;
+    }
+
+    NextClusterPosition = BytesToNum_sd(Ptr+BytsPerAdd * (StartClusNum%BytsPerFAT), BytsPerAdd);
+#ifdef SD_DATA_PRINT
+    voprintf_verbose("SDCard: NextClusterPosition = %08x\n", NextClusterPosition);
+#endif
+    return NextClusterPosition;
+}
+
+uint32_t FindNextClusInFAT_sd(uint32_t StartClusNum, uint8_t *Ptr)
+{
+    uint32_t SectorNum;
+    uint32_t NextClusterPosition;
+    uint32_t BytsPerFAT;
+    uint32_t BytsPerAdd;
+    uint32_t TempPage;
+    if (m_bFATInfo.FileSysType==FAT_32)
+        BytsPerAdd = 4;//FAT32
+    else
+        BytsPerAdd = 2;//FAT16
+
+    BytsPerFAT = m_bFATInfo.BPB_BytsPerSec/BytsPerAdd;
+    TempPage = StartClusNum/BytsPerFAT;
+    if (TempPage!=m_bLastFATPage) {
+        SectorNum = m_bFATInfo.FATStartSec+TempPage;
+#ifdef SD_DATA_PRINT
+        DBGKDUMP_PRINTK("SDCard: now FATSec = %d \n",SectorNum);
+#endif
+        if (!fatfs_dev_read(dumpdev, SectorNum,Ptr,1)) {
+            voprintf_error("SDCard: can not FindNextClusInFAT_sd! \n");
+            // FIXME: this is not right, why return 0?
+            return 0;
+        }
+        m_bLastFATPage=TempPage;
+#if 0
+        for (j=0; j<(int)m_bFATInfo.BPB_BytsPerSec; j++) {
+            if ((j%16)==0) DBGKDUMP_PRINTK("i= 0x%04x    ",j);
+            DBGKDUMP_PRINTK(" %02x ", Ptr[j]);
+            if (((j+1)%16)==0) DBGKDUMP_PRINTK("     i= %d\n",j);
+        }
+#endif
+    }
+    NextClusterPosition=BytesToNum_sd(Ptr+BytsPerAdd*(StartClusNum%BytsPerFAT),BytsPerAdd);
+#ifdef SD_DATA_PRINT
+    DBGKDUMP_PRINTK("SDCard: NextClusterPosition = %08x \n",NextClusterPosition);
+#endif
+    return NextClusterPosition;
+}
+
+uint32_t FindFirstFreeClusInFAT_sd(FileHandler *pFileHandler)
+{
+    uint32_t i;
+    uint32_t SectorNum;
+    uint32_t FreeClusterNum;
+    uint32_t value;
+    uint32_t FATSector, FATOffset;
+    uint32_t EntryPerSector;
+    uint32_t BytsPerAdd;
+
+    if (m_bFATInfo.FileSysType==FAT_32)
+        BytsPerAdd = 4;//FAT32
+    else
+        BytsPerAdd = 2;//FAT16
+
+    FreeClusterNum = 0;
+    EntryPerSector = m_bFATInfo.BPB_BytsPerSec/BytsPerAdd;
+    FATSector = pFileHandler->CurrClusterNum/EntryPerSector;
+    FATOffset = pFileHandler->CurrClusterNum%EntryPerSector + 1;     // start search frome next cluster
+
+    // for safty, we don't use all FAT entries, just reserve the last FAT sector
+    while (FATSector < (m_bFATInfo.BPB_FATSz-1)) {
+        // Read new FAT sector to cache
+        SectorNum = m_bFATInfo.FATStartSec+FATSector;
+        if (!fatfs_dev_read(dumpdev, SectorNum, pFileHandler->FATBuffer, 1)) {
+            voprintf_error("SDCard: %s read failed\n", __func__);
+            return 0;
+        }
+
+        for (i=FATOffset; i<EntryPerSector; i++) {
+            value = BytesToNum_sd(pFileHandler->FATBuffer+i*BytsPerAdd, BytsPerAdd);
+            if (value == 0) {
+                FreeClusterNum = FATSector*EntryPerSector + i;  // found free entry in FAT
+                pFileHandler->FATSector = FATSector;
+                return FreeClusterNum;
+            }
+        }
+        // try next FAT sector
+        FATSector++;
+        FATOffset = 0;
+    }
+
+    return 0;
+}
+
+uint32_t ChainFreeClusInFAT_sd(FileHandler *pFileHandler)
+{
+    uint32_t i;
+    uint32_t SectorNum;
+    uint32_t FreeClusterNum;
+    uint32_t value;
+    uint32_t CurrFATSector, CurrFATOffset;
+    uint32_t NextFATSector, NextFATOffset;
+    uint32_t EntryPerSector;
+    uint32_t BytsPerAdd;
+    uint8_t  TempFAT[512];
+    uint8_t  *pBuf;
+
+    if (m_bFATInfo.FileSysType==FAT_32)
+        BytsPerAdd = 4;//FAT32
+    else
+        BytsPerAdd = 2;//FAT16
+
+    FreeClusterNum = 0;
+    EntryPerSector = m_bFATInfo.BPB_BytsPerSec/BytsPerAdd;
+    CurrFATSector = pFileHandler->CurrClusterNum/EntryPerSector;
+    CurrFATOffset = pFileHandler->CurrClusterNum%EntryPerSector;
+    NextFATSector = CurrFATSector;
+    NextFATOffset = CurrFATOffset+1;    // start search frome next cluster
+    memset(TempFAT,0,512);
+
+    pBuf = pFileHandler->FATBuffer;
+    // for safty, we don't use all FAT entries, just reserve the last FAT sector
+    while (NextFATSector < (m_bFATInfo.BPB_FATSz-1)) {
+        if (NextFATSector != pFileHandler->FATSector) {
+            // FAT sector changed, read new FAT sector to temp buffer
+            pBuf = TempFAT;
+            SectorNum = m_bFATInfo.FATStartSec+NextFATSector;
+            if (!fatfs_dev_read(dumpdev, SectorNum, pBuf, 1)) {
+                voprintf_error("SDCard: %s read failed\n", __func__);
+                return 0;
+            }
+        }
+        // find free cluster in FAT cache
+        for (i=NextFATOffset; i<EntryPerSector; i++) {
+            value = BytesToNum_sd(pBuf+i*BytsPerAdd, BytsPerAdd);
+            if (value == 0) {
+                FreeClusterNum = NextFATSector*EntryPerSector + i;  // found free entry in FAT
+                // commit FAT entry
+                fatfs_commit_fat_entry(pFileHandler, CurrFATOffset, FreeClusterNum);
+                break;
+            }
+        }
+
+        if (FreeClusterNum!=0) {
+            break;
+        }
+
+        // try next FAT sector
+        NextFATSector++;
+        NextFATOffset = 0;
+    }
+
+    // check if need to refresh cache
+    if ((FreeClusterNum != 0) && (NextFATSector != pFileHandler->FATSector)) {
+        // FAT sector changed, flush cache to SD
+        SectorNum = m_bFATInfo.FATStartSec+CurrFATSector;
+        if (!fatfs_dev_write(dumpdev, SectorNum, pFileHandler->FATBuffer, 1)) {
+            voprintf_error("SDCard: %s write failed\n", __func__);
+            return 0;
+        }
+
+        // copy temp buffer to cache
+        memcpy(pFileHandler->FATBuffer, TempFAT, 512);
+        pFileHandler->FATSector = NextFATSector;
+    }
+
+    return FreeClusterNum;
+}
+
+bool MarkEndClusInFAT_sd(FileHandler *pFileHandler)
+{
+    uint32_t SectorNum;
+    uint32_t BytsPerAdd;
+    uint32_t EntryPerSector;
+    uint32_t FATSector;
+    uint32_t FATOffset;
+
+    if (m_bFATInfo.FileSysType==FAT_32)
+        BytsPerAdd = 4;//FAT32
+    else
+        BytsPerAdd = 2;//FAT16
+
+    EntryPerSector = m_bFATInfo.BPB_BytsPerSec/BytsPerAdd;
+    FATSector = pFileHandler->CurrClusterNum/EntryPerSector;
+    FATOffset = pFileHandler->CurrClusterNum%EntryPerSector;
+    SectorNum = m_bFATInfo.FATStartSec+FATSector;
+
+    if (FATSector != pFileHandler->FATSector) {
+        if (!fatfs_dev_read(dumpdev, SectorNum, pFileHandler->FATBuffer, 1)) {
+            voprintf_error("SDCard: MarkEndClusInFAT_sd dumpdev->read failed\n");
+            return false;
+        }
+    }
+
+    fatfs_commit_fat_entry(pFileHandler, FATOffset, 0xffffffff);
+
+    // flush FAT cache to SD
+    if (!fatfs_dev_write(dumpdev, SectorNum, pFileHandler->FATBuffer, 1)) {
+        voprintf_error("SDCard: MarkEndClusInFAT_sd dumpdev->write failed\n");
+        return false;
+    }
+    return true;
+}
+
+bool DeleteFileInFAT_sd(FileHandler *pFileHandler)
+{
+    uint32_t StartClusNum;
+    uint32_t SectorNum;
+    uint32_t NextClusNum;
+    uint32_t FATSector, FATOffset;
+    uint32_t EntryPerSector;
+    uint32_t BytsPerAdd;
+    bool NewSector = true;
+    bool LastEntry = false;
+
+    if (m_bFATInfo.FileSysType == FAT_32) {
+        BytsPerAdd = 4;//FAT32
+    } else {
+        BytsPerAdd = 2;//FAT16
+    }
+
+    EntryPerSector = m_bFATInfo.BPB_BytsPerSec/BytsPerAdd;
+    StartClusNum = pFileHandler->CurrClusterNum;
+    SectorNum = m_bFATInfo.FATStartSec+StartClusNum/EntryPerSector;
+
+    while (!LastEntry) {
+        FATSector = StartClusNum/EntryPerSector;
+        FATOffset = StartClusNum%EntryPerSector;
+
+        if (NewSector) {
+            SectorNum = m_bFATInfo.FATStartSec+FATSector;
+#ifdef SD_DATA_PRINT
+            DBGKDUMP_PRINTK("SDCard: now FATSec = %d \n",SectorNum);
+#endif
+            if (!fatfs_dev_read(dumpdev, SectorNum, pFileHandler->FATBuffer, 1)) {
+                voprintf_error("SDCard: DeleteFile_sd read failed\n");
+                return false;
+            }
+            NewSector = false;
+        }
+
+        NextClusNum = BytesToNum_sd(pFileHandler->FATBuffer+FATOffset*BytsPerAdd, BytsPerAdd);
+
+        fatfs_commit_fat_entry(pFileHandler, FATOffset, 0x0);
+        // Release FAT entry
+        if (m_bFATInfo.FileSysType==FAT_32) {
+
+            if ((NextClusNum >= 0xFFFFFF8) || (NextClusNum == 0)) {
+                LastEntry = true;
+            }
+        } else {
+            if ((NextClusNum >= 0xFFF8) || (NextClusNum == 0)) {
+                LastEntry = true;
+            }
+        }
+
+        if (NextClusNum/EntryPerSector != FATSector) {
+            NewSector = true;   // next cluster is not at current FAT Sector, write current FAT sector back
+        }
+
+        if (NewSector || LastEntry) {
+            if (!fatfs_dev_write(dumpdev, SectorNum, pFileHandler->FATBuffer, 1)) {
+                voprintf_error("SDCard: DeleteFile_sd write failed\n");
+                return false;
+            }
+        }
+
+        StartClusNum = NextClusNum;
+    }
+
+#ifdef SD_DATA_PRINT
+    DBGKDUMP_PRINTK("SDCard: NextClusterPosition = %08x \n",NextClusterPosition);
+#endif
+
+    return true;
+}
+
+static bool OpenDumpFile_sd(FileHandler *pFileHandler)
+{
+    int i, j, times;
+    uint32_t SectorNum;
+    uint32_t Temp;
+    uint32_t dwStartTick;
+    uint32_t FindFile_TIMEOUT = 60000;
+    int SecLen;
+    uint32_t NextRootFAT = 0;
+    uint8_t RootDirFAT[512];
+    bool foundLfn = false;
+
+    // init File Handler
+    memset(pFileHandler, 0, sizeof(FileHandler));
+    if (!GetBPBInfo_sd(pFileHandler->FileBuffer)) {
+        return false;
+    }
+
+    dwStartTick = OALGetTickCount();
+
+    voprintf_debug("SDCard: FATStartSec=%d RootdirStartSec=%d\n", m_bFATInfo.FATStartSec, m_bFATInfo.RootDirStartSec);
+    SectorNum = m_bFATInfo.RootDirStartSec;
+    if (m_bFATInfo.FileSysType == FAT_16) {
+        SecLen=32;
+        times=1;
+    } else {
+        SecLen = m_bFATInfo.BPB_SecPerClus;
+        times=MaxFindFileClusNum;
+    }
+
+    while (times) {
+        for (i = 0; i < SecLen; i++) {
+            if (!fatfs_dev_read(dumpdev, SectorNum, pFileHandler->FileBuffer, 1)) {
+                voprintf_error("SDCard: can not read RootDir!\n");
+                return false;
+            }
+
+            for (j=0; j<(int)m_bFATInfo.BPB_BytsPerSec; j+=32) {
+                if (foundLfn) {
+                    Temp = BytesToNum_sd(pFileHandler->FileBuffer+j+20, 2);
+                    pFileHandler->CurrClusterNum |= (Temp<<16);
+                    Temp = BytesToNum_sd(pFileHandler->FileBuffer+j+26, 2);
+                    pFileHandler->CurrClusterNum |= (Temp&0xFFFF);
+
+                    // delete file DIR entries
+                    memset(pFileHandler->FileBuffer+j, 0, 32);
+                    if (!fatfs_dev_write(dumpdev, SectorNum, pFileHandler->FileBuffer, 1)) {
+                        voprintf_error("SDCard: can not write directory entry!\n");
+                        return false;
+                    }
+                    // delete file in FAT entries
+                    if (!DeleteFileInFAT_sd(pFileHandler)) {
+                        voprintf_error("SDCard: can not delete file in FAT entries!\n");
+                        return false;
+                    }
+                    goto Done;
+                } else if (pFileHandler->FileBuffer[j] == 0x41 &&
+                           Compare_sd(pFileHandler->FileBuffer+j+1, g_LfnEntry.name1, 10) &&
+                           Compare_sd(pFileHandler->FileBuffer+j+14, g_LfnEntry.name2, 12)) {
+#if 0
+                    // delete LFN entries
+                    memset(pFileHandler->FileBuffer+j, 0, 32);
+                    if (!fatfs_dev_write(dumpdev, SectorNum, pFileHandler->FileBuffer, 1)) {
+                        voprintf_error("SDCard: can not write LFN entry!\n");
+                        return false;
+                    }
+                    foundLfn = true;
+#else
+                    voprintf_error("SDCard: dump file exist, skip dumping\n");
+                    mrdump_status_error("File exist at SDCARD, skip dumping\n");
+                    return false;
+#endif
+                }
+            }
+            SectorNum+=1;
+        }
+        if ((OALGetTickCount() - dwStartTick) >= FindFile_TIMEOUT) {
+            voprintf_error("SDCard: Find File timeout\n");
+            return false;
+        }
+        if (m_bFATInfo.FileSysType==FAT_32) {
+            if (times==MaxFindFileClusNum) {
+                NextRootFAT=FindFirstClusInFAT_sd(m_bFATInfo.BPB_RootClus, RootDirFAT);
+                if (NextRootFAT>=0xFFFFFF8) {
+                    break;
+                }
+            } else {
+                NextRootFAT=FindNextClusInFAT_sd(NextRootFAT, RootDirFAT);
+                if (NextRootFAT >= 0xFFFFFF8) {
+                    break;
+                }
+            }
+            voprintf_info("SDCard: NextRootFAT=0x%08x  \n", NextRootFAT);
+            SectorNum=m_bFATInfo.ClusStartSec + (NextRootFAT-2)*(m_bFATInfo.BPB_SecPerClus);
+        } else {
+            // FAT16
+            break;
+        }
+        times--;
+    }
+
+Done:
+    // return a free cluster to create new file
+    pFileHandler->CurrClusterNum = 2;
+    pFileHandler->CurrClusterNum = FindFirstFreeClusInFAT_sd(pFileHandler);
+    pFileHandler->PrevClusterNum = pFileHandler->CurrClusterNum;
+    g_DirEntry.clusFirstHigh = (uint16_t)((pFileHandler->CurrClusterNum >> 16) & 0xFFFF);
+    g_DirEntry.clusFirst = (uint16_t)(pFileHandler->CurrClusterNum & 0xFFFF);
+    if (!pFileHandler->CurrClusterNum) {
+        pFileHandler->DiskFull = true;
+        voprintf_error("SDCard full, not free space available at create file\n");
+        mrdump_status_error("SDCard full, not free space available at create file\n");
+        return false;
+    }
+
+    voprintf_debug("%s: ok\n", __func__);
+    return true;
+}
+
+bool UpdateDirectoryEntry_sd(FileHandler *pFileHandler)
+{
+    int i, j, times;
+    uint32_t SectorNum;
+    uint32_t dwStartTick;
+    uint32_t FindFile_TIMEOUT = 60000;
+    int SecLen;
+    uint32_t NextRootFAT = 0;
+    uint8_t RootDirFAT[512];
+
+    dwStartTick = OALGetTickCount();
+    voprintf_info("SDCard: FATStartSec = %d \n",m_bFATInfo.FATStartSec);
+    voprintf_info("SDCard: RootDirStartSec = %d \n", m_bFATInfo.RootDirStartSec);
+    SectorNum = m_bFATInfo.RootDirStartSec;
+
+    if (m_bFATInfo.FileSysType==FAT_16) {
+        SecLen=32;
+        times=1;
+    } else {
+        SecLen = m_bFATInfo.BPB_SecPerClus;
+        times=MaxFindFileClusNum;
+    }
+
+    while (times) {
+        for (i = 0; i < SecLen; i++) {
+            if (!fatfs_dev_read(dumpdev, SectorNum, pFileHandler->FileBuffer, 1)) {
+                voprintf_error("SDCard: can not read RootDir!\n");
+                return false;
+            }
+
+            for (j = 0; j < (int)(m_bFATInfo.BPB_BytsPerSec - 32); j += 32) {
+                if ((pFileHandler->FileBuffer[j] == 0x0 || pFileHandler->FileBuffer[j] == 0xE5) &&
+                        (pFileHandler->FileBuffer[j+32] == 0x0 || pFileHandler->FileBuffer[j+32] == 0xE5)) {
+                    memcpy(pFileHandler->FileBuffer+j, &g_LfnEntry, sizeof(LfnEntry));
+                    memcpy(pFileHandler->FileBuffer+j+32, &g_DirEntry, sizeof(DirEntry));
+
+                    if (!fatfs_dev_write(dumpdev, SectorNum, pFileHandler->FileBuffer, 1)) {
+                        voprintf_error("SDCard: can not read RootDir! \n");
+                        return false;
+                    }
+                    return true;
+                }
+            }
+            SectorNum += 1;
+        }
+        if ((OALGetTickCount() - dwStartTick) >= FindFile_TIMEOUT) {
+            voprintf_error("SDCard: Find File Error timeout\n");
+            return false;
+        }
+        if (m_bFATInfo.FileSysType==FAT_32) {
+            if (times == MaxFindFileClusNum) {
+                NextRootFAT=FindFirstClusInFAT_sd(m_bFATInfo.BPB_RootClus, RootDirFAT);
+                if (NextRootFAT>=0xFFFFFF8) {
+                    voprintf_error("SDCard: Dump file not exsited.\n");
+                    break;
+                }
+            } else {
+                NextRootFAT=FindNextClusInFAT_sd(NextRootFAT, RootDirFAT);
+                if (NextRootFAT>=0xFFFFFF8) {
+                    voprintf_error("SDCard: Dump file not exsited.\n");
+                    break;
+                }
+            }
+            voprintf_error("SDCard: NextRootFAT=0x%08x  \n", NextRootFAT);
+            SectorNum=m_bFATInfo.ClusStartSec + (NextRootFAT-2)*(m_bFATInfo.BPB_SecPerClus);
+        } else {
+            // FAT16
+            break;
+        }
+        times--;
+    }
+
+    return false;
+}
+
+static bool WriteDumpFile_sd(FileHandler *pFileHandler, uint8_t *Ptr, uint32_t Length, uint32_t Total)
+{
+    uint32_t i;
+    uint32_t SectorNum;
+    uint32_t FreeClusterNum;
+    uint8_t val;
+
+    uint32_t ClusterSize = m_bFATInfo.BPB_SecPerClus * m_bFATInfo.BPB_BytsPerSec;
+
+    while (Length > 0) {
+        // for every cluster boundary, check disk free space
+        if (pFileHandler->DiskFull) {
+            return false;
+        }
+
+        for (i = pFileHandler->BufferLen; (i < ClusterSize) && (Length > 0); i++) {
+            val = *Ptr++;
+            pFileHandler->FileBuffer[pFileHandler->BufferLen++] = val;
+            pFileHandler->CheckSum += val;
+            pFileHandler->TotalLen++;
+            Length--;
+        }
+
+        // a cluster collected, flush to SD
+        if (pFileHandler->BufferLen == ClusterSize) {
+            pFileHandler->BufferLen = 0;
+            SectorNum=m_bFATInfo.ClusStartSec + (pFileHandler->CurrClusterNum-2)*(m_bFATInfo.BPB_SecPerClus);
+            //DBGKDUMP_PRINTK("SDCard: WriteDumpFile_sd() write sd card from %d blocks!\n",SectorNum);
+
+            if (!fatfs_dev_write(dumpdev, SectorNum, pFileHandler->FileBuffer, m_bFATInfo.BPB_SecPerClus)) {
+                voprintf_error("SDCard: WriteDumpFile_sd() write file content from %d blocks failed!!!!\n",SectorNum);
+                return false;
+            }
+
+            pFileHandler->PrevClusterNum = pFileHandler->CurrClusterNum;
+            FreeClusterNum =  ChainFreeClusInFAT_sd(pFileHandler);
+            if (FreeClusterNum == 0) {
+                pFileHandler->DiskFull = true;
+                voprintf_error("SDcard full, no free space available\n");
+                mrdump_status_error("SDcard full, no free space available\n");
+                return false;
+            }
+            pFileHandler->CurrClusterNum =FreeClusterNum;
+        } else if (pFileHandler->BufferLen > ClusterSize) {
+            voprintf_error("SDCard: WriteDumpFile_sd() BufferLen error!\n");
+        }
+    }
+
+    return true;
+}
+
+static bool CloseDumpFile_sd(FileHandler *pFileHandler)
+{
+    uint32_t SectorNum;
+
+    g_DirEntry.size = pFileHandler->TotalLen;
+
+#if 0
+    uint16_t year;
+    g_DirEntry.createdTime = g_DirEntry.time = (((INREG16(&m_pRTCRegs->RTC_TC_HOU) << 11) & 0xF800) |
+                             ((INREG16(&m_pRTCRegs->RTC_TC_MIN) << 5) & 0x7E0) |
+                             ((INREG16(&m_pRTCRegs->RTC_TC_SEC)>>1) & 0x1F));
+    year = INREG16(&m_pRTCRegs->RTC_TC_YEA);
+    year = (year > 20) ? (year-20) : 0;
+    g_DirEntry.createdDate = g_DirEntry.date = (((year<<9) & 0xFE00) |
+                             ((INREG16(&m_pRTCRegs->RTC_TC_MTH)<<5) & 0x1E0) |
+                             (INREG16(&m_pRTCRegs->RTC_TC_DOM) & 0x1F));
+#endif
+    g_DirEntry.createdTime = g_DirEntry.time = 0;
+    g_DirEntry.createdDate = g_DirEntry.date = 0;
+
+    if (pFileHandler->BufferLen == 0) {
+        // the free cluster is not used, so that the last cluster should be the previous one
+        pFileHandler->CurrClusterNum = pFileHandler->PrevClusterNum;
+    } else if (!pFileHandler->DiskFull) {
+        // flush the reset data
+        SectorNum=m_bFATInfo.ClusStartSec + (pFileHandler->CurrClusterNum-2)*(m_bFATInfo.BPB_SecPerClus);
+        if (!fatfs_dev_write(dumpdev, SectorNum, pFileHandler->FileBuffer, m_bFATInfo.BPB_SecPerClus)) {
+            voprintf_error("SDCard: CloseFile_sd() write file content failed!\n");
+            return false;
+        }
+    }
+
+    if (!MarkEndClusInFAT_sd(pFileHandler)) {
+        voprintf_error("SDCard: CloseFile_sd() MarkEndClusInFAT_sd failed!\n");
+        return false;
+    }
+
+    if (!UpdateDirectoryEntry_sd(pFileHandler)) {
+        voprintf_error("SDCard: CloseFile_sd() UpdateDirectoryEntry_sd failed!\n");
+        return false;
+    }
+
+    return true;
+}
+
+static int sd_write_cb(void *handle, void *buf, int size)
+{
+    if (WriteDumpFile_sd(handle, buf, size, 0)) {
+        return size;
+    } else {
+        return 0;
+    }
+}
+
+int mrdump_vfat_output(const struct mrdump_control_block *mrdump_cb, const struct kzip_addlist *memlist, struct mrdump_dev *mrdump_dev)
+{
+    if (mrdump_dev == NULL) {
+        return -1;
+    }
+
+    dumpdev = mrdump_dev;
+    voprintf_info("Output to VFAT Partition %s\n", dumpdev->name);
+
+    FileHandler *file_handle = memalign(16, sizeof(FileHandler));
+    if (file_handle == NULL) {
+        voprintf_error("No enough memory.");
+        return -1;
+    }
+    memset(file_handle, 0, sizeof(FileHandler));
+
+    mtk_wdt_restart();
+    bool ok = true;
+    if (OpenDumpFile_sd(file_handle)) {
+        mtk_wdt_restart();
+        struct kzip_file *zf = kzip_open(file_handle, sd_write_cb);
+        if (zf != NULL) {
+            if (!kzip_add_file(zf, memlist, "SYS_COREDUMP")) {
+                ok = false;
+            }
+            kzip_close(zf);
+            zf = NULL;
+        } else {
+            ok = false;
+        }
+
+        mtk_wdt_restart();
+        CloseDumpFile_sd(file_handle);
+        free(file_handle);
+
+        if (ok) {
+            mrdump_status_ok("OUTPUT:%s\nMODE:%s\n", "VFAT_INT_STORAGE", mrdump_mode2string(mrdump_cb->crash_record.reboot_mode));
+        }
+    }
+
+    return ok ? 0 : -1;
+}
+
diff --git a/src/bsp/lk/lib/aee/kdump_usb.c b/src/bsp/lk/lib/aee/kdump_usb.c
new file mode 100644
index 0000000..d2a6b9a
--- /dev/null
+++ b/src/bsp/lk/lib/aee/kdump_usb.c
@@ -0,0 +1,265 @@
+/*
+ * Copyright (c) 2018 MediaTek Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#if !defined(__KDUMP_USB_C__)
+#define __KDUMP_USB_C__
+
+#include <mrdump.h>
+#include <malloc.h>
+#include <printf.h>
+#include <string.h>
+#include <sys/types.h>
+#include "aee.h"
+#include "kdump.h"
+
+/*
+ * USB Connectivity
+ * Note: for usb transmission
+ *   QMU mode : MAX packet length: 63x1024 = 64512 byte. -> GPD_BUF_SIZE_ALIGN
+ *   ZLP issue: EXSPACE should not be multiple size of 512 byte.
+ */
+#define EXSPACE      64256
+#define MAX_RSP_SIZE 64
+#define CON_TIMEOUT  5000
+
+/* Flow control */
+#define USB_RTS      "_RTS"
+#define USB_CTS      "_CTS"
+#define USB_FIN      "_FIN"
+#define USBDONE      "DONE"
+
+/*
+ * Need to align 64 bytes to meet cache line length
+ * 1. cmd[MAX_RSP_SIZE]
+ * 2. data[EXSPACE]
+ */
+struct mrdump_usb_handle {
+    char cmd[MAX_RSP_SIZE];
+    uint8_t data[EXSPACE];
+    unsigned int zipsize;
+    int idx;
+};
+
+/* flow control of usb connection */
+static bool usb_data_transfer(struct mrdump_usb_handle *handle, int length)
+{
+    int len;
+
+    /* send RTS */
+    memset(handle->cmd, 0, MAX_RSP_SIZE);
+    len = snprintf(handle->cmd, MAX_RSP_SIZE, "%s", USB_RTS);
+    len = usb_write_with_timeout(handle->cmd, strlen(handle->cmd), CON_TIMEOUT);
+    if (len > 0) {
+
+        /* receive CTS */
+        memset(handle->cmd, 0, MAX_RSP_SIZE);
+        len = usb_read_with_timeout(handle->cmd, MAX_RSP_SIZE, CON_TIMEOUT);
+        if ((len == (int)strlen(USB_CTS))&&
+                (!strncmp(handle->cmd, USB_CTS, strlen(USB_CTS)))) {
+
+            /* send DATA */
+            len = usb_write_with_timeout(handle->data, length, CON_TIMEOUT);
+            if (len > 0) {
+
+                /* get FIN */
+                memset(handle->cmd, 0, sizeof(handle->cmd));
+                len = usb_read_with_timeout(handle->cmd, sizeof(handle->cmd), CON_TIMEOUT);
+                if ((len == (int)strlen(USB_FIN)) &&
+                        (!strncmp(handle->cmd, USB_FIN, strlen(USB_FIN)))) {
+                    return true;
+                } else {
+                    voprintf_error("%s: failed to get FIN.cmd<%p,%d><%x,%x,%x,%x>\n", __func__,
+                                   handle->cmd, len, handle->cmd[0], handle->cmd[1], handle->cmd[2], handle->cmd[3]);
+                }
+
+            } else {
+                voprintf_error("%s: send DATA error.\n", __func__);
+            }
+        } else {
+            voprintf_error("%s: Not CTS after RTS.cmd<%p,%d><%x,%x,%x,%x>\n", __func__,
+                           handle->cmd, len, handle->cmd[0], handle->cmd[1], handle->cmd[2], handle->cmd[3]);
+        }
+    } else {
+        voprintf_error("%s: send RTS error.\n", __func__);
+    }
+    return false;
+}
+
+/* store data in pool (EXSPACE) and write when pool is full */
+static int do_store_or_write(struct mrdump_usb_handle *handle, uint8_t *buf, uint32_t length)
+{
+    int total;
+    unsigned int leftspace, mylen, reval;
+
+
+    /* count for leftspace */
+    total = EXSPACE;
+    leftspace = total - handle->idx;
+
+    /* check length */
+    if (length > leftspace) {
+        mylen = leftspace;
+        reval = length - leftspace;
+    } else {
+        mylen = length;
+        reval = 0;
+    }
+
+    /* store */
+    while (mylen > 0) {
+        handle->data[handle->idx] = *buf;
+        handle->idx++;
+        buf++;
+        mylen--;
+    }
+
+    /* write */
+    if (handle->idx == total) {
+        if (!usb_data_transfer(handle, handle->idx)) {
+            voprintf_error("%s: connection failed.(error idx: %d)\n",
+                           __func__, handle->idx);
+            return -1;
+        }
+        handle->idx = 0;
+    }
+
+    return reval;
+}
+
+static int usb_write_cb(void *opaque_handle, void *buf, int size)
+{
+    unsigned int    len, moves;
+    int             ret = 0;
+    uint8_t         *ptr;
+
+    struct mrdump_usb_handle *handle = opaque_handle;
+
+    handle->zipsize += size;
+
+    /* EOF, write the left Data in handle data buffer... */
+    if ((buf == NULL) && (size == 0)) {
+
+        /* MUST: a delay for the last transmission */
+        mdelay(10);
+
+        if (!usb_data_transfer(handle, handle->idx)) {
+            voprintf_error("%s: connection failed.(error idx: %d)\n",
+                           __func__, handle->idx);
+            return -1;
+        }
+
+        /* send "MRDUMP ZLP" */
+        memset((void *)handle->data, 0, sizeof(handle->data));
+        size = snprintf((char *)handle->data, sizeof(handle->data), "%s_%s",
+                        MRDUMP_GO_DUMP, USBDONE);
+        if (0 > usb_write_with_timeout(handle->data, strlen((char *)handle->data),
+                                       CON_TIMEOUT)) {
+            voprintf_error(" USB Dump: Write MRDUMP ZLP failed.\n");
+            return -1;
+        }
+
+        return 0;
+    }
+
+    /* buf should not be NULL if not EOF */
+    if (buf == NULL)
+        return -1;
+
+    /* process of Store and write */
+    len = size;
+    ptr = (uint8_t *)buf;
+    while (1) {
+        ret = do_store_or_write(handle, ptr, len);
+        if (ret < 0) {
+            voprintf_error(" USB Dump: store and write failed.\n");
+            return -1;
+        } else if (ret == 0) {
+            break;
+        } else {
+            moves = len - ret;
+            ptr += moves;
+            len = ret;
+        }
+    }
+
+    return size;
+}
+
+int kdump_usb_output(const struct mrdump_control_block *mrdump_cb,
+                     const struct kzip_addlist *memlist)
+{
+    int i;
+    struct kzip_addlist expdb_file[2];
+    char *expdb_filename;
+    unsigned int expdb_offset, expdb_filesize;
+    voprintf_info("Output by USB\n");
+
+    struct mrdump_usb_handle *handle = memalign(64, sizeof(struct mrdump_usb_handle));
+    if (handle == NULL) {
+        voprintf_error("No enough memory.");
+        return -1;
+    }
+    memset(handle, 0, sizeof(struct mrdump_usb_handle));
+
+    mdelay(100);
+    bool ok = true;
+    mtk_wdt_restart();
+    struct kzip_file *zf = kzip_open(handle, usb_write_cb);
+    if (zf != NULL) {
+        /* add SYS_COREDUMP */
+        if (!kzip_add_file(zf, memlist, "SYS_COREDUMP"))
+            ok = false;
+
+        /* add file on expdb */
+        for (i = 0; i < IPANIC_NR_SECTIONS; i++) {
+            if (kedump_get_data_info(i, &expdb_filename, &expdb_offset, &expdb_filesize) == 0) {
+                expdb_file[0].address = expdb_offset;
+                expdb_file[0].size = expdb_filesize;
+                expdb_file[0].type = EXPDB_FILE;
+                expdb_file[1].address = 0;
+                expdb_file[1].size = 0;
+                expdb_file[1].type = MEM_NO_MAP;
+                if (!kzip_add_file(zf, expdb_file, expdb_filename))
+                    ok = false;
+            }
+        }
+
+        /* close zipfile */
+        kzip_close(zf);
+        usb_write_cb(handle, NULL, 0); /* really write the last part */
+        zf = NULL;
+    } else {
+        ok = false;
+    }
+    free(handle);
+
+    mtk_wdt_restart();
+    if (ok) {
+        mrdump_status_ok("OUTPUT:%s\nMODE:%s\n", "USB DUMP",
+                         mrdump_mode2string(mrdump_cb->crash_record.reboot_mode));
+    }
+
+    return ok ? 0 : -1;
+}
+
+#endif
diff --git a/src/bsp/lk/lib/aee/kdump_zip.c b/src/bsp/lk/lib/aee/kdump_zip.c
new file mode 100644
index 0000000..70ffdbe
--- /dev/null
+++ b/src/bsp/lk/lib/aee/kdump_zip.c
@@ -0,0 +1,604 @@
+/*
+ * Copyright (c) 2018 MediaTek Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include <aee.h>
+#include <assert.h>
+#include <kdump.h>
+#include <lib/mempool.h>
+#include <lib/zlib.h>
+#include <lib/zutil.h>
+#include <malloc.h>
+#include <platform.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+#include "lib/cksum.h"
+
+#ifdef MTK_3LEVEL_PAGETABLE
+#include <stdlib.h>
+#include <err.h>
+#endif
+
+#define KZIP_DEBUG(x...)
+
+#define KDUMP_SIZE_REPORT 0x1000000
+#define KDUMP_TICK_WDT 0x10000
+
+#ifdef MRDUMP_USB_DUMP_NO_COMPRESSION
+#define KDUMP_ZLIB_LEVEL Z_NO_COMPRESSION
+#else
+#define KDUMP_ZLIB_LEVEL Z_BEST_SPEED
+#endif
+
+#define ZIPVERSION_NEEDED 45UL
+
+static void putvalue(void *dest, uint64_t x, int nbByte)
+{
+    uint8_t *buf = (uint8_t *)dest;
+    int n;
+    for (n = 0; n < nbByte; n++) {
+        buf[n] = (unsigned char)(x & 0xff);
+        x >>= 8;
+    }
+#if 0
+    if (x != 0) {
+        /* data overflow - hack for ZIP64 */
+        for (n = 0; n < nbByte; n++) {
+            buf[n] = 0xff;
+        }
+    }
+#endif
+}
+
+static int put_zip64_eoc_directory_record(uint8_t *buf, int record_num, uint64_t zip_centralheader_offset, int zip_centralheader_size)
+{
+    uint8_t *oldbuf = buf;
+    putvalue(buf, ZIP64ENDOFCENTRALDIRMAGIC, 4);
+    buf += 4;
+    putvalue(buf, 44, 8); /* zip64 eoc size */
+    buf += 8;
+    putvalue(buf, ZIPVERSION_NEEDED, 2); /* version made by */
+    buf += 2;
+    putvalue(buf, ZIPVERSION_NEEDED, 2); /* version needed to extract */
+    buf += 2;
+    putvalue(buf, 0, 4); /* number of this disk */
+    buf += 4;
+    putvalue(buf, 0, 4); /* number of the disk with the start of the central directory */
+    buf += 4;
+    putvalue(buf, record_num, 8); /* total number of entries in the central directory on this disk */
+    buf += 8;
+    putvalue(buf, record_num, 8); /* total number of entries in the central directory */
+    buf += 8;
+    putvalue(buf, zip_centralheader_size, 8); /* size of the central directory */
+    buf += 8;
+    putvalue(buf, zip_centralheader_offset, 8); /* offset of start of central directory with respect to the starting disk number */
+    buf += 8;
+    return buf - oldbuf;
+}
+
+static int put_zip64_eoc_directory_locator(uint8_t *buf, uint64_t zip64_eoc_offset)
+{
+    uint8_t *oldbuf = buf;
+    putvalue(buf, ZIP64ENDOFCENTRALDIRLOCATORMAGIC, 4);
+    buf += 4;
+    putvalue(buf, 0, 4); /* number of the disk with the start of the zip64 end of central directory */
+    buf += 4;
+    putvalue(buf, zip64_eoc_offset, 8); /* relative offset of the zip64 end of central directory record */
+    buf += 8;
+    putvalue(buf, 1, 4); /* total number of disks */
+    buf += 4;
+    return buf - oldbuf;
+}
+
+static int put_eoc_directory_record(uint8_t *buf, int record_num, uint64_t zip_centralheader_offset, int zip_centralheader_size)
+{
+    uint8_t *oldbuf = buf;
+    putvalue(buf, ENDOFCENTRALDIRMAGIC, 4);
+    buf += 4;
+    putvalue(buf, 0, 2); /* Number of this disk */
+    buf += 2;
+    putvalue(buf, 0, 2); /* Disk where central directory starts */
+    buf += 2;
+    putvalue(buf, record_num, 2); /* Number of central directory records on this disk */
+    buf += 2;
+    putvalue(buf, record_num, 2); /* Total number of central directory records */
+    buf += 2;
+    putvalue(buf, zip_centralheader_size, 4);
+    buf += 4;
+    putvalue(buf, 0xffffffff, 4);
+    buf += 4;
+    putvalue(buf, 0, 2); /* Comment length (n) */
+    buf += 2;
+    return buf - oldbuf;
+}
+
+static int put_localheader(uint8_t *buf, const char *filename, int level)
+{
+    uint8_t *oldbuf = buf;
+    putvalue(buf, LOCALHEADERMAGIC, 4);
+    buf += 4;
+    putvalue(buf, ZIPVERSION_NEEDED, 2);
+    buf += 2;
+
+    uint16_t flag = 0;
+    if ((level==8) || (level == 9))
+        flag |= 2;
+    if (level == 2)
+        flag |= 4;
+    if (level == 1)
+        flag |= 6;
+#if 0
+    if (password != NULL)
+        flag |= 1;
+#endif
+
+    putvalue(buf, flag | 0x8, 2);
+    buf += 2;
+
+    putvalue(buf, Z_DEFLATED, 2);
+    buf += 2;
+
+    putvalue(buf,0UL, 4);
+    buf += 4;
+
+    // CRC / Compressed size / Uncompressed size will be filled in later and rewritten later
+    putvalue(buf, 0UL, 4); /* crc 32, unknown */
+    buf += 4;
+    putvalue(buf, 0xFFFFFFFFUL, 4); /* compressed size, unknown */
+    buf += 4;
+    putvalue(buf, 0xFFFFFFFFUL, 4); /* uncompressed size, unknown */
+    buf += 4;
+    putvalue(buf, strlen(filename), 2); /* size of filename */
+    buf += 2;
+    putvalue(buf, 4 + 8 + 8, 2); /* size of extra field */
+    buf += 2;
+
+    memcpy(buf, filename, strlen(filename));
+    buf += strlen(filename);
+
+    /* ZIP64 extension */
+    putvalue(buf, 0x0001, 2); /* ZIP64_EXTENSION */
+    buf += 2;
+    putvalue(buf, 8 + 8, 2);
+    buf += 2;
+    putvalue(buf, 0UL, 8);
+    buf += 8;
+    putvalue(buf, 0UL, 8);
+    buf += 8;
+
+    return buf - oldbuf;
+}
+
+static int put_centralheader(uint8_t *buf, const char *filename, int level, uint64_t zip_localheader_offset, uint64_t size, uint64_t uncomp_size, uint32_t crc32_value)
+{
+    uint8_t *oldbuf = buf;
+
+    putvalue(buf, CENTRALHEADERMAGIC, 4);
+    buf += 4;
+    putvalue(buf, ZIPVERSION_NEEDED, 2);
+    buf += 2;
+    putvalue(buf, ZIPVERSION_NEEDED, 2);
+    buf += 2;
+
+    uint16_t flag = 0;
+    if ((level==8) || (level == 9))
+        flag |= 2;
+    if (level == 2)
+        flag |= 4;
+    if (level == 1)
+        flag |= 6;
+#if 0
+    if (password != NULL)
+        flag |= 1;
+#endif
+
+    putvalue(buf, flag | 0x8, 2);
+    buf += 2;
+
+    putvalue(buf, Z_DEFLATED, 2);
+    buf += 2;
+
+    putvalue(buf,0UL, 4);
+    buf += 4;
+
+    // CRC / Compressed size / Uncompressed size will be filled in later and rewritten later
+    putvalue(buf, crc32_value, 4); /* crc 32 */
+    buf += 4;
+    putvalue(buf, 0xffffffffUL, 4); /* compressed size */
+    buf += 4;
+    putvalue(buf, 0xffffffffUL, 4); /* uncompressed size */
+    buf += 4;
+    putvalue(buf, strlen(filename), 2);
+    buf += 2;
+    putvalue(buf, 4 + 8 + 8 + 8, 2); /* size of extra field */
+    buf += 2;
+    putvalue(buf, 0UL, 2); /* size of comment field */
+    buf += 2;
+    putvalue(buf, 0UL, 2); /* disk number */
+    buf += 2;
+    putvalue(buf, 0UL, 2); /* internal attributes */
+    buf += 2;
+    putvalue(buf, 0UL, 4); /* external file attributes */
+    buf += 4;
+    putvalue(buf, 0xffffffffUL, 4); /* Relative offset */
+    buf += 4;
+    memcpy(buf, filename, strlen(filename));
+    buf += strlen(filename);
+
+    /* ZIP64 extension */
+    putvalue(buf, 0x0001, 2); /* ZIP64_EXTENSION */
+    buf += 2;
+    putvalue(buf, 8 + 8 + 8, 2);
+    buf += 2;
+    putvalue(buf, uncomp_size, 8);
+    buf += 8;
+    putvalue(buf, size, 8);
+    buf += 8;
+    putvalue(buf, zip_localheader_offset, 8);
+    buf += 8;
+
+    return buf - oldbuf;
+}
+
+static int kzip_write_current(struct kzip_file *zfile, void *buf, int len)
+{
+    KZIP_DEBUG("%s: write_cb %p len %d\n", __func__, zfile->write_cb, len);
+    int retval = zfile->write_cb(zfile->handle, buf, len);
+    if (retval > 0) {
+        zfile->current_size += retval;
+    }
+    if ((zfile->current_size - zfile->reported_size) >= KDUMP_SIZE_REPORT) {
+        vo_show_progress(zfile->current_size / 0x100000);
+        zfile->reported_size = zfile->current_size;
+    }
+    if ((zfile->current_size - zfile->wdk_kick_size) >= KDUMP_TICK_WDT) {
+        mtk_wdt_restart();
+        zfile->wdk_kick_size = zfile->current_size;
+    }
+    return retval;
+}
+
+struct kzip_file *kzip_open(void *handle, int (*write_cb)(void *handle, void *p, int size))
+{
+    struct kzip_file *zf = mempool_alloc(sizeof(struct kzip_file), MEMPOOL_ANY);
+    memset(zf, 0, sizeof(struct kzip_file));
+    zf->handle = handle;
+    zf->write_cb = write_cb;
+    KZIP_DEBUG("%s: handle zf %p %p write_cb %p\n", __func__, zf, zf->handle, zf->write_cb);
+
+    vo_show_progress(0);
+    return zf;
+}
+
+bool kzip_close(struct kzip_file *zf)
+{
+    uint64_t central_header_offset = zf->current_size;
+    struct kzip_entry *zentries = zf->zentries;
+    int num = zf->entries_num;
+
+    int i, hsize = 0, local_hsize;
+    uint8_t databuf[128];
+    for (i = 0; i < num; i++) {
+        local_hsize = put_centralheader(databuf, zentries[i].filename, zentries[i].level,
+                                        zentries[i].localheader_offset,
+                                        zentries[i].comp_size,
+                                        zentries[i].uncomp_size,
+                                        zentries[i].crc32);
+        if (kzip_write_current(zf, databuf, local_hsize) != local_hsize) {
+            return false;
+        }
+        hsize += local_hsize;
+    }
+    voprintf_debug("%s: current_size %lld hoffset %lld\n", __func__, zf->current_size, central_header_offset);
+
+    uint64_t zip64_eoc_offset = zf->current_size;
+    local_hsize = put_zip64_eoc_directory_record(databuf, num, central_header_offset, hsize);
+    if ((local_hsize > 0) && (kzip_write_current(zf, databuf, local_hsize) != local_hsize)) {
+        return false;
+    }
+
+    local_hsize = put_zip64_eoc_directory_locator(databuf, zip64_eoc_offset);
+    if ((local_hsize > 0) && (kzip_write_current(zf, databuf, local_hsize) != local_hsize)) {
+        return false;
+    }
+
+    local_hsize = put_eoc_directory_record(databuf, num, central_header_offset, hsize);
+    if (kzip_write_current(zf, databuf, local_hsize) != local_hsize) {
+        return false;
+    }
+    mempool_free(zf);
+    return true;
+}
+
+#define CHUNK 65536
+
+/* Compress from file source to file dest until EOF on source.
+   def() returns Z_OK on success, Z_MEM_ERROR if memory could not be
+   allocated for processing, Z_STREAM_ERROR if an invalid compression
+   level is supplied, Z_VERSION_ERROR if the version of zlib.h and the
+   version of the library linked do not match, or Z_ERRNO if there is
+   an error reading or writing the files. */
+
+static bool kzip_add_file_no_mapped(struct kzip_file *zfile, const struct kzip_addlist *memlist,
+                                    int *flush, int *ret, uint8_t *in, uint8_t *out,
+                                    struct kzip_entry *zentry, z_stream *strm, struct aee_timer *zip_time)
+{
+    lk_time_t t = current_time();
+    uint64_t mem_size = memlist->size;
+    uint8_t *memsrc = (uint8_t *)(uintptr_t)memlist->address;
+    *flush = (memlist->size == 0) ? Z_FINISH : Z_NO_FLUSH;
+    voprintf_debug("-- Compress memory %llx, size %llu\n",
+                   memlist->address, memlist->size);
+
+    do {
+        int in_size = mem_size > CHUNK ? CHUNK : mem_size;
+        if ((current_time() - t)/1000 > 10) {
+            voprintf_debug("-- I am working(interval to 10s) --\n");
+            t = current_time();
+        }
+        memcpy(in, memsrc, in_size);
+        zentry->crc32 = crc32_no_comp(zentry->crc32, in, in_size);
+        memsrc += in_size;
+        mem_size -= in_size;
+        strm->avail_in = in_size;
+        strm->next_in = in;
+
+        /* run deflate() on input until output buffer not full, finish
+           compression if all of source has been read in */
+        do {
+            strm->avail_out = CHUNK;
+            strm->next_out = out;
+            *ret = deflate(strm, *flush);    /* no bad return value */
+            assert(*ret != Z_STREAM_ERROR);  /* state not clobbered */
+            int have = CHUNK - strm->avail_out;
+            if (have > 0) {
+                aee_timer_stop(zip_time);
+                if (kzip_write_current(zfile, out, have) != have) {
+                    voprintf_debug("-- Compress memory %llx, error. surplus size: %u\n",
+                                   memlist->address, mem_size);
+                    return false;
+                }
+                aee_timer_start(zip_time);
+            }
+        } while (strm->avail_out == 0);
+        assert(strm->avail_in == 0);     /* all input will be used */
+    } while (mem_size > 0);
+
+    voprintf_debug("-- Compress memory %llx, done. surplus size: %u\n",
+                   memlist->address, mem_size);
+    return true;
+}
+
+#ifndef MTK_3LEVEL_PAGETABLE
+/* full mapping at LK, only one function is needed. kzip_add_file_no_mapped() */
+#define kzip_add_file_do_mapped kzip_add_file_no_mapped
+#else
+/* LPAE, map before accessing the address of memory */
+#define MAX_MAP_CNT (SECTION_SIZE/CHUNK)
+#define mapflags (MMU_MEMORY_TYPE_NORMAL_WRITE_BACK | MMU_MEMORY_AP_P_RW_U_NA)
+static bool kzip_add_file_do_mapped(struct kzip_file *zfile, const struct kzip_addlist *memlist,
+                                    int *flush, int *ret, uint8_t *in, uint8_t *out,
+                                    struct kzip_entry *zentry, z_stream *strm, struct aee_timer *zip_time)
+{
+    /* multiple physical address mapped onto static 2MB address space. (scratch_addr) */
+    int cnt = 0;
+    uint64_t paddr = memlist->address;
+    vaddr_t vaddr = ROUNDUP(scratch_addr(), SECTION_SIZE);
+    voprintf_debug("-- map: paddr=0x%016llx, vaddr=0x%08x\n", paddr, vaddr);
+
+    uint64_t mem_size = memlist->size;
+    uint8_t *memsrc;
+    *flush = (memlist->size == 0) ? Z_FINISH : Z_NO_FLUSH;
+    voprintf_debug("-- Compress memory %llx, size %llu\n", memlist->address, memlist->size);
+
+    do {
+        /* arch_mmu_map by each 2MB size */
+        if (cnt == 0) {
+            int map_ok = arch_mmu_map(paddr, vaddr, mapflags, SECTION_SIZE);
+            if (map_ok != NO_ERROR) {
+                voprintf_debug("-- arch_mmu_map map error: map_ok=%d, paddr=0x%016llx, vaddr=0x%08x\n",
+                               map_ok, paddr, vaddr);
+                return false;
+            }
+            memsrc = (uint8_t *)vaddr;
+        }
+
+        int in_size = mem_size > CHUNK ? CHUNK : mem_size;
+        memcpy(in, memsrc, in_size);
+        zentry->crc32 = crc32_no_comp(zentry->crc32, in, in_size);
+        memsrc += in_size;
+        mem_size -= in_size;
+        strm->avail_in = in_size;
+        strm->next_in = in;
+
+        /* run deflate() on input until output buffer not full, finish
+           compression if all of source has been read in */
+        do {
+            strm->avail_out = CHUNK;
+            strm->next_out = out;
+            *ret = deflate(strm, *flush);    /* no bad return value */
+            assert(*ret != Z_STREAM_ERROR);  /* state not clobbered */
+            int have = CHUNK - strm->avail_out;
+            if (have > 0) {
+                aee_timer_stop(zip_time);
+                if (kzip_write_current(zfile, out, have) != have) {
+                    voprintf_debug("-- Compress memory %llx, error. surplus size: %u\n",
+                                   memlist->address, mem_size);
+                    return false;
+                }
+                aee_timer_start(zip_time);
+            }
+        } while (strm->avail_out == 0);
+        assert(strm->avail_in == 0);     /* all input will be used */
+
+        /* mod by 2MB (SECTION_SIZE) */
+        cnt++;
+        cnt %= MAX_MAP_CNT;
+        if (cnt == 0)
+            paddr += SECTION_SIZE;
+
+    } while (mem_size > 0);
+
+    voprintf_debug("-- Compress memory %llx, done. surplus size: %u\n", memlist->address, mem_size);
+    return true;
+}
+#endif
+
+static bool kzip_add_file_from_expdb(struct kzip_file *zfile, const struct kzip_addlist *addlist,
+                                     int *flush, int *ret, uint8_t *in, uint8_t *out,
+                                     struct kzip_entry *zentry, z_stream *strm, struct aee_timer *zip_time)
+{
+    uint64_t offset_src = addlist->address;
+    int64_t mem_size = addlist->size;
+
+    *flush = (addlist->size == 0) ? Z_FINISH : Z_NO_FLUSH;
+    voprintf_debug("-- Compress expdb offset %llx, size %llu\n", offset_src, mem_size);
+
+    do {
+        /* read from expdb to memsrc */
+        if (mem_size > CHUNK) {
+            //mrdump_read_expdb(in, CHUNK, offset_src);
+        } else {
+            //mrdump_read_expdb(in, (int)mem_size, offset_src);
+        }
+
+        int in_size = mem_size > CHUNK ? CHUNK : mem_size;
+        zentry->crc32 = crc32_no_comp(zentry->crc32, in, in_size);
+        mem_size -= in_size;
+        strm->avail_in = in_size;
+        strm->next_in = in;
+
+        /* run deflate() on input until output buffer not full, finish
+           compression if all of source has been read in */
+        do {
+            strm->avail_out = CHUNK;
+            strm->next_out = out;
+            *ret = deflate(strm, *flush);    /* no bad return value */
+            assert(*ret != Z_STREAM_ERROR);  /* state not clobbered */
+            int have = CHUNK - strm->avail_out;
+            if (have > 0) {
+                aee_timer_stop(zip_time);
+                if (kzip_write_current(zfile, out, have) != have) {
+                    voprintf_debug("-- Compress expdb offset %llx, error. surplus size: %u\n",
+                                   offset_src, mem_size);
+                    return false;
+                }
+                aee_timer_start(zip_time);
+            }
+        } while (strm->avail_out == 0);
+        assert(strm->avail_in == 0);     /* all input will be used */
+
+        offset_src += in_size;
+
+    } while (mem_size > 0);
+
+    voprintf_debug("-- Compress expdb offset %llx, done. surplus size: %u\n", offset_src, mem_size);
+    return true;
+}
+
+bool kzip_add_file(struct kzip_file *zfile, const struct kzip_addlist *addlist, const char *zfilename)
+{
+    int ret, flush;
+    z_stream strm;
+    struct aee_timer zip_time;
+
+    if (zfile->entries_num >= KZIP_ENTRY_MAX) {
+        voprintf_error("Too many zip entry %d\n", zfile->entries_num);
+        return false;
+    }
+
+    voprintf_debug("%s: zf %p(%p) %s\n", __func__, zfile, zfile->write_cb, zfilename);
+    struct kzip_entry *zentry = &zfile->zentries[zfile->entries_num++];
+    zentry->filename = strdup(zfilename);
+    zentry->localheader_offset = zfile->current_size;
+    zentry->level = KDUMP_ZLIB_LEVEL;
+    zentry->crc32 = 0xffffffffUL;
+
+    KZIP_DEBUG("%s: write local header\n", __func__);
+    uint8_t zip_localheader[128];
+    int hsize = put_localheader(zip_localheader, zfilename, zentry->level);
+    if (kzip_write_current(zfile, zip_localheader, hsize) != hsize) {
+        return false;
+    }
+
+    /* allocate deflate state */
+    memset(&strm, 0, sizeof(z_stream));
+    ret = deflateInit2(&strm, zentry->level, Z_DEFLATED, -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY);
+    if (ret != Z_OK) {
+        voprintf_error("zlib compress init failed\n");
+        return false;
+    }
+
+    uint8_t *out = mempool_alloc(CHUNK, MEMPOOL_ANY);
+    uint8_t *in = mempool_alloc(CHUNK, MEMPOOL_ANY);
+    if ((out == NULL) || (in == NULL)) {
+        voprintf_error("%s: malloc failed.\n", __func__);
+        goto error;
+    }
+
+    aee_timer_init(&zip_time);
+    aee_timer_start(&zip_time);
+
+    uint64_t start = zfile->current_size, uncomp_size = 0;
+    do {
+        switch (addlist->type) {
+            case MEM_NO_MAP:
+                if (kzip_add_file_no_mapped(zfile, addlist, &flush, &ret, in, out, zentry, &strm, &zip_time) == false)
+                    goto error;
+                break;
+            case MEM_DO_MAP:
+                if (kzip_add_file_do_mapped(zfile, addlist, &flush, &ret, in, out, zentry, &strm, &zip_time) == false)
+                    goto error;
+                break;
+            case EXPDB_FILE:
+                if (kzip_add_file_from_expdb(zfile, addlist, &flush, &ret, in, out, zentry, &strm, &zip_time) == false)
+                    goto error;
+                break;
+            default:
+                goto error;
+                break;
+        }
+        uncomp_size += addlist->size;
+        addlist++;
+        /* done when last data in file processed */
+    } while (flush != Z_FINISH);
+    assert(ret == Z_STREAM_END);        /* stream will be complete */
+
+    deflateEnd(&strm);
+    mempool_free(out);
+    mempool_free(in);
+    aee_timer_stop(&zip_time);
+    voprintf_info("Zip time: %d sec\n", zip_time.acc_ms / 1000);
+
+    zentry->comp_size = zfile->current_size - start;
+    zentry->uncomp_size = uncomp_size;
+    zentry->crc32 = zentry->crc32 ^ 0xffffffffUL;
+
+    return true;
+
+error:
+    mempool_free(out);
+    mempool_free(in);
+    deflateEnd(&strm);
+    return false;
+}
diff --git a/src/bsp/lk/lib/aee/mrdump_aee.c b/src/bsp/lk/lib/aee/mrdump_aee.c
new file mode 100644
index 0000000..b2e03c2
--- /dev/null
+++ b/src/bsp/lk/lib/aee/mrdump_aee.c
@@ -0,0 +1,502 @@
+/*
+ * Copyright (c) 2018 MediaTek Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include <arch/ops.h>
+#include <boot_args.h>
+#include <env.h>
+#include <lib/bio.h>
+#include <lib/cksum.h>
+#include <lib/kcmdline.h>
+#include <lib/mempool.h>
+#include <lib/zlib.h>
+#include <libfdt.h>
+#include <malloc.h>
+#include <mrdump.h>
+#include <platform.h>
+#include <platform/mtk_wdt.h>
+#include <printf.h>
+#include <stdarg.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#ifdef MTK_PMIC_FULL_RESET
+#include <platform/pmic.h>
+#endif
+
+#include "aee.h"
+#include "kdump.h"
+#include "ram_console.h"
+
+#if WITH_KERNEL_VM
+#include <kernel/vm.h>
+#else
+#include <kernel/novm.h>
+#endif
+
+#ifdef MTK_3LEVEL_PAGETABLE
+#include <target.h>
+#endif
+
+#define MRDUMP_DELAY_TIME 10
+
+extern BOOT_ARGUMENT *g_boot_arg;
+
+static struct mrdump_control_block *mrdump_cblock = NULL;
+static struct mrdump_cblock_result cblock_result;
+static unsigned int log_size;
+static int output_device;
+
+void voprintf(char type, const char *msg, va_list ap)
+{
+    char msgbuf[128], *p;
+
+    p = msgbuf;
+    if (msg[0] == '\r') {
+        *p++ = msg[0];
+        msg++;
+    }
+
+    *p++ = type;
+    *p++ = ':';
+    vsnprintf(p, sizeof(msgbuf) - (p - msgbuf), msg, ap);
+    switch (type) {
+        case 'I':
+        case 'W':
+        case 'E':
+            //video_printf("%s", msgbuf);
+            break;
+    }
+
+    dprintf(CRITICAL,"[%s] %s", MRDUMP_GO_DUMP, msgbuf);
+
+    /* Write log buffer */
+    p = msgbuf;
+    while ((*p != 0) && (log_size < sizeof(cblock_result.log_buf))) {
+        cblock_result.log_buf[log_size] = *p++;
+        log_size++;
+    }
+}
+
+void voprintf_verbose(const char *msg, ...)
+{
+    va_list ap;
+    va_start(ap, msg);
+    voprintf('V', msg, ap);
+    va_end(ap);
+}
+
+void voprintf_debug(const char *msg, ...)
+{
+    va_list ap;
+    va_start(ap, msg);
+    voprintf('D', msg, ap);
+    va_end(ap);
+}
+
+void voprintf_info(const char *msg, ...)
+{
+    va_list ap;
+    va_start(ap, msg);
+    voprintf('I', msg, ap);
+    va_end(ap);
+}
+
+void voprintf_warning(const char *msg, ...)
+{
+    va_list ap;
+    va_start(ap, msg);
+    voprintf('W', msg, ap);
+    va_end(ap);
+}
+
+void voprintf_error(const char *msg, ...)
+{
+    va_list ap;
+    va_start(ap, msg);
+    voprintf('E', msg, ap);
+    va_end(ap);
+}
+
+void vo_show_progress(int sizeM)
+{
+#if 0
+    video_set_cursor((video_get_rows() / 4) * 3, (video_get_colums() - 22)/ 2);
+    video_printf("=====================\n");
+    video_set_cursor((video_get_rows() / 4) * 3 + 1, (video_get_colums() - 22)/ 2);
+    video_printf(">>> Written %4dM <<<\n", sizeM);
+    video_set_cursor((video_get_rows() / 4) * 3 + 2, (video_get_colums() - 22)/ 2);
+    video_printf("=====================\n");
+    video_set_cursor(video_get_rows() - 1, 0);
+
+    dprintf(CRITICAL,"... Written %dM\n", sizeM);
+#endif
+}
+
+static void mrdump_status(const char *status, const char *fmt, va_list ap)
+{
+    char *dest = cblock_result.status;
+    dest += strlcpy(dest, status, sizeof(cblock_result.status));
+    *dest++ = '\n';
+
+    vsnprintf(dest, sizeof(cblock_result.status) - (dest - cblock_result.status), fmt, ap);
+}
+
+void mrdump_status_ok(const char *fmt, ...)
+{
+    va_list ap;
+    va_start(ap, fmt);
+    mrdump_status("OK", fmt, ap);
+    va_end(ap);
+}
+
+void mrdump_status_none(const char *fmt, ...)
+{
+    va_list ap;
+    va_start(ap, fmt);
+    mrdump_status("NONE", fmt, ap);
+    va_end(ap);
+}
+
+void mrdump_status_error(const char *fmt, ...)
+{
+    va_list ap;
+    va_start(ap, fmt);
+    mrdump_status("FAILED", fmt, ap);
+    va_end(ap);
+}
+
+uint32_t g_aee_mode = AEE_MODE_MTK_ENG;
+
+const char *mrdump_mode2string(uint8_t mode)
+{
+    switch (mode) {
+        case AEE_REBOOT_MODE_NORMAL:
+            return "NORMAL-BOOT";
+
+        case AEE_REBOOT_MODE_KERNEL_OOPS:
+            return "KERNEL-OOPS";
+
+        case AEE_REBOOT_MODE_KERNEL_PANIC:
+            return "KERNEL-PANIC";
+
+        case AEE_REBOOT_MODE_NESTED_EXCEPTION:
+            return "NESTED-CPU-EXCEPTION";
+
+        case AEE_REBOOT_MODE_WDT:
+            return "HWT";
+
+        case AEE_REBOOT_MODE_EXCEPTION_KDUMP:
+            return "MANUALDUMP";
+
+        case AEE_REBOOT_MODE_MRDUMP_KEY:
+            return "MRDUMP_KEY";
+
+        case AEE_REBOOT_MODE_HANG_DETECT:
+            return "KERNEL-HANG-DETECT";
+
+        default:
+            return "UNKNOWN-BOOT";
+    }
+}
+
+#define MRDUMP_EXPDB_OFFSET 3145728
+
+static void mrdump_write_result(void)
+{
+    bdev_t *bdev;
+
+    bdev = bio_open_by_label("expdb");
+    if (!bdev) {
+        dprintf(CRITICAL, "%s: no %s partition\n", __func__, "expdb");
+        return;
+    }
+
+    if (bdev->total_size < MRDUMP_EXPDB_OFFSET) {
+        dprintf(CRITICAL, "%s: partition size(%llx) is less then reserved (%x)\n", __func__,
+            bdev->total_size, MRDUMP_EXPDB_OFFSET);
+        return;
+    }
+    u64 part_offset = bdev->total_size - MRDUMP_EXPDB_OFFSET;
+
+    dprintf(CRITICAL, "%s: offset %lld size %lld\n", __func__, part_offset, bdev->total_size);
+
+    bio_write(bdev, (uchar *)&cblock_result, part_offset, sizeof(cblock_result));
+}
+
+#define SIZE_1MB 1048576ULL
+#define SIZE_64MB 67108864ULL
+
+static uint64_t mrdump_mem_size(void)
+{
+    return physical_memory_size();
+}
+
+static int mrdump_output_device(void)
+{
+    //now only support ext4
+    return MRDUMP_DEV_ISTORAGE_EXT4;
+}
+
+static struct kzip_addlist *mrdump_memlist_fill(void)
+{
+    struct kzip_addlist *memlist =
+        mempool_alloc(sizeof(struct kzip_addlist) * 4, MEMPOOL_ANY);
+    if (memlist == NULL) {
+        return NULL;
+    }
+    void *bufp = mempool_alloc(KDUMP_CORE_HEADER_SIZE, MEMPOOL_ANY);
+    memset(bufp, 0, KDUMP_CORE_HEADER_SIZE);
+
+    dprintf(CRITICAL, "%s address:%p\n", __func__, bufp);
+
+    memlist[0].address = (uint64_t)(uintptr_t) bufp;
+    memlist[0].size = KDUMP_CORE_HEADER_SIZE;
+    memlist[0].type = MEM_NO_MAP;
+    memlist[1].address = (uint64_t)PA_TO_VA((paddr_t)mrdump_cb_addr());
+    memlist[1].size = mrdump_cb_size();
+    memlist[1].type = MEM_NO_MAP;
+    memlist[2].address = (uint64_t)PA_TO_VA(DRAM_BASE_PHY);
+    memlist[2].size = mrdump_mem_size();
+    memlist[2].type = MEM_NO_MAP;
+    memlist[3].address = 0;
+    memlist[3].size = 0;
+    memlist[3].type = MEM_NO_MAP;
+    return memlist;
+}
+
+static void mrdump_memlist_free(struct kzip_addlist *memlist)
+{
+    mempool_free((void *)(uintptr_t)memlist[0].address);
+    mempool_free(memlist);
+}
+
+static void kdump_ui(struct mrdump_control_block *mrdump_cblock)
+{
+#if 0
+    video_clean_screen();
+    video_set_cursor(0, 0);
+#endif
+    mrdump_status_error("Unknown error\n");
+    voprintf_info("Kdump triggerd by '%s' (address:%x, size:%lluM)\n",
+                  mrdump_mode2string(mrdump_cblock->crash_record.reboot_mode),
+                  DRAM_BASE_PHY, mrdump_mem_size() / 0x100000UL);
+
+    /* check machdesc crc */
+    uint32_t mcrc = crc32(0xffffffff, (const unsigned char *)&mrdump_cblock->machdesc,
+                          sizeof(struct mrdump_machdesc)) ^ 0xffffffff;
+    if (mcrc != mrdump_cblock->machdesc_crc) {
+        voprintf_error("Control block machdesc field CRC error (%08x, %08x).\n",
+                       mcrc, mrdump_cblock->machdesc_crc);
+        return;
+    }
+
+    struct kzip_addlist *memlist = mrdump_memlist_fill();
+    if (memlist == NULL) {
+        voprintf_error("Cannot allcate memlist memory.\n");
+        return;
+    }
+    kdump_core_header_init(mrdump_cblock, memlist);
+
+    struct aee_timer elapse_time;
+    aee_timer_init(&elapse_time);
+    aee_timer_start(&elapse_time);
+    int dump_ok = -1;
+    switch (output_device) {
+        case  MRDUMP_DEV_NONE:
+            mrdump_status_none("Output to None (disabled)\n");
+            voprintf_info("Output to None (disabled)\n");
+            dump_ok = 0;
+            break;
+        case MRDUMP_DEV_NULL:
+            //dump_ok = kdump_null_output(mrdump_cblock, memlist);
+            break;
+        case MRDUMP_DEV_ISTORAGE_EXT4:
+            dump_ok = mrdump_ext4_output(mrdump_cblock, memlist, mrdump_dev_emmc_ext4());
+            break;
+        case MRDUMP_DEV_ISTORAGE_VFAT:
+            //dump_ok = mrdump_vfat_output(mrdump_cblock, memlist, mrdump_dev_emmc_vfat());
+            break;
+        case MRDUMP_DEV_USB:
+            //dump_ok = kdump_usb_output(mrdump_cblock, memlist);
+            break;
+        default:
+            voprintf_error("Unsupport device id %d\n", output_device);
+            dump_ok = -1;
+    }
+    mrdump_memlist_free(memlist);
+
+    aee_mrdump_flush_cblock(mrdump_cblock);
+    aee_timer_stop(&elapse_time);
+    voprintf_info("Dump finished.(%s, %d sec)\n", dump_ok == 0 ? "ok" : "failed",
+        elapse_time.acc_ms / 1000);
+
+    mtk_wdt_restart();
+#if 0
+    video_clean_screen();
+    video_set_cursor(0, 0);
+#endif
+}
+
+int mrdump_detection(void)
+{
+    if (!ram_console_is_abnormal_boot()) {
+        dprintf(CRITICAL, "MT-RAMDUMP: No exception detected, skipped\n");
+        return 0;
+    }
+
+    mrdump_cblock = aee_mrdump_get_params();
+    if (mrdump_cblock == NULL) {
+        dprintf(CRITICAL, "MT-RAMDUMP control block not found\n");
+        return 0;
+    }
+
+    memset(&cblock_result, 0, sizeof(struct mrdump_cblock_result));
+    log_size = 0;
+    strlcpy(cblock_result.sig, MRDUMP_GO_DUMP, sizeof(cblock_result.sig));
+
+    uint8_t reboot_mode = mrdump_cblock->crash_record.reboot_mode;
+
+    if (!g_boot_arg->ddr_reserve_enable) {
+        voprintf_debug("DDR reserve mode disabled\n");
+        mrdump_status_none("DDR reserve mode disabled\n");
+        goto error;
+    }
+
+    if (!g_boot_arg->ddr_reserve_success) {
+        voprintf_debug("DDR reserve mode failed\n");
+        mrdump_status_none("DDR reserve mode failed\n");
+        goto error;
+    }
+
+    if (mrdump_cblock->enabled != MRDUMP_ENABLE_COOKIE) {
+        voprintf_debug("Runtime disabled %x\n", mrdump_cblock->enabled);
+        mrdump_status_none("Runtime disabled\n");
+        goto error;
+    }
+
+    output_device = mrdump_output_device();
+    voprintf_debug("sram record with mode %d\n", reboot_mode);
+    switch (reboot_mode) {
+        case AEE_REBOOT_MODE_GZ_WDT:
+        case AEE_REBOOT_MODE_WDT: {
+            goto end;
+        }
+        case AEE_REBOOT_MODE_NORMAL: {
+            /* MRDUMP_KEY reboot*/
+            if (ram_console_reboot_by_mrdump_key && ram_console_reboot_by_mrdump_key()) {
+                mrdump_cblock->crash_record.reboot_mode = AEE_REBOOT_MODE_MRDUMP_KEY;
+                goto end;
+            } else
+                return 0;
+        }
+        case AEE_REBOOT_MODE_KERNEL_OOPS:
+        case AEE_REBOOT_MODE_KERNEL_PANIC:
+        case AEE_REBOOT_MODE_NESTED_EXCEPTION:
+        case AEE_REBOOT_MODE_EXCEPTION_KDUMP:
+        case AEE_REBOOT_MODE_MRDUMP_KEY:
+        case AEE_REBOOT_MODE_GZ_KE:
+        case AEE_REBOOT_MODE_HANG_DETECT:
+            goto end;
+    }
+    voprintf_debug("Unsupport exception type\n");
+    mrdump_status_none("Unsupport exception type\n");
+
+error:
+    mrdump_write_result();
+    return 0;
+end:
+    if (output_device == MRDUMP_DEV_USB) {
+        g_boot_arg->boot_mode = 2;
+        //set_env("mrdump_output", "usb");
+    }
+
+    return 1;
+}
+
+void mrdump_reboot(void)
+{
+#ifdef MTK_PMIC_FULL_RESET
+    voprintf_debug("Ready for full pmic reset\n");
+    mrdump_write_result();
+    pmic_cold_reset();
+#else
+    voprintf_debug("Ready for reset\n");
+    mrdump_write_result();
+    mtk_arch_reset(1);
+#endif
+}
+
+int mrdump_run2(void)
+{
+    if (mrdump_cblock != NULL) {
+        kdump_ui(mrdump_cblock);
+#ifndef MTK_TC7_FEATURE
+        if (output_device != MRDUMP_DEV_USB) {
+            mrdump_reboot();
+        }
+#endif
+        mrdump_write_result();
+        return 1;
+    }
+    return 0;
+}
+
+void aee_timer_init(struct aee_timer *t)
+{
+    memset(t, 0, sizeof(struct aee_timer));
+}
+
+void aee_timer_start(struct aee_timer *t)
+{
+    t->start_ms = current_time();
+}
+
+void aee_timer_stop(struct aee_timer *t)
+{
+    t->acc_ms += (current_time() - t->start_ms);
+    t->start_ms = 0;
+}
+
+void kdump_core_header_init(const struct mrdump_control_block *kparams,
+    const struct kzip_addlist *memlist)
+{
+    if (kparams->machdesc.page_offset <= 0xffffffffULL) {
+        voprintf_info("32b kernel detected:offset:0x%llx\n", kparams->machdesc.page_offset);
+        kdump_core32_header_init(kparams, memlist);
+    } else {
+        voprintf_info("64b kernel detected:offset:0x%llx\n", kparams->machdesc.page_offset);
+        kdump_core64_header_init(kparams, memlist);
+    }
+}
+
+#ifdef MTK_3LEVEL_PAGETABLE
+vaddr_t scratch_addr(void)
+{
+    return (vaddr_t)target_get_scratch_address();
+}
+#endif
+
+void mrdump_setup_version(void)
+{
+    kcmdline_append("mrdump.lk=" MRDUMP_GO_DUMP);
+}
diff --git a/src/bsp/lk/lib/aee/mrdump_dummy.c b/src/bsp/lk/lib/aee/mrdump_dummy.c
new file mode 100644
index 0000000..0d8be50
--- /dev/null
+++ b/src/bsp/lk/lib/aee/mrdump_dummy.c
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2018 MediaTek Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include <mrdump.h>
+#include "kdump.h"
+
+int mrdump_detection(void) __attribute__((weak));
+int mrdump_detection(void)
+{
+    return 0;
+}
+
+void mrdump_setup_cblock(void) __attribute__((weak));
+void mrdump_setup_cblock(void)
+{
+}
+
+void mrdump_reserve_memory(void) __attribute__((weak));
+void mrdump_reserve_memory(void)
+{
+}
+
+int mrdump_run2(void) __attribute__((weak));
+int mrdump_run2(void)
+{
+    return 0;
+}
+
+int kdump_usb_output(const struct mrdump_control_block *mrdump_cb,
+                     const struct kzip_addlist *memlist) __attribute__((weak));
+int kdump_usb_output(const struct mrdump_control_block *mrdump_cb,
+                     const struct kzip_addlist *memlist)
+{
+    return 0;
+}
+
+int kedump_restore_mem(void) __attribute__((weak));
+int kedump_restore_mem(void)
+{
+    return 0;
+}
+
+void mrdump_reboot(void) __attribute__((weak));
+void mrdump_reboot(void)
+{
+}
+
+void mrdump_setup_version(void) __attribute__((weak));
+void mrdump_setup_version(void)
+{
+}
+
+void mrdump_setup_boot_reason(void) __attribute__((weak));
+void mrdump_setup_boot_reason(void)
+{
+}
diff --git a/src/bsp/lk/lib/aee/mrdump_elf.c b/src/bsp/lk/lib/aee/mrdump_elf.c
new file mode 100644
index 0000000..c24a813
--- /dev/null
+++ b/src/bsp/lk/lib/aee/mrdump_elf.c
@@ -0,0 +1,212 @@
+/*
+ * Copyright (c) 2018 MediaTek Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include <kernel/vm.h>
+#include <malloc.h>
+#include <printf.h>
+#include <stdlib.h>
+#include <string.h>
+#include "kdump.h"
+#include "mrdump_elf.h"
+
+/* An ELF note in memory */
+struct memelfnote {
+    const char *name;
+    int type;
+    unsigned int datasz;
+    void *data;
+};
+
+static int notesize(struct memelfnote *en)
+{
+    int sz;
+
+    sz = sizeof(struct elf_note);
+    sz += ROUNDUP((strlen(en->name) + 1), 4);
+    sz += ROUNDUP(en->datasz, 4);
+
+    return sz;
+}
+
+static uint8_t *storenote(struct memelfnote *men, uint8_t *bufp)
+{
+    struct elf_note en;
+    en.n_namesz = strlen(men->name) + 1;
+    en.n_descsz = men->datasz;
+    en.n_type = men->type;
+
+    memcpy(bufp, &en, sizeof(en));
+    bufp += sizeof(en);
+
+    memcpy(bufp, men->name, en.n_namesz);
+    bufp += en.n_namesz;
+
+    bufp = (uint8_t *) ROUNDUP((unsigned long)bufp, 4);
+    memcpy(bufp, men->data, men->datasz);
+    bufp += men->datasz;
+
+    bufp = (uint8_t *) ROUNDUP((unsigned long)bufp, 4);
+    return bufp;
+}
+
+static uint8_t *kdump_core_write_cpu_note(const struct mrdump_control_block *mrdump_cb, int cpu, struct elf32_phdr *nhdr, uint8_t *bufp)
+{
+    struct memelfnote notes;
+    struct elf32_arm_prstatus prstatus;
+    char cpustr[16];
+
+    memset(&prstatus, 0, sizeof(struct elf32_arm_prstatus));
+
+    snprintf(cpustr, sizeof(cpustr), "CPU%d", cpu);
+    /* set up the process status */
+    notes.name = cpustr;
+    notes.type = NT_PRSTATUS;
+    notes.datasz = sizeof(struct elf32_arm_prstatus);
+    notes.data = &prstatus;
+
+    prstatus.pr_pid = cpu + 1;
+    memcpy(&prstatus.pr_reg, (unsigned long *)&mrdump_cb->crash_record.cpu_regs[cpu].arm32_regs, sizeof(elf_arm_gregset_t));
+
+    nhdr->p_filesz += notesize(&notes);
+    return storenote(&notes, bufp);
+}
+
+static uint8_t *kdump_core_write_machdesc(const struct mrdump_control_block *mrdump_cb, struct elf32_phdr *nhdr, uint8_t *bufp)
+{
+    struct memelfnote notes;
+    struct elf_mrdump_machdesc machdesc;
+    const struct mrdump_machdesc *kparams = &mrdump_cb->machdesc;
+
+    memset(&machdesc, 0, sizeof(struct elf_mrdump_machdesc));
+
+    notes.name = "MRDUMP01";
+    notes.type = NT_MRDUMP_MACHDESC;
+    notes.datasz = sizeof(struct elf_mrdump_machdesc);
+    notes.data = &machdesc;
+
+    machdesc.flags = MRDUMP_TYPE_FULL_MEMORY;
+    machdesc.nr_cpus = kparams->nr_cpus;
+    machdesc.phys_offset = kparams->phys_offset;
+    machdesc.page_offset = kparams->page_offset;
+    machdesc.high_memory = kparams->high_memory;
+    machdesc.kimage_vaddr = kparams->kimage_vaddr;
+    machdesc.modules_start = kparams->modules_start;
+    machdesc.modules_end = kparams->modules_end;
+    machdesc.vmalloc_start = kparams->vmalloc_start;
+    machdesc.vmalloc_end = kparams->vmalloc_end;
+    machdesc.master_page_table = kparams->master_page_table;
+
+    nhdr->p_filesz += notesize(&notes);
+    return storenote(&notes, bufp);
+}
+
+static uint8_t *kdump_core_write_mrdump_cb(const struct mrdump_control_block *mrdump_cb, struct elf32_phdr *nhdr, uint8_t *bufp)
+{
+    struct memelfnote notes;
+    uint64_t mrdump_cb_paddr = (uint64_t)(uintptr_t)kvaddr_to_paddr((void *)mrdump_cb);
+
+    notes.name = MRDUMP_GO_DUMP;
+    notes.type = NT_MRDUMP_CBLOCK;
+    notes.datasz = sizeof(mrdump_cb_paddr);
+    notes.data = &mrdump_cb_paddr;
+
+    nhdr->p_filesz += notesize(&notes);
+    return storenote(&notes, bufp);
+}
+
+void kdump_core32_header_init(const struct mrdump_control_block *mrdump_cb, const struct kzip_addlist *memlist)
+{
+    struct elf32_phdr *nhdr, *phdr;
+    struct elf32_hdr *elf;
+    off_t offset = 0;
+    const struct mrdump_machdesc *kparams = &mrdump_cb->machdesc;
+
+    uint8_t *bufp = (uint8_t *)(uintptr_t)memlist[0].address;
+
+    elf = (struct elf32_hdr *) bufp;
+    bufp += sizeof(struct elf32_hdr);
+    offset += sizeof(struct elf32_hdr);
+
+    nhdr = (struct elf32_phdr *) bufp;
+    bufp += sizeof(struct elf32_phdr);
+    offset += sizeof(struct elf32_phdr);
+    memset(nhdr, 0, sizeof(struct elf32_phdr));
+    nhdr->p_type = PT_NOTE;
+
+    unsigned long long foffset = KDUMP_CORE_HEADER_SIZE;
+    int i;
+    for (i = 1; memlist[i].address != 0; i++) {
+        phdr = (struct elf32_phdr *) bufp;
+        bufp += sizeof(struct elf32_phdr);
+        offset += sizeof(struct elf32_phdr);
+
+        phdr->p_type    = PT_LOAD;
+        phdr->p_flags   = PF_R|PF_W|PF_X;
+        phdr->p_offset  = foffset;
+        phdr->p_vaddr   = 0;
+        phdr->p_paddr   = (Elf32_Addr)kvaddr_to_paddr((void *)memlist[i].address);
+        phdr->p_filesz  = memlist[i].size;
+        phdr->p_memsz   = memlist[i].size;
+        phdr->p_align   = 0;
+
+        foffset += phdr->p_filesz;
+    }
+
+    mrdump_elf_setup_eident(elf->e_ident, ELFCLASS32);
+    mrdump_elf_setup_elfhdr(elf, EM_ARM, struct elf32_hdr, struct elf32_phdr, i);
+
+    nhdr->p_offset = offset;
+
+    /* NT_PRPSINFO */
+    struct elf32_prpsinfo prpsinfo;
+    struct memelfnote notes;
+    /* set up the process info */
+    notes.name = CORE_STR;
+    notes.type = NT_PRPSINFO;
+    notes.datasz = sizeof(struct elf32_prpsinfo);
+    notes.data = &prpsinfo;
+
+    memset(&prpsinfo, 0, sizeof(struct elf32_prpsinfo));
+    prpsinfo.pr_state = 0;
+    prpsinfo.pr_sname = 'R';
+    prpsinfo.pr_zomb = 0;
+    prpsinfo.pr_gid = prpsinfo.pr_uid = mrdump_cb->crash_record.fault_cpu + 1;
+    strlcpy(prpsinfo.pr_fname, "vmlinux", sizeof(prpsinfo.pr_fname));
+    strlcpy(prpsinfo.pr_psargs, "vmlinux", ELF_PRARGSZ);
+
+    nhdr->p_filesz += notesize(&notes);
+    bufp = storenote(&notes, bufp);
+
+    bufp = kdump_core_write_machdesc(mrdump_cb, nhdr, bufp);
+
+    /* Store pre-cpu backtrace */
+    bufp = kdump_core_write_cpu_note(mrdump_cb, mrdump_cb->crash_record.fault_cpu, nhdr, bufp);
+    for (unsigned int cpu = 0; cpu < kparams->nr_cpus; cpu++) {
+        if (cpu != mrdump_cb->crash_record.fault_cpu) {
+            bufp = kdump_core_write_cpu_note(mrdump_cb, cpu, nhdr, bufp);
+        }
+    }
+
+    /* store mrdump control block */
+    bufp = kdump_core_write_mrdump_cb(mrdump_cb, nhdr, bufp);
+}
diff --git a/src/bsp/lk/lib/aee/mrdump_elf64.c b/src/bsp/lk/lib/aee/mrdump_elf64.c
new file mode 100644
index 0000000..1420aff
--- /dev/null
+++ b/src/bsp/lk/lib/aee/mrdump_elf64.c
@@ -0,0 +1,241 @@
+/*
+ * Copyright (c) 2018 MediaTek Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include <kernel/vm.h>
+#include <malloc.h>
+#include <printf.h>
+#include <stdlib.h>
+#include <string.h>
+#include "kdump.h"
+#include "mrdump_elf64.h"
+
+struct memelfnote {
+    const char *name;
+    int type;
+    unsigned int datasz;
+    void *data;
+};
+
+static int notesize(struct memelfnote *en)
+{
+    int sz;
+
+    sz = sizeof(struct elf64_note);
+    sz += ROUNDUP((strlen(en->name) + 1), 4);
+    sz += ROUNDUP(en->datasz, 4);
+
+    return sz;
+}
+
+static uint8_t *storenote(struct memelfnote *men, uint8_t *bufp)
+{
+    struct elf64_note en;
+    en.n_namesz = strlen(men->name) + 1;
+    en.n_descsz = men->datasz;
+    en.n_type = men->type;
+
+    memcpy(bufp, &en, sizeof(en));
+    bufp += sizeof(en);
+
+    memcpy(bufp, men->name, en.n_namesz);
+    bufp += en.n_namesz;
+    bufp = (uint8_t *) ROUNDUP((uint64_t)bufp, 4);
+    memcpy(bufp, men->data, men->datasz);
+    bufp += men->datasz;
+
+    bufp = (uint8_t *) ROUNDUP((uint64_t)bufp, 4);
+    return bufp;
+}
+
+static uint8_t *kdump_core_write_cpu_note(const struct mrdump_control_block *mrdump_cb, int cpu, struct elf64_phdr *nhdr, uint8_t *bufp)
+{
+    struct memelfnote notes;
+    struct elf_arm64_prstatus64 prstatus;
+    char cpustr[16];
+
+    memset(&prstatus, 0, sizeof(struct elf_arm64_prstatus64));
+
+    snprintf(cpustr, sizeof(cpustr), "CPU%d", cpu);
+    /* set up the process status */
+    notes.name = cpustr;
+    notes.type = NT_PRSTATUS;
+    notes.datasz = sizeof(struct elf_arm64_prstatus64);
+    notes.data = &prstatus;
+
+    prstatus.pr_pid = cpu + 1;
+    memcpy(&prstatus.pr_reg, &mrdump_cb->crash_record.cpu_regs[cpu].arm64_regs, sizeof(elf_arm64_gregset_t));
+
+    nhdr->p_filesz += notesize(&notes);
+    return storenote(&notes, bufp);
+}
+
+static uint8_t *kdump_core_write_machdesc(const struct mrdump_control_block *mrdump_cb, struct elf64_phdr *nhdr, uint8_t *bufp)
+{
+    struct memelfnote notes;
+    struct elf_mrdump_machdesc machdesc;
+    const struct mrdump_machdesc *kparams = &mrdump_cb->machdesc;
+
+    memset(&machdesc, 0, sizeof(struct elf_mrdump_machdesc));
+
+    notes.name = "MRDUMP01";
+    notes.type = NT_MRDUMP_MACHDESC;
+    notes.datasz = sizeof(struct elf_mrdump_machdesc);
+    notes.data = &machdesc;
+
+    machdesc.flags = MRDUMP_TYPE_FULL_MEMORY;
+    machdesc.nr_cpus = kparams->nr_cpus;
+    machdesc.phys_offset = kparams->phys_offset;
+    machdesc.page_offset = kparams->page_offset;
+    machdesc.high_memory = kparams->high_memory;
+    machdesc.kimage_vaddr = kparams->kimage_vaddr;
+    machdesc.modules_start = kparams->modules_start;
+    machdesc.modules_end = kparams->modules_end;
+    machdesc.vmalloc_start = kparams->vmalloc_start;
+    machdesc.vmalloc_end = kparams->vmalloc_end;
+    machdesc.master_page_table = kparams->master_page_table;
+
+    nhdr->p_filesz += notesize(&notes);
+    return storenote(&notes, bufp);
+}
+
+static uint8_t *mrdump_elf64_write_vmcoreinfo(const struct mrdump_control_block *mrdump_cb, struct elf64_phdr *nhdr, uint8_t *bufp)
+{
+    struct memelfnote notes;
+    const struct mrdump_machdesc *kparams = &mrdump_cb->machdesc;
+    char vmcoreinfo[512];
+
+    memset(vmcoreinfo, 0, sizeof(vmcoreinfo));
+
+    notes.name = "VMCOREINFO";
+    notes.type = 0;
+    notes.datasz = 0;
+    notes.data = &vmcoreinfo;
+    snprintf(vmcoreinfo, sizeof(vmcoreinfo),
+             "PAGESIZE=4096\n"
+             "NUMBER(kimage_voffset)=0x%llx\n"
+             "SYMBOL(_stext)=0x%llx\n"
+             "NUMBER(VA_BITS)=%d\n"
+             "NUMBER(PHYS_OFFSET)=0x%llx\n",
+             (uint64_t)kparams->kimage_voffset,
+             (uint64_t)kparams->kimage_stext_real,
+             39,
+             (uint64_t)kparams->phys_offset);
+    notes.datasz = strlen(vmcoreinfo);
+
+    nhdr->p_filesz += notesize(&notes);
+    return storenote(&notes, bufp);
+}
+
+static uint8_t *kdump_core_write_mrdump_cb(const struct mrdump_control_block *mrdump_cb, struct elf64_phdr *nhdr, uint8_t *bufp)
+{
+    struct memelfnote notes;
+    uint64_t mrdump_cb_paddr = (uint64_t)(uintptr_t)kvaddr_to_paddr((void *)mrdump_cb);
+
+    notes.name = MRDUMP_GO_DUMP;
+    notes.type = NT_MRDUMP_CBLOCK;
+    notes.datasz = sizeof(mrdump_cb_paddr);
+    notes.data = &mrdump_cb_paddr;
+
+    nhdr->p_filesz += notesize(&notes);
+    return storenote(&notes, bufp);
+}
+
+void kdump_core64_header_init(const struct mrdump_control_block *mrdump_cb, const struct kzip_addlist *memlist)
+{
+    struct elf64_phdr *nhdr, *phdr;
+    struct elf64_hdr *elf;
+    off_t offset = 0;
+    const struct mrdump_machdesc *kparams = &mrdump_cb->machdesc;
+
+    uint8_t *bufp = (uint8_t *)(uintptr_t)memlist[0].address;
+
+    elf = (struct elf64_hdr *) bufp;
+    bufp += sizeof(struct elf64_hdr);
+    offset += sizeof(struct elf64_hdr);
+
+    nhdr = (struct elf64_phdr *) bufp;
+    bufp += sizeof(struct elf64_phdr);
+    offset += sizeof(struct elf64_phdr);
+    memset(nhdr, 0, sizeof(struct elf64_phdr));
+    nhdr->p_type = PT_NOTE;
+
+    unsigned long long foffset = KDUMP_CORE_HEADER_SIZE;
+    int i;
+    for (i = 1; memlist[i].address != 0; i++) {
+        phdr = (struct elf64_phdr *) bufp;
+        bufp += sizeof(struct elf64_phdr);
+        offset += sizeof(struct elf64_phdr);
+
+        phdr->p_type    = PT_LOAD;
+        phdr->p_flags   = PF_R|PF_W|PF_X;
+        phdr->p_offset  = foffset;
+        phdr->p_vaddr   = 0;
+        phdr->p_paddr   = (uint64_t)kvaddr_to_paddr((void *)memlist[i].address);
+        phdr->p_filesz  = memlist[i].size;
+        phdr->p_memsz   = memlist[i].size;
+        phdr->p_align   = 0;
+
+        foffset += phdr->p_filesz;
+    }
+
+    mrdump_elf_setup_eident(elf->e_ident, ELFCLASS64);
+    mrdump_elf_setup_elfhdr(elf, EM_AARCH64, struct elf64_hdr, struct elf64_phdr, i);
+    dprintf(CRITICAL, "%s after\n", __func__);
+
+    nhdr->p_offset = offset;
+
+    /* NT_PRPSINFO */
+    struct elf_prpsinfo64 prpsinfo;
+    struct memelfnote notes;
+    /* set up the process info */
+    notes.name = CORE_STR;
+    notes.type = NT_PRPSINFO;
+    notes.datasz = sizeof(struct elf_prpsinfo64);
+    notes.data = &prpsinfo;
+
+    memset(&prpsinfo, 0, sizeof(struct elf_prpsinfo64));
+    prpsinfo.pr_state = 0;
+    prpsinfo.pr_sname = 'R';
+    prpsinfo.pr_zomb = 0;
+    prpsinfo.pr_gid = prpsinfo.pr_uid = mrdump_cb->crash_record.fault_cpu + 1;
+    strlcpy(prpsinfo.pr_fname, "vmlinux", sizeof(prpsinfo.pr_fname));
+    strlcpy(prpsinfo.pr_psargs, "vmlinux", ELF_PRARGSZ);
+
+    nhdr->p_filesz += notesize(&notes);
+    bufp = storenote(&notes, bufp);
+
+    bufp = kdump_core_write_machdesc(mrdump_cb, nhdr, bufp);
+    bufp = mrdump_elf64_write_vmcoreinfo(mrdump_cb, nhdr, bufp);
+
+    /* Store pre-cpu backtrace */
+    bufp = kdump_core_write_cpu_note(mrdump_cb, mrdump_cb->crash_record.fault_cpu, nhdr, bufp);
+    for (unsigned int cpu = 0; cpu < kparams->nr_cpus; cpu++) {
+        if (cpu != mrdump_cb->crash_record.fault_cpu) {
+            bufp = kdump_core_write_cpu_note(mrdump_cb, cpu, nhdr, bufp);
+        }
+    }
+    dprintf(CRITICAL, "%s %d\n", __func__, __LINE__);
+
+    /* store mrdump control block */
+    bufp = kdump_core_write_mrdump_cb(mrdump_cb, nhdr, bufp);
+}
diff --git a/src/bsp/lk/lib/aee/mrdump_rsvmem.c b/src/bsp/lk/lib/aee/mrdump_rsvmem.c
new file mode 100644
index 0000000..c203c3e
--- /dev/null
+++ b/src/bsp/lk/lib/aee/mrdump_rsvmem.c
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2018 MediaTek Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include <lib/kcmdline.h>
+#include <printf.h>
+#include <stdarg.h>
+
+#define RSV_MEM_LEN 128
+
+void aee_reserve_memory(char *str, ...)
+{
+    char aee_rsv_mem[RSV_MEM_LEN] = {0};
+    va_list ap;
+
+    va_start(ap, str);
+    vsnprintf(aee_rsv_mem, RSV_MEM_LEN - 1, str, ap);
+    va_end(ap);
+    kcmdline_append(aee_rsv_mem);
+}
diff --git a/src/bsp/lk/lib/aee/mrdump_sddev.c b/src/bsp/lk/lib/aee/mrdump_sddev.c
new file mode 100644
index 0000000..6149eb0
--- /dev/null
+++ b/src/bsp/lk/lib/aee/mrdump_sddev.c
@@ -0,0 +1,143 @@
+/*
+ * Copyright (c) 2018 MediaTek Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include <lib/bio.h>
+#include <malloc.h>
+#include <platform/mtk_mrdump.h>
+#include <stddef.h>
+#include <stdint.h>
+#include "aee.h"
+#include "kdump.h"
+#include "kdump_sdhc.h"
+
+static char *part_device_init(struct mrdump_dev *dev, const char *part_name)
+{
+    dev->bdev = bio_open_by_label(part_name);
+
+    if (!dev->bdev)
+        return NULL;
+
+    voprintf_info("%s size: %lu Mb\n", part_name, (dev->bdev->total_size) / 0x100000UL);
+
+    return (char *) part_name;
+}
+
+static bool part_device_read(struct mrdump_dev *dev, uint64_t offset, uint8_t *buf, int32_t len)
+{
+    if (dev == NULL) {
+        voprintf_error("%s dev is NULL!\n", __func__);
+        return false;
+    } else {
+        return bio_read(dev->bdev, buf, offset, len) == len;
+    }
+}
+
+static bool part_device_write(struct mrdump_dev *dev, uint64_t offset, uint8_t *buf, int32_t len)
+{
+    if (dev == NULL) {
+        voprintf_error("%s dev is NULL!\n", __func__);
+        return false;
+    } else {
+        return bio_write(dev->bdev, buf, offset, len) == len;
+    }
+}
+
+struct mrdump_dev *mrdump_dev_emmc_vfat(void)
+{
+    char *fatpart;
+    struct mrdump_dev *dev = malloc(sizeof(struct mrdump_dev));
+    if (!dev) {
+        voprintf_error("%s: malloc() failed!\n", __func__);
+        return NULL;
+    }
+
+    fatpart = part_device_init(0, "intsd");
+    if (fatpart == NULL) {
+        voprintf_error("No VFAT partition found!\n");
+        free(dev);
+        return NULL;
+    }
+    dev->name = "emmc";
+    dev->handle = fatpart;
+    dev->read = part_device_read;
+    dev->write = part_device_write;
+    return dev;
+}
+
+static char *mrdump_get_ext4_partition(struct mrdump_dev *dev)
+{
+    char *ext4part;
+
+    ext4part = part_device_init(dev, MRDUMP_OUTPUT_PARTITION);
+    if (ext4part != NULL)
+        return ext4part;
+
+    return NULL;
+}
+
+struct mrdump_dev *mrdump_dev_emmc_ext4(void)
+{
+    char *ext4part;
+    struct mrdump_dev *dev = malloc(sizeof(struct mrdump_dev));
+    if (!dev) {
+        voprintf_error("%s: malloc() failed!\n", __func__);
+        return NULL;
+    }
+
+    ext4part = mrdump_get_ext4_partition(dev);
+    if (ext4part == NULL) {
+        voprintf_error("No EXT4 partition found!\n");
+        free(dev);
+        return NULL;
+    }
+    dev->name = "emmc";
+    dev->handle = ext4part;
+    dev->read = part_device_read;
+    dev->write = part_device_write;
+    return dev;
+}
+
+
+#if 0
+static bool mrdump_dev_sdcard_read(struct mrdump_dev *dev, uint32_t sector_addr, uint8_t *pdBuf, int32_t blockLen)
+{
+    return mmc_wrap_bread(1, sector_addr, blockLen, pdBuf) == 1;
+}
+
+static bool mrdump_dev_sdcard_write(struct mrdump_dev *dev, uint32_t sector_addr, uint8_t *pdBuf, int32_t blockLen)
+{
+    return mmc_wrap_bwrite(1, sector_addr, blockLen, pdBuf) == 1;
+}
+
+struct mrdump_dev *mrdump_dev_sdcard(void)
+{
+    struct mrdump_dev *dev = malloc(sizeof(struct mrdump_dev));
+    dev->name = "sdcard";
+    dev->handle = NULL;
+    dev->read = mrdump_dev_sdcard_read;
+    dev->write = mrdump_dev_sdcard_write;
+
+    mmc_legacy_init(2);
+    return dev;
+}
+#endif
diff --git a/src/bsp/lk/lib/aee/mrdump_setup.c b/src/bsp/lk/lib/aee/mrdump_setup.c
new file mode 100644
index 0000000..be9495d
--- /dev/null
+++ b/src/bsp/lk/lib/aee/mrdump_setup.c
@@ -0,0 +1,212 @@
+/*
+ * Copyright (c) 2018 MediaTek Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include <arch/ops.h>
+#include <boot_args.h>
+#include <env.h>
+#include <lib/kcmdline.h>
+#include <libfdt.h>
+#include <malloc.h>
+#include <mrdump.h>
+#include <platform.h>
+#include <platform/mtk_wdt.h>
+#include <platform/platform_blx.h>
+#include <printf.h>
+#include <ram_console.h>
+#include <stdarg.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include "aee.h"
+#include "kdump.h"
+
+extern BOOT_ARGUMENT *g_boot_arg;
+extern int kedump_restore_mem(void);
+
+#define MRDUMP_RSV_MEM      "mrdump_rsvmem=0x%x,0x%x,0x%x,0x%x,0x%x,0x%x,0x%x,0x%x,0x%x,0x%x"
+#define MRDUMP_CB_RSV_MEM   "mrdump_cb=0x%x,0x%x"
+#define RAM_CONSOLE_RSV_MEM "ram_console_rsvmem=0x%x,0x%x"
+#define MINIDUMP_RSV_MEM    "minirdump_rsvmem=0x%x,0x%x"
+#define PSTORE_RSV_MEM      "pstore_rsvmem=0x%x,0x%x,0x%x,0x%x"
+
+unsigned int get_reboot_reason(unsigned int boot_reason)
+{
+    unsigned int rc_wdt_status;
+    unsigned int rc_exp_type;
+    unsigned int ret = 0;
+    if (boot_reason == BR_WDT_BY_PASS_PWK) {
+        if (ram_console_get_wdt_status(&rc_wdt_status) && ram_console_get_exp_type(&rc_exp_type)){
+        dprintf(CRITICAL, "rc_wdt_status = %d, rc_exp_type = %d\n", rc_wdt_status, rc_exp_type);
+        switch (rc_exp_type) {
+            case 0:
+                if (rc_wdt_status == 5)
+                    ret = REBOOT_REASON_WATCHDOG;
+                break;
+            case AEE_EXP_TYPE_HWT:
+                ret = REBOOT_REASON_WATCHDOG;
+                break;
+            case AEE_EXP_TYPE_DM_VERITY_CORRUPTION:
+                ret = REBOOT_REASON_DM_VERITY_CORRUPTION;
+                break;
+            case AEE_EXP_TYPE_KE:
+            case AEE_EXP_TYPE_NESTED_PANIC:
+                ret = REBOOT_REASON_KERNEL_PANIC;
+                break;
+            default:
+                break;
+            }
+        }
+    }
+    else if (boot_reason == BR_2SEC_REBOOT) {
+        ret = REBOOT_REASON_2S_REBOOT;
+    } else {
+        ret = REBOOT_REASON_REBOOT;
+    }
+    return ret;
+}
+
+static void mrdump_ddr_reserved_mode_control(void)
+{
+    if (g_boot_arg->ddr_reserve_ready != AEE_MRDUMP_DDR_RSV_READY) {
+        kcmdline_append("mrdump_ddrsv=no");
+        dprintf(CRITICAL, "MT-RAMDUMP: DDR reserve mode not ready, skipped (0x%x)\n",
+            g_boot_arg->ddr_reserve_ready);
+    } else
+        kcmdline_append("mrdump_ddrsv=yes");
+}
+
+void mrdump_setup_boot_reason(void)
+{
+    unsigned int boot_reason = 0;
+    unsigned int reboot_reason = 0;
+    char tmpbuf[128];
+    unsigned int len_bootreason=0;
+    const char aee_reboot_reason[][20] = {"reboot", "watchdog", "kernel_panic", "oemerr_2sec_reboot","dmveri_corruption"};
+
+    boot_reason = platform_boot_status();
+    reboot_reason=get_reboot_reason(boot_reason);
+    len_bootreason = strlen(" androidboot.bootreason=") + strlen(aee_reboot_reason[reboot_reason]);
+    snprintf(tmpbuf,len_bootreason,"%s%s", "androidboot.bootreason=",aee_reboot_reason[reboot_reason]);
+    dprintf(CRITICAL, "tmpbuf %s\n", tmpbuf);
+    kcmdline_append(tmpbuf);
+}
+
+void mrdump_append_cmdline(void)
+{
+    mrdump_ddr_reserved_mode_control();
+    /* mrdump control block reserve memory*/
+#ifdef MTK_MRDUMP_SRAM_CB
+    aee_reserve_memory(MRDUMP_CB_RSV_MEM, MRDUMP_CB_ADDR, MRDUMP_CB_SIZE);
+#endif
+
+    /* mrdump reserve memory*/
+    aee_reserve_memory(MRDUMP_RSV_MEM, MEMBASE, AEE_MRDUMP_LK_RSV_SIZE,
+            DRAM_BOOTARG_BASE, DRAM_BOOTARG_SIZE, DRAM_ARENA_BASE,
+            DRAM_ARENA_SIZE, kvaddr_to_paddr((void *)UNCACHED_MEMPOOL_ADDR),
+            UNCACHED_MEMPOOL_SIZE, kvaddr_to_paddr((void *)CACHED_MEMPOOL_ADDR),
+            CACHED_MEMPOOL_SIZE);
+
+    /* ram_console reserve memory*/
+#if RAM_CONSOLE_DRAM_ADDR
+    aee_reserve_memory(RAM_CONSOLE_RSV_MEM, RAM_CONSOLE_DEF_ADDR,
+            RAM_CONSOLE_DEF_SIZE);
+#endif
+
+    /* minidump reserve memory*/
+#if MINIRDUMP_MEM_ADDR
+    aee_reserve_memory(MINIDUMP_RSV_MEM, MINIRDUMP_MEM_ADDR,
+            MINIRDUMP_MEM_SIZE);
+#endif
+
+    /* pstore reserve memory*/
+#if PSTORE_RESERVE_ADDR
+    aee_reserve_memory(PSTORE_RSV_MEM, PSTORE_RESERVE_ADDR, PSTORE_RESERVE_SIZE,
+            PSTORE_CONSOEL_SIZE, PSTORE_PMSG_SIZE);
+#endif
+    mrdump_setup_version();
+    mrdump_setup_boot_reason();
+}
+
+static int kedump_get_bootreason(unsigned int wdt_status)
+{
+    unsigned int g_rgu_status = 0;
+
+    if (wdt_status & MTK_WDT_STATUS_HWWDT_RST) {
+        /* For E1 bug, that SW reset value is 0xC000, we using "==" to check */
+        /* Time out reboot always by pass power key */
+        g_rgu_status = RE_BOOT_BY_WDT_HW;
+    } else if (wdt_status & MTK_WDT_STATUS_SWWDT_RST) {
+        g_rgu_status = RE_BOOT_BY_WDT_SW;
+    } else {
+        g_rgu_status = RE_BOOT_REASON_UNKNOW;
+    }
+
+    if (wdt_status & MTK_WDT_STATUS_IRQWDT_RST) {
+        g_rgu_status |= RE_BOOT_WITH_INTTERUPT;
+    }
+#ifdef MTK_THERMAL_RESET_SUPPORT
+    if (wdt_status & MTK_WDT_STATUS_SPM_THERMAL_RST) {
+        g_rgu_status |= RE_BOOT_BY_SPM_THERMAL;
+    }
+#endif
+    if (wdt_status & MTK_WDT_STATUS_SPMWDT_RST) {
+        g_rgu_status |= RE_BOOT_BY_SPM;
+    }
+    if (wdt_status & MTK_WDT_STATUS_THERMAL_CTL_RST) {
+        g_rgu_status |= RE_BOOT_BY_THERMAL_DIRECT;
+    }
+    if (wdt_status & MTK_WDT_STATUS_DEBUGWDT_RST) {
+        g_rgu_status |= RE_BOOT_BY_DEBUG;
+    }
+    if (wdt_status & MTK_WDT_STATUS_SECURITY_RST) {
+        g_rgu_status |= RE_BOOT_BY_SECURITY;
+    }
+
+#ifdef MTK_PMIC_FULL_RESET
+    if (mtk_wdt_is_pmic_full_reset())
+        g_rgu_status |= RE_BOOT_BY_PMIC_FULL_RST;
+#endif
+    return g_rgu_status;
+}
+
+int kedump_init(void)
+{
+    static int kedump_dumped = 0;
+    unsigned int boot_reason = kedump_get_bootreason(g_boot_arg->boot_reason);
+
+    pl_ram_console_init();
+    ram_console_reboot_reason_save(boot_reason);
+
+    ram_console_init();
+
+    /* this flow should be executed once only */
+    if (kedump_dumped == 0) {
+        kedump_dumped = 1;
+        if (ram_console_is_abnormal_boot())
+            return -1;
+    }
+
+    // for power lost or reboot before KE DB collected scenario
+    kedump_restore_mem();
+    return 0;
+}
diff --git a/src/bsp/lk/lib/aee/platform_debug.c b/src/bsp/lk/lib/aee/platform_debug.c
new file mode 100644
index 0000000..8854e16
--- /dev/null
+++ b/src/bsp/lk/lib/aee/platform_debug.c
@@ -0,0 +1,241 @@
+/*
+ * Copyright (c) 2018 MediaTek Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include <arch/arm/mmu.h>
+#include <dev/aee_platform_debug.h>
+#include <part_interface.h>
+#include <platform/plat_atf_dbg_info.h>
+#include <printf.h>
+#include <stdlib.h>
+
+unsigned int (* plat_dfd20_get)(u64 offset, int *len, CALLBACK dev_write) = NULL;
+unsigned int (* plat_dram_get)(u64 offset, int *len, CALLBACK dev_write) = NULL;
+unsigned int (* plat_cpu_bus_get)(u64 offset, int *len, CALLBACK dev_write) = NULL;
+unsigned int (* plat_spm_data_get)(u64 offset, int *len, CALLBACK dev_write) = NULL;
+unsigned int (* plat_spm_sram_data_get)(u64 offset, int *len, CALLBACK dev_write) = NULL;
+unsigned int (* plat_atf_log_get)(u64 offset, int *len, CALLBACK dev_write) = NULL;
+unsigned int (* plat_atf_crash_get)(u64 offset, int *len, CALLBACK dev_write) = NULL;
+unsigned int (* plat_atf_raw_log_get)(u64 offset, int *len, CALLBACK dev_write) = NULL;
+unsigned int (* plat_atf_rdump_get)(u64 offset, int *len, CALLBACK dev_write) = NULL;
+unsigned int (* plat_hvfs_get)(u64 offset, int *len, CALLBACK dev_write) = NULL;
+#ifdef MTK_TINYSYS_SSPM_SUPPORT
+unsigned int (* plat_sspm_coredump_get)(u64 offset, int *len, CALLBACK dev_write) = NULL;
+unsigned int (* plat_sspm_data_get)(u64 offset, int *len, CALLBACK dev_write) = NULL;
+unsigned int (* plat_sspm_xfile_get)(u64 offset, int *len, CALLBACK dev_write) = NULL;
+unsigned int (* plat_sspm_log_get)(u64 offset, int *len, CALLBACK dev_write) = NULL;
+#endif
+unsigned int (* plat_pllk_last_log_get)(u64 offset, int *len, CALLBACK dev_write) = NULL;
+unsigned int (* plat_dur_lkdump_get)(u64 offset, int *len, CALLBACK dev_write) = NULL;
+unsigned int (* plat_mcdi_get)(u64 offset, int *len, CALLBACK dev_write) = NULL;
+#ifdef MTK_TINYSYS_SCP_SUPPORT
+unsigned int (* plat_scp_coredump_get)(u64 offset, int *len, CALLBACK dev_write) = NULL;
+#endif
+
+/* in case that platform didn't support platform_debug_init() */
+int platform_debug_init(void) __attribute__((weak));
+int platform_debug_init(void)
+{
+    return 0;
+}
+
+int lkdump_debug_init(void)
+{
+    if (g_boot_arg->boot_mode != DOWNLOAD_BOOT)
+        atf_log_init();
+
+    return platform_debug_init();
+}
+
+/* function pointer should be set after platform_debug_init() */
+unsigned int kedump_plat_savelog(int condition, u64 offset, int *len, CALLBACK dev_write)
+{
+    switch (condition) {
+        case AEE_PLAT_DFD20:
+            return (!plat_dfd20_get ? 0 : plat_dfd20_get(offset, len, dev_write));
+        case AEE_PLAT_DRAM:
+            return (!plat_dram_get ? 0 : plat_dram_get(offset, len, dev_write));
+        case AEE_PLAT_CPU_BUS:
+            return (!plat_cpu_bus_get ? 0 : plat_cpu_bus_get(offset, len, dev_write));
+        case AEE_PLAT_SPM_DATA:
+            return (!plat_spm_data_get ? 0 : plat_spm_data_get(offset, len, dev_write));
+        case AEE_PLAT_SPM_SRAM_DATA:
+            return (!plat_spm_sram_data_get ? 0 : plat_spm_sram_data_get(offset, len, dev_write));
+        case AEE_PLAT_ATF_LAST_LOG:
+            return (!plat_atf_log_get ? 0 : plat_atf_log_get(offset, len, dev_write));
+        case AEE_PLAT_ATF_CRASH_REPORT:
+            return (!plat_atf_crash_get ? 0 : plat_atf_crash_get(offset, len, dev_write));
+        case AEE_PLAT_ATF_RAW_LOG:
+            return (!plat_atf_raw_log_get ? 0 : plat_atf_raw_log_get(offset, len, dev_write));
+        case AEE_PLAT_ATF_RDUMP_LOG:
+            return (!plat_atf_rdump_get ? 0 : plat_atf_rdump_get(offset, len, dev_write));
+        case AEE_PLAT_HVFS:
+            return (!plat_hvfs_get ? 0 : plat_hvfs_get(offset, len, dev_write));
+#ifdef MTK_TINYSYS_SSPM_SUPPORT
+        case AEE_PLAT_SSPM_COREDUMP:
+            return (!plat_sspm_coredump_get ? 0 : plat_sspm_coredump_get(offset, len, dev_write));
+        case AEE_PLAT_SSPM_DATA:
+            return (!plat_sspm_data_get ? 0 : plat_sspm_data_get(offset, len, dev_write));
+        case AEE_PLAT_SSPM_XFILE:
+            return (!plat_sspm_xfile_get ? 0 : plat_sspm_xfile_get(offset, len, dev_write));
+        case AEE_PLAT_SSPM_LAST_LOG:
+            return (!plat_sspm_log_get ? 0 : plat_sspm_log_get(offset, len, dev_write));
+#endif
+        case AEE_PLAT_PLLK_LAST_LOG:
+            return (!plat_pllk_last_log_get ? 0 : plat_pllk_last_log_get(offset, len, dev_write));
+        case AEE_PLAT_LOG_DUR_LKDUMP:
+            return (!plat_dur_lkdump_get ? 0 : plat_dur_lkdump_get(offset, len, dev_write));
+        case AEE_PLAT_MCDI_DATA:
+            return (!plat_mcdi_get ? 0 : plat_mcdi_get(offset, len, dev_write));
+#ifdef MTK_TINYSYS_SCP_SUPPORT
+        case AEE_PLAT_SCP_COREDUMP:
+            return (!plat_scp_coredump_get ? 0 : plat_scp_coredump_get(offset, len, dev_write));
+#endif
+        default:
+            break;
+    }
+    return 0;
+}
+
+void mrdump_write_log(u64 offset_dst, void *data, int len)
+{
+    dprintf(CRITICAL, "%s: Enter\n", __func__);
+
+    if ((offset_dst > MRDUMP_EXPDB_DRAM_KLOG_OFFSET) || (offset_dst < MRDUMP_EXPDB_BOTTOM_OFFSET)) {
+        dprintf(CRITICAL, "%s: access not permitted. offset(0x%llx).\n", __func__, offset_dst);
+        return;
+    }
+
+    if ((offset_dst - len) < MRDUMP_EXPDB_BOTTOM_OFFSET) {
+        dprintf(CRITICAL, "%s: log size(0x%x) too big.\n", __func__, len);
+        return;
+    }
+
+    int index = partition_get_index("expdb");
+    part_dev_t *dev = mt_part_get_device();
+    if (index == -1 || dev == NULL) {
+        dprintf(CRITICAL, "%s: no %s partition[%d]\n", __func__, "expdb", index);
+        return;
+    }
+#if defined(MTK_NEW_COMBO_EMMC_SUPPORT)  || defined(MTK_TLC_NAND_SUPPORT) || defined(MTK_MLC_NAND_SUPPORT) || defined(MTK_UFS_SUPPORT)
+    int part_id = partition_get_region(index);
+#endif
+    u64 part_size = partition_get_size(index);
+    if (part_size < offset_dst) {
+        dprintf(CRITICAL, "%s: partition size(%llx) is less then reserved (%llx)\n", __func__, part_size, offset_dst);
+        return;
+    }
+    u64 part_offset = partition_get_offset(index) + part_size - offset_dst;
+
+    dprintf(CRITICAL, "%s: offset %lld size %lld\n", __func__, part_offset, part_size);
+
+#if defined(MTK_EMMC_SUPPORT) || defined(MTK_UFS_SUPPORT)
+#if defined(MTK_NEW_COMBO_EMMC_SUPPORT) || defined(MTK_UFS_SUPPORT)
+    dev->write(dev, (uchar *)data, part_offset, len, part_id);
+#else
+    dev->write(dev, (uchar *)data, part_offset, len);
+#endif
+#else
+    dev->write(dev, (uchar *)data, part_offset, len, part_id);
+#endif
+}
+
+void mrdump_read_log(void *data, int len, u64 offset_src)
+{
+    dprintf(CRITICAL, "%s: Enter\n", __func__);
+
+    if ((offset_src > MRDUMP_EXPDB_DRAM_KLOG_OFFSET) || (offset_src < MRDUMP_EXPDB_BOTTOM_OFFSET)) {
+        dprintf(CRITICAL, "%s: access not permitted. offset(0x%llx).\n", __func__, offset_src);
+        return;
+    }
+
+    if ((offset_src - len) < MRDUMP_EXPDB_BOTTOM_OFFSET) {
+        dprintf(CRITICAL, "%s: log size(0x%x) too big.\n", __func__, len);
+        return;
+    }
+
+    int index = partition_get_index("expdb");
+    part_dev_t *dev = mt_part_get_device();
+    if (index == -1 || dev == NULL) {
+        dprintf(CRITICAL, "%s: no %s partition[%d]\n", __func__, "expdb", index);
+        return;
+    }
+#if defined(MTK_NEW_COMBO_EMMC_SUPPORT) || defined(MTK_TLC_NAND_SUPPORT) || defined(MTK_MLC_NAND_SUPPORT) || defined(MTK_UFS_SUPPORT)
+    int part_id = partition_get_region(index);
+#endif
+    u64 part_size = partition_get_size(index);
+    if (part_size < offset_src) {
+        dprintf(CRITICAL, "%s: partition size(%llx) is less then reserved (%llx)\n", __func__, part_size, offset_src);
+        return;
+    }
+    u64 part_offset = partition_get_offset(index) + part_size - offset_src;
+
+    dprintf(CRITICAL, "%s: offset %lld size %lld\n", __func__, part_offset, part_size);
+
+#if defined(MTK_EMMC_SUPPORT) || defined(MTK_UFS_SUPPORT)
+#if defined(MTK_NEW_COMBO_EMMC_SUPPORT) || defined(MTK_UFS_SUPPORT)
+    dev->read(dev, part_offset, (uchar *)data, len, part_id);
+#else
+    dev->read(dev, part_offset, (uchar *)data, len);
+#endif
+#else
+    dev->read(dev, part_offset, (uchar *)data, len, part_id);
+#endif
+}
+
+void mrdump_read_expdb(void *data, int len, u64 offset_src)
+{
+    dprintf(CRITICAL, "%s: Enter\n", __func__);
+
+    int index = partition_get_index("expdb");
+    part_dev_t *dev = mt_part_get_device();
+    if (index == -1 || dev == NULL) {
+        dprintf(CRITICAL, "%s: no %s partition[%d]\n", __func__, "expdb", index);
+        return;
+    }
+#if defined(MTK_NEW_COMBO_EMMC_SUPPORT) || defined(MTK_TLC_NAND_SUPPORT) || defined(MTK_MLC_NAND_SUPPORT) || defined(MTK_UFS_SUPPORT)
+    int part_id = partition_get_region(index);
+#endif
+    u64 part_size = partition_get_size(index);
+    if (part_size < offset_src) {
+        dprintf(CRITICAL, "%s: partition size(%llx) is less then reserved (%llx)\n", __func__, part_size, offset_src);
+        return;
+    }
+    if ((offset_src + len) > (part_size - MRDUMP_EXPDB_DRAM_KLOG_OFFSET)) {
+        dprintf(CRITICAL, "%s: log size(0x%x) too big.\n", __func__, len);
+        return;
+    }
+    u64 part_offset = partition_get_offset(index) + offset_src;
+
+    dprintf(CRITICAL, "%s: offset %lld size %lld\n", __func__, part_offset, part_size);
+
+#if defined(MTK_EMMC_SUPPORT) || defined(MTK_UFS_SUPPORT)
+#if defined(MTK_NEW_COMBO_EMMC_SUPPORT) || defined(MTK_UFS_SUPPORT)
+    dev->read(dev, part_offset, (uchar *)data, len, part_id);
+#else
+    dev->read(dev, part_offset, (uchar *)data, len);
+#endif
+#else
+    dev->read(dev, part_offset, (uchar *)data, len, part_id);
+#endif
+}
+
diff --git a/src/bsp/lk/lib/aee/ram_console.c b/src/bsp/lk/lib/aee/ram_console.c
new file mode 100644
index 0000000..02078dd
--- /dev/null
+++ b/src/bsp/lk/lib/aee/ram_console.c
@@ -0,0 +1,346 @@
+/*
+ * Copyright (c) 2018 MediaTek Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include <arch/mmu.h>
+#include <platform/mtk_wdt.h>
+#include <ram_console.h>
+#include <stdio.h>
+#include <stdlib.h>     // for ALIGN()
+#include <string.h>
+#include <sys/types.h>
+
+#define RAM_CONSOLE_SIG (0x43474244) /* DBGC */
+#define MOD "RAM_CONSOLE"
+
+struct ram_console_buffer {
+    u32 sig;
+    /* for size comptible */
+    u32 off_pl;
+    u32 off_lpl;
+    u32 sz_pl;
+    u32 off_lk;
+    u32 off_llk; /* last lk */
+    u32 sz_lk;
+    u32 padding[2]; /* size = 2 * 16 = 32 byte */
+    u32 dump_step;
+    u32 sz_buffer;
+    u32 off_linux;
+    u32 off_console;
+    u32 padding2[3];
+};
+
+#define RAM_CONSOLE_PL_SIZE 3
+struct reboot_reason_pl {
+    u32 wdt_status;
+    u32 last_func[RAM_CONSOLE_PL_SIZE];
+};
+
+#define RAM_CONSOLE_LK_SIZE 16
+struct reboot_reason_lk {
+    u32 last_func[RAM_CONSOLE_LK_SIZE];
+};
+
+struct reboot_reason_kernel {
+    u32 fiq_step;
+    /* 0xaeedeadX: X=1 (HWT), X=2 (KE), X=3 (nested panic) */
+    /* details see enum AEE_EXP_TYPE_NUM in ram_console_common.h */
+    u32 exp_type;
+    u32 others[0];
+};
+
+static struct ram_console_buffer *ram_console = NULL;
+static uint32_t ram_console_size;
+
+#define U_VAR(type) rc_##type
+static unsigned int U_VAR(wdt_status), U_VAR(fiq_step), U_VAR(exp_type);
+static bool U_VAR(set_flag) = false;
+
+static void ram_console_ptr_init(void)
+{
+    if (ram_console && ram_console_size) {
+        LOG("%s. already init start: 0x%zx, size: 0x%x, sig: 0x%x\n",
+             MOD, (size_t)ram_console, ram_console_size, ram_console->sig);
+        return;
+    }
+
+    ram_console = (struct ram_console_buffer *)PA_TO_VA((paddr_t)RAM_CONSOLE_DEF_ADDR);
+    ram_console_size = RAM_CONSOLE_DEF_SIZE;
+    LOG("%s. pa start: 0x%zx, size: 0x%x\n", MOD, (size_t)RAM_CONSOLE_DEF_ADDR, RAM_CONSOLE_DEF_SIZE);
+}
+
+int sLOG(const char *fmt, ...)
+{
+    va_list args;
+    static int pos = 0;
+    va_start(args, fmt);
+    if (pos < SZLOG - 1) /* vsnprintf bug */
+        pos += vsnprintf(logbuf + pos, SZLOG - pos - 1, fmt, args);
+    va_end(args);
+    return 0;
+}
+
+void pl_ram_console_init(void)
+{
+    int i;
+    struct reboot_reason_pl *rr_pl;
+    ram_console = (struct ram_console_buffer *)PA_TO_VA((paddr_t)RAM_CONSOLE_DEF_ADDR);
+    ram_console_size = RAM_CONSOLE_DEF_SIZE;
+    LOG("pl_ram_console_init ram_console pa: 0x%zx, va:0x%zx, size: 0x%x\n",
+         (size_t)RAM_CONSOLE_DEF_ADDR, (size_t)ram_console, RAM_CONSOLE_DEF_SIZE);
+
+    if (ram_console->sig == RAM_CONSOLE_SIG && ram_console->sz_pl == sizeof(struct reboot_reason_pl)
+        && ram_console->off_pl + ALIGN(ram_console->sz_pl, 64) == ram_console->off_lpl) {
+        rr_pl = (void *)ram_console + ram_console->off_pl;
+        for (i = 0; i < RAM_CONSOLE_PL_SIZE; i++) {
+            LOG("0x%x ", rr_pl->last_func[i]);
+        }
+        LOG("\n");
+        memcpy((void *)ram_console + ram_console->off_lpl, (void *)ram_console + ram_console->off_pl,
+            ram_console->sz_pl);
+    } else {
+        memset(ram_console, 0, ram_console_size);
+        ram_console->sig = RAM_CONSOLE_SIG;
+        ram_console->off_pl = sizeof(struct ram_console_buffer);
+        ram_console->sz_pl = sizeof(struct reboot_reason_pl);
+        ram_console->off_lpl = ram_console->off_pl + ALIGN(ram_console->sz_pl, 64);
+        LOG("pl_ram_console_init first init\n");
+    }
+}
+
+void ram_console_init(void)
+{
+    int i;
+    struct reboot_reason_lk *rr_lk;
+
+    ram_console_ptr_init();
+    if (ram_console) {
+        LOG("%s. start: 0x%lx, size: 0x%x\n", MOD, (size_t)ram_console, ram_console_size);
+    } else {
+        LOG("%s. sig not match\n", MOD);
+        return;
+    }
+
+    ram_console->off_lk = ram_console->off_lpl + ALIGN(ram_console->sz_pl, 64);;
+    ram_console->off_llk = ram_console->off_lk + ALIGN(sizeof(struct reboot_reason_lk), 64);
+    ram_console->sz_lk = sizeof(struct reboot_reason_lk);
+    if (ram_console->sz_lk == sizeof(struct reboot_reason_lk) && (ram_console->off_lk +
+        ram_console->sz_lk == ram_console->off_llk)) {
+        LOG("%s. lk last status: ", MOD);
+        rr_lk = (void *)ram_console + ram_console->off_lk;
+        for (i = 0; i < RAM_CONSOLE_LK_SIZE; i++) {
+            LOG("0x%x ", rr_lk->last_func[i]);
+        }
+        LOG("\n");
+        memcpy((void *)ram_console + ram_console->off_llk, (void *)ram_console +
+            ram_console->off_lk, ram_console->sz_lk);
+    } else {
+        LOG("%s. lk size mismatch %x + %x != %x\n", MOD, ram_console->sz_lk,
+            ram_console->off_lk, ram_console->off_llk);
+        ram_console->sz_lk = sizeof(struct reboot_reason_lk);
+    }
+    ram_console->off_linux = ram_console->off_llk + ALIGN(ram_console->sz_lk, 64);
+}
+
+void ram_console_reboot_reason_save(u32 rgu_status)
+{
+    struct reboot_reason_pl *rr_pl;
+    if (ram_console) {
+        rr_pl = (void *)ram_console + ram_console->off_pl;
+        rr_pl->wdt_status = rgu_status;
+        LOG("%s wdt status (0x%x)=0x%x\n", MOD, rr_pl->wdt_status, rgu_status);
+    }
+}
+
+//#define RE_BOOT_BY_WDT_SW 2
+#define RE_BOOT_NORMAL_BOOT 0
+#define RE_BOOT_BY_EINT 256/*we can find the definition from preloader ,this value should  sync with preloader incase issue happened*/
+#define RE_BOOT_BY_SYSRST 512/*we can find the definition from preloader ,this value should  sync with preloader incase issue happened*/
+
+#ifdef MTK_PMIC_FULL_RESET
+#define RE_BOOT_FULL_PMIC 0x800
+#endif
+
+int ram_console_reboot_by_mrdump_key(void)
+{
+    unsigned int wdt_status;
+    wdt_status = ((struct reboot_reason_pl *)((void *)ram_console + ram_console->off_pl))->wdt_status;
+    return ((wdt_status & RE_BOOT_BY_EINT)|(wdt_status & RE_BOOT_BY_SYSRST))?true:false;
+}
+
+bool ram_console_should_restore(unsigned char *ram_console_ptr)
+{
+    unsigned int fiq_step, wdt_status, exp_type;
+    struct ram_console_buffer *tmp_ram_console = (struct ram_console_buffer *)ram_console_ptr;
+
+    if (U_VAR(set_flag) && tmp_ram_console && tmp_ram_console->off_linux &&
+        (tmp_ram_console->off_linux == (tmp_ram_console->off_llk +
+        ALIGN(tmp_ram_console->sz_lk, 64))) &&
+        (tmp_ram_console->off_pl == sizeof(struct ram_console_buffer))) {
+        wdt_status = ((struct reboot_reason_pl*)((void*)tmp_ram_console +
+            tmp_ram_console->off_pl))->wdt_status;
+        fiq_step = ((struct reboot_reason_kernel*)((void*)tmp_ram_console +
+            tmp_ram_console->off_linux))->fiq_step;
+        exp_type = RAM_CONSOLE_EXP_TYPE_DEC(((struct reboot_reason_kernel *)((void *)tmp_ram_console
+            + tmp_ram_console->off_linux))->exp_type);
+
+        if ((wdt_status != 0 && wdt_status != U_VAR(wdt_status)) ||
+            (fiq_step != 0 && fiq_step != U_VAR(fiq_step)) ||
+            (exp_type != 0 && exp_type != U_VAR(exp_type))) {
+                return true;
+            }
+    }
+    return false;
+}
+
+#ifdef MTK_PMIC_FULL_RESET
+bool ram_console_reboot_by_cold_reset(void)
+{
+    unsigned int wdt_status;
+    wdt_status = ((struct reboot_reason_pl *)((void *)ram_console + ram_console->off_pl))->wdt_status;
+    return (wdt_status & RE_BOOT_FULL_PMIC) ? true : false;
+}
+#endif
+
+int ram_console_get_wdt_status(unsigned int *wdt_status)
+{
+    if (wdt_status && U_VAR(set_flag)) {
+        *wdt_status = U_VAR(wdt_status);
+        return true;
+    }
+    return false;
+}
+
+int ram_console_get_fiq_step(unsigned int *fiq_step)
+{
+    if (fiq_step && U_VAR(set_flag)) {
+        *fiq_step = U_VAR(fiq_step);
+        return true;
+    }
+    return false;
+}
+
+int ram_console_get_exp_type(unsigned int *exp_type)
+{
+    if (exp_type && U_VAR(set_flag)) {
+        *exp_type = U_VAR(exp_type);
+        return true;
+    }
+    return false;
+}
+
+int ram_console_set_exp_type(unsigned int exp_type)
+{
+    bool ret = false;
+    if (ram_console && ram_console->off_linux &&
+            (ram_console->off_linux == (ram_console->off_llk + ALIGN(ram_console->sz_lk, 64))) &&
+            (ram_console->off_pl == sizeof(struct ram_console_buffer))) {
+        if (exp_type < 16) {
+            exp_type = exp_type ^ RAM_CONSOLE_EXP_TYPE_MAGIC;
+            ((struct reboot_reason_kernel *)((void *)ram_console + ram_console->off_linux))->exp_type = exp_type;
+            ret = true;
+        } else {
+            LOG("%s. set exp type failed: off_linux:0x%x, off_llk:0x%x, off_pl:0x%x, exp type:%d\n",
+                MOD, ram_console->off_linux, ram_console->off_llk, ram_console->off_pl, exp_type);
+        }
+    }
+    return ret;
+}
+
+int ram_console_is_abnormal_boot(void)
+{
+    unsigned int fiq_step, wdt_status, exp_type;
+    int reinit_flag = 0;
+
+    if (!ram_console) {
+        ram_console_ptr_init();
+        reinit_flag = 1;
+    }
+    if (ram_console && ram_console->off_linux &&
+            (ram_console->off_linux == (ram_console->off_llk + ALIGN(ram_console->sz_lk, 64))) &&
+            (ram_console->off_pl == sizeof(struct ram_console_buffer))) {
+        wdt_status = ((struct reboot_reason_pl *)((void *)ram_console + ram_console->off_pl))->wdt_status;
+        fiq_step = ((struct reboot_reason_kernel *)((void *)ram_console + ram_console->off_linux))->fiq_step;
+        exp_type = ((struct reboot_reason_kernel *)((void *)ram_console + ram_console->off_linux))->exp_type;
+        LOG("%s. wdt_status 0x%x, fiq_step 0x%x, exp_type 0x%x\n", MOD, wdt_status, fiq_step, RAM_CONSOLE_EXP_TYPE_DEC(exp_type));
+        if (fiq_step != 0 && (exp_type ^ RAM_CONSOLE_EXP_TYPE_MAGIC) >= 16) {
+            fiq_step = 0;
+            ((struct reboot_reason_kernel *)((void *)ram_console + ram_console->off_linux))->fiq_step = fiq_step;
+        }
+        U_VAR(wdt_status) = wdt_status;
+        U_VAR(fiq_step) = fiq_step;
+        U_VAR(exp_type) = RAM_CONSOLE_EXP_TYPE_DEC(exp_type);
+        U_VAR(set_flag) = true;
+        LOG("%s. set reboot reason info done\n", MOD);
+
+        if ((wdt_status == RE_BOOT_BY_WDT_SW && fiq_step == 0 && U_VAR(exp_type) == 0) /* adb reboot */
+#ifdef MTK_PMIC_FULL_RESET
+            || (wdt_status == RE_BOOT_FULL_PMIC && fiq_step == 0) /* full pmic reset */
+#endif
+            || (wdt_status == RE_BOOT_NORMAL_BOOT))  /* power off->on */
+            return false;
+        else
+            return true;
+    } else {
+        if (ram_console) {
+            LOG("%s. set reboot reason info failed: off_linux:0x%x, off_llk:0x%x, off_pl:0x%x, reinit flag:%d\n",
+                MOD, ram_console->off_linux, ram_console->off_llk, ram_console->off_pl, reinit_flag);
+        } else {
+            LOG("%s. ram console buffer NULL\n", MOD);
+        }
+    }
+    return false;
+}
+
+void ram_console_lk_save(unsigned int val, int index)
+{
+    struct reboot_reason_lk *rr_lk;
+    if (ram_console && ram_console->off_lk < ram_console_size) {
+        rr_lk = (void *)ram_console + ram_console->off_lk;
+        if (index < RAM_CONSOLE_LK_SIZE)
+            rr_lk->last_func[index] = val;
+    }
+}
+
+void ram_console_addr_size(unsigned long *addr, unsigned long *size)
+{
+    *addr = (unsigned long)ram_console;
+    *size = ram_console_size;
+}
+
+void ram_console_set_dump_step(unsigned int step)
+{
+    if (ram_console) {
+        ram_console->dump_step = step;
+    }
+}
+
+int ram_console_get_dump_step(void)
+{
+    if (ram_console)
+        return ram_console->dump_step;
+    else {
+        LOG("%s. ram_console not ready\n", MOD);
+        return 0;
+    }
+}
+
diff --git a/src/bsp/lk/lib/aee/reboot_record.c b/src/bsp/lk/lib/aee/reboot_record.c
new file mode 100644
index 0000000..72959a9
--- /dev/null
+++ b/src/bsp/lk/lib/aee/reboot_record.c
@@ -0,0 +1,132 @@
+/*
+ * Copyright (c) 2018 MediaTek Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include <arch/ops.h>
+#include <debug.h>
+#include <kernel/vm.h>
+#include <mrdump.h>
+#include <string.h>
+#include "aee.h"
+#include "kdump.h"
+#include "ram_console.h"
+
+#ifdef MTK_MRDUMP_SRAM_CB
+struct mrdump_control_block *mrdump_cb_addr(void)
+{
+    /* directly return the address of debug service on SRAM */
+    return (struct mrdump_control_block *)MRDUMP_CB_ADDR;
+}
+
+int mrdump_cb_size(void)
+{
+    return MRDUMP_CB_SIZE;
+}
+
+#else
+#ifdef MTK_3LEVEL_PAGETABLE
+#include <stdlib.h>
+#include <err.h>
+#endif
+
+#define SEARCH_SIZE 33554432
+#define SEARCH_STEP 1024
+
+#ifdef MTK_3LEVEL_PAGETABLE
+#define MAX_MAP_CNT (SECTION_SIZE/SEARCH_STEP)
+#define mapflags (MMU_MEMORY_TYPE_NORMAL_WRITE_BACK | MMU_MEMORY_AP_P_RW_U_NA)
+struct mrdump_control_block *mrdump_cb_addr(void)
+{
+    int i, cnt = 0;
+
+    /* to write sig, use 1-on-1 mapping */
+    uint64_t paddr = DRAM_BASE_PHY;
+    vaddr_t vaddr = (vaddr_t)paddr;
+
+    for (i = 0; i < SEARCH_SIZE; i += SEARCH_STEP) {
+        if (cnt == 0) {
+            int map_ok = arch_mmu_map(paddr, vaddr, mapflags, SECTION_SIZE);
+            if (map_ok != NO_ERROR) {
+                voprintf_debug("%s: arch_mmu_map error.\n", __func__);
+                return NULL;
+            }
+        }
+
+        struct mrdump_control_block *bufp = (struct mrdump_control_block *)vaddr;
+        if (memcmp(bufp->sig, MRDUMP_GO_DUMP, 8) == 0) {
+            return bufp;
+        }
+
+        cnt++;
+        cnt %= MAX_MAP_CNT;
+        paddr += SEARCH_STEP;
+        vaddr += SEARCH_STEP;
+    }
+    return NULL;
+}
+#else
+struct mrdump_control_block *mrdump_cb_addr(void)
+{
+    int i;
+    for (i = 0; i < SEARCH_SIZE; i += SEARCH_STEP) {
+        struct mrdump_control_block *bufp = (struct mrdump_control_block *)(DRAM_BASE_PHY + i);
+        if (memcmp(bufp->sig, MRDUMP_GO_DUMP, 8) == 0) {
+            return bufp;
+        }
+    }
+    return NULL;
+}
+#endif
+
+int mrdump_cb_size(void)
+{
+    return 8192; /* Hardcode for old platform */
+}
+
+#endif //MTK_MRDUMP_SRAM_CB
+
+struct mrdump_control_block *aee_mrdump_get_params(void)
+{
+    struct mrdump_control_block *bufp =
+        (struct mrdump_control_block *)PA_TO_VA((paddr_t)mrdump_cb_addr());
+    if (bufp == NULL) {
+        voprintf_debug("mrdump_cb is NULL\n");
+        return NULL;
+    }
+
+    if (memcmp(bufp->sig, MRDUMP_GO_DUMP, 8) == 0) {
+        bufp->sig[0] = 'X';
+        aee_mrdump_flush_cblock(bufp);
+        voprintf_debug("Boot record found at %p[%02x%02x]\n", bufp, bufp->sig[0], bufp->sig[1]);
+        return bufp;
+    } else {
+        voprintf_debug("No Boot record found\n");
+        return NULL;
+    }
+}
+
+void aee_mrdump_flush_cblock(struct mrdump_control_block *bufp)
+{
+    if (bufp != NULL) {
+        arch_clean_cache_range((addr_t)bufp, sizeof(struct mrdump_control_block));
+    }
+}
diff --git a/src/bsp/lk/lib/aee/rules.mk b/src/bsp/lk/lib/aee/rules.mk
new file mode 100644
index 0000000..a2b26ca
--- /dev/null
+++ b/src/bsp/lk/lib/aee/rules.mk
@@ -0,0 +1,43 @@
+LOCAL_DIR := $(GET_LOCAL_DIR)
+
+MODULE := $(LOCAL_DIR)
+
+ifeq ($(MTK_MRDUMP_SUPPORT), yes)
+MODULE_SRCS += $(LOCAL_DIR)/mrdump_aee.c \
+               $(LOCAL_DIR)/kdump_ext4.c \
+               $(LOCAL_DIR)/kdump_zip.c \
+               $(LOCAL_DIR)/mrdump_sddev.c \
+               $(LOCAL_DIR)/env.c \
+               $(LOCAL_DIR)/reboot_record.c \
+               $(LOCAL_DIR)/mrdump_elf.c \
+               $(LOCAL_DIR)/mrdump_elf64.c
+endif
+
+ifeq ($(MTK_KEDUMP_MINI_SUPPORT), yes)
+MODULE_SRCS += $(LOCAL_DIR)/KEDump.c
+
+ifneq ($(MTK_MRDUMP_SUPPORT), yes)
+# for mrdump_reboot when disable mrdump
+MODULE_SRCS += $(LOCAL_DIR)/kdump_aee.c
+endif
+endif
+
+ifeq ($(MTK_BOOT_REASON_SUPPORT), yes)
+MODULE_SRCS += $(LOCAL_DIR)/ram_console.c \
+               $(LOCAL_DIR)/dump_joint.c \
+               $(LOCAL_DIR)/mrdump_rsvmem.c \
+               $(LOCAL_DIR)/mrdump_setup.c \
+               $(LOCAL_DIR)/mrdump_dummy.c
+endif
+
+MODULE_DEPS += \
+    lib/kcmdline \
+    lib/zlib
+
+ifeq ($(MTK_MRDUMP_SUPPORT), yes)
+    #Now only support SRAM_CB
+    GLOBAL_DEFINES += MTK_MRDUMP_SRAM_CB
+endif
+
+MODULE_COMPILEFLAGS += -Wno-sign-compare
+include make/module.mk