/*
 * 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, &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, &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, 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, 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, &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, &reserved, 4);
    proxy.writeBlob(addr + 16, &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, &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);
}
