diff --git a/linux-ramdump-parser-v2/README b/linux-ramdump-parser-v2/README
index efeea31b704496bf2a433ad2decd78694b32158a..ac50385e585f2d8409b5bd9e69f94e35bd6e7acd 100644
--- a/linux-ramdump-parser-v2/README
+++ b/linux-ramdump-parser-v2/README
@@ -72,6 +72,11 @@ specify the paths to these tools. This can be done in three ways
 1) Using --gdb-path and --nm-path to specify the absolute path
 2) Using CROSS_COMPILE to specify the prefix
 3) Using local_settings.py as described below
+4) Install this library from https://github.com/eliben/pyelftools
+    - Download the code from avobe github link. Download the zip file.
+    - After download the zip file, you will find a folder pyelftools-master.
+    - Inside this folder you will find another folder named "elftools"
+	- copy that entire folder and paste it in below directory <installed Python path>\Lib\site-packages
 
 Just having gdb/nm on the path is not supported as there are too many
 variations on names to invoke.
diff --git a/linux-ramdump-parser-v2/boards.py b/linux-ramdump-parser-v2/boards.py
old mode 100755
new mode 100644
index 3909b106623b8774ad99ede4b8d907230b00d093..fc96d4dcb10a9cbc6f71baf349f91e20ef9ea1cc
--- a/linux-ramdump-parser-v2/boards.py
+++ b/linux-ramdump-parser-v2/boards.py
@@ -451,6 +451,7 @@ class Board660(Board):
         self.cpu = 'CORTEXA53'
         self.ram_start = 0x80000000
         self.smem_addr = 0x6000000
+        self.smem_addr_buildinfo = 0x6006ec0
         self.phys_offset = 0x80000000
         self.imem_start = 0x14680000
         self.kaslr_addr = 0x146bf6d0
diff --git a/linux-ramdump-parser-v2/debug_image_v2.py b/linux-ramdump-parser-v2/debug_image_v2.py
old mode 100755
new mode 100644
index 302ee628847008983dbf2a445f631fd9c2856f88..5e6332a970db917c28675cb722962d21fe52b562
--- a/linux-ramdump-parser-v2/debug_image_v2.py
+++ b/linux-ramdump-parser-v2/debug_image_v2.py
@@ -86,6 +86,25 @@ qdss_tag_to_field_name = {
     'MSM_DUMP_DATA_DBGUI_REG': 'dbgui_start',
 }
 
+# Client functions will be executed in top-to-bottom order
+minidump_dump_table_type = [
+    ('MSM_DUMP_DATA_SCANDUMP', 'KSCANDUMP'),
+    ('MSM_DUMP_DATA_CPU_CTX', 'KCPU_CTX'),
+    ('MSM_DUMP_DATA_L1_INST_TLB', 'KCPUSS'),
+    ('MSM_DUMP_DATA_L1_DATA_TLB','KCPUSS'),
+    ('MSM_DUMP_DATA_L1_INST_CACHE', 'KCPUSS'),
+    ('MSM_DUMP_DATA_L1_DATA_CACHE', 'KCPUSS'),
+    ('MSM_DUMP_DATA_L2_CACHE', 'KCPUSS'),
+    ('MSM_DUMP_DATA_L3_CACHE', 'KCPUSS'),
+    ('MSM_DUMP_DATA_VSENSE', 'KVSENSE'),
+    ('MSM_DUMP_DATA_PMIC', 'KPMIC'),
+    ('MSM_DUMP_DATA_DCC_REG', 'KDCC_REG'),
+    ('MSM_DUMP_DATA_DCC_SRAM', 'KDCC_SRAM'),
+    ('MSM_DUMP_DATA_TMC_ETF', 'KTMC_ETF'),
+    ('MSM_DUMP_DATA_TMC_REG', 'KTMC_REG')
+
+]
+
 class DebugImage_v2():
 
     def __init__(self, ramdump):
@@ -491,6 +510,21 @@ class DebugImage_v2():
 
         results.sort(key=lambda(x): client_names.index(x[0]))
         return results
+    def minidump_data_clients(self, ram_dump, client_id,entry_pa_addr,
+                                      end_addr):
+        results = list()
+        client_table = dict(client_types)
+        # get first column of client_types
+
+        client_name = self.dump_data_id_lookup_table[client_id]
+
+        if client_name not in client_table:
+            print_out_str(
+                '!!! {0} Does not have an associated function. Skipping!'.format(client_name))
+            return None
+
+        results.append((client_name, client_id,client_table[client_name], entry_pa_addr,end_addr))
+        return results
 
     def parse_dump_v2(self, ram_dump):
         self.dump_type_lookup_table = ram_dump.gdbmi.get_enum_lookup_table(
@@ -532,141 +566,207 @@ class DebugImage_v2():
             client.MSM_DUMP_DATA_LOG_BUF_FIRST_IDX] = 'MSM_DUMP_DATA_LOG_BUF_FIRST_IDX'
         self.dump_data_id_lookup_table[
             client.MSM_DUMP_DATA_L2_TLB] = 'MSM_DUMP_DATA_L2_TLB'
