// Copyright 2018 The Fuchsia Authors
//
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file or at
// https://opensource.org/licenses/MIT

#include <lib/acpi_lite.h>

#include <inttypes.h>
#include <zircon/compiler.h>
#include <trace.h>
#include <vm/physmap.h>

#define LOCAL_TRACE 1


// global state of the acpi lite library
struct acpi_lite_state {
    const acpi_rsdp *rsdp;
    const acpi_rsdt_xsdt *sdt;
    size_t num_tables; // number of top level tables
    bool xsdt; // are the pointers 64 or 32bit?
} acpi;

static inline const void *phys_to_ptr(uintptr_t pa) {
    if (!is_physmap_phys_addr(pa)) {
        return nullptr;
    }
    // consider 0 to be invalid
    if (pa == 0) {
        return nullptr;
    }

    return static_cast<const void *>(paddr_to_physmap(pa));
}

static uint8_t acpi_checksum(const void *_buf, size_t len) {
    uint8_t c = 0;

    const uint8_t *buf = static_cast<const uint8_t *>(_buf);
    for (size_t i = 0; i < len; i++) {
        c = (uint8_t)(c + buf[i]);
    }

    return c;
}

static bool validate_rsdp(const acpi_rsdp *rsdp) {
    // check the signature
    if (memcmp(ACPI_RSDP_SIG, rsdp->sig, 8)) {
        return false;
    }

    // validate the v1 checksum on the first 20 bytes of the table
    uint8_t c = acpi_checksum(rsdp, 20);
    if (c) {
        return false;
    }

    // is it v2?
    if (rsdp->revision >= 2) {
        if (rsdp->length < 36 || rsdp->length > 4096) {
            // keep the table length within reason
            return false;
        }

        c = acpi_checksum(rsdp, rsdp->length);
        if (c) {
            return false;
        }
    }

    // seems okay
    return true;
}

static zx_paddr_t find_rsdp_pc() {
    // search for it in the BIOS EBDA area (0xe0000..0xfffff) on 16 byte boundaries
    for (zx_paddr_t ptr = 0xe0000; ptr <= 0xfffff; ptr += 16) {
        const auto rsdp = static_cast<const acpi_rsdp *>(phys_to_ptr(ptr));

        if (validate_rsdp(rsdp)) {
            return ptr;
        }
    }

    return 0;
}

static bool validate_sdt(const acpi_rsdt_xsdt *sdt, size_t *num_tables, bool *xsdt) {
    LTRACEF("%p\n", sdt);

    // check the signature and see if it's a rsdt or xsdt
    if (!memcmp(sdt->header.sig, "XSDT", 4)) {
        *xsdt = true;
    } else if (!memcmp(sdt->header.sig, "RSDT", 4)) {
        *xsdt = false;
    } else {
        return false;
    }

    // is the length sane?
    if (sdt->header.length < 36 || sdt->header.length > 4096) {
        return false;
    }

    // is it a revision we understand?
    if (sdt->header.revision != 1) {
        return false;
    }

    // checksum the entire table
    uint8_t c = acpi_checksum(sdt, sdt->header.length);
    if (c) {
        return false;
    }

    // compute the number of pointers to tables we have
    *num_tables = (sdt->header.length - 36u) / (*xsdt ? 8u : 4u);

    // looks okay
    return true;
}

const acpi_sdt_header *acpi_get_table_at_index(size_t index) {
    if (index >= acpi.num_tables) {
        return nullptr;
    }

    zx_paddr_t pa;
    if (acpi.xsdt) {
        pa = acpi.sdt->addr64[index];
    } else {
        pa = acpi.sdt->addr32[index];
    }

    return static_cast<const acpi_sdt_header *>(phys_to_ptr(pa));
}

const acpi_sdt_header *acpi_get_table_by_sig(const char *sig) {
    // walk the list of tables
    for (size_t i = 0; i < acpi.num_tables; i++) {
        const auto header = acpi_get_table_at_index(i);
        if (!header) {
            continue;
        }

        if (!memcmp(sig, header->sig, 4)) {
            return header;
        }
    }

    return nullptr;
}

