/*
 * Copyright (c) 2008 The Hewlett-Packard Development Company
 * All rights reserved.
 *
 * The license below extends only to copyright in the software and shall
 * not be construed as granting a license to any other intellectual
 * property including but not limited to intellectual property relating
 * to a hardware implementation of the functionality of the software
 * licensed hereunder.  You may use the software subject to the license
 * terms below provided that you ensure that this notice is replicated
 * unmodified and in its entirety in all distributions of the software,
 * modified or unmodified, in source code or in binary form.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met: redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer;
 * redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution;
 * neither the name of the copyright holders nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * Authors: Gabe Black
 */

#include "arch/x86/bios/intelmp.hh"

#include "arch/x86/isa_traits.hh"
#include "base/logging.hh"
#include "base/types.hh"
#include "mem/port_proxy.hh"
#include "sim/byteswap.hh"

// Config entry types
#include "params/X86IntelMPBaseConfigEntry.hh"
#include "params/X86IntelMPExtConfigEntry.hh"

// General table structures
#include "params/X86IntelMPConfigTable.hh"
#include "params/X86IntelMPFloatingPointer.hh"

// Base entry types
#include "params/X86IntelMPBus.hh"
#include "params/X86IntelMPIOAPIC.hh"
#include "params/X86IntelMPIOIntAssignment.hh"
#include "params/X86IntelMPLocalIntAssignment.hh"
#include "params/X86IntelMPProcessor.hh"

// Extended entry types
#include "params/X86IntelMPAddrSpaceMapping.hh"
#include "params/X86IntelMPBusHierarchy.hh"
#include "params/X86IntelMPCompatAddrSpaceMod.hh"

using namespace std;

const char X86ISA::IntelMP::FloatingPointer::signature[] = "_MP_";

template<class T>
uint8_t
writeOutField(PortProxy& proxy, Addr addr, T val)
{
    uint64_t guestVal = X86ISA::htog(val);
    proxy.writeBlob(addr, (uint8_t *)(&guestVal), sizeof(T));

    uint8_t checkSum = 0;
    while (guestVal) {
        checkSum += guestVal;
        guestVal >>= 8;
    }
    return checkSum;
}

uint8_t
writeOutString(PortProxy& proxy, Addr addr, string str, int length)
{
    char cleanedString[length + 1];
    cleanedString[length] = 0;

    if (str.length() > length) {
        memcpy(cleanedString, str.c_str(), length);
        warn("Intel MP configuration table string \"%s\" "
             "will be truncated to \"%s\".\n", str, (char *)&cleanedString);
    } else {
        memcpy(cleanedString, str.c_str(), str.length());
        memset(cleanedString + str.length(), 0, length - str.length());
    }
    proxy.writeBlob(addr, (uint8_t *)(&cleanedString), length);

    uint8_t checkSum = 0;
    for (int i = 0; i < length; i++)
        checkSum += cleanedString[i];

    return checkSum;
}

Addr
X86ISA::IntelMP::FloatingPointer::writeOut(PortProxy& proxy, Addr addr)
{
    // Make sure that either a config table is present or a default
    // configuration was found but not both.
    if (!tableAddr && !defaultConfig)
        fatal("Either an MP configuration table or a default configuration "
                "must be used.");
    if (tableAddr && defaultConfig)
        fatal("Both an MP configuration table and a default configuration "
                "were set.");

    uint8_t checkSum = 0;

    proxy.writeBlob(addr, (uint8_t *)signature, 4);
    for (int i = 0; i < 4; i++)
        checkSum += signature[i];

    checkSum += writeOutField(proxy, addr + 4, tableAddr);

    // The length of the structure in paragraphs, aka 16 byte chunks.
    uint8_t length = 1;
    proxy.writeBlob(addr + 8, &length, 1);
    checkSum += length;

    proxy.writeBlob(addr + 9, &specRev, 1);
    checkSum += specRev;

    proxy.writeBlob(addr + 11, &defaultConfig, 1);
    checkSum += defaultConfig;

    uint32_t features2_5 = imcrPresent ? (1 << 7) : 0;
    checkSum += writeOutField(proxy, addr + 12, features2_5);

    checkSum = -checkSum;
    proxy.writeBlob(addr + 10, &checkSum, 1);

    return 16;
}

