/*
// Copyright (c) 2019 Intel Corporation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
*/

#include "peci_pcie.hpp"

#include "pciDeviceClass.hpp"
#include "pciVendors.hpp"

#include <boost/asio/io_context.hpp>
#include <boost/asio/steady_timer.hpp>
#include <boost/container/flat_map.hpp>
#include <boost/container/flat_set.hpp>
#include <sdbusplus/asio/object_server.hpp>
#include <sdbusplus/bus/match.hpp>

#include <iomanip>
#include <iostream>
#include <set>
#include <sstream>
#include <unordered_set>

namespace peci_pcie
{

struct PcieInterfaces
{
    std::shared_ptr<sdbusplus::asio::dbus_interface> deviceIface;
    std::shared_ptr<sdbusplus::asio::dbus_interface> assetIface;
};

static boost::container::flat_map<
    int, boost::container::flat_map<
             int, boost::container::flat_map<int, PcieInterfaces>>>
    pcieDeviceDBusMap;

static bool abortScan;
static bool scanInProgress;

constexpr const bool debug = false;

namespace function
{
static constexpr const char* functionTypeName = "FunctionType";
static constexpr const char* deviceClassName = "DeviceClass";
static constexpr const char* vendorIdName = "VendorId";
static constexpr const char* deviceIdName = "DeviceId";
static constexpr const char* classCodeName = "ClassCode";
static constexpr const char* revisionIdName = "RevisionId";
static constexpr const char* subsystemIdName = "SubsystemId";
static constexpr const char* subsystemVendorIdName = "SubsystemVendorId";
} // namespace function

static constexpr const std::array pciConfigInfo{
    std::tuple<const char*, int, int>{function::functionTypeName, -1, -1},
    std::tuple<const char*, int, int>{function::deviceClassName, -1, -1},
    std::tuple<const char*, int, int>{function::vendorIdName, 0, 2},
    std::tuple<const char*, int, int>{function::deviceIdName, 2, 2},
    std::tuple<const char*, int, int>{function::classCodeName, 9, 3},
    std::tuple<const char*, int, int>{function::revisionIdName, 8, 1},
    std::tuple<const char*, int, int>{function::subsystemIdName, 0x2e, 2},
    std::tuple<const char*, int, int>{function::subsystemVendorIdName, 0x2c,
                                      2}};
} // namespace peci_pcie

enum class resCode
{
    resOk,
    resSkip,
    resErr
};

struct CPUInfo
{
    size_t addr;
    bool skipCpuBuses;
    boost::container::flat_set<size_t> cpuBusNums;
};

// PECI Client Address Map
static resCode getCPUBusMap(std::vector<CPUInfo>& cpuInfo)
{
    cpuInfo.clear();
    for (size_t addr = MIN_CLIENT_ADDR; addr <= MAX_CLIENT_ADDR; addr++)
    {
        if (peci_Ping(addr) != PECI_CC_SUCCESS)
        {
            continue;
        }

        auto& cpu = cpuInfo.emplace_back(CPUInfo{addr, false, {}});
        uint8_t cc = 0;
        CPUModel model{};
        uint8_t stepping = 0;
        if (peci_GetCPUID(addr, &model, &stepping, &cc) != PECI_CC_SUCCESS)
        {
            std::cerr << "Cannot get CPUID!\n";
            return resCode::resErr;
        }

        switch (model)
        {
            case skx:
            {
                // Get the assigned CPU bus numbers from CPUBUSNO and CPUBUSNO1
                // (B(0) D8 F2 offsets CCh and D0h)
                uint32_t cpuBusNum = 0;
                if (peci_RdPCIConfigLocal(addr, 0, 8, 2, 0xCC, 4,
                                          (uint8_t*)&cpuBusNum,
                                          &cc) != PECI_CC_SUCCESS)
                {
                    return resCode::resErr;
                }
                uint32_t cpuBusNum1 = 0;
                if (peci_RdPCIConfigLocal(addr, 0, 8, 2, 0xD0, 4,
                                          (uint8_t*)&cpuBusNum1,
                                          &cc) != PECI_CC_SUCCESS)
                {
                    return resCode::resErr;
                }

                // Add the CPU bus numbers to the set for this CPU
                while (cpuBusNum)
                {
                    // Get the LSB
                    size_t busNum = cpuBusNum & 0xFF;
                    cpu.cpuBusNums.insert(busNum);
                    // Shift right by one byte
                    cpuBusNum >>= 8;
                }
                while (cpuBusNum1)
                {
                    // Get the LSB
                    size_t busNum = cpuBusNum1 & 0xFF;
                    cpu.cpuBusNums.insert(busNum);
                    // Shift right by one byte
                    cpuBusNum1 >>= 8;
                }
                cpu.skipCpuBuses = true;
            }
        }
    }
    return cpuInfo.empty() ? resCode::resErr : resCode::resOk;
}

