/**
 * Describes utility functions for parsing CPER into JSON IR. 
 * 
 * Author: Lawrence.Tang@arm.com
 **/

#include <stdio.h>
#include "json.h"
#include "edk/Cper.h"
#include "cper-utils.h"

//The available severity types for CPER.
const char* CPER_SEVERITY_TYPES[4] = {"Recoverable", "Fatal", "Corrected", "Informational"};

//Converts the given generic CPER error status to JSON IR.
json_object* cper_generic_error_status_to_ir(EFI_GENERIC_ERROR_STATUS* error_status)
{
    json_object* error_status_ir = json_object_new_object();

    //Error type.
    json_object_object_add(error_status_ir, "errorType", integer_to_readable_pair_with_desc(error_status->Type, 18,
        CPER_GENERIC_ERROR_TYPES_KEYS,
        CPER_GENERIC_ERROR_TYPES_VALUES,
        CPER_GENERIC_ERROR_TYPES_DESCRIPTIONS,
        "Unknown (Reserved)"));

    //Boolean bit fields.
    json_object_object_add(error_status_ir, "addressSignal", json_object_new_boolean(error_status->AddressSignal));
    json_object_object_add(error_status_ir, "controlSignal", json_object_new_boolean(error_status->ControlSignal));
    json_object_object_add(error_status_ir, "dataSignal", json_object_new_boolean(error_status->DataSignal));
    json_object_object_add(error_status_ir, "detectedByResponder", json_object_new_boolean(error_status->DetectedByResponder));
    json_object_object_add(error_status_ir, "detectedByRequester", json_object_new_boolean(error_status->DetectedByRequester));
    json_object_object_add(error_status_ir, "firstError", json_object_new_boolean(error_status->FirstError));
    json_object_object_add(error_status_ir, "overflowDroppedLogs", json_object_new_boolean(error_status->OverflowNotLogged));
    
    return error_status_ir;
}

//Converts a single uniform struct of UINT64s into intermediate JSON IR format, given names for each field in byte order.
json_object* uniform_struct64_to_ir(UINT64* start, int len, const char* names[])
{
    json_object* result = json_object_new_object();

    UINT64* cur = start;
    for (int i=0; i<len; i++)
    {
        json_object_object_add(result, names[i], json_object_new_uint64(*cur));
        cur++;
    }

    return result;
}

//Converts a single uniform struct of UINT32s into intermediate JSON IR format, given names for each field in byte order.
json_object* uniform_struct_to_ir(UINT32* start, int len, const char* names[])
{
    json_object* result = json_object_new_object();

    UINT32* cur = start;
    for (int i=0; i<len; i++)
    {
        json_object_object_add(result, names[i], json_object_new_uint64(*cur));
        cur++;
    }

    return result;
}

//Converts a single integer value to an object containing a value, and a readable name if possible.
json_object* integer_to_readable_pair(UINT64 value, int len, int keys[], const char* values[], const char* default_value)
{
    json_object* result = json_object_new_object();
    json_object_object_add(result, "value", json_object_new_uint64(value));

    //Search for human readable name, add.
    const char* name = default_value;
    for (int i=0; i<len; i++)
    {
        if (keys[i] == value)
            name = values[i];
    }

    json_object_object_add(result, "name", json_object_new_string(name));
    return result;
}

//Converts a single integer value to an object containing a value, readable name and description if possible.
json_object* integer_to_readable_pair_with_desc(int value, int len, int keys[], const char* values[], 
    const char* descriptions[], const char* default_value) 
{
    json_object* result = json_object_new_object();
    json_object_object_add(result, "value", json_object_new_int(value));

    //Search for human readable name, add.
    const char* name = default_value;
    for (int i=0; i<len; i++)
    {
        if (keys[i] == value) 
        {
            name = values[i];
            json_object_object_add(result, "description", json_object_new_string(descriptions[i]));
        }
    }

    json_object_object_add(result, "name", json_object_new_string(name));
    return result;
}

//Converts the given 64 bit bitfield to IR, assuming bit 0 starts on the left.
json_object* bitfield_to_ir(UINT64 bitfield, int num_fields, const char* names[])
{
    json_object* result = json_object_new_object();
    for (int i=0; i<num_fields; i++)
    {
        json_object_object_add(result, names[i], json_object_new_boolean((bitfield >> i) & 0b1));
    }

    return result;
}

//Converts the given UINT64 array into a JSON IR array, given the length.
json_object* uint64_array_to_ir_array(UINT64* array, int len)
{
    json_object* array_ir = json_object_new_array();
    for (int i=0; i<len; i++)
        json_object_array_add(array_ir, json_object_new_uint64(array[i]));
    return array_ir;
}

//Converts a single UINT16 revision number into JSON IR representation.
json_object* revision_to_ir(UINT16 revision)
{
    json_object* revision_info = json_object_new_object();
    json_object_object_add(revision_info, "major", json_object_new_int(revision >> 8));
    json_object_object_add(revision_info, "minor", json_object_new_int(revision & 0xFF));
    return revision_info;
}

//Returns the appropriate string for the given integer severity.
const char* severity_to_string(UINT8 severity)
{
    return severity < 4 ? CPER_SEVERITY_TYPES[severity] : "Unknown";
}

//Helper function to convert an EDK EFI GUID into a string for intermediate use.
void guid_to_string(char* out, EFI_GUID* guid)
{
    sprintf(out, "%08x-%04x-%04x-%02x%02x%02x%02x%02x%02x%02x%02x", 
        guid->Data1, 
        guid->Data2, 
        guid->Data3,
        guid->Data4[0],
        guid->Data4[1],
        guid->Data4[2],
        guid->Data4[3],
        guid->Data4[4],
        guid->Data4[5],
        guid->Data4[6],
        guid->Data4[7]);
}

//Returns one if two EFI GUIDs are equal, zero otherwise.
int guid_equal(EFI_GUID* a, EFI_GUID* b)
{
    //Check top base 3 components.
    if (a->Data1 != b->Data1
        || a->Data2 != b->Data2
        || a->Data3 != b->Data3) 
    {
        return 0;
    }

    //Check Data4 array for equality.
    for (int i=0; i<8; i++)
    {
        if (a->Data4[i] != b->Data4[i])
            return 0;
    }

    return 1;
}

//Converts the given BCD byte to a standard integer.
int bcd_to_int(UINT8 bcd)
{
    return ((bcd & 0xF0) >> 4) * 10 + (bcd & 0x0F);
}