X86ISA::IntelMP::FloatingPointer::FloatingPointer(Params * p) :
    SimObject(p), tableAddr(0), specRev(p->spec_rev),
    defaultConfig(p->default_config), imcrPresent(p->imcr_present)
{}

X86ISA::IntelMP::FloatingPointer *
X86IntelMPFloatingPointerParams::create()
{
    return new X86ISA::IntelMP::FloatingPointer(this);
}

Addr
X86ISA::IntelMP::BaseConfigEntry::writeOut(PortProxy& proxy,
        Addr addr, uint8_t &checkSum)
{
    proxy.writeBlob(addr, &type, 1);
    checkSum += type;
    return 1;
}

X86ISA::IntelMP::BaseConfigEntry::BaseConfigEntry(Params * p, uint8_t _type) :
    SimObject(p), type(_type)
{}

Addr
X86ISA::IntelMP::ExtConfigEntry::writeOut(PortProxy& proxy,
        Addr addr, uint8_t &checkSum)
{
    proxy.writeBlob(addr, &type, 1);
    checkSum += type;
    proxy.writeBlob(addr + 1, &length, 1);
    checkSum += length;
    return 1;
}

X86ISA::IntelMP::ExtConfigEntry::ExtConfigEntry(Params * p,
        uint8_t _type, uint8_t _length) :
    SimObject(p), type(_type), length(_length)
{}

const char X86ISA::IntelMP::ConfigTable::signature[] = "PCMP";

Addr
X86ISA::IntelMP::ConfigTable::writeOut(PortProxy& proxy, Addr addr)
{
    uint8_t checkSum = 0;

    proxy.writeBlob(addr, (uint8_t *)signature, 4);
    for (int i = 0; i < 4; i++)
        checkSum += signature[i];

    // Base table length goes here but will be calculated later.

    proxy.writeBlob(addr + 6, (uint8_t *)(&specRev), 1);
    checkSum += specRev;

    // The checksum goes here but is still being calculated.

    checkSum += writeOutString(proxy, addr + 8, oemID, 8);
    checkSum += writeOutString(proxy, addr + 16, productID, 12);

    checkSum += writeOutField(proxy, addr + 28, oemTableAddr);
    checkSum += writeOutField(proxy, addr + 32, oemTableSize);
    checkSum += writeOutField(proxy, addr + 34, (uint16_t)baseEntries.size());
    checkSum += writeOutField(proxy, addr + 36, localApic);

    uint8_t reserved = 0;
    proxy.writeBlob(addr + 43, &reserved, 1);
    checkSum += reserved;

    vector<BaseConfigEntry *>::iterator baseEnt;
    uint16_t offset = 44;
    for (baseEnt = baseEntries.begin();
            baseEnt != baseEntries.end(); baseEnt++) {
        offset += (*baseEnt)->writeOut(proxy, addr + offset, checkSum);
    }

    // We've found the end of the base table this point.
    checkSum += writeOutField(proxy, addr + 4, offset);

    vector<ExtConfigEntry *>::iterator extEnt;
    uint16_t extOffset = 0;
    uint8_t extCheckSum = 0;
    for (extEnt = extEntries.begin();
            extEnt != extEntries.end(); extEnt++) {
        extOffset += (*extEnt)->writeOut(proxy,
                addr + offset + extOffset, extCheckSum);
    }

    checkSum += writeOutField(proxy, addr + 40, extOffset);
    extCheckSum = -extCheckSum;
    checkSum += writeOutField(proxy, addr + 42, extCheckSum);

    // And now, we finally have the whole check sum completed.
    checkSum = -checkSum;
    writeOutField(proxy, addr + 7, checkSum);

    return offset + extOffset;
};

X86ISA::IntelMP::ConfigTable::ConfigTable(Params * p) : SimObject(p),
    specRev(p->spec_rev), oemID(p->oem_id), productID(p->product_id),
    oemTableAddr(p->oem_table_addr), oemTableSize(p->oem_table_size),
    localApic(p->local_apic),
    baseEntries(p->base_entries), extEntries(p->ext_entries)
{}