-        dump_table_ptr_offset = ram_dump.field_offset(
-            'struct msm_memory_dump', 'table')
-        dump_table_version_offset = ram_dump.field_offset(
-            'struct msm_dump_table', 'version')
-        dump_table_num_entry_offset = ram_dump.field_offset(
-            'struct msm_dump_table', 'num_entries')
-        dump_table_entry_offset = ram_dump.field_offset(
-            'struct msm_dump_table', 'entries')
-        dump_entry_id_offset = ram_dump.field_offset(
-            'struct msm_dump_entry', 'id')
-        dump_entry_name_offset = ram_dump.field_offset(
-            'struct msm_dump_entry', 'name')
-        dump_entry_type_offset = ram_dump.field_offset(
-            'struct msm_dump_entry', 'type')
-        dump_entry_addr_offset = ram_dump.field_offset(
-            'struct msm_dump_entry', 'addr')
-        dump_data_version_offset = ram_dump.field_offset(
-            'struct msm_dump_data', 'version')
-        dump_data_magic_offset =  ram_dump.field_offset(
-            'struct msm_dump_data', 'magic')
-        dump_data_name_offset = ram_dump.field_offset(
-            'struct msm_dump_data', 'name')
-        dump_data_addr_offset = ram_dump.field_offset(
-            'struct msm_dump_data', 'addr')
-        dump_data_len_offset = ram_dump.field_offset(
-            'struct msm_dump_data', 'len')
-        dump_data_reserved_offset = ram_dump.field_offset(
-            'struct msm_dump_data', 'reserved')
-        dump_entry_size = ram_dump.sizeof('struct msm_dump_entry')
-        dump_data_size = ram_dump.sizeof('struct msm_dump_data')
-
-        mem_dump_data = ram_dump.address_of('memdump')
-
-        mem_dump_table = ram_dump.read_word(
-            mem_dump_data + dump_table_ptr_offset)
-
-        mem_table_version = ram_dump.read_u32(
-            mem_dump_table + dump_table_version_offset)
-        if mem_table_version is None:
-            print_out_str('Version is bogus! Can\'t parse debug image')
-            return
-        mem_table_num_entry = ram_dump.read_u32(
-            mem_dump_table + dump_table_num_entry_offset)
-        if mem_table_num_entry is None or mem_table_num_entry > 100:
-            print_out_str('num_entries is bogus! Can\'t parse debug image')
-            return
-
-        print_out_str('\nDebug image version: {0}.{1} Number of table entries {2}'.format(
-            mem_table_version >> 20, mem_table_version & 0xFFFFF, mem_table_num_entry))
-        print_out_str('--------')
-
-        for i in range(0, mem_table_num_entry):
-            this_entry = mem_dump_table + dump_table_entry_offset + \
-                i * dump_entry_size
-            entry_id = ram_dump.read_u32(this_entry + dump_entry_id_offset)
-            entry_type = ram_dump.read_u32(this_entry + dump_entry_type_offset)
-            entry_addr = ram_dump.read_word(this_entry + dump_entry_addr_offset)
-
-            if entry_id < 0 or entry_id > len(self.dump_table_id_lookup_table):
-                print_out_str(
-                    '!!! Invalid dump table entry id found {0:x}'.format(entry_id))
-                continue
-
-            if entry_type > len(self.dump_type_lookup_table):
-                print_out_str(
-                    '!!! Invalid dump table entry type found {0:x}'.format(entry_type))
-                continue
 
-            table_version = ram_dump.read_u32(
-                entry_addr + dump_table_version_offset, False)
-            if table_version is None:
-                print_out_str('Dump table entry version is bogus! Can\'t parse debug image')
+        if not ram_dump.minidump:
+            dump_table_ptr_offset = ram_dump.field_offset(
+                'struct msm_memory_dump', 'table')
+            dump_table_version_offset = ram_dump.field_offset(
+                'struct msm_dump_table', 'version')
+            dump_table_num_entry_offset = ram_dump.field_offset(
+                'struct msm_dump_table', 'num_entries')
+            dump_table_entry_offset = ram_dump.field_offset(
+                'struct msm_dump_table', 'entries')
+            dump_entry_id_offset = ram_dump.field_offset(
+                'struct msm_dump_entry', 'id')
+            dump_entry_name_offset = ram_dump.field_offset(
+                'struct msm_dump_entry', 'name')
+            dump_entry_type_offset = ram_dump.field_offset(
+                'struct msm_dump_entry', 'type')
+            dump_entry_addr_offset = ram_dump.field_offset(
+                'struct msm_dump_entry', 'addr')
+            dump_data_version_offset = ram_dump.field_offset(
+                'struct msm_dump_data', 'version')
+            dump_data_magic_offset =  ram_dump.field_offset(
+                'struct msm_dump_data', 'magic')
+            dump_data_name_offset = ram_dump.field_offset(
+                'struct msm_dump_data', 'name')
+            dump_data_addr_offset = ram_dump.field_offset(
+                'struct msm_dump_data', 'addr')
+            dump_data_len_offset = ram_dump.field_offset(
+                'struct msm_dump_data', 'len')
+            dump_data_reserved_offset = ram_dump.field_offset(
+                'struct msm_dump_data', 'reserved')
+            dump_entry_size = ram_dump.sizeof('struct msm_dump_entry')
+            dump_data_size = ram_dump.sizeof('struct msm_dump_data')
+
+            mem_dump_data = ram_dump.address_of('memdump')
+
+            mem_dump_table = ram_dump.read_word(
+                mem_dump_data + dump_table_ptr_offset)
+
+            mem_table_version = ram_dump.read_u32(
+                mem_dump_table + dump_table_version_offset)
+            if mem_table_version is None:
+                print_out_str('Version is bogus! Can\'t parse debug image')
                 return
-            table_num_entries = ram_dump.read_u32(
-                entry_addr + dump_table_num_entry_offset, False)
-            if table_num_entries is None or table_num_entries > 100:
-                print_out_str('Dump table entry num_entries is bogus! Can\'t parse debug image')
+            mem_table_num_entry = ram_dump.read_u32(
+                mem_dump_table + dump_table_num_entry_offset)
+            if mem_table_num_entry is None or mem_table_num_entry > 100:
+                print_out_str('num_entries is bogus! Can\'t parse debug image')
                 return
 