static bool isPECIAvailable(void)
{
    for (size_t i = MIN_CLIENT_ADDR; i <= MAX_CLIENT_ADDR; i++)
    {
        if (peci_Ping(i) == PECI_CC_SUCCESS)
        {
            return true;
        }
    }
    return false;
}

static resCode getDataFromPCIeConfig(const int& clientAddr, const int& bus,
                                     const int& dev, const int& func,
                                     const int& offset, const int& size,
                                     uint32_t& pciData)
{
    // PECI RdPCIConfig() currently only supports 4 byte reads, so adjust
    // the offset and size to get the right data
    static constexpr const int pciReadSize = 4;
    int mod = offset % pciReadSize;
    int pciOffset = offset - mod;
    if (mod + size > pciReadSize)
    {
        return resCode::resErr;
    }

    std::array<uint8_t, pciReadSize> data;
    uint8_t cc;
    int ret = PECI_CC_TIMEOUT;
    for (int index = 0; (index < 15) && (ret == PECI_CC_TIMEOUT); index++)
    {
#ifdef USE_RDENDPOINTCFG
        ret = peci_RdEndPointConfigPci(clientAddr,  // CPU Address
                                       0,           // PCI Seg (use 0 for now)
                                       bus,         // PCI Bus
                                       dev,         // PCI Device
                                       func,        // PCI Function
                                       pciOffset,   // PCI Offset
                                       pciReadSize, // PCI Read Size
                                       data.data(), // PCI Read Data
                                       &cc);        // PECI Completion Code
#else
        ret = peci_RdPCIConfig(clientAddr,  // CPU Address
                               bus,         // PCI Bus
                               dev,         // PCI Device
                               func,        // PCI Function
                               pciOffset,   // PCI Offset
                               data.data(), // PCI Read Data
                               &cc);        // PECI Completion Code
#endif
        if constexpr (peci_pcie::debug)
        {
            std::cerr << "Request: bus " << bus << " dev " << dev << " func "
                      << func << " pciOffset " << pciOffset << " ret: " << ret
                      << " cc: " << static_cast<int>(cc) << "\n";
        }
    }
    if (ret != PECI_CC_SUCCESS)
    {
        return resCode::resErr;
    }
    else if (cc != PECI_DEV_CC_SUCCESS)
    {
        return resCode::resSkip;
    }

    // Now build the requested data into a single number
    pciData = 0;
    for (int i = mod; i < mod + size; i++)
    {
        pciData |= static_cast<uint32_t>(data[i]) << 8 * (i - mod);
    }

    return resCode::resOk;
}

static resCode getStringFromData(const int& size, const uint32_t& data,
                                 std::string& res)
{
    // And convert it to a string
    std::stringstream dataStream;
    dataStream << "0x" << std::hex << std::setfill('0') << std::setw(size * 2)
               << data;
    res = dataStream.str();
    return resCode::resOk;
}

static resCode getVendorName(const int& clientAddr, const int& bus,
                             const int& dev, std::string& res)
{
    static constexpr const int vendorIDOffset = 0x00;
    static constexpr const int vendorIDSize = 2;

    // Get the header type register from function 0
    uint32_t vendorID = 0;
    if (getDataFromPCIeConfig(clientAddr, bus, dev, 0, vendorIDOffset,
                              vendorIDSize, vendorID) != resCode::resOk)
    {
        return resCode::resErr;
    }
    // Get the vendor name or use Other if it doesn't exist
    res = pciVendors.try_emplace(vendorID, otherVendor).first->second;
    return resCode::resOk;
}