zx_status_t acpi_lite_init(zx_paddr_t rsdp_pa) {
    LTRACEF("passed in rsdp %#" PRIxPTR "\n", rsdp_pa);

    // see if the rsdp pointer is valid
    if (rsdp_pa == 0) {
        // search around for it in a platform-specific way
#if PLATFORM_PC
        rsdp_pa = find_rsdp_pc();
        if (rsdp_pa == 0) {
            dprintf(INFO, "ACPI LITE: couldn't find ACPI RSDP in BIOS area\n");
        }
#endif

        if (rsdp_pa == 0) {
            return ZX_ERR_NOT_FOUND;
        }
    }

    const void *ptr = phys_to_ptr(rsdp_pa);
    if (!ptr) {
        dprintf(INFO, "ACPI LITE: failed to translate RSDP address %#" PRIxPTR " to virtual\n", rsdp_pa);
        return ZX_ERR_NOT_FOUND;
    }

    // see if the RSDP is there
    acpi.rsdp = static_cast<const acpi_rsdp *>(ptr);
    if (!validate_rsdp(acpi.rsdp)) {
        dprintf(INFO, "ACPI LITE: RSDP structure does not check out\n");
        return ZX_ERR_NOT_FOUND;
    }

    dprintf(SPEW, "ACPI LITE: RSDP checks out\n");

    // find the pointer to either the RSDT or XSDT
    acpi.sdt = nullptr;
    if (acpi.rsdp->revision < 2) {
        // v1 RSDP, pointing at a RSDT
        acpi.sdt = static_cast<const acpi_rsdt_xsdt *>(phys_to_ptr(acpi.rsdp->rsdt_address));
    } else {
        // v2+ RSDP, pointing at a XSDT
        // try to use the 64bit address first
        acpi.sdt = static_cast<const acpi_rsdt_xsdt *>(phys_to_ptr(acpi.rsdp->xsdt_address));
        if (!acpi.sdt) {
            acpi.sdt = static_cast<const acpi_rsdt_xsdt *>(phys_to_ptr(acpi.rsdp->rsdt_address));
        }
    }

    if (!validate_sdt(acpi.sdt, &acpi.num_tables, &acpi.xsdt)) {
        dprintf(INFO, "ACPI LITE: RSDT/XSDT structure does not check out\n");
        return ZX_ERR_NOT_FOUND;
    }

    dprintf(SPEW, "ACPI LITE: RSDT/XSDT checks out, %zu tables\n", acpi.num_tables);

    acpi_lite_dump_tables();

    return ZX_OK;
}

void acpi_lite_dump_tables() {
    if (!acpi.sdt) {
        return;
    }

    printf("root table:\n");
    hexdump(acpi.sdt, acpi.sdt->header.length);

    // walk the table list
    for (size_t i = 0; i < acpi.num_tables; i++) {
        const auto header = acpi_get_table_at_index(i);
        if (!header) {
            continue;
        }

        printf("table %zu:\n", i);
        hexdump(header, header->length);
    }
}

zx_status_t acpi_process_madt_entries_etc(const uint8_t search_type, const MadtEntryCallback& callback) {
    const acpi_madt_table *madt = reinterpret_cast<const acpi_madt_table *>(acpi_get_table_by_sig(ACPI_MADT_SIG));
    if (!madt) {
        return ZX_ERR_NOT_FOUND;
    }

    // bytewise array of the same table
    const uint8_t *madt_array = reinterpret_cast<const uint8_t *>(madt);

    // walk the table off the end of the header, looking for the requested type
    size_t off = sizeof(*madt);
    while (off < madt->header.length) {
        uint8_t type = madt_array[off];
        uint8_t length = madt_array[off + 1];

        if (type == search_type) {
            callback(static_cast<const void *>(&madt_array[off]) , length);
        }

        off += length;
    }

    return ZX_OK;
}