-            print_out_str(
-                'Debug image version: {0}.{1} Entry id: {2} Entry type: {3} Number of entries: {4}'.format(
-                    table_version >> 20, table_version & 0xFFFFF, self.dump_table_id_lookup_table[entry_id],
-                    self.dump_type_lookup_table[entry_type], table_num_entries))
-
-            lst = self.sorted_dump_data_clients(
-                    ram_dump, entry_addr + dump_table_entry_offset,
-                    table_num_entries)
-            for (client_name, func, client_entry) in lst:
-                print_out_str('--------')
-                client_id = ram_dump.read_u32(
-                                client_entry + dump_entry_id_offset, False)
-                client_type = ram_dump.read_u32(
-                                client_entry + dump_entry_type_offset, False)
-                client_addr = ram_dump.read_word(
-                                client_entry + dump_entry_addr_offset, False)
-
-                if client_type > len(self.dump_type_lookup_table):
+            print_out_str('\nDebug image version: {0}.{1} Number of table entries {2}'.format(
+                mem_table_version >> 20, mem_table_version & 0xFFFFF, mem_table_num_entry))
+            print_out_str('--------')
+
+            for i in range(0, mem_table_num_entry):
+                this_entry = mem_dump_table + dump_table_entry_offset + \
+                    i * dump_entry_size
+                entry_id = ram_dump.read_u32(this_entry + dump_entry_id_offset)
+                entry_type = ram_dump.read_u32(this_entry + dump_entry_type_offset)
+                entry_addr = ram_dump.read_word(this_entry + dump_entry_addr_offset)
+
+                if entry_id < 0 or entry_id > len(self.dump_table_id_lookup_table):
                     print_out_str(
-                        '!!! Invalid dump client type found {0:x}'.format(client_type))
+                        '!!! Invalid dump table entry id found {0:x}'.format(entry_id))
                     continue
 
-                dump_data_magic = ram_dump.read_u32(
-                                client_addr + dump_data_magic_offset, False)
-                dump_data_version = ram_dump.read_u32(
-                                client_addr + dump_data_version_offset, False)
-                dump_data_name = ram_dump.read_cstring(
-                        client_addr + dump_data_name_offset,
-                        ram_dump.sizeof('((struct msm_dump_data *)0x0)->name'),
-                        False)
-                dump_data_addr = ram_dump.read_dword(
-                                    client_addr + dump_data_addr_offset, False)
-                dump_data_len = ram_dump.read_dword(
-                                    client_addr + dump_data_len_offset, False)
-                print_out_str('Parsing debug information for {0}. Version: {1} Magic: {2:x} Source: {3}'.format(
-                    client_name, dump_data_version, dump_data_magic,
-                    dump_data_name))
-
-                if dump_data_magic is None:
-                    print_out_str("!!! Address {0:x} is bogus! Can't parse!".format(
-                                client_addr + dump_data_magic_offset))
+                if entry_type > len(self.dump_type_lookup_table):
+                    print_out_str(
+                        '!!! Invalid dump table entry type found {0:x}'.format(entry_type))
                     continue
 
-                if dump_data_magic != MEMDUMPV2_MAGIC:
-                    print_out_str("!!! Magic {0:x} doesn't match! No context will be parsed".format(dump_data_magic))
+                table_version = ram_dump.read_u32(
+                    entry_addr + dump_table_version_offset, False)
+                if table_version is None:
+                    print_out_str('Dump table entry version is bogus! Can\'t parse debug image')
+                    return
+                table_num_entries = ram_dump.read_u32(
+                    entry_addr + dump_table_num_entry_offset, False)
+                if table_num_entries is None or table_num_entries > 100:
+                    print_out_str('Dump table entry num_entries is bogus! Can\'t parse debug image')
+                    return
+
+                print_out_str(
+                    'Debug image version: {0}.{1} Entry id: {2} Entry type: {3} Number of entries: {4}'.format(
+                        table_version >> 20, table_version & 0xFFFFF, self.dump_table_id_lookup_table[entry_id],
+                        self.dump_type_lookup_table[entry_type], table_num_entries))
+
+                lst = self.sorted_dump_data_clients(
+                        ram_dump, entry_addr + dump_table_entry_offset,
+                        table_num_entries)
+                for (client_name, func, client_entry) in lst:
+                    print_out_str('--------')
+                    client_id = ram_dump.read_u32(
+                                    client_entry + dump_entry_id_offset, False)
+                    client_type = ram_dump.read_u32(
+                                    client_entry + dump_entry_type_offset, False)
+                    client_addr = ram_dump.read_word(
+                                    client_entry + dump_entry_addr_offset, False)
+
+                    if client_type > len(self.dump_type_lookup_table):
+                        print_out_str(
+                            '!!! Invalid dump client type found {0:x}'.format(client_type))
+                        continue
+
+                    dump_data_magic = ram_dump.read_u32(
+                                    client_addr + dump_data_magic_offset, False)
+                    dump_data_version = ram_dump.read_u32(
+                                    client_addr + dump_data_version_offset, False)
+                    dump_data_name = ram_dump.read_cstring(
+                            client_addr + dump_data_name_offset,
+                            ram_dump.sizeof('((struct msm_dump_data *)0x0)->name'),
+                            False)
+                    dump_data_addr = ram_dump.read_dword(
+                                        client_addr + dump_data_addr_offset, False)
+                    dump_data_len = ram_dump.read_dword(
+                                        client_addr + dump_data_len_offset, False)
+                    print_out_str('Parsing debug information for {0}. Version: {1} Magic: {2:x} Source: {3}'.format(
+                        client_name, dump_data_version, dump_data_magic,
+                        dump_data_name))
+
+                    if dump_data_magic is None:
+                        print_out_str("!!! Address {0:x} is bogus! Can't parse!".format(
+                                    client_addr + dump_data_magic_offset))
+                        continue
+
+                    if dump_data_magic != MEMDUMPV2_MAGIC:
+                        print_out_str("!!! Magic {0:x} doesn't match! No context will be parsed".format(dump_data_magic))
+                        continue
+
+                    getattr(DebugImage_v2, func)(
+                        self, dump_data_version, dump_data_addr,
+                        dump_data_addr + dump_data_len, client_id, ram_dump)
+        else:
+            dump_smem_table_ptr_offset = ram_dump.field_offset(
+                'struct md_table', 'md_smem_table')
+            dump_table_version_offset = ram_dump.field_offset(
+                'struct md_smem_table', 'version')
+            dump_table_num_entry_offset = ram_dump.field_offset(
+                'struct md_table', 'num_regions')
+            dump_table_entry_offset = ram_dump.field_offset(
+                'struct md_table', 'entry')
+            dump_entry_name_offset = ram_dump.field_offset(
+                'struct md_region', 'name')
+            dump_entry_id_offset = ram_dump.field_offset(
+                'struct md_region', 'id')
+            dump_entry_va_offset = ram_dump.field_offset(
+                'struct md_region', 'virt_addr')
+            dump_entry_pa_offset = ram_dump.field_offset(
+                'struct md_region', 'phys_addr')
+            dump_entry_size_offset = ram_dump.field_offset(
+                'struct md_region', 'size')
+
+            dump_entry_size = ram_dump.sizeof('struct md_region')
+
+            mem_dump_data = ram_dump.address_of('minidump_table')
+
+            mem_dump_table = ram_dump.read_word(
+                mem_dump_data + dump_table_entry_offset)
+
+            mem_dump_smem_table = ram_dump.read_word(
+                mem_dump_data + dump_smem_table_ptr_offset)
+
+            mem_table_version = ram_dump.read_u32(
+                mem_dump_smem_table + dump_table_version_offset)
+            mem_table_num_entry = ram_dump.read_u32(
+                mem_dump_data + dump_table_num_entry_offset)
+
+            print_out_str('--------')
+
+            for i in range(0, mem_table_num_entry):
+                this_entry = mem_dump_data + dump_table_entry_offset + \
+                             i * dump_entry_size
+                entry_id = ram_dump.read_u32(this_entry + dump_entry_id_offset)
+                entry_va_addr = ram_dump.read_u64(this_entry + dump_entry_va_offset)
+                entry_pa_addr = ram_dump.read_u64(this_entry + dump_entry_pa_offset)
+                entry_size = ram_dump.read_u64(this_entry + dump_entry_size_offset)
+
+                if entry_id < 0 or entry_id > len(self.dump_table_id_lookup_table):
+                    print_out_str(
+                        '!!! Invalid dump table entry id found {0:x}'.format(entry_id))
                     continue
