#!/usr/bin/env python3
#
# Copyright (c) 2020 Intel Corporation
#
# SPDX-License-Identifier: Apache-2.0

import logging
import struct


# Note: keep sync with C code
Z_COREDUMP_HDR_ID = b'ZE'
Z_COREDUMP_HDR_VER = 1
LOG_HDR_STRUCT = "<ccHHBBI"
LOG_HDR_SIZE = struct.calcsize(LOG_HDR_STRUCT)

Z_COREDUMP_ARCH_HDR_ID = b'A'
LOG_ARCH_HDR_STRUCT = "<cHH"
LOG_ARCH_HDR_SIZE = struct.calcsize(LOG_ARCH_HDR_STRUCT)

Z_COREDUMP_MEM_HDR_ID = b'M'
Z_COREDUMP_MEM_HDR_VER = 1
LOG_MEM_HDR_STRUCT = "<cH"
LOG_MEM_HDR_SIZE = struct.calcsize(LOG_MEM_HDR_STRUCT)


logger = logging.getLogger("parser")


def reason_string(reason):
    # Keep sync with "enum k_fatal_error_reason"
    ret = "(Unknown)"

    if reason == 0:
        ret = "K_ERR_CPU_EXCEPTION"
    elif reason == 1:
        ret = "K_ERR_SPURIOUS_IRQ"
    elif reason == 2:
        ret = "K_ERR_STACK_CHK_FAIL"
    elif reason == 3:
        ret = "K_ERR_KERNEL_OOPS"
    elif reason == 4:
        ret = "K_ERR_KERNEL_PANIC"

    return ret


class CoredumpLogFile:
    """
    Process the binary coredump file for register block
    and memory blocks.
    """

    def __init__(self, logfile):
        self.logfile = logfile
        self.fd = None

        self.log_hdr = None
        self.arch_data = list()
        self.memory_regions = list()

    def open(self):
        self.fd = open(self.logfile, "rb")

    def close(self):
        self.fd.close()

    def get_arch_data(self):
        return self.arch_data

    def get_memory_regions(self):
        return self.memory_regions

    def parse_arch_section(self):
        hdr = self.fd.read(LOG_ARCH_HDR_SIZE)
        _, hdr_ver, num_bytes = struct.unpack(LOG_ARCH_HDR_STRUCT, hdr)

        arch_data = self.fd.read(num_bytes)

        self.arch_data = {"hdr_ver" : hdr_ver, "data" : arch_data}

        return True

    def parse_memory_section(self):
        hdr = self.fd.read(LOG_MEM_HDR_SIZE)
        _, hdr_ver = struct.unpack(LOG_MEM_HDR_STRUCT, hdr)

        if hdr_ver != Z_COREDUMP_MEM_HDR_VER:
            logger.error(f"Memory block version: {hdr_ver}, expected {Z_COREDUMP_MEM_HDR_VER}!")
            return False

        # Figure out how to read the start and end addresses
        ptr_fmt = None
        if self.log_hdr["ptr_size"] == 64:
            ptr_fmt = "QQ"
        elif self.log_hdr["ptr_size"] == 32:
            ptr_fmt = "II"
        else:
            return False

        data = self.fd.read(struct.calcsize(ptr_fmt))
        saddr, eaddr = struct.unpack(ptr_fmt, data)

        size = eaddr - saddr

        data = self.fd.read(size)

        mem = {"start": saddr, "end": eaddr, "data": data}
        self.memory_regions.append(mem)

        logger.info("Memory: 0x%x to 0x%x of size %d" %
                    (saddr, eaddr, size))

        return True

    def parse(self):
        if self.fd is None:
            self.open()

        hdr = self.fd.read(LOG_HDR_SIZE)
        id1, id2, hdr_ver, tgt_code, ptr_size, flags, reason = struct.unpack(LOG_HDR_STRUCT, hdr)

        if (id1 + id2) != Z_COREDUMP_HDR_ID:
            # ID in header does not match
            logger.error("Log header ID not found...")
            return False

        if hdr_ver != Z_COREDUMP_HDR_VER:
            logger.error(f"Log version: {hdr_ver}, expected: {Z_COREDUMP_HDR_VER}!")
            return False

        ptr_size = 2 ** ptr_size

        self.log_hdr = {
                        "hdr_version": hdr_ver,
                        "tgt_code": tgt_code,
                        "ptr_size": ptr_size,
                        "flags": flags,
                        "reason": reason,
                        }

        logger.info("Reason: {0}".format(reason_string(reason)))
        logger.info(f"Pointer size {ptr_size}")

        del id1, id2, hdr_ver, tgt_code, ptr_size, flags, reason

        while True:
            section_id = self.fd.read(1)
            if not section_id:
                # no more data to read
                break

            self.fd.seek(-1, 1) # go back 1 byte
            if section_id == Z_COREDUMP_ARCH_HDR_ID:
                if not self.parse_arch_section():
                    logger.error("Cannot parse architecture section")
                    return False
            elif section_id == Z_COREDUMP_MEM_HDR_ID:
                if not self.parse_memory_section():
                    logger.error("Cannot parse memory section")
                    return False
            else:
                # Unknown section in log file
                logger.error(f"Unknown section in log file with ID {section_id}")
                return False

        return True