static resCode getDeviceClass(const int& clientAddr, const int& bus,
                              const int& dev, const int& func, std::string& res)
{
    static constexpr const int baseClassOffset = 0x0b;
    static constexpr const int baseClassSize = 1;

    // Get the Device Base Class
    uint32_t baseClass = 0;
    if (getDataFromPCIeConfig(clientAddr, bus, dev, func, baseClassOffset,
                              baseClassSize, baseClass) != resCode::resOk)
    {
        return resCode::resErr;
    }
    // Get the base class name or use Other if it doesn't exist
    res = pciDeviceClasses.try_emplace(baseClass, otherClass).first->second;
    return resCode::resOk;
}

static resCode getCapReading(const int& clientAddr, const int& bus,
                             const int& dev, uint32_t& capReading,
                             const int compareCapID, const int offsetAddress,
                             const int offsetLength)
{
    resCode error;
    uint32_t capAddress = 0;
    uint32_t capabilityID;
    uint32_t nextCapPointer = peci_pcie::pointToCapStruct;

    do
    {
        // Get capability address
        error = getDataFromPCIeConfig(clientAddr, bus, dev, 0, nextCapPointer,
                                      1, capAddress);
        if (error != resCode::resOk)
        {
            return error;
        }
        // Capability struct address is a pointer which point to next capability
        // struct, so if capability struct address is 0 means it doesn't have
        // next capability struct.
        if (capAddress == 0)
        {
            return resCode::resSkip;
        }
        // Get capability ID
        error = getDataFromPCIeConfig(clientAddr, bus, dev, 0, capAddress, 1,
                                      capabilityID);
        if (error != resCode::resOk)
        {
            return error;
        }
        nextCapPointer = capAddress + peci_pcie::capPointerOffset;

    } while (capabilityID != compareCapID);
    // Get capability reading.
    error = getDataFromPCIeConfig(clientAddr, bus, dev, 0,
                                  capAddress + offsetAddress, offsetLength,
                                  capReading);
    if (error != resCode::resOk)
    {
        return error;
    }
    return resCode::resOk;
}

static resCode getGenerationInUse(const int& clientAddr, const int& bus,
                                  const int& dev, std::string& generationInUse)
{
    static std::unordered_set<uint32_t> linkSpeedSkipMap;
    resCode error;
    std::string res;
    uint32_t capReading = 0;

    // Capability ID 0x10(16) is PCI Express
    constexpr int pcieCapID = 16;
    constexpr int capLength = 2;
    uint32_t linkStatus;

    error = getCapReading(clientAddr, bus, dev, linkStatus, pcieCapID,
                          peci_pcie::linkStatusOffset, capLength);
    if (error != resCode::resOk)
    {
        return error;
    }

    uint32_t linkSpeed = linkStatus & peci_pcie::maskOfCLS;

    switch (linkSpeed)
    {
        case peci_pcie::pcieGen1:
            generationInUse = "xyz.openbmc_project.Inventory.Item."
                              "PCIeSlot.Generations.Gen1";
            error = resCode::resOk;
            break;
        case peci_pcie::pcieGen2:
            generationInUse = "xyz.openbmc_project.Inventory.Item."
                              "PCIeSlot.Generations.Gen2";
            error = resCode::resOk;
            break;
        case peci_pcie::pcieGen3:
            generationInUse = "xyz.openbmc_project.Inventory.Item."
                              "PCIeSlot.Generations.Gen3";
            error = resCode::resOk;
            break;
        case peci_pcie::pcieGen4:
            generationInUse = "xyz.openbmc_project.Inventory.Item."
                              "PCIeSlot.Generations.Gen4";
            error = resCode::resOk;
            break;
        case peci_pcie::pcieGen5:
            generationInUse = "xyz.openbmc_project.Inventory.Item."
                              "PCIeSlot.Generations.Gen5";
            error = resCode::resOk;
            break;
        default:
            if (!linkSpeedSkipMap.contains(linkSpeed))
            {
                std::cerr << "Link speed : " << linkSpeed
                          << " can not mapping to PCIe type list.\n";
                linkSpeedSkipMap.emplace(linkSpeed);
            }
            error = resCode::resSkip;
    }
    return error;
}