+                end_addr = entry_pa_addr + entry_size
+                minidump_dump_table_value = dict(minidump_dump_table_type)
+                if entry_pa_addr in ram_dump.ebi_pa_name_map:
+                    section_name = ram_dump.ebi_pa_name_map[entry_pa_addr]
+                    section_name = re.sub("\d+", "", section_name)
+                    if section_name in minidump_dump_table_value.values():
+                        lst = self.minidump_data_clients(
+                            ram_dump, entry_id,entry_pa_addr,end_addr)
+                        if lst:
+                            client_name, client_id,func,\
+                                client_entry,client_end = lst[0]
+                            print_out_str('--------')
+                            getattr(DebugImage_v2, func)(
+                                self, 20, client_entry,
+                                client_end, client_id, ram_dump)
+        if ram_dump.dcc:
+            self.parse_dcc(ram_dump)
+        self.qdss.dump_standard(ram_dump)
+        if not ram_dump.skip_qdss_bin:
+            self.qdss.save_etf_bin(ram_dump)
+            self.qdss.save_etr_bin(ram_dump)
+        if ram_dump.qtf:
+            self.parse_qtf(ram_dump)
 
-                getattr(DebugImage_v2, func)(
-                    self, dump_data_version, dump_data_addr,
-                    dump_data_addr + dump_data_len, client_id, ram_dump)
-
-            self.qdss.dump_standard(ram_dump)
-            if not ram_dump.skip_qdss_bin:
-                self.qdss.save_etf_bin(ram_dump)
-                self.qdss.save_etr_bin(ram_dump)
-            if ram_dump.qtf:
-                self.parse_qtf(ram_dump)
-            if ram_dump.dcc:
-                self.parse_dcc(ram_dump)
diff --git a/linux-ramdump-parser-v2/minidump_util.py b/linux-ramdump-parser-v2/minidump_util.py
new file mode 100644
index 0000000000000000000000000000000000000000..92ef72b29cb6355f2e4a107989076fff2bb966ed
--- /dev/null
+++ b/linux-ramdump-parser-v2/minidump_util.py
@@ -0,0 +1,56 @@
+# Copyright (c) 2012-2017, The Linux Foundation. All rights reserved.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License version 2 and
+# only version 2 as published by the Free Software Foundation.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+import sys
+import re
+import os
+from print_out import print_out_str
+
+
+def minidump_virt_to_phys(ebi_files,addr):
+    pa_addr = None
+    for a in ebi_files:
+        idx, pa, end_addr, va,size = a
+        if addr >= va and addr <= va +  size:
+            offset = addr - va
+            pa_addr = pa + offset
+            return pa_addr
+    return pa_addr
+
+def read_physical_minidump(ebi_files,ebi_files_ramfile,elffile,addr,length):
+    ebi = [-1, -1, -1, -1, -1]
+    for a in ebi_files:
+        idx, start, end, va, size = a
+        if addr >= start and addr <= end:
+            ebi = a
+            break
+    if ebi[0] != -1:
+        idx = ebi[0]
+        textSec = elffile.get_segment(idx)
+        off = addr - ebi[1]
+        elf_content = bytearray(a[4])
+        val = textSec.data()
+        elf_content[0:a[4]] = val
+        data = elf_content[off:]
+        return data[:length]
+    else:
+        ebi = (-1, -1, -1)
+        for a in ebi_files_ramfile:
+            fd, start, end, path = a
+            if addr >= start and addr <= end:
+                ebi = a
+                break
+        if ebi[0] is -1:
+            return None
+        offset = addr - ebi[1]
+        ebi[0].seek(offset)
+        a = ebi[0].read(length)
+        return a
diff --git a/linux-ramdump-parser-v2/ramdump.py b/linux-ramdump-parser-v2/ramdump.py
index 8d126080e578ad26bf71c80875335732cd1a8ba1..d6814a8da1463bfe6cc31633b43c463fe535736c 100644
--- a/linux-ramdump-parser-v2/ramdump.py
+++ b/linux-ramdump-parser-v2/ramdump.py
@@ -27,6 +27,8 @@ import gdbmi
 from print_out import print_out_str
 from mmu import Armv7MMU, Armv7LPAEMMU, Armv8MMU
 import parser_util
