[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(¬es);
+ return storenote(¬es, 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(¬es);
+ return storenote(¬es, 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(¬es);
+ return storenote(¬es, 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(¬es);
+ bufp = storenote(¬es, 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(¬es);
+ return storenote(¬es, 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(¬es);
+ return storenote(¬es, 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(¬es);
+ return storenote(¬es, 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(¬es);
+ return storenote(¬es, 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(¬es);
+ bufp = storenote(¬es, 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