static resCode isMultiFunction(const int& clientAddr, const int& bus,
                               const int& dev, bool& res)
{
    static constexpr const int headerTypeOffset = 0x0e;
    static constexpr const int headerTypeSize = 1;
    static constexpr const int multiFuncBit = 1 << 7;

    res = false;
    // Get the header type register from function 0
    uint32_t headerType = 0;
    if (getDataFromPCIeConfig(clientAddr, bus, dev, 0, headerTypeOffset,
                              headerTypeSize, headerType) != resCode::resOk)
    {
        return resCode::resErr;
    }
    // Check if it's a multifunction device
    if (headerType & multiFuncBit)
    {
        res = true;
    }
    return resCode::resOk;
}

static resCode pcieFunctionExists(const int& clientAddr, const int& bus,
                                  const int& dev, const int& func, bool& res)
{
    constexpr const int pciIDOffset = 0;
    constexpr const int pciIDSize = 4;
    uint32_t pciID = 0;
    res = false;

    resCode error = getDataFromPCIeConfig(clientAddr, bus, dev, func,
                                          pciIDOffset, pciIDSize, pciID);
    if (error == resCode::resSkip)
    {
        return resCode::resOk;
    }
    else if (error == resCode::resErr)
    {
        return resCode::resErr;
    }

    // if VID and DID are all 0s or 1s, then the device doesn't exist
    if (pciID != 0x00000000 && pciID != 0xFFFFFFFF)
    {
        res = true;
    }
    return resCode::resOk;
}

static resCode pcieDeviceExists(const int& clientAddr, const int& bus,
                                const int& dev, bool& res)
{
    // Check if this device exists by checking function 0
    return pcieFunctionExists(clientAddr, bus, dev, 0, res);
}

static resCode setPCIeProperty(const int& clientAddr, const int& bus,
                               const int& dev, const std::string& propertyName,
                               const std::string& propertyValue)
{
    peci_pcie::PcieInterfaces pcieIfaces =
        peci_pcie::pcieDeviceDBusMap[clientAddr][bus][dev];

    std::shared_ptr<sdbusplus::asio::dbus_interface> iface;
    if (propertyName == "Manufacturer")
    {
        iface = pcieIfaces.assetIface;
    }
    else
    {
        iface = pcieIfaces.deviceIface;
    }

    if (iface->is_initialized())
    {
        if (!iface->set_property(propertyName, propertyValue))
            return resCode::resErr;
    }
    else
    {
        if (!iface->register_property(propertyName, propertyValue))
            return resCode::resErr;
    }
    return resCode::resOk;
}

static void setDefaultPCIeFunctionProperties(const int& clientAddr,
                                             const int& bus, const int& dev,
                                             const int& func)
{
    // Set the function-specific properties
    for (const auto& [name, offset, size] : peci_pcie::pciConfigInfo)
    {
        setPCIeProperty(clientAddr, bus, dev,
                        "Function" + std::to_string(func) + std::string(name),
                        std::string());
    }
}

static resCode setPCIeFunctionProperties(const int& clientAddr, const int& bus,
                                         const int& dev, const int& func)
{
    uint32_t data = 0;
    std::string res;
    resCode error;

    for (const auto& [name, offset, size] : peci_pcie::pciConfigInfo)
    {
        if (offset < 0)
        {
            continue;
        }

        error = getDataFromPCIeConfig(clientAddr, bus, dev, func, offset, size,
                                      data);
        if (error != resCode::resOk)
        {
            return error;
        }
        getStringFromData(size, data, res);
        setPCIeProperty(clientAddr, bus, dev,
                        "Function" + std::to_string(func) + std::string(name),
                        res);
    }

    // Set the function type always to physical for now
    setPCIeProperty(clientAddr, bus, dev,
                    "Function" + std::to_string(func) +
                        std::string(peci_pcie::function::functionTypeName),
                    "Physical");

    // Set the function Device Class
    error = getDeviceClass(clientAddr, bus, dev, func, res);
    if (error != resCode::resOk)
    {
        return error;
    }
    setPCIeProperty(clientAddr, bus, dev,
                    "Function" + std::to_string(func) +
                        std::string(peci_pcie::function::deviceClassName),
                    res);
    return resCode::resOk;
}