+import minidump_util
+from importlib import import_module
 
 FP = 11
 SP = 13
@@ -49,7 +51,8 @@ extra_mem_file_names = ['EBI1CS1.BIN', 'DDRCS1.BIN', 'ebi1_cs1.bin',
 
 DDR_FILE_NAMES = ['DDRCS0.BIN', 'DDRCS1.BIN', 'DDRCS0_0.BIN',
                   'DDRCS1_0.BIN', 'DDRCS0_1.BIN', 'DDRCS1_1.BIN']
-OTHER_DUMP_FILE_NAMES = ['PIMEM.BIN', 'OCIMEM.BIN']
+OTHER_DUMP_FILE_NAMES = ['PIMEM.BIN', 'OCIMEM.BIN','md_shared_imem.BIN',
+                         'md_smem_info.BIN']
 RAM_FILE_NAMES = set(DDR_FILE_NAMES +
                      OTHER_DUMP_FILE_NAMES +
                      first_mem_file_names +
@@ -499,6 +502,8 @@ class RamDump():
 
     def __init__(self, options, nm_path, gdb_path, objdump_path):
         self.ebi_files = []
+        self.ebi_files_minidump = []
+        self.ebi_pa_name_map = {}
         self.phys_offset = None
         self.kaslr_offset = options.kaslr_offset
         self.tz_start = 0
@@ -530,6 +535,20 @@ class RamDump():
         self.ipc_log_help = options.ipc_help
         self.use_stdout = options.stdout
         self.kernel_version = (0, 0, 0)
+        self.minidump = options.minidump
+        self.elffile = None
+        self.ram_elf_file = None
+
+        if self.minidump:
+            try:
+                mod = import_module('elftools.elf.elffile')
+                ELFFile = mod.ELFFile
+                StringTableSection = mod.StringTableSection
+                mod = import_module('elftools.common.py3compat')
+                bytes2str = mod.bytes2str
+            except ImportError:
+                print "Oops, missing required library for minidump. Check README"
+                sys.exit(1)
 
         if options.ram_addr is not None:
             # TODO sanity check to make sure the memory regions don't overlap
@@ -540,11 +559,31 @@ class RamDump():
                         'Could not open {0}. Will not be part of dump'.format(file_path))
                     continue
                 self.ebi_files.append((fd, start, end, file_path))
-        else:
+        elif not options.minidump:
             if not self.auto_parse(options.autodump):
                 return None
-        if self.ebi_start == 0:
-            self.ebi_start = self.ebi_files[0][1]
+        if options.minidump:
+            file_path = options.ram_elf_addr
+            self.ram_elf_file = file_path
+            fd = open(file_path, 'rb')
+            self.elffile = ELFFile(fd)
+            for idx, s in enumerate(self.elffile.iter_segments()):
+                pa = int(s['p_paddr'])
+                va = int(s['p_vaddr'])
+                size = int(s['p_filesz'])
+                end_addr = pa + size
+                for section in self.elffile.iter_sections():
+                    if (not section.is_null() and
+                            s.section_in_segment(section)):
+                        self.ebi_pa_name_map[pa] = section.name
+                self.ebi_files_minidump.append((idx, pa, end_addr, va,size))
+
+        if options.minidump:
+            if self.ebi_start == 0:
+                self.ebi_start = self.ebi_files_minidump[0][1]
+        else:
+            if self.ebi_start == 0:
+                self.ebi_start = self.ebi_files[0][1]
         if self.phys_offset is None:
             self.get_hw_id()
 
@@ -600,10 +639,12 @@ class RamDump():
         self.swapper_pg_dir_addr = self.address_of('swapper_pg_dir')
         if self.swapper_pg_dir_addr is None:
             print_out_str('!!! Could not get the swapper page directory!')
-            print_out_str(
-                '!!! Your vmlinux is probably wrong for these dumps')
-            print_out_str('!!! Exiting now')
-            sys.exit(1)
+            if not self.minidump:
+                print_out_str(
+                    '!!! Your vmlinux is probably wrong for these dumps')
+
+                print_out_str('!!! Exiting now')
+                sys.exit(1)
 
         stext = self.address_of('stext')
         if self.kimage_voffset is None:
@@ -664,11 +705,12 @@ class RamDump():
                 '!!! Your vmlinux is probably wrong for these dumps')
             print_out_str('!!! Exiting now')
             sys.exit(1)
-        if not self.get_config():
-            print_out_str('!!! Could not get saved configuration')
-            print_out_str(
-                '!!! This is really bad and probably indicates RAM corruption')
-            print_out_str('!!! Some features may be disabled!')
+        if not self.minidump:
+            if not self.get_config():
+                print_out_str('!!! Could not get saved configuration')
+                print_out_str(
+                    '!!! This is really bad and probably indicates RAM corruption')
+                print_out_str('!!! Some features may be disabled!')
 
         self.unwind = self.Unwinder(self)
 
@@ -755,14 +797,17 @@ class RamDump():
         return s in self.config
 
     def kernel_virt_to_phys(self, addr):
-        va_bits = 39
-        if self.kimage_voffset is None:
-            return addr - self.page_offset + self.phys_offset
+        if self.minidump:
+            return minidump_util.minidump_virt_to_phys(self.ebi_files_minidump,addr)
         else:
-            if addr & (1 << (va_bits - 1)):
+            va_bits = 39
+            if self.kimage_voffset is None:
                 return addr - self.page_offset + self.phys_offset
             else:
-                return addr - (self.kimage_voffset)
+                if addr & (1 << (va_bits - 1)):
+                    return addr - self.page_offset + self.phys_offset
+                else:
+                    return addr - (self.kimage_voffset)
 
     def get_version(self):
         banner_addr = self.address_of('linux_banner')
