int mrdump_detection(void) { struct mrdump_control_block *mrdump_cblock = aee_mrdump_get_params(); if (mrdump_cblock == NULL) { return 0; } memset(&mrdump_cblock->result, 0, sizeof(struct mrdump_cblock_result)); cblock_result = &mrdump_cblock->result; if (!g_boot_arg->ddr_reserve_enable) { voprintf_debug("DDR reserve mode disabled\n"); mrdump_status_none("DDR reserve mode disabled\n"); return 0; } if (!g_boot_arg->ddr_reserve_success) { voprintf_debug("DDR reserve mode failed\n"); mrdump_status_none("DDR reserve mode failed\n"); return 0; } uint8_t reboot_mode = mrdump_cblock->crash_record.reboot_mode; if (mrdump_cblock->machdesc.nr_cpus == 0) { voprintf_debug("Runtime disabled\n"); mrdump_status_none("Runtime disabled\n"); return 0; } voprintf_debug("sram record with mode %d\n", reboot_mode); switch (reboot_mode) { case AEE_REBOOT_MODE_NORMAL: { if (!ram_console_is_abnormal_boot()) { mrdump_status_none("Normal boot\n"); return 0; } else { /* SoC trigger HW REBOOT */ mrdump_cblock->crash_record.reboot_mode = AEE_REBOOT_MODE_WDT; return 1; } } case AEE_REBOOT_MODE_KERNEL_OOPS: case AEE_REBOOT_MODE_KERNEL_PANIC: case AEE_REBOOT_MODE_NESTED_EXCEPTION: case AEE_REBOOT_MODE_WDT: case AEE_REBOOT_MODE_EXCEPTION_KDUMP: return 1; } return 0; }
static void mrdump_query_bootinfo(void) { if (mrdump_cb == NULL) { struct mrdump_control_block *bufp = (struct mrdump_control_block *)MRDUMP_CB_ADDR; if (memcmp(bufp->sig, "MRDUMP01", 8) == 0) { voprintf_debug("Boot record found at %p\n", bufp); mrdump_cb = bufp; bufp->sig[0] = 'X'; aee_mrdump_flush_cblock(); } else { voprintf_debug("No boot record found at %p[%02x%02x]\n", bufp, bufp->sig[0], bufp->sig[1]); } } }
bool kzip_add_file(struct kzip_file *zfile, const struct kzip_memlist *memlist, const char *zfilename) { int ret, flush; z_stream strm; struct aee_timer zip_time; if (zfile->entries_num >= KZIP_ENTRY_MAX) { voprintf_error("Too manry 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 = DEF_MEM_LEVEL; KZIP_DEBUG("%s: write local header\n", __func__); uint8_t zip_localheader[128]; int hsize = put_localheader(zip_localheader, zfilename, DEF_MEM_LEVEL); if (kzip_write_current(zfile, zip_localheader, hsize) != hsize) { return false; } KZIP_DEBUG("%s: init compressor\n", __func__); /* allocate deflate state */ strm.workspace = malloc(zlib_deflate_workspacesize(-MAX_WBITS, DEF_MEM_LEVEL)); ret = zlib_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"); free(strm.workspace); return false; } uint8_t *out = malloc(CHUNK); aee_timer_init(&zip_time); aee_timer_start(&zip_time); /* compress until end of file */ do { flush = (memlist->size == 0) ? Z_FINISH : Z_NO_FLUSH; KZIP_DEBUG("-- Compress memory %x, size %d\n", memlist->address, memlist->size); strm.avail_in = memlist->size; strm.next_in = memlist->address; /* 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 = zlib_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) { goto error; } aee_timer_start(&zip_time); } } while (strm.avail_out == 0); assert(strm.avail_in == 0); /* all input will be used */ memlist++; /* done when last data in file processed */ } while (flush != Z_FINISH); assert(ret == Z_STREAM_END); /* stream will be complete */ /* clean up and return */ (void)zlib_deflateEnd(&strm); free(strm.workspace); free(out); aee_timer_stop(&zip_time); voprintf_info("Zip time: %d sec\n", zip_time.acc_ms / 1000); zentry->comp_size = strm.total_out; zentry->uncomp_size = strm.total_in; zentry->crc32 = strm.crc32 ^ 0xffffffffUL; return true; error: free(strm.workspace); free(out); (void)zlib_deflateEnd(&strm); return false; }
void *kdump_core_header_init(const struct mrdump_control_block *mrdump_cb, uint32_t kmem_address, uint32_t kmem_size) { struct elf_phdr *nhdr, *phdr; struct elfhdr *elf; off_t offset = 0; const struct mrdump_machdesc *kparams = &mrdump_cb->machdesc; uint8_t *oldbufp = malloc(KDUMP_CORE_SIZE); uint8_t *bufp = oldbufp; /* setup ELF header */ elf = (struct elfhdr *) bufp; bufp += sizeof(struct elfhdr); offset += sizeof(struct elfhdr); memcpy(elf->e_ident, ELFMAG, SELFMAG); elf->e_ident[EI_CLASS] = ELFCLASS32; elf->e_ident[EI_DATA] = ELFDATA2LSB; elf->e_ident[EI_VERSION]= EV_CURRENT; elf->e_ident[EI_OSABI] = ELFOSABI_NONE; memset(elf->e_ident+EI_PAD, 0, EI_NIDENT-EI_PAD); elf->e_type = ET_CORE; elf->e_machine = EM_ARM; elf->e_version = EV_CURRENT; elf->e_entry = 0; elf->e_phoff = sizeof(struct elfhdr); elf->e_shoff = 0; elf->e_flags = ELF_CORE_EFLAGS; elf->e_ehsize = sizeof(struct elfhdr); elf->e_phentsize= sizeof(struct elf_phdr); elf->e_phnum = 2; elf->e_shentsize= 0; elf->e_shnum = 0; elf->e_shstrndx = 0; nhdr = (struct elf_phdr *) bufp; bufp += sizeof(struct elf_phdr); offset += sizeof(struct elf_phdr); memset(nhdr, 0, sizeof(struct elf_phdr)); nhdr->p_type = PT_NOTE; phdr = (struct elf_phdr *) bufp; bufp += sizeof(struct elf_phdr); offset += sizeof(struct elf_phdr); uint32_t low_memory_size = kparams->high_memory - kparams->page_offset; if (low_memory_size > kmem_size) { low_memory_size = kmem_size; } phdr->p_type = PT_LOAD; phdr->p_flags = PF_R|PF_W|PF_X; phdr->p_offset = KDUMP_CORE_SIZE; phdr->p_vaddr = (size_t) kparams->page_offset; phdr->p_paddr = kmem_address; phdr->p_filesz = kmem_size; phdr->p_memsz = low_memory_size; phdr->p_align = KDUMP_CORE_SIZE; nhdr->p_offset = offset; struct elf_prpsinfo prpsinfo; /* NT_PRPSINFO */ struct memelfnote notes; /* set up the process info */ notes.name = CORE_STR; notes.type = NT_PRPSINFO; notes.datasz = sizeof(struct elf_prpsinfo); notes.data = &prpsinfo; memset(&prpsinfo, 0, sizeof(struct elf_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); } } voprintf_debug("%s cpu %d header size %d\n", __FUNCTION__, kparams->nr_cpus, bufp - oldbufp); return oldbufp; }