static resCode setPCIeDeviceProperties(const int& clientAddr, const int& bus,
                                       const int& dev)
{
    // Set the device manufacturer
    std::string manuf;
    resCode error = getVendorName(clientAddr, bus, dev, manuf);
    if (error != resCode::resOk)
    {
        return error;
    }
    setPCIeProperty(clientAddr, bus, dev, "Manufacturer", manuf);

    // Set the device type
    constexpr const char* deviceTypeName = "DeviceType";
    bool multiFunc;
    error = isMultiFunction(clientAddr, bus, dev, multiFunc);
    if (error != resCode::resOk)
    {
        return error;
    }
    if (multiFunc)
    {
        setPCIeProperty(clientAddr, bus, dev, deviceTypeName, "MultiFunction");
    }
    else
    {
        setPCIeProperty(clientAddr, bus, dev, deviceTypeName, "SingleFunction");
    }

    // Set PCIe Generation
    constexpr const char* generationInUseName = "GenerationInUse";
    std::string generationInUse;
    error = getGenerationInUse(clientAddr, bus, dev, generationInUse);
    if (error == resCode::resErr)
    {
        return error;
    }
    // "resSkip" status means it can't get the capability reading, such like
    // this device is not PCI Express.
    if (error == resCode::resSkip)
    {
        setPCIeProperty(clientAddr, bus, dev, generationInUseName, "");
        return resCode::resOk;
    }
    setPCIeProperty(clientAddr, bus, dev, generationInUseName, generationInUse);

    return resCode::resOk;
}

static resCode updatePCIeDevice(const int& clientAddr, const int& bus,
                                const int& dev)
{
    if (setPCIeDeviceProperties(clientAddr, bus, dev) != resCode::resOk)
    {
        return resCode::resErr;
    }

    // Walk through and populate the functions for this device
    for (int func = 0; func < peci_pcie::maxPCIFunctions; func++)
    {
        bool res;
        resCode error = pcieFunctionExists(clientAddr, bus, dev, func, res);
        if (error != resCode::resOk)
        {
            return error;
        }
        if (res)
        {
            // Set the properties for this function
            if (setPCIeFunctionProperties(clientAddr, bus, dev, func) !=
                resCode::resOk)
            {
                return resCode::resErr;
            }
        }
        else
        {
            // Set default properties for unused functions
            setDefaultPCIeFunctionProperties(clientAddr, bus, dev, func);
        }
    }
    return resCode::resOk;
}

static void removePCIeDevice(sdbusplus::asio::object_server& objServer,
                             const int& clientAddr, const int& bus,
                             const int& dev)
{
    peci_pcie::PcieInterfaces ifaces =
        peci_pcie::pcieDeviceDBusMap[clientAddr][bus][dev];

    objServer.remove_interface(ifaces.deviceIface);
    objServer.remove_interface(ifaces.assetIface);

    peci_pcie::pcieDeviceDBusMap[clientAddr][bus].erase(dev);
    if (peci_pcie::pcieDeviceDBusMap[clientAddr][bus].empty())
    {
        peci_pcie::pcieDeviceDBusMap[clientAddr].erase(bus);
    }
    if (peci_pcie::pcieDeviceDBusMap[clientAddr].empty())
    {
        peci_pcie::pcieDeviceDBusMap.erase(clientAddr);
    }
}

static resCode addPCIeDevice(sdbusplus::asio::object_server& objServer,
                             const int& clientAddr, const int& cpu,
                             const int& bus, const int& dev)
{
    std::string pathName = std::string(peci_pcie::peciPCIePath) + "/S" +
                           std::to_string(cpu) + "B" + std::to_string(bus) +
                           "D" + std::to_string(dev);
    peci_pcie::PcieInterfaces ifaces;
    ifaces.deviceIface =
        objServer.add_interface(pathName, peci_pcie::peciPCIeDeviceInterface);
    ifaces.assetIface =
        objServer.add_interface(pathName, peci_pcie::peciPCIeAssetInterface);
    peci_pcie::pcieDeviceDBusMap[clientAddr][bus][dev] = ifaces;

    // Update the properties for the new device
    if (updatePCIeDevice(clientAddr, bus, dev) != resCode::resOk)
    {
        removePCIeDevice(objServer, clientAddr, bus, dev);
        return resCode::resErr;
    }

    ifaces.deviceIface->initialize();
    ifaces.assetIface->initialize();
    return resCode::resOk;
}