@@ -803,10 +848,34 @@ class RamDump():
         else:
             print_out_str('!!! Could not lookup saved command line address')
             return False
+        
+    def print_socinfo_minidump(self):
+        content_socinfo = None
+        boards = get_supported_boards()
+        for board in boards:
+            if self.hw_id == board.board_num:
+                content_socinfo = board.ram_start + board.smem_addr_buildinfo
+                break
+        sernum_offset = self.field_offset('struct socinfo_v10', 'serial_number')
+        if sernum_offset is None:
+            sernum_offset = self.field_offset('struct socinfo_v0_10', 'serial_number')
+            if sernum_offset is None:
+                print_out_str("No serial number information available")
+                return False
+        if content_socinfo:
+            addr_of_sernum = content_socinfo + sernum_offset
+            serial_number = self.read_u32(addr_of_sernum, False)
+            if serial_number is not None:
+                print_out_str('Serial number %s' % hex(serial_number))
+                return True
+            return False
+
+        return False
 
     def print_socinfo(self):
         content_socinfo = hex(self.read_pointer('socinfo'))
         content_socinfo = content_socinfo.strip('L')
+
         sernum_offset = self.field_offset('struct socinfo_v10', 'serial_number')
         if sernum_offset is None:
             sernum_offset = self.field_offset('struct socinfo_v0_10', 'serial_number')
@@ -819,6 +888,7 @@ class RamDump():
         if serial_number is not None:
             print_out_str('Serial number %s' % hex(serial_number))
             return True
+
         return False
 
     def auto_parse(self, file_path):
@@ -889,41 +959,46 @@ class RamDump():
             ebi_path = os.path.abspath(ram[3])
             startup_script.write('data.load.binary {0} 0x{1:x}\n'.format(
                 ebi_path, ram[1]).encode('ascii', 'ignore'))
-        if self.arm64:
-            startup_script.write('Register.Set NS 1\n'.encode('ascii', 'ignore'))
-            startup_script.write('Data.Set SPR:0x30201 %Quad 0x{0:x}\n'.format(
-                self.kernel_virt_to_phys(self.swapper_pg_dir_addr))
-                .encode('ascii', 'ignore'))
-
-            if is_cortex_a53:
-                startup_script.write('Data.Set SPR:0x30202 %Quad 0x00000012B5193519\n'.encode('ascii', 'ignore'))
-                startup_script.write('Data.Set SPR:0x30A20 %Quad 0x000000FF440C0400\n'.encode('ascii', 'ignore'))
-                startup_script.write('Data.Set SPR:0x30A30 %Quad 0x0000000000000000\n'.encode('ascii', 'ignore'))
-                startup_script.write('Data.Set SPR:0x30100 %Quad 0x0000000034D5D91D\n'.encode('ascii', 'ignore'))
+        if self.minidump:
+            dload_ram_elf = 'data.load.elf {} /LOGLOAD /nosymbol\n'.format(self.ram_elf_file)
+            startup_script.write(dload_ram_elf.encode('ascii', 'ignore'))
+
+        if not self.minidump:
+            if self.arm64:
+                startup_script.write('Register.Set NS 1\n'.encode('ascii', 'ignore'))
+                startup_script.write('Data.Set SPR:0x30201 %Quad 0x{0:x}\n'.format(
+                    self.kernel_virt_to_phys(self.swapper_pg_dir_addr))
+                    .encode('ascii', 'ignore'))
+
+                if is_cortex_a53:
+                    startup_script.write('Data.Set SPR:0x30202 %Quad 0x00000012B5193519\n'.encode('ascii', 'ignore'))
+                    startup_script.write('Data.Set SPR:0x30A20 %Quad 0x000000FF440C0400\n'.encode('ascii', 'ignore'))
+                    startup_script.write('Data.Set SPR:0x30A30 %Quad 0x0000000000000000\n'.encode('ascii', 'ignore'))
+                    startup_script.write('Data.Set SPR:0x30100 %Quad 0x0000000034D5D91D\n'.encode('ascii', 'ignore'))
+                else:
+                    startup_script.write('Data.Set SPR:0x30202 %Quad 0x00000032B5193519\n'.encode('ascii', 'ignore'))
+                    startup_script.write('Data.Set SPR:0x30A20 %Quad 0x000000FF440C0400\n'.encode('ascii', 'ignore'))
+                    startup_script.write('Data.Set SPR:0x30A30 %Quad 0x0000000000000000\n'.encode('ascii', 'ignore'))
+                    startup_script.write('Data.Set SPR:0x30100 %Quad 0x0000000004C5D93D\n'.encode('ascii', 'ignore'))
+
+                startup_script.write('Register.Set CPSR 0x3C5\n'.encode('ascii', 'ignore'))
+                startup_script.write('MMU.Delete\n'.encode('ascii', 'ignore'))
+                startup_script.write('MMU.SCAN PT 0xFFFFFF8000000000--0xFFFFFFFFFFFFFFFF\n'.encode('ascii', 'ignore'))
+                startup_script.write('mmu.on\n'.encode('ascii', 'ignore'))
+                startup_script.write('mmu.pt.list 0xffffff8000000000\n'.encode('ascii', 'ignore'))
             else:
