[Feature]add MT2731_MP2_MR2_SVN388 baseline version
Change-Id: Ief04314834b31e27effab435d3ca8ba33b499059
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);
+}