static bool pcieDeviceInDBusMap(const int& clientAddr, const int& bus,
                                const int& dev)
{
    if (auto clientAddrIt = peci_pcie::pcieDeviceDBusMap.find(clientAddr);
        clientAddrIt != peci_pcie::pcieDeviceDBusMap.end())
    {
        if (auto busIt = clientAddrIt->second.find(bus);
            busIt != clientAddrIt->second.end())
        {
            if (auto devIt = busIt->second.find(dev);
                devIt != busIt->second.end())
            {
                if (devIt->second.deviceIface != nullptr ||
                    devIt->second.assetIface != nullptr)
                {
                    return true;
                }
            }
        }
    }
    return false;
}

static resCode probePCIeDevice(boost::asio::io_context& io,
                               sdbusplus::asio::object_server& objServer,
                               size_t addr, int cpu, int bus, int dev)
{
    bool res;
    resCode error = pcieDeviceExists(addr, bus, dev, res);
    if (error != resCode::resOk)
    {
        return error;
    }
    if (res)
    {
        if (pcieDeviceInDBusMap(addr, bus, dev))
        {
            // This device is already in D-Bus, so update it
            if (updatePCIeDevice(addr, bus, dev) != resCode::resOk)
            {
                return resCode::resErr;
            }
        }
        else
        {
            // This device is not in D-Bus, so add it
            if (addPCIeDevice(objServer, addr, cpu, bus, dev) != resCode::resOk)
            {
                return resCode::resErr;
            }
        }
    }
    else
    {
        // If PECI is not available, then stop scanning
        if (!isPECIAvailable())
        {
            return resCode::resErr;
        }

        if (pcieDeviceInDBusMap(addr, bus, dev))
        {
            // This device is in D-Bus, so remove it
            removePCIeDevice(objServer, addr, bus, dev);
        }
    }
    return resCode::resOk;
}

static void scanNextPCIeDevice(boost::asio::io_context& io,
                               sdbusplus::asio::object_server& objServer,
                               std::vector<CPUInfo>& cpuInfo, int cpu, int bus,
                               int dev);
static void scanPCIeDevice(boost::asio::io_context& io,
                           sdbusplus::asio::object_server& objServer,
                           std::vector<CPUInfo>& cpuInfo, int cpu, int bus,
                           int dev)
{
    if (cpu >= cpuInfo.size())
    {
        std::cerr << "Request to scan CPU" << cpu
                  << " while CPU array has size " << cpuInfo.size() << "\n";
        return;
    }
    auto& info = cpuInfo[cpu];
    // Check if this is a CPU bus that we should skip
    if (info.skipCpuBuses && info.cpuBusNums.count(bus))
    {
        std::cout << "Skipping CPU " << cpu << " Bus Number " << bus << "\n";
        // Skip all the devices on this bus
        dev = peci_pcie::maxPCIDevices;
    }
    else
    {
        if (probePCIeDevice(io, objServer, info.addr, cpu, bus, dev) !=
            resCode::resOk)
        {
            std::cerr << "Failed to probe CPU " << cpu << " Bus " << bus
                      << " Device " << dev << "\n";
            peci_pcie::abortScan = true;
        }
    }

    scanNextPCIeDevice(io, objServer, cpuInfo, cpu, bus, dev);
    return;
}

static void scanNextPCIeDevice(boost::asio::io_context& io,
                               sdbusplus::asio::object_server& objServer,
                               std::vector<CPUInfo>& cpuInfo, int cpu, int bus,
                               int dev)
{
    if (peci_pcie::abortScan)
    {
        peci_pcie::scanInProgress = false;
        std::cerr << "PCIe scan aborted\n";
        return;
    }

    // PCIe Device scan completed, so move to the next device
    if (++dev >= peci_pcie::maxPCIDevices)
    {
        // All devices scanned, so move to the next bus
        dev = 0;
        if (++bus >= peci_pcie::maxPCIBuses)
        {
            // All buses scanned, so move to the next CPU
            bus = 0;
            if (++cpu >= cpuInfo.size())
            {
                // All CPUs scanned, so we're done
                peci_pcie::scanInProgress = false;
                std::cerr << "PCIe scan completed\n";
                return;
            }
        }
    }
    boost::asio::post(io, [&io, &objServer, &cpuInfo, cpu, bus, dev]() mutable {
        scanPCIeDevice(io, objServer, cpuInfo, cpu, bus, dev);
    });
}