-                startup_script.write('Data.Set SPR:0x30202 %Quad 0x00000032B5193519\n'.encode('ascii', 'ignore'))
-                startup_script.write('Data.Set SPR:0x30A20 %Quad 0x000000FF440C0400\n'.encode('ascii', 'ignore'))
-                startup_script.write('Data.Set SPR:0x30A30 %Quad 0x0000000000000000\n'.encode('ascii', 'ignore'))
-                startup_script.write('Data.Set SPR:0x30100 %Quad 0x0000000004C5D93D\n'.encode('ascii', 'ignore'))
-
-            startup_script.write('Register.Set CPSR 0x3C5\n'.encode('ascii', 'ignore'))
-            startup_script.write('MMU.Delete\n'.encode('ascii', 'ignore'))
-            startup_script.write('MMU.SCAN PT 0xFFFFFF8000000000--0xFFFFFFFFFFFFFFFF\n'.encode('ascii', 'ignore'))
-            startup_script.write('mmu.on\n'.encode('ascii', 'ignore'))
-            startup_script.write('mmu.pt.list 0xffffff8000000000\n'.encode('ascii', 'ignore'))
-        else:
-            startup_script.write(
-                'PER.S.F C15:0x2 %L 0x{0:x}\n'.format(self.mmu.ttbr).encode('ascii', 'ignore'))
-            if isinstance(self.mmu, Armv7LPAEMMU):
-                # TTBR1. This gets setup once and never change again even if TTBR0
-                # changes
-                startup_script.write('PER.S.F C15:0x102 %L 0x{0:x}\n'.format(
-                    self.mmu.ttbr + 0x4000).encode('ascii', 'ignore'))
-                # TTBCR with EAE and T1SZ set approprately
                 startup_script.write(
-                    'PER.S.F C15:0x202 %L 0x80030000\n'.encode('ascii', 'ignore'))
-            startup_script.write('mmu.on\n'.encode('ascii', 'ignore'))
-            startup_script.write('mmu.scan\n'.encode('ascii', 'ignore'))
+                    'PER.S.F C15:0x2 %L 0x{0:x}\n'.format(self.mmu.ttbr).encode('ascii', 'ignore'))
+                if isinstance(self.mmu, Armv7LPAEMMU):
+                    # TTBR1. This gets setup once and never change again even if TTBR0
+                    # changes
+                    startup_script.write('PER.S.F C15:0x102 %L 0x{0:x}\n'.format(
+                        self.mmu.ttbr + 0x4000).encode('ascii', 'ignore'))
+                    # TTBCR with EAE and T1SZ set approprately
+                    startup_script.write(
+                        'PER.S.F C15:0x202 %L 0x80030000\n'.encode('ascii', 'ignore'))
+                startup_script.write('mmu.on\n'.encode('ascii', 'ignore'))
+                startup_script.write('mmu.scan\n'.encode('ascii', 'ignore'))
 
         where = os.path.abspath(self.vmlinux)
         if self.kaslr_offset is not None:
@@ -953,8 +1028,8 @@ class RamDump():
                     'task.config /opt/t32/demo/arm/kernel/linux/linux.t32\n'.encode('ascii', 'ignore'))
                 startup_script.write(
                     'menu.reprogram /opt/t32/demo/arm/kernel/linux/linux.men\n'.encode('ascii', 'ignore'))
-
-        startup_script.write('task.dtask\n'.encode('ascii', 'ignore'))
+        if not self.minidump:
+            startup_script.write('task.dtask\n'.encode('ascii', 'ignore'))
         startup_script.write(
             'v.v  %ASCII %STRING linux_banner\n'.encode('ascii', 'ignore'))
         if os.path.exists(out_path + '/regs_panic.cmm'):
@@ -1024,30 +1099,38 @@ class RamDump():
         boards = get_supported_boards()
 
         if (self.hw_id is None):
-            heap_toc_offset = self.field_offset('struct smem_shared', 'heap_toc')
-            if heap_toc_offset is None:
-                print_out_str(
-                    '!!!! Could not get a necessary offset for auto detection!')
-                print_out_str(
-                    '!!!! Please check the gdb path which is used for offsets!')
-                print_out_str('!!!! Also check that the vmlinux is not stripped')
-                print_out_str('!!!! Exiting...')
-                sys.exit(1)
+            if not self.minidump:
+                heap_toc_offset = self.field_offset('struct smem_shared', 'heap_toc')
+                if heap_toc_offset is None:
+                    print_out_str(
+                        '!!!! Could not get a necessary offset for auto detection!')
+                    print_out_str(
+                        '!!!! Please check the gdb path which is used for offsets!')
+                    print_out_str('!!!! Also check that the vmlinux is not stripped')
+                    print_out_str('!!!! Exiting...')
+                    sys.exit(1)
 
-            smem_heap_entry_size = self.sizeof('struct smem_heap_entry')
-            offset_offset = self.field_offset('struct smem_heap_entry', 'offset')
+                smem_heap_entry_size = self.sizeof('struct smem_heap_entry')
+                offset_offset = self.field_offset('struct smem_heap_entry', 'offset')
             for board in boards:
-                socinfo_start_addr = board.smem_addr + heap_toc_offset + smem_heap_entry_size * SMEM_HW_SW_BUILD_ID + offset_offset
+                if not self.minidump:
+                    socinfo_start_addr = board.smem_addr + heap_toc_offset + smem_heap_entry_size * SMEM_HW_SW_BUILD_ID + offset_offset
+                else:
+                    if hasattr(board, 'smem_addr_buildinfo'):
+                        socinfo_start_addr = board.smem_addr_buildinfo
+                    else:
+                        continue
                 if add_offset:
                     socinfo_start_addr += board.ram_start
-                soc_start = self.read_int(socinfo_start_addr, False)
-                if soc_start is None:
-                    continue
-
-                socinfo_start = board.smem_addr + soc_start
-                if add_offset:
-                    socinfo_start += board.ram_start
-
+                if not self.minidump:
+                    soc_start = self.read_int(socinfo_start_addr, False)
+                    if soc_start is None:
+                        continue
+                    socinfo_start = board.smem_addr + soc_start
+                    if add_offset:
+                        socinfo_start += board.ram_start
+                else:
+                    socinfo_start = socinfo_start_addr
                 socinfo_id = self.read_int(socinfo_start + 4, False)
                 if socinfo_id != board.socid:
                     continue
@@ -1117,7 +1200,10 @@ class RamDump():
     def virt_to_phys(self, virt_or_name):
         """Does a virtual-to-physical address lookup of the virtual address or
         variable name."""
