/*
 * CXL CDAT Structure
 *
 * Copyright (C) 2021 Avery Design Systems, Inc.
 *
 * This work is licensed under the terms of the GNU GPL, version 2 or later.
 * See the COPYING file in the top-level directory.
 */

#include "qemu/osdep.h"
#include "hw/pci/pci.h"
#include "hw/cxl/cxl.h"
#include "qapi/error.h"
#include "qemu/error-report.h"

static void cdat_len_check(CDATSubHeader *hdr, Error **errp)
{
    assert(hdr->length);
    assert(hdr->reserved == 0);

    switch (hdr->type) {
    case CDAT_TYPE_DSMAS:
        assert(hdr->length == sizeof(CDATDsmas));
        break;
    case CDAT_TYPE_DSLBIS:
        assert(hdr->length == sizeof(CDATDslbis));
        break;
    case CDAT_TYPE_DSMSCIS:
        assert(hdr->length == sizeof(CDATDsmscis));
        break;
    case CDAT_TYPE_DSIS:
        assert(hdr->length == sizeof(CDATDsis));
        break;
    case CDAT_TYPE_DSEMTS:
        assert(hdr->length == sizeof(CDATDsemts));
        break;
    case CDAT_TYPE_SSLBIS:
        assert(hdr->length >= sizeof(CDATSslbisHeader));
        assert((hdr->length - sizeof(CDATSslbisHeader)) %
               sizeof(CDATSslbe) == 0);
        break;
    default:
        error_setg(errp, "Type %d is reserved", hdr->type);
    }
}

static void ct3_build_cdat(CDATObject *cdat, Error **errp)
{
    g_autofree CDATTableHeader *cdat_header = NULL;
    g_autofree CDATEntry *cdat_st = NULL;
    uint8_t sum = 0;
    int ent, i;

    /* Use default table if fopen == NULL */
    assert(cdat->build_cdat_table);

    cdat_header = g_malloc0(sizeof(*cdat_header));
    if (!cdat_header) {
        error_setg(errp, "Failed to allocate CDAT header");
        return;
    }

    cdat->built_buf_len = cdat->build_cdat_table(&cdat->built_buf, cdat->private);

    if (!cdat->built_buf_len) {
        /* Build later as not all data available yet */
        cdat->to_update = true;
        return;
    }
    cdat->to_update = false;

    cdat_st = g_malloc0(sizeof(*cdat_st) * (cdat->built_buf_len + 1));
    if (!cdat_st) {
        error_setg(errp, "Failed to allocate CDAT entry array");
        return;
    }

    /* Entry 0 for CDAT header, starts with Entry 1 */
    for (ent = 1; ent < cdat->built_buf_len + 1; ent++) {
        CDATSubHeader *hdr = cdat->built_buf[ent - 1];
        uint8_t *buf = (uint8_t *)cdat->built_buf[ent - 1];

        cdat_st[ent].base = hdr;
        cdat_st[ent].length = hdr->length;

        cdat_header->length += hdr->length;
        for (i = 0; i < hdr->length; i++) {
            sum += buf[i];
        }
    }

    /* CDAT header */
    cdat_header->revision = CXL_CDAT_REV;
    /* For now, no runtime updates */
    cdat_header->sequence = 0;
    cdat_header->length += sizeof(CDATTableHeader);
    sum += cdat_header->revision + cdat_header->sequence +
        cdat_header->length;
    /* Sum of all bytes including checksum must be 0 */
    cdat_header->checksum = ~sum + 1;

    cdat_st[0].base = g_steal_pointer(&cdat_header);
    cdat_st[0].length = sizeof(*cdat_header);
    cdat->entry_len = 1 + cdat->built_buf_len;
    cdat->entry = g_steal_pointer(&cdat_st);
}

static void ct3_load_cdat(CDATObject *cdat, Error **errp)
{
    g_autofree CDATEntry *cdat_st = NULL;
    g_autofree char *buf = NULL;
    uint8_t sum = 0;
    int num_ent;
    int i = 0, ent = 1;
    gsize file_size = 0;
    CDATSubHeader *hdr;
    GError *error = NULL;

    /* Read CDAT file and create its cache */
    if (!g_file_get_contents(cdat->filename, (gchar **)&buf,
                             &file_size, &error)) {
        error_setg(errp, "CDAT: File read failed: %s", error->message);
        g_error_free(error);
        return;
    }
    if (file_size < sizeof(CDATTableHeader)) {
        error_setg(errp, "CDAT: File too short");
        return;
    }
    i = sizeof(CDATTableHeader);
    num_ent = 1;
    while (i < file_size) {
        hdr = (CDATSubHeader *)(buf + i);
        if (i + sizeof(CDATSubHeader) > file_size) {
            error_setg(errp, "CDAT: Truncated table");
            return;
        }
        cdat_len_check(hdr, errp);
        i += hdr->length;
        if (i > file_size) {
            error_setg(errp, "CDAT: Truncated table");
            return;
        }
        num_ent++;
    }
    if (i != file_size) {
        error_setg(errp, "CDAT: File length mismatch");
        return;
    }

    cdat_st = g_new0(CDATEntry, num_ent);

    /* Set CDAT header, Entry = 0 */
    cdat_st[0].base = buf;
    cdat_st[0].length = sizeof(CDATTableHeader);
    i = 0;

    while (i < cdat_st[0].length) {
        sum += buf[i++];
    }

    /* Read CDAT structures */
    while (i < file_size) {
        hdr = (CDATSubHeader *)(buf + i);
        cdat_st[ent].base = hdr;
        cdat_st[ent].length = hdr->length;

        while (buf + i < (char *)cdat_st[ent].base + cdat_st[ent].length) {
            assert(i < file_size);
            sum += buf[i++];
        }

        ent++;
    }

    if (sum != 0) {
        warn_report("CDAT: Found checksum mismatch in %s", cdat->filename);
    }
    cdat->entry_len = num_ent;
    cdat->entry = g_steal_pointer(&cdat_st);
    cdat->buf = g_steal_pointer(&buf);
}

void cxl_doe_cdat_init(CXLComponentState *cxl_cstate, Error **errp)
{
    CDATObject *cdat = &cxl_cstate->cdat;

    if (cdat->filename) {
        ct3_load_cdat(cdat, errp);
    } else {
        ct3_build_cdat(cdat, errp);
    }
}

void cxl_doe_cdat_update(CXLComponentState *cxl_cstate, Error **errp)
{
    CDATObject *cdat = &cxl_cstate->cdat;

    if (cdat->to_update) {
        ct3_build_cdat(cdat, errp);
    }
}

void cxl_doe_cdat_release(CXLComponentState *cxl_cstate)
{
    CDATObject *cdat = &cxl_cstate->cdat;

    free(cdat->entry);
    if (cdat->built_buf) {
        cdat->free_cdat_table(cdat->built_buf, cdat->built_buf_len,
                              cdat->private);
    }
    g_free(cdat->buf);
}