static void startPCIeScan(boost::asio::io_context& io,
                          sdbusplus::asio::object_server& objServer,
                          std::vector<CPUInfo>& cpuInfo)
{
    if (!peci_pcie::scanInProgress)
    {
        // get the PECI client address list
        std::cerr << "Getting map\n";
        if (getCPUBusMap(cpuInfo) != resCode::resOk)
        {
            peci_pcie::abortScan = true;
            return;
        }
        std::cerr << "PCIe scan started\n";
        // scan PCIe starting from CPU 0, Bus 0, Device 0
        peci_pcie::scanInProgress = true;
        peci_pcie::abortScan = false;
        scanPCIeDevice(io, objServer, cpuInfo, 0, 0, 0);
    }
}

static void peciAvailableCheck(boost::asio::steady_timer& peciWaitTimer,
                               boost::asio::io_context& io,
                               sdbusplus::asio::object_server& objServer,
                               std::vector<CPUInfo>& cpuInfo)
{
    static bool lastPECIState = false;
    bool peciAvailable = isPECIAvailable();
    if constexpr (peci_pcie::debug)
    {
        std::cerr << "peciAvailableCheck " << peciAvailable << " "
                  << lastPECIState << " " << peci_pcie::abortScan << "\n";
    }
    if (peciAvailable && (!lastPECIState || peci_pcie::abortScan))
    {
        lastPECIState = true;
        auto pcieTimeout = std::make_shared<boost::asio::steady_timer>(io);
        constexpr const int pcieWaitTime = 60;
        if constexpr (peci_pcie::debug)
        {
            std::cerr << "Scanning in 60 seconds\n";
        }
        pcieTimeout->expires_after(std::chrono::seconds(pcieWaitTime));
        pcieTimeout->async_wait([&io, &objServer, &cpuInfo, pcieTimeout](
                                    const boost::system::error_code& ec) {
            if (ec)
            {
                // operation_aborted is expected if timer is canceled
                // before completion.
                if (ec != boost::asio::error::operation_aborted)
                {
                    std::cerr << "PECI PCIe async_wait failed " << ec;
                }
                lastPECIState = false;
                return;
            }
            startPCIeScan(io, objServer, cpuInfo);
        });
    }
    else if (!peciAvailable && lastPECIState)
    {
        lastPECIState = false;
    }

    peciWaitTimer.expires_after(
        std::chrono::seconds(peci_pcie::peciCheckInterval));
    peciWaitTimer.async_wait([&peciWaitTimer, &io, &objServer,
                              &cpuInfo](const boost::system::error_code& ec) {
        if (ec)
        {
            // operation_aborted is expected if timer is canceled
            // before completion.
            if (ec != boost::asio::error::operation_aborted)
            {
                std::cerr << "PECI Available Check async_wait failed " << ec;
            }
            return;
        }
        peciAvailableCheck(peciWaitTimer, io, objServer, cpuInfo);
    });
}

static void waitForOSStandbyDelay(boost::asio::io_context& io,
                                  sdbusplus::asio::object_server& objServer,
                                  boost::asio::steady_timer& osStandbyTimer,
                                  std::vector<CPUInfo>& cpuInfo)
{
    osStandbyTimer.expires_after(
        std::chrono::seconds(peci_pcie::osStandbyDelaySeconds));

    osStandbyTimer.async_wait(
        [&io, &objServer, &cpuInfo](const boost::system::error_code& ec) {
        if (ec == boost::asio::error::operation_aborted)
        {
            return; // we're being canceled
        }
        else if (ec)
        {
            std::cerr << "OS Standby async_wait failed: " << ec.value() << ": "
                      << ec.message() << "\n";
            return;
        }
        startPCIeScan(io, objServer, cpuInfo);
    });
}