-        return self.mmu.virt_to_phys(self.resolve_virt(virt_or_name))
+        if self.minidump:
+            return minidump_util.minidump_virt_to_phys(self.ebi_files_minidump,self.resolve_virt(virt_or_name))
+        else:
+            return self.mmu.virt_to_phys(self.resolve_virt(virt_or_name))
 
     def setup_symbol_tables(self):
         stream = os.popen(self.nm_path + ' -n ' + self.vmlinux)
@@ -1249,18 +1335,24 @@ class RamDump():
             return (self.lookup_table[mid][1], self.lookup_table[mid + 1][0] - self.lookup_table[mid][0])
 
     def read_physical(self, addr, length):
-        ebi = (-1, -1, -1)
-        for a in self.ebi_files:
-            fd, start, end, path = a
-            if addr >= start and addr <= end:
-                ebi = a
-                break
-        if ebi[0] is -1:
-            return None
-        offset = addr - ebi[1]
-        ebi[0].seek(offset)
-        a = ebi[0].read(length)
-        return a
+        if self.minidump:
+            addr_data = minidump_util.read_physical_minidump(
+                        self.ebi_files_minidump, self.ebi_files,self.elffile,
+                        addr, length)
+            return addr_data
+        else:
+            ebi = (-1, -1, -1)
+            for a in self.ebi_files:
+                fd, start, end, path = a
+                if addr >= start and addr <= end:
+                    ebi = a
+                    break
+            if ebi[0] is -1:
+                return None
+            offset = addr - ebi[1]
+            ebi[0].seek(offset)
+            a = ebi[0].read(length)
+            return a
 
     def read_dword(self, addr_or_name, virtual=True, cpu=None):
         s = self.read_string(addr_or_name, '<Q', virtual, cpu)
diff --git a/linux-ramdump-parser-v2/ramparse.py b/linux-ramdump-parser-v2/ramparse.py
index 7245e9bbb3a05809f892c1985ac666f1af0f249c..89a6257a7e216c4b2dd790207d231a5c93986759 100644
--- a/linux-ramdump-parser-v2/ramparse.py
+++ b/linux-ramdump-parser-v2/ramparse.py
@@ -152,6 +152,10 @@ if __name__ == '__main__':
     parser.add_option('', '--eval',
                       help='Evaluate some python code directly, or from stdin if "-" is passed. The "dump" variable will be available, as it is with the --shell option.')  # noqa
     parser.add_option('', '--wlan', dest='wlan', help='wlan.ko path')
+    parser.add_option('', '--minidump', action='store_true', dest='minidump',
+                      help='Parse minidump')
+    parser.add_option('', '--ram-elf', dest='ram_elf_addr',
+                      help='pass ap_minidump.elf generated by crashscope')
 
     for p in parser_util.get_parsers():
         parser.add_option(p.shortopt or '',
@@ -161,6 +165,11 @@ if __name__ == '__main__':
                           action='store_true')
 
     (options, args) = parser.parse_args()
+    if options.minidump:
+        default_list = []
+        default_list.append("Dmesg")
+        default_list.append("RTB")
+        default_list.append("DebugImage")
 
     if options.outdir:
         if not os.path.exists(options.outdir):
@@ -224,7 +233,7 @@ if __name__ == '__main__':
 
     print_out_str('using vmlinux file {0}'.format(options.vmlinux))
 
-    if options.ram_addr is None and options.autodump is None:
+    if options.ram_addr is None and options.autodump is None and not options.minidump:
         print_out_str('Need one of --auto-dump or at least one --ram-file')
         sys.exit(1)
 
@@ -343,14 +352,20 @@ if __name__ == '__main__':
             shell.interact()
         sys.exit(0)
 
-    if not dump.print_command_line():
-        print_out_str('!!! Error printing saved command line.')
-        print_out_str('!!! The vmlinux is probably wrong for the ramdumps')
-        print_out_str('!!! Exiting now...')
-        sys.exit(1)
+    if not options.minidump:
+        if not dump.print_command_line():
+            print_out_str('!!! Error printing saved command line.')
+            print_out_str('!!! The vmlinux is probably wrong for the ramdumps')
+            print_out_str('!!! Exiting now...')
+            sys.exit(1)
 
-    if not dump.print_socinfo():
-        print_out_str('!!! No serial number information available.')
+    if options.minidump:
+        if not dump.print_socinfo_minidump():
+            print_out_str('!!! No serial number information '
+                          'available for this minidump.')
+    else:
+        if not dump.print_socinfo():
+            print_out_str('!!! No serial number information available.')
 
     if options.qdss:
         print_out_str('!!! --parse-qdss is now deprecated')
@@ -365,12 +380,24 @@ if __name__ == '__main__':
     # we called parser.add_option with dest=p.cls.__name__ above,
     # so if the user passed that option then `options' will have a
     # p.cls.__name__ attribute.
-    parsers_to_run = [p for p in parser_util.get_parsers()
+    if options.minidump:
+        parsers_to_run = [p for p in parser_util.get_parsers()
+                          if getattr(options, p.cls.__name__)
+                          or (options.everything and p.cls.__name__ in default_list)]
+    else:
+        parsers_to_run = [p for p in parser_util.get_parsers()
                       if getattr(options, p.cls.__name__)
                       or (options.everything and not p.optional)]
     for i,p in enumerate(parsers_to_run):
         if i == 0:
             sys.stderr.write("\n")
+        if options.minidump:
+            if p.cls.__name__ not in default_list:
+                sys.stderr.write("    [%d/%d] %s ... not supported in minidump \n" %
+                                 (i + 1, len(parsers_to_run), p.longopt))
+                continue
+
+
         sys.stderr.write("    [%d/%d] %s ... " %
                          (i + 1, len(parsers_to_run), p.longopt))
         before = time.time()
@@ -387,5 +414,6 @@ if __name__ == '__main__':
 
     sys.stderr.write("\n")
 
-    if options.t32launcher or options.everything:
+    if options.t32launcher or options.everything or options.minidump:
         dump.create_t32_launcher()
+