X86ISA::IntelMP::ConfigTable *
X86IntelMPConfigTableParams::create()
{
    return new X86ISA::IntelMP::ConfigTable(this);
}

Addr
X86ISA::IntelMP::Processor::writeOut(
        PortProxy& proxy, Addr addr, uint8_t &checkSum)
{
    BaseConfigEntry::writeOut(proxy, addr, checkSum);
    checkSum += writeOutField(proxy, addr + 1, localApicID);
    checkSum += writeOutField(proxy, addr + 2, localApicVersion);
    checkSum += writeOutField(proxy, addr + 3, cpuFlags);
    checkSum += writeOutField(proxy, addr + 4, cpuSignature);
    checkSum += writeOutField(proxy, addr + 8, featureFlags);

    uint32_t reserved = 0;
    proxy.writeBlob(addr + 12, (uint8_t *)(&reserved), 4);
    proxy.writeBlob(addr + 16, (uint8_t *)(&reserved), 4);
    return 20;
}

X86ISA::IntelMP::Processor::Processor(Params * p) : BaseConfigEntry(p, 0),
    localApicID(p->local_apic_id), localApicVersion(p->local_apic_version),
    cpuFlags(0), cpuSignature(0), featureFlags(p->feature_flags)
{
    if (p->enable)
        cpuFlags |= (1 << 0);
    if (p->bootstrap)
        cpuFlags |= (1 << 1);

    replaceBits(cpuSignature, 0, 3, p->stepping);
    replaceBits(cpuSignature, 4, 7, p->model);
    replaceBits(cpuSignature, 8, 11, p->family);
}

X86ISA::IntelMP::Processor *
X86IntelMPProcessorParams::create()
{
    return new X86ISA::IntelMP::Processor(this);
}

Addr
X86ISA::IntelMP::Bus::writeOut(
        PortProxy& proxy, Addr addr, uint8_t &checkSum)
{
    BaseConfigEntry::writeOut(proxy, addr, checkSum);
    checkSum += writeOutField(proxy, addr + 1, busID);
    checkSum += writeOutString(proxy, addr + 2, busType, 6);
    return 8;
}

X86ISA::IntelMP::Bus::Bus(Params * p) : BaseConfigEntry(p, 1),
    busID(p->bus_id), busType(p->bus_type)
{}

X86ISA::IntelMP::Bus *
X86IntelMPBusParams::create()
{
    return new X86ISA::IntelMP::Bus(this);
}

Addr
X86ISA::IntelMP::IOAPIC::writeOut(
        PortProxy& proxy, Addr addr, uint8_t &checkSum)
{
    BaseConfigEntry::writeOut(proxy, addr, checkSum);
    checkSum += writeOutField(proxy, addr + 1, id);
    checkSum += writeOutField(proxy, addr + 2, version);
    checkSum += writeOutField(proxy, addr + 3, flags);
    checkSum += writeOutField(proxy, addr + 4, address);
    return 8;
}

X86ISA::IntelMP::IOAPIC::IOAPIC(Params * p) : BaseConfigEntry(p, 2),
    id(p->id), version(p->version), flags(0), address(p->address)
{
    if (p->enable)
        flags |= 1;
}

X86ISA::IntelMP::IOAPIC *
X86IntelMPIOAPICParams::create()
{
    return new X86ISA::IntelMP::IOAPIC(this);
}

Addr
X86ISA::IntelMP::IntAssignment::writeOut(
        PortProxy& proxy, Addr addr, uint8_t &checkSum)
{
    BaseConfigEntry::writeOut(proxy, addr, checkSum);
    checkSum += writeOutField(proxy, addr + 1, interruptType);
    checkSum += writeOutField(proxy, addr + 2, flags);
    checkSum += writeOutField(proxy, addr + 4, sourceBusID);
    checkSum += writeOutField(proxy, addr + 5, sourceBusIRQ);
    checkSum += writeOutField(proxy, addr + 6, destApicID);
    checkSum += writeOutField(proxy, addr + 7, destApicIntIn);
    return 8;
}