static void monitorOSStandby(boost::asio::io_context& io,
                             std::shared_ptr<sdbusplus::asio::connection> conn,
                             sdbusplus::asio::object_server& objServer,
                             boost::asio::steady_timer& osStandbyTimer,
                             std::vector<CPUInfo>& cpuInfo)
{
    std::cerr << "Start OperatingSystemState Monitor\n";

    static sdbusplus::bus::match_t osStateMatch(
        *conn,
        "type='signal',interface='org.freedesktop.DBus.Properties',member='"
        "PropertiesChanged',arg0='xyz.openbmc_project.State.OperatingSystem."
        "Status'",
        [&io, &objServer, &osStandbyTimer,
         &cpuInfo](sdbusplus::message_t& msg) {
        // Get the OS State from the message
        std::string osStateInterface;
        boost::container::flat_map<std::string, std::variant<std::string>>
            propertiesChanged;
        msg.read(osStateInterface, propertiesChanged);

        for (const auto& [name, value] : propertiesChanged)
        {
            if (name == "OperatingSystemState")
            {
                const std::string* state = std::get_if<std::string>(&value);
                if (state == nullptr)
                {
                    std::cerr << "Unable to read OS state value\n";
                    return;
                }
                // Note: Short version of OperatingSystemState value is
                // deprecated and would be removed in the future
                if ((*state == "Standby") ||
                    (*state == "xyz.openbmc_project.State.OperatingSystem."
                               "Status.OSStatus.Standby"))
                {
                    peci_pcie::abortScan = false;
                    waitForOSStandbyDelay(io, objServer, osStandbyTimer,
                                          cpuInfo);
                }
                else if ((*state == "Inactive") ||
                         (*state == "xyz.openbmc_project.State.OperatingSystem."
                                    "Status.OSStatus.Inactive"))
                {
                    peci_pcie::abortScan = true;
                    osStandbyTimer.cancel();
                }
            }
        }
        });

    // Check if the OS state is already available
    conn->async_method_call(
        [&io, &objServer, &osStandbyTimer,
         &cpuInfo](boost::system::error_code ec,
                   const std::variant<std::string>& property) {
        if (ec)
        {
            std::cerr << "error with OS state async_method_call\n";
            return;
        }

        const std::string* state = std::get_if<std::string>(&property);
        if (state == nullptr)
        {
            std::cerr << "Unable to read OS state value\n";
            return;
        }

        // If the OS state is in Standby, then BIOS is done and we can
        // continue.  Otherwise, we just wait for the match
        // Note: Short version of OperatingSystemState value is deprecated
        // and would be removed in the future

        if ((*state == "Standby") ||
            (*state == "xyz.openbmc_project.State.OperatingSystem.Status."
                       "OSStatus.Standby"))
        {
            waitForOSStandbyDelay(io, objServer, osStandbyTimer, cpuInfo);
        }
        },
        "xyz.openbmc_project.State.OperatingSystem",
        "/xyz/openbmc_project/state/os", "org.freedesktop.DBus.Properties",
        "Get", "xyz.openbmc_project.State.OperatingSystem.Status",
        "OperatingSystemState");
}

int main(int argc, char* argv[])
{
    // setup connection to dbus
    boost::asio::io_context io;
    std::shared_ptr<sdbusplus::asio::connection> conn =
        std::make_shared<sdbusplus::asio::connection>(io);

    // PECI PCIe Object
    conn->request_name(peci_pcie::peciPCIeObject);
    sdbusplus::asio::object_server server =
        sdbusplus::asio::object_server(conn);

    // CPU map
    std::vector<CPUInfo> cpuInfo;

#ifdef WAIT_FOR_OS_STANDBY
    boost::asio::steady_timer osStandbyTimer(io);
    monitorOSStandby(io, conn, server, osStandbyTimer, cpuInfo);
#else
    // Start the PECI check loop
    boost::asio::steady_timer peciWaitTimer(
        io, std::chrono::seconds(peci_pcie::peciCheckInterval));
    peciWaitTimer.async_wait([&peciWaitTimer, &io, &server,
                              &cpuInfo](const boost::system::error_code& ec) {
        if (ec)
        {
            // operation_aborted is expected if timer is canceled
            // before completion.
            if (ec != boost::asio::error::operation_aborted)
            {
                std::cerr << "PECI Available Check async_wait failed " << ec;
            }
            return;
        }
        peciAvailableCheck(peciWaitTimer, io, server, cpuInfo);
    });
#endif

    io.run();

    return 0;
}