X86ISA::IntelMP::IOIntAssignment::IOIntAssignment(Params * p) :
    IntAssignment(p, p->interrupt_type, p->polarity, p->trigger, 3,
            p->source_bus_id, p->source_bus_irq,
            p->dest_io_apic_id, p->dest_io_apic_intin)
{}

X86ISA::IntelMP::IOIntAssignment *
X86IntelMPIOIntAssignmentParams::create()
{
    return new X86ISA::IntelMP::IOIntAssignment(this);
}

X86ISA::IntelMP::LocalIntAssignment::LocalIntAssignment(Params * p) :
    IntAssignment(p, p->interrupt_type, p->polarity, p->trigger, 4,
            p->source_bus_id, p->source_bus_irq,
            p->dest_local_apic_id, p->dest_local_apic_intin)
{}

X86ISA::IntelMP::LocalIntAssignment *
X86IntelMPLocalIntAssignmentParams::create()
{
    return new X86ISA::IntelMP::LocalIntAssignment(this);
}

Addr
X86ISA::IntelMP::AddrSpaceMapping::writeOut(
        PortProxy& proxy, Addr addr, uint8_t &checkSum)
{
    ExtConfigEntry::writeOut(proxy, addr, checkSum);
    checkSum += writeOutField(proxy, addr + 2, busID);
    checkSum += writeOutField(proxy, addr + 3, addrType);
    checkSum += writeOutField(proxy, addr + 4, addr);
    checkSum += writeOutField(proxy, addr + 12, addrLength);
    return length;
}

X86ISA::IntelMP::AddrSpaceMapping::AddrSpaceMapping(Params * p) :
    ExtConfigEntry(p, 128, 20),
    busID(p->bus_id), addrType(p->address_type),
    addr(p->address), addrLength(p->length)
{}

X86ISA::IntelMP::AddrSpaceMapping *
X86IntelMPAddrSpaceMappingParams::create()
{
    return new X86ISA::IntelMP::AddrSpaceMapping(this);
}

Addr
X86ISA::IntelMP::BusHierarchy::writeOut(
        PortProxy& proxy, Addr addr, uint8_t &checkSum)
{
    ExtConfigEntry::writeOut(proxy, addr, checkSum);
    checkSum += writeOutField(proxy, addr + 2, busID);
    checkSum += writeOutField(proxy, addr + 3, info);
    checkSum += writeOutField(proxy, addr + 4, parentBus);

    uint32_t reserved = 0;
    proxy.writeBlob(addr + 5, (uint8_t *)(&reserved), 3);

    return length;
}

X86ISA::IntelMP::BusHierarchy::BusHierarchy(Params * p) :
    ExtConfigEntry(p, 129, 8),
    busID(p->bus_id), info(0), parentBus(p->parent_bus)
{
    if (p->subtractive_decode)
        info |= 1;
}

X86ISA::IntelMP::BusHierarchy *
X86IntelMPBusHierarchyParams::create()
{
    return new X86ISA::IntelMP::BusHierarchy(this);
}

Addr
X86ISA::IntelMP::CompatAddrSpaceMod::writeOut(
        PortProxy& proxy, Addr addr, uint8_t &checkSum)
{
    ExtConfigEntry::writeOut(proxy, addr, checkSum);
    checkSum += writeOutField(proxy, addr + 2, busID);
    checkSum += writeOutField(proxy, addr + 3, mod);
    checkSum += writeOutField(proxy, addr + 4, rangeList);
    return length;
}

X86ISA::IntelMP::CompatAddrSpaceMod::CompatAddrSpaceMod(Params * p) :
    ExtConfigEntry(p, 130, 8),
    busID(p->bus_id), mod(0), rangeList(p->range_list)
{
    if (p->add)
        mod |= 1;
}

X86ISA::IntelMP::CompatAddrSpaceMod *
X86IntelMPCompatAddrSpaceModParams::create()
{
    return new X86ISA::IntelMP::CompatAddrSpaceMod(this);
}
