/*
// Copyright (c) 2018 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.
*/
#pragma once

#include "app.hpp"
#include "dbus_utility.hpp"
#include "error_messages.hpp"
#include "external_storer.hpp"
#include "health.hpp"
#include "managed_store.hpp"
#include "managed_store_types.hpp"
#include "query.hpp"
#include "registries/privilege_registry.hpp"
#include "utils/collection.hpp"
#include "utils/dbus_utils.hpp"
#include "utils/hex_utils.hpp"
#include "utils/json_utils.hpp"
#include "utils/location_utils.hpp"
#include "utils/system_utils.hpp"

#include <boost/container/flat_map.hpp>
#include <boost/system/error_code.hpp>
#include <sdbusplus/asio/property.hpp>
#include <sdbusplus/message/native_types.hpp>
#include <sdbusplus/unpack_properties.hpp>
#include <sdbusplus/utility/dedup_variant.hpp>

#include <algorithm>
#include <array>
#include <cstdint>
#include <limits>
#include <string_view>
#include <unordered_map>

#ifdef UNIT_TEST_BUILD
#include "test/g3/mock_managed_store.hpp" // NOLINT
#endif

namespace redfish
{

using resourceIdToSubtreeRespMapType =
    std::unordered_map<std::string,
                       std::pair<std::string, dbus::utility::MapperServiceMap>>;
using ManagedObjectByServiceMap =
    std::unordered_map<std::string, dbus::utility::ManagedObjectType>;

constexpr std::array<std::string_view, 2> processorInterfaces = {
    "xyz.openbmc_project.Inventory.Item.Cpu",
    "xyz.openbmc_project.Inventory.Item.Accelerator"};

constexpr std::array<std::string_view, 1> subProcessorCoreInterfaces = {
    "xyz.openbmc_project.Inventory.Item.CpuCore"};

constexpr std::array<std::string_view, 1> subProcessorThreadInterfaces = {
    "xyz.openbmc_project.Inventory.Item.CpuThread"};

inline void getSubProcessorThreadCollectionWithExpand(
    const std::shared_ptr<bmcweb::AsyncResp>& aResp,
    const nlohmann::json::json_pointer& jsonPtr, uint8_t expandLevel,
    const std::string& processorId, const std::string& coreId,
    const std::string& corePath,
    const dbus::utility::MapperGetSubTreeResponse& subtree,
    const ManagedObjectByServiceMap& managedObjectsMap);

inline void getSubProcessorCoreCollectionWithExpand(
    const std::shared_ptr<bmcweb::AsyncResp>& aResp,
    const nlohmann::json::json_pointer& jsonPtr, uint8_t expandLevel,
    const std::string& processorId, const std::string& cpuPath,
    const dbus::utility::MapperGetSubTreeResponse& subtree,
    const ManagedObjectByServiceMap& managedObjectsMap);

inline void getProcessorCollectionWithExpand(
    const std::shared_ptr<bmcweb::AsyncResp>& aResp,
    const dbus::utility::MapperGetSubTreeResponse& subtree,
    const ManagedObjectByServiceMap& managedObjectsMap, uint8_t expandLevel,
    const std::string& systempath);

inline void handleGetCpuCoreThreadMetrics(
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const nlohmann::json::json_pointer& jsonPtr, const std::string& cpuArg,
    const std::string& coreArg, const std::string& threadArg);

inline void
    handleGetCpuMetrics(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
                        const nlohmann::json::json_pointer& jsonPtr,
                        const std::string& cpuArg);

/**
 * @brief Returns a collection of dbus interfaces applicable to SubProcessor's
 * subtree.
 *
 * @param[in] expandLevel Requested expand level.
 *
 * @return Vector of strings capturing dbus interface names.
 */
inline std::vector<std::string>
    getInterfacesForSubProcessorSubtree(uint8_t expandLevel)
{
    std::vector<std::string> subProcessorSubtreeInterfaces = {
        subProcessorCoreInterfaces.begin(), subProcessorCoreInterfaces.end()};
    if (expandLevel > 0)
    {
        subProcessorSubtreeInterfaces.insert(
            subProcessorSubtreeInterfaces.end(),
            subProcessorThreadInterfaces.begin(),
            subProcessorThreadInterfaces.end());
        return subProcessorSubtreeInterfaces;
    }
    return subProcessorSubtreeInterfaces;
}

/**
 * @brief Returns a collection of dbus interfaces applicable to Processor's
 * subtree.
 *
 * @param[in] expandLevel Requested expand level.
 *
 * @return Vector of strings capturing dbus interface names.
 */
inline std::vector<std::string>
    getInterfacesForProcessorSubtree(uint8_t expandLevel)
{
    if (expandLevel > 0)
    {
        std::vector<std::string> processorSubtreeInterfaces =
            getInterfacesForSubProcessorSubtree(expandLevel - 1);
        processorSubtreeInterfaces.insert(processorSubtreeInterfaces.end(),
                                          processorInterfaces.begin(),
                                          processorInterfaces.end());
        return processorSubtreeInterfaces;
    }
    return {processorInterfaces.begin(), processorInterfaces.end()};
}

/**
 * @brief Fill out uuid info of a processor by
 * requesting data from the given D-Bus object.
 *
 * @param[in,out]   aResp           Async HTTP response.
 * @param[in]       objPath         D-Bus object to query.
 * @param[in]       interface       D-Bus interface to query.
 * @param[in]       jsonPtr         json pointer to index the response fields
 * @param[in]       managedObjects  Dbus objects with interfaces and properties.
 */
inline void
    getProcessorUUID(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
                     const std::string& objPath, const std::string& interface,
                     const nlohmann::json::json_pointer& jsonPtr,
                     const dbus::utility::ManagedObjectType& managedObjects)
{
    BMCWEB_LOG_DEBUG << "Get Processor UUID";
    dbus::utility::DBusPropertiesMap properties;
    dbus_utils::getPropertiesFromManagedObjects(managedObjects, objPath,
                                                interface, properties);

    const std::string* property = nullptr;

    const bool success = sdbusplus::unpackPropertiesNoThrow(
        dbus_utils::UnpackErrorPrinter(), properties, "UUID", property);

    if (!success)
    {
        messages::internalError(aResp->res);
        return;
    }

    if (property != nullptr)
    {
        aResp->res.jsonValue[jsonPtr]["UUID"] = *property;
    }
}

/**
 * @brief Populates Cpu information using given dbus properties.
 *
 * @param[in] aResp             Async HTTP response.
 * @param[in] jsonPtr           json pointer to index the response fields.
 * @param[in] dbusProperties    DBusPropertiesMap to parse for Cpu data.
 *
 * @return void
 */
inline void getCpuDataFromDbusProperties(
    const std::shared_ptr<bmcweb::AsyncResp>& aResp,
    const nlohmann::json::json_pointer& jsonPtr,
    const dbus::utility::DBusPropertiesMap& dbusProperties)
{
    BMCWEB_LOG_DEBUG << "Get CPU resources from dbus properties.";

    // Set the default value of state
    aResp->res.jsonValue[jsonPtr]["Status"]["State"] = "Enabled";
    aResp->res.jsonValue[jsonPtr]["Status"]["Health"] = "OK";

    for (const auto& property : dbusProperties)
    {
        if (property.first == "Present")
        {
            const bool* cpuPresent = std::get_if<bool>(&property.second);
            if (cpuPresent == nullptr)
            {
                // Important property not in desired type
                messages::internalError(aResp->res);
                return;
            }
            if (!*cpuPresent)
            {
                // Slot is not populated
                aResp->res.jsonValue[jsonPtr]["Status"]["State"] = "Absent";
            }
        }
        else if (property.first == "Functional")
        {
            const bool* cpuFunctional = std::get_if<bool>(&property.second);
            if (cpuFunctional == nullptr)
            {
                messages::internalError(aResp->res);
                return;
            }
            if (!*cpuFunctional)
            {
                aResp->res.jsonValue[jsonPtr]["Status"]["Health"] = "Critical";
            }
        }
        else if (property.first == "CoreCount")
        {
            const uint16_t* coresCount =
                std::get_if<uint16_t>(&property.second);
            if (coresCount == nullptr)
            {
                messages::internalError(aResp->res);
                return;
            }
            aResp->res.jsonValue[jsonPtr]["TotalCores"] = *coresCount;
        }
        else if (property.first == "MaxSpeedInMhz")
        {
            const uint32_t* value = std::get_if<uint32_t>(&property.second);
            if (value != nullptr)
            {
                aResp->res.jsonValue[jsonPtr]["MaxSpeedMHz"] = *value;
            }
        }
        else if (property.first == "Socket")
        {
            const std::string* value =
                std::get_if<std::string>(&property.second);
            if (value != nullptr)
            {
                aResp->res.jsonValue[jsonPtr]["Socket"] = *value;
            }
        }
        else if (property.first == "ThreadCount")
        {
            const uint16_t* value = std::get_if<uint16_t>(&property.second);
            if (value != nullptr)
            {
                aResp->res.jsonValue[jsonPtr]["TotalThreads"] = *value;
            }
        }
        else if (property.first == "CoreEnable")
        {
            const uint16_t* value = std::get_if<uint16_t>(&property.second);
            if (value != nullptr)
            {
                aResp->res.jsonValue[jsonPtr]["TotalEnabledCores"] = *value;
            }
        }
        else if (property.first == "EffectiveFamily")
        {
            const uint16_t* value = std::get_if<uint16_t>(&property.second);
            if (value != nullptr && *value != 2)
            {
                aResp->res
                    .jsonValue[jsonPtr]["ProcessorId"]["EffectiveFamily"] =
                    "0x" + intToHexString(*value, 4);
            }
        }
        else if (property.first == "EffectiveModel")
        {
            const uint16_t* value = std::get_if<uint16_t>(&property.second);
            if (value == nullptr)
            {
                messages::internalError(aResp->res);
                return;
            }
            if (*value != 0)
            {
                aResp->res.jsonValue[jsonPtr]["ProcessorId"]["EffectiveModel"] =
                    "0x" + intToHexString(*value, 4);
            }
        }
        else if (property.first == "Id")
        {
            const uint64_t* value = std::get_if<uint64_t>(&property.second);
            if (value != nullptr && *value != 0)
            {
                aResp->res.jsonValue[jsonPtr]["ProcessorId"]
                                    ["IdentificationRegisters"] =
                    "0x" + intToHexString(*value, 16);
            }
        }
        else if (property.first == "Microcode")
        {
            const uint32_t* value = std::get_if<uint32_t>(&property.second);
            if (value == nullptr)
            {
                messages::internalError(aResp->res);
                return;
            }
            if (*value != 0)
            {
                aResp->res.jsonValue[jsonPtr]["ProcessorId"]["MicrocodeInfo"] =
                    "0x" + intToHexString(*value, 8);
            }
        }
        else if (property.first == "Step")
        {
            const uint16_t* value = std::get_if<uint16_t>(&property.second);
            if (value == nullptr)
            {
                messages::internalError(aResp->res);
                return;
            }
            if (*value != std::numeric_limits<uint16_t>::max())
            {
                aResp->res.jsonValue[jsonPtr]["ProcessorId"]["Step"] =
                    "0x" + intToHexString(*value, 4);
            }
        }
    }
}

/**
 * @brief Populates Cpu information using given dbus Managed Objects.
 *
 * @param[in] aResp         Async HTTP response.
 * @param[in] cpuId         Cpu identifier.
 * @param[in] objPath       Cpu dbus object path.
 * @param[in] interface     Cpu dbus interface name.
 * @param[in] jsonPtr       json pointer to index the response fields.
 * @param[in] dbusData      Dbus Managed Objects to parse for Cpu data.
 *
 * @return void
 */
inline void getCpuData(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
                       const std::string& cpuId, const std::string& objPath,
                       const std::string& interface,
                       const nlohmann::json::json_pointer& jsonPtr,
                       const dbus::utility::ManagedObjectType& dbusData)
{
    BMCWEB_LOG_DEBUG << "Get Cpu data from managed objects for object "
                     << objPath;
    aResp->res.jsonValue[jsonPtr]["Id"] = cpuId;
    aResp->res.jsonValue[jsonPtr]["Name"] = "Processor";
    aResp->res.jsonValue[jsonPtr]["ProcessorType"] = "CPU";

    bool slotPresent = false;
    std::string corePath = objPath + "/core";
    size_t totalCores = 0;
    for (const auto& object : dbusData)
    {
        dbus::utility::DBusPropertiesMap properties;
        if (object.first.str == objPath)
        {
            dbus_utils::getPropertiesFromManagedObjects(dbusData, objPath,
                                                        interface, properties);
            getCpuDataFromDbusProperties(aResp, jsonPtr, properties);
        }
        else if (object.first.str.starts_with(corePath))
        {
            dbus_utils::getPropertiesFromManagedObjects(
                dbusData, object.first.str,
                "xyz.openbmc_project.Inventory.Item", properties);

            for (const auto& property : properties)
            {
                if (property.first != "Present")
                {
                    continue;
                }
                const bool* present = std::get_if<bool>(&property.second);
                if (present != nullptr && *present)
                {
                    slotPresent = true;
                    totalCores++;
                }
            }
        }
    }
    // In getCpuDataFromDbusProperties(), state and health are set based on the
    // present and functional status. If core count is zero, then it has a
    // higher precedence.
    if (slotPresent)
    {
        if (totalCores == 0)
        {
            // Slot is not populated, set status end return
            aResp->res.jsonValue[jsonPtr]["Status"]["State"] = "Absent";
            aResp->res.jsonValue[jsonPtr]["Status"]["Health"] = "OK";
        }
        aResp->res.jsonValue[jsonPtr]["TotalCores"] = totalCores;
    }
}

/**
 * @brief Populates Cpu asset information using given dbus Managed Objects.
 *
 * @param[in] aResp             Async HTTP response.
 * @param[in] objPath           Cpu dbus object path.
 * @param[in] interface         Cpu dbus interface name.
 * @param[in] jsonPtr           json pointer to index the response fields.
 * @param[in] managedObjects    Dbus Managed Objects to parse for Cpu data.
 *
 * @return void
 */
inline void
    getCpuAssetData(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
                    const std::string& objPath, const std::string& interface,
                    const nlohmann::json::json_pointer& jsonPtr,
                    const dbus::utility::ManagedObjectType& managedObjects)
{
    BMCWEB_LOG_DEBUG << "Get Cpu Asset Data";
    const std::string* serialNumber = nullptr;
    const std::string* model = nullptr;
    const std::string* manufacturer = nullptr;
    const std::string* partNumber = nullptr;
    const std::string* sparePartNumber = nullptr;

    dbus::utility::DBusPropertiesMap properties;
    dbus_utils::getPropertiesFromManagedObjects(managedObjects, objPath,
                                                interface, properties);

    const bool success = sdbusplus::unpackPropertiesNoThrow(
        dbus_utils::UnpackErrorPrinter(), properties, "SerialNumber",
        serialNumber, "Model", model, "Manufacturer", manufacturer,
        "PartNumber", partNumber, "SparePartNumber", sparePartNumber);

    if (!success)
    {
        messages::internalError(aResp->res);
        return;
    }

    if (serialNumber != nullptr && !serialNumber->empty())
    {
        aResp->res.jsonValue[jsonPtr]["SerialNumber"] = *serialNumber;
    }

    if ((model != nullptr) && !model->empty())
    {
        aResp->res.jsonValue[jsonPtr]["Model"] = *model;
    }

    if (manufacturer != nullptr)
    {
        aResp->res.jsonValue[jsonPtr]["Manufacturer"] = *manufacturer;

        // Otherwise would be unexpected.
        if (manufacturer->find("Intel") != std::string::npos)
        {
            aResp->res.jsonValue[jsonPtr]["ProcessorArchitecture"] = "x86";
            aResp->res.jsonValue[jsonPtr]["InstructionSet"] = "x86-64";
        }
        else if (manufacturer->find("IBM") != std::string::npos)
        {
            aResp->res.jsonValue[jsonPtr]["ProcessorArchitecture"] = "Power";
            aResp->res.jsonValue[jsonPtr]["InstructionSet"] = "PowerISA";
        }
    }

    if (partNumber != nullptr)
    {
        aResp->res.jsonValue[jsonPtr]["PartNumber"] = *partNumber;
    }

    if (sparePartNumber != nullptr && !sparePartNumber->empty())
    {
        aResp->res.jsonValue[jsonPtr]["SparePartNumber"] = *sparePartNumber;
    }
}

/**
 * @brief Populates Cpu revision data using given dbus Managed Objects.
 *
 * @param[in] aResp             Async HTTP response.
 * @param[in] objPath           Cpu dbus object path.
 * @param[in] interface         Cpu dbus interface name.
 * @param[in] jsonPtr           json pointer to index the response fields.
 * @param[in] managedObjects    Dbus Managed Objects to parse for Cpu data.
 *
 * @return void
 */
inline void
    getCpuRevisionData(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
                       const std::string& objPath, const std::string& interface,
                       const nlohmann::json::json_pointer& jsonPtr,
                       const dbus::utility::ManagedObjectType& managedObjects)
{
    BMCWEB_LOG_DEBUG << "Get Cpu Revision Data";
    dbus::utility::DBusPropertiesMap properties;
    dbus_utils::getPropertiesFromManagedObjects(managedObjects, objPath,
                                                interface, properties);

    const std::string* version = nullptr;

    const bool success = sdbusplus::unpackPropertiesNoThrow(
        dbus_utils::UnpackErrorPrinter(), properties, "Version", version);

    if (!success)
    {
        messages::internalError(aResp->res);
        return;
    }

    if (version != nullptr)
    {
        aResp->res.jsonValue[jsonPtr]["Version"] = *version;
    }
}

/**
 * @brief Populates accelerator data using given dbus Managed Objects.
 *
 * @param[in] aResp             Async HTTP response.
 * @param[in] acclrtrId         Accelerator identifier.
 * @param[in] objPath           Accelerator dbus object path.
 * @param[in] interface         Accelerator dbus interface name.
 * @param[in] jsonPtr           json pointer to index the response fields.
 * @param[in] managedObjects    Dbus Managed Objects to parse.
 *
 * @return void
 */
inline void
    getAcceleratorData(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
                       const std::string& acclrtrId, const std::string& objPath,
                       const std::string& interface,
                       const nlohmann::json::json_pointer& jsonPtr,
                       const dbus::utility::ManagedObjectType& managedObjects)
{
    BMCWEB_LOG_DEBUG
        << "Get available system Accelerator resources by service.";

    const bool* functional = nullptr;
    const bool* present = nullptr;

    dbus::utility::DBusPropertiesMap properties;
    dbus_utils::getPropertiesFromManagedObjects(managedObjects, objPath,
                                                interface, properties);

    const bool success = sdbusplus::unpackPropertiesNoThrow(
        dbus_utils::UnpackErrorPrinter(), properties, "Functional", functional,
        "Present", present);

    if (!success)
    {
        messages::internalError(aResp->res);
        return;
    }

    std::string state = "Enabled";
    std::string health = "OK";

    if (present != nullptr && !*present)
    {
        state = "Absent";
    }

    if (functional != nullptr && !*functional)
    {
        if (state == "Enabled")
        {
            health = "Critical";
        }
    }

    aResp->res.jsonValue[jsonPtr]["Id"] = acclrtrId;
    aResp->res.jsonValue[jsonPtr]["Name"] = "Processor";
    aResp->res.jsonValue[jsonPtr]["Status"]["State"] = state;
    aResp->res.jsonValue[jsonPtr]["Status"]["Health"] = health;
    aResp->res.jsonValue[jsonPtr]["ProcessorType"] = "Accelerator";
}

// OperatingConfig D-Bus Types
using TurboProfileProperty = std::vector<std::tuple<uint32_t, size_t>>;
using BaseSpeedPrioritySettingsProperty =
    std::vector<std::tuple<uint32_t, std::vector<uint32_t>>>;
// uint32_t and size_t may or may not be the same type, requiring a dedup'd
// variant

/**
 * Fill out the HighSpeedCoreIDs in a Processor resource from the given
 * OperatingConfig D-Bus property.
 *
 * @param[in,out]   aResp               Async HTTP response.
 * @param[in]       jsonPtr     json pointer to index the response fields
 * @param[in]       baseSpeedSettings   Full list of base speed priority groups,
 *                                      to use to determine the list of high
 *                                      speed cores.
 */
inline void highSpeedCoreIdsHandler(
    const std::shared_ptr<bmcweb::AsyncResp>& aResp,
    const nlohmann::json::json_pointer& jsonPtr,
    const BaseSpeedPrioritySettingsProperty& baseSpeedSettings)
{
    // The D-Bus property does not indicate which bucket is the "high
    // priority" group, so let's discern that by looking for the one with
    // highest base frequency.
    auto highPriorityGroup = baseSpeedSettings.cend();
    uint32_t highestBaseSpeed = 0;
    for (auto it = baseSpeedSettings.cbegin(); it != baseSpeedSettings.cend();
         ++it)
    {
        const uint32_t baseFreq = std::get<uint32_t>(*it);
        if (baseFreq > highestBaseSpeed)
        {
            highestBaseSpeed = baseFreq;
            highPriorityGroup = it;
        }
    }

    nlohmann::json& jsonCoreIds =
        aResp->res.jsonValue[jsonPtr]["HighSpeedCoreIDs"];
    jsonCoreIds = nlohmann::json::array();

    // There may not be any entries in the D-Bus property, so only populate
    // if there was actually something there.
    if (highPriorityGroup != baseSpeedSettings.cend())
    {
        jsonCoreIds = std::get<std::vector<uint32_t>>(*highPriorityGroup);
    }
}

/**
 * Fill out OperatingConfig related items in a Processor resource by requesting
 * data from the given D-Bus object.
 *
 * @param[in,out]   aResp           Async HTTP response.
 * @param[in]       cpuId           CPU D-Bus name.
 * @param[in]       objPath         D-Bus object to query.
 * @param[in]       interface       D-Bus interface to query.
 * @param[in]       jsonPtr         json pointer to index the response fields
 * @param[in]       managedObjects  Dbus objects with interfaces and properties.
 */
inline void
    getCpuConfigData(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
                     const std::string& cpuId, const std::string& objPath,
                     const std::string& interface,
                     const nlohmann::json::json_pointer& jsonPtr,
                     const dbus::utility::ManagedObjectType& managedObjects)
{
    BMCWEB_LOG_INFO << "Getting CPU operating configs for " << cpuId;

    nlohmann::json& json = aResp->res.jsonValue;

    const sdbusplus::message::object_path* appliedConfig = nullptr;
    const bool* baseSpeedPriorityEnabled = nullptr;
    const BaseSpeedPrioritySettingsProperty* baseSpeedList = nullptr;

    dbus::utility::DBusPropertiesMap properties;
    dbus_utils::getPropertiesFromManagedObjects(managedObjects, objPath,
                                                interface, properties);

    const bool success = sdbusplus::unpackPropertiesNoThrow(
        dbus_utils::UnpackErrorPrinter(), properties, "AppliedConfig",
        appliedConfig, "BaseSpeedPriorityEnabled", baseSpeedPriorityEnabled);

    if (!success)
    {
        messages::internalError(aResp->res);
        return;
    }

    if (appliedConfig != nullptr)
    {
        const std::string& dbusPath = appliedConfig->str;
        std::string uri = "/redfish/v1/Systems/system/Processors/" + cpuId +
                          "/OperatingConfigs";
        nlohmann::json::object_t operatingConfig;
        operatingConfig["@odata.id"] = uri;
        json[jsonPtr]["OperatingConfigs"] = std::move(operatingConfig);

        // Reuse the D-Bus config object name for the Redfish
        // URI
        size_t baseNamePos = dbusPath.rfind('/');
        if (baseNamePos == std::string::npos ||
            baseNamePos == (dbusPath.size() - 1))
        {
            // If the AppliedConfig was somehow not a valid path,
            // skip adding any more properties, since everything
            // else is tied to this applied config.
            messages::internalError(aResp->res);
            return;
        }
        uri += '/';
        uri += dbusPath.substr(baseNamePos + 1);
        nlohmann::json::object_t appliedOperatingConfig;
        appliedOperatingConfig["@odata.id"] = uri;
        json[jsonPtr]["AppliedOperatingConfig"] =
            std::move(appliedOperatingConfig);

        // Once we found the current applied config, read the base freq core ids
        // out of Operating config.

        dbus::utility::DBusPropertiesMap config;
        dbus_utils::getPropertiesFromManagedObjects(
            managedObjects, dbusPath,
            "xyz.openbmc_project.Inventory.Item.Cpu.OperatingConfig", config);

        const bool parseConfigSuccess = sdbusplus::unpackPropertiesNoThrow(
            dbus_utils::UnpackErrorPrinter(), config,
            "BaseSpeedPrioritySettings", baseSpeedList);

        if (!parseConfigSuccess)
        {
            messages::internalError(aResp->res);
            return;
        }

        if (baseSpeedList != nullptr)
        {
            highSpeedCoreIdsHandler(aResp, jsonPtr, *baseSpeedList);
        }
    }

    if (baseSpeedPriorityEnabled != nullptr)
    {
        json[jsonPtr]["BaseSpeedPriorityState"] =
            *baseSpeedPriorityEnabled ? "Enabled" : "Disabled";
    }
}

/**
 * Populate the unique identifier in a Processor resource by requesting data
 * from the given D-Bus object.
 *
 * @param[in,out]   aResp           Async HTTP response.
 * @param[in]       objPath         D-Bus object to query.
 * @param[in]       interface       D-Bus interface to query.
 * @param[in]       jsonPtr         json pointer to index the response fields
 * @param[in]       managedObjects  Dbus objects with interfaces and properties.
 */
inline void
    getCpuUniqueId(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
                   const std::string& objectPath, const std::string& interface,
                   const nlohmann::json::json_pointer& jsonPtr,
                   const dbus::utility::ManagedObjectType& managedObjects)
{
    BMCWEB_LOG_DEBUG << "Get CPU UniqueIdentifier";
    dbus::utility::DBusPropertiesMap properties;
    dbus_utils::getPropertiesFromManagedObjects(managedObjects, objectPath,
                                                interface, properties);

    const std::string* id = nullptr;

    const bool success = sdbusplus::unpackPropertiesNoThrow(
        dbus_utils::UnpackErrorPrinter(), properties, "UniqueIdentifier", id);

    if (!success)
    {
        messages::internalError(aResp->res);
        return;
    }

    if (id != nullptr)
    {
        aResp->res.jsonValue[jsonPtr]["ProcessorId"]
                            ["ProtectedIdentificationNumber"] = *id;
    }
}

inline void getCpuChassisAssociation(
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const std::string& processorId, const std::string& objectPath,
    const nlohmann::json::json_pointer& jsonPtr)
{
    BMCWEB_LOG_DEBUG << "Get CPU -- Chassis association";

    managedStore::ManagedObjectStoreContext requestContext(asyncResp);
    dbus_utils::getProperty<std::vector<std::string>>(
        "xyz.openbmc_project.ObjectMapper", objectPath + "/chassis",
        "xyz.openbmc_project.Association", "endpoints", requestContext,
        [asyncResp{asyncResp}, jsonPtr,
         processorId](const boost::system::error_code ec,
                      const std::vector<std::string>& chassisList) {
        if (ec)
        {
            return;
        }
        if (chassisList.empty())
        {
            return;
        }
        if (chassisList.size() > 1)
        {
            BMCWEB_LOG_DEBUG << processorId
                             << " is associated with mutliple chassis";
            return;
        }

        sdbusplus::message::object_path chassisPath(chassisList[0]);
        std::string chassisName = chassisPath.filename();
        if (chassisName.empty())
        {
            BMCWEB_LOG_ERROR << "filename() is empty in " << chassisPath.str;
            return;
        }
        asyncResp->res.jsonValue[jsonPtr]["Links"]["Chassis"] = {
            {"@odata.id", "/redfish/v1/Chassis/" + chassisName}};
    });
}

/**
 * @brief Fill out the links to associated memory of a processor
 * by looking up its D-Bus association.
 *
 * @param[in,out]   aResp       Async HTTP response.
 * @param[in]       objPath     D-Bus object to query.
 */
inline void getMemoryLinks(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
                           const std::string& objectPath,
                           const nlohmann::json::json_pointer& jsonPtr)
{
    BMCWEB_LOG_DEBUG << "Get Processor -- Memory association";

    managedStore::ManagedObjectStoreContext requestContext(asyncResp);
    dbus_utils::getProperty<std::vector<std::string>>(
        "xyz.openbmc_project.ObjectMapper", objectPath + "/memory",
        "xyz.openbmc_project.Association", "endpoints", requestContext,
        [asyncResp, jsonPtr](const boost::system::error_code ec,
                             const std::vector<std::string>& memoryList) {
        if (ec)
        {
            return;
        }
        if (memoryList.empty())
        {
            return;
        }
        nlohmann::json::array_t memoryLinks;
        for (const std::string& memory : memoryList)
        {
            sdbusplus::message::object_path memoryPath(memory);
            const std::string memoryName = memoryPath.filename();
            if (memoryName.empty())
            {
                BMCWEB_LOG_ERROR << "filename() is empty in " << memoryPath.str;
                return;
            }
            nlohmann::json::object_t memoryObject;
            memoryObject["@odata.id"] =
                "/redfish/v1/Systems/system/Memory/" + memoryName;
            memoryLinks.emplace_back(memoryObject);
        }
        asyncResp->res.jsonValue[jsonPtr]["Links"]["Memory"] =
            std::move(memoryLinks);
    });
}

/**
 * Find the D-Bus object representing the requested Processor, and call the
 * handler with the results. If matching object is not found, add 404 error to
 * response and don't call the handler.
 *
 * @param[in,out]   resp            Async HTTP response.
 * @param[in]       processorId     Redfish Processor Id.
 * @param[in]       handler         Callback to continue processing request upon
 *                                  successfully finding object.
 */
template <typename Handler>
inline void getProcessorObject(const std::shared_ptr<bmcweb::AsyncResp>& resp,
                               const std::string& processorId,
                               const std::string& systemPath, Handler&& handler)
{
    BMCWEB_LOG_DEBUG << "Get available system processor resources.";

    const bool multiHost = !systemPath.empty();

    // Default systemName is system and change if system is multi-host
    std::string systemName = "system";
    // The subtree to query for Dimms changes if single or multi-host
    std::string subtreeRoot = "/xyz/openbmc_project/inventory";

    if (multiHost)
    {
        systemName = sdbusplus::message::object_path(systemPath).filename();
        subtreeRoot = systemPath;
    }

    managedStore::ManagedObjectStoreContext context(resp);
    managedStore::GetManagedObjectStore()->getSubTree(
        subtreeRoot, 0, processorInterfaces, context,
        [resp{resp}, processorId, multiHost, systemPath,
         handler = std::forward<Handler>(handler), context](
            const boost::system::error_code& ec,
            const dbus::utility::MapperGetSubTreeResponse& subtree) mutable {
        if (ec)
        {
            BMCWEB_LOG_ERROR << "DBUS response error: " << ec.value();
            messages::internalError(resp->res);
            return;
        }

        std::vector<std::string> serviceNames =
            dbus_utils::getServiceNamesFromSubtree(subtree);
        if (serviceNames.empty())
        {
            BMCWEB_LOG_ERROR << "Service list is empty";
            messages::internalError(resp->res);
            return;
        }

        sdbusplus::message::object_path path("/xyz/openbmc_project/inventory");
        dbus_utils::getManagedObjectsInEachService(
            std::move(serviceNames), path, context,
            [resp{std::move(resp)}, subtree, processorId, multiHost, systemPath,
             handler = std::forward<Handler>(handler)](
                const ManagedObjectByServiceMap& managedObjectsByService) {
            if (managedObjectsByService.empty())
            {
                BMCWEB_LOG_ERROR
                    << "GetManagedObjects does not return any object.";
                messages::internalError(resp->res);
                return;
            }
            BMCWEB_LOG_DEBUG << "Looping through subtree";

            for (const auto& [objectPath, serviceMap] : subtree)
            {
                BMCWEB_LOG_DEBUG << objectPath;
                if (multiHost && !objectPath.starts_with(systemPath))
                {
                    continue;
                }

                // Ignore any objects which don't end with our desired cpu name
                if (!objectPath.ends_with(processorId))
                {
                    continue;
                }

                // Filter out objects that don't have the CPU-specific
                // interfaces to make sure we can return 404 on non-CPUs
                // (e.g. /redfish/../Processors/dimm0)
                if (!dbus_utils::findInterfacesInServiceMap(
                        serviceMap, processorInterfaces))
                {
                    continue;
                }
                handler(objectPath, subtree, managedObjectsByService);
                return;
            }
            messages::resourceNotFound(resp->res, "Processor", processorId);
        });
    });
}

inline void
    getProcessorState(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
                      const std::string& service, const std::string& objPath)
{

    managedStore::ManagedObjectStoreContext requestContext(asyncResp);
    dbus_utils::getProperty<bool>(
        service, objPath, "xyz.openbmc_project.Inventory.Item", "Present",
        requestContext,
        [asyncResp, objPath](const boost::system::error_code& ec,
                             bool present) {
        if (ec)
        {
            BMCWEB_LOG_DEBUG << "get presence failed for Processor State "
                             << objPath << " with error " << ec;

            if (ec.value() != EBADR)
            {
                messages::internalError(asyncResp->res);
            }
            return;
        }
        asyncResp->res.jsonValue["Status"]["State"] =
            present ? "Enabled" : "Absent";
        });
}

inline void
    getProcessorStateData(App& app, const crow::Request& req,
                          const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
                          const std::string& systemName,
                          const std::string& processorId,
                          const std::string& procStateId)
{
    if (!redfish::setUpRedfishRoute(app, req, asyncResp))
    {
        return;
    }
    BMCWEB_LOG_DEBUG << "Processor State Id: " << procStateId;
    asyncResp->res.jsonValue["@odata.id"] = crow::utility::urlFromPieces(
        "redfish", "v1", "Systems", systemName, "Processors", processorId,
        "Oem", "Google", "ProcessorStates", procStateId);
    asyncResp->res.jsonValue["@odata.type"] =
        "#GoogleProcessorState.GoogleProcessorState";
    asyncResp->res.jsonValue["Id"] = procStateId;
    asyncResp->res.jsonValue["Name"] = "Processor";
    getProcessorState(asyncResp, "xyz.openbmc_project.EntityManager",
                      "/xyz/openbmc_project/inventory/system/processorstate/" +
                          procStateId);
}

using Mapper = dbus::utility::MapperGetSubTreePathsResponse;
inline void getProcessorStateLinks(
    const std::shared_ptr<bmcweb::AsyncResp>& aResp,
    const std::string& processorId, const nlohmann::json::json_pointer& jsonPtr,
    const boost::system::error_code& ec, const Mapper& procStatePaths)
{
    BMCWEB_LOG_DEBUG << "Get Processor State URL";

    if (ec)
    {
        BMCWEB_LOG_ERROR
            << "ProcessorState Collection GetSubTreePaths handler Dbus error "
            << ec;
        return;
    }
    nlohmann::json::array_t procStateLinks;
    for (const std::string& procState : procStatePaths)
    {
        nlohmann::json::object_t procStateObj;
        std::string procStateId =
            sdbusplus::message::object_path(procState).filename();
        procStateObj["@odata.id"] = crow::utility::urlFromPieces(
            "redfish", "v1", "Systems", "system", "Processors", processorId,
            "Oem", "Google", "ProcessorStates", procStateId);
        procStateLinks.emplace_back(procStateObj);
    }
    aResp->res.jsonValue[jsonPtr]["Oem"]["Google"]["ProcessorStates"] =
        std::move(procStateLinks);
}

inline void
    getProcessorData(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
                     const nlohmann::json::json_pointer& jsonPtr,
                     uint8_t expandLevel, const std::string& processorId,
                     const std::string& systemPath,
                     const std::string& objectPath,
                     const dbus::utility::MapperGetSubTreeResponse& subtree,
                     const ManagedObjectByServiceMap& managedObjectsMap)
{
    BMCWEB_LOG_DEBUG << "Get processor data.";

    const bool multiHost = !systemPath.empty();

    // Default systemName is system and change if system is multi-host
    std::string systemName = "system";

    if (multiHost)
    {
        systemName = sdbusplus::message::object_path(systemPath).filename();
    }

    aResp->res.addHeader(
        boost::beast::http::field::link,
        "</redfish/v1/JsonSchemas/Processor/Processor.json>; rel=describedby");
    aResp->res.jsonValue[jsonPtr]["@odata.type"] =
        "#Processor.v1_11_0.Processor";
    aResp->res.jsonValue[jsonPtr]["@odata.id"] = crow::utility::urlFromPieces(
        "redfish", "v1", "Systems", systemName, "Processors", processorId);

    // Get service to interface map for cpu
    dbus::utility::MapperServiceMap serviceMap;
    for (const auto& [parsedObjectPath, parsedServiceMap] : subtree)
    {
        if (objectPath == parsedObjectPath)
        {
            serviceMap = parsedServiceMap;
            break;
        }
    }

    for (const auto& [serviceName, interfaceList] : serviceMap)
    {
        auto iter = managedObjectsMap.find(serviceName);
        if (iter == managedObjectsMap.end())
        {
            BMCWEB_LOG_DEBUG << "Cpu data not available for serviceName "
                             << serviceName;
            continue;
        }

        BMCWEB_LOG_DEBUG << "Populate processor data from dbus interfaces.";
        for (const auto& interface : interfaceList)
        {
            if (interface == "xyz.openbmc_project.Inventory.Decorator.Asset")
            {
                getCpuAssetData(aResp, objectPath, interface, jsonPtr,
                                iter->second);
            }
            else if (interface ==
                     "xyz.openbmc_project.Inventory.Decorator.Revision")
            {
                getCpuRevisionData(aResp, objectPath, interface, jsonPtr,
                                   iter->second);
            }
            else if (interface == "xyz.openbmc_project.Inventory.Item.Cpu")
            {
                getCpuData(aResp, processorId, objectPath, interface, jsonPtr,
                           iter->second);
            }
            else if (interface ==
                     "xyz.openbmc_project.Inventory.Item.Accelerator")
            {
                getAcceleratorData(aResp, processorId, objectPath, interface,
                                   jsonPtr, iter->second);
            }
            else if (
                interface ==
                "xyz.openbmc_project.Control.Processor.CurrentOperatingConfig")
            {
                getCpuConfigData(aResp, processorId, objectPath, interface,
                                 jsonPtr, iter->second);
            }
            else if (interface ==
                     "xyz.openbmc_project.Inventory.Decorator.LocationCode")
            {
                location_util::getLocationCodeFromManagedObject(
                    aResp, objectPath, interface, jsonPtr / "Location",
                    iter->second);
                location_util::getPartLocationContext(
                    aResp, jsonPtr / "Location", objectPath + "/chassis");
            }
            else if (interface == "xyz.openbmc_project.Common.UUID")
            {
                getProcessorUUID(aResp, objectPath, interface, jsonPtr,
                                 iter->second);
            }
            else if (interface ==
                     "xyz.openbmc_project.Inventory.Decorator.UniqueIdentifier")
            {
                getCpuUniqueId(aResp, objectPath, interface, jsonPtr,
                               iter->second);
            }
            else
            {
                std::optional<std::string> locationType =
                    location_util::getLocationType(interface);
                if (locationType == std::nullopt)
                {
                    BMCWEB_LOG_DEBUG
                        << "getLocationType for Processor failed for "
                        << interface;
                    continue;
                }

                aResp->res.jsonValue[jsonPtr]["Location"]["PartLocation"]
                                    ["LocationType"] = *locationType;
            }
        }
    }
    getCpuChassisAssociation(aResp, processorId, objectPath, jsonPtr);
    getMemoryLinks(aResp, objectPath, jsonPtr);

    managedStore::ManagedObjectStoreContext context(aResp);
    constexpr std::array<std::string_view, 1> procStateIntf = {
        "xyz.openbmc_project.Inventory.Item.ProcessorState"};
    dbus_utils::getSubTreePaths(
        "/xyz/openbmc_project/inventory", 0, procStateIntf, context,
        std::bind_front(getProcessorStateLinks, aResp, processorId, jsonPtr));

    // TODO(edward): Support SubProcessors and ProcessorMetrics for Multi-Host
    // as use-cases arise
    if (!multiHost)
    {
        if (expandLevel > 0)
        {
            nlohmann::json::json_pointer subProcessorPtr =
                jsonPtr / "SubProcessors";
            getSubProcessorCoreCollectionWithExpand(
                aResp, subProcessorPtr, expandLevel - 1, processorId,
                objectPath, subtree, managedObjectsMap);
        }
        else
        {
            aResp->res.jsonValue[jsonPtr]["SubProcessors"]["@odata.id"] =
                crow::utility::urlFromPieces("redfish", "v1", "Systems",
                                             "system", "Processors",
                                             processorId, "SubProcessors");
        }

        if (expandLevel > 0)
        {
            nlohmann::json::json_pointer metricsPtr = jsonPtr / "Metrics";
            handleGetCpuMetrics(aResp, metricsPtr, processorId);
        }
        else
        {
            // Inserting the "Metrics" JSON stanza
            std::string metricsUrl = aResp->res.jsonValue[jsonPtr]["@odata.id"];
            metricsUrl += "/ProcessorMetrics";
            nlohmann::json::object_t metricsObj;
            metricsObj["@odata.id"] = std::move(metricsUrl);
            aResp->res.jsonValue[jsonPtr]["Metrics"] = std::move(metricsObj);
        }
    }
}

template <typename Handler>
inline void getProcessorPaths(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
                              const std::string& processorId, Handler&& handler)
{
    std::array<std::string_view, 1> interfaces{
        "xyz.openbmc_project.Inventory.Item.Cpu"};

    managedStore::ManagedObjectStoreContext requestContext(aResp);
    managedStore::GetManagedObjectStore()->getSubTreePaths(
        "/xyz/openbmc_project/inventory", 0, interfaces, requestContext,
        [processorId, aResp{aResp},
         handler{std::forward<Handler>(handler)}](
            const boost::system::error_code ec,
            const std::vector<std::string>& subTreePaths) {
        if (ec)
        {
            handler(ec, "");
            return;
        }

        for (const std::string& cpuPath : subTreePaths)
        {
            if (sdbusplus::message::object_path(cpuPath).filename() !=
                processorId)
            {
                continue;
            }

            handler(ec, cpuPath);
            return;
        }

        // Set an error code since valid cpu path is not found
        handler(boost::system::errc::make_error_code(
                    boost::system::errc::no_such_file_or_directory),
                "");
    });
}

template <typename Handler>
inline void
    getSubProcessorCorePaths(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
                             const std::string& processorId,
                             const std::string& coreId, Handler&& handler)
{

    std::array<std::string_view, 1> interfaces{
        "xyz.openbmc_project.Inventory.Item.Cpu"};
    managedStore::ManagedObjectStoreContext requestContext(aResp);
    managedStore::GetManagedObjectStore()->getSubTreePaths(
        "/xyz/openbmc_project/inventory", 0, interfaces, requestContext,
        [processorId, coreId, aResp{aResp},
         handler{std::forward<Handler>(handler)},
         requestContext](const boost::system::error_code ec,
                         const std::vector<std::string>& subTreeCpuPaths) {
        if (ec)
        {
            handler(ec, "");
            return;
        }

        for (const std::string& cpuPath : subTreeCpuPaths)
        {
            if (sdbusplus::message::object_path(cpuPath).filename() !=
                processorId)
            {
                continue;
            }

            std::array<std::string_view, 1> interfaces{
                "xyz.openbmc_project.Inventory.Item.CpuCore"};
            managedStore::GetManagedObjectStore()->getSubTreePaths(
                "/xyz/openbmc_project/inventory", 0, interfaces, requestContext,
                [processorId, coreId, aResp{aResp},
                 handler](const boost::system::error_code ec2,
                          const std::vector<std::string>& subTreeCorePaths) {
                if (ec2)
                {
                    handler(ec2, "");
                    return;
                }

                for (const std::string& corePath : subTreeCorePaths)
                {
                    if (sdbusplus::message::object_path(corePath).filename() !=
                        coreId)
                    {
                        continue;
                    }
                    handler(ec2, corePath);
                    return;
                }
                // Set an error code since valid processor core path is not
                // found
                handler(boost::system::errc::make_error_code(
                            boost::system::errc::no_such_file_or_directory),
                        "");
            });
            return;
        }

        // Set an error code since valid processor cpu path is not found
        handler(boost::system::errc::make_error_code(
                    boost::system::errc::no_such_file_or_directory),
                "");
    });
}

inline void
    getCoreThreadData(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
                      const nlohmann::json::json_pointer& jsonPtr,
                      [[maybe_unused]] const uint8_t expandLevel,
                      const std::string& processorId, const std::string& coreId,
                      const std::string& threadId,
                      const std::string& threadPath,
                      const dbus::utility::MapperGetSubTreeResponse& subtree,
                      const ManagedObjectByServiceMap& managedObjectsMap)
{
    aResp->res.jsonValue[jsonPtr]["@odata.type"] =
        "#Processor.v1_11_0.Processor";
    aResp->res.jsonValue[jsonPtr]["@odata.id"] = crow::utility::urlFromPieces(
        "redfish", "v1", "Systems", "system", "Processors", processorId,
        "SubProcessors", coreId, "SubProcessors", threadId);
    aResp->res.jsonValue[jsonPtr]["Name"] = "SubProcessor";
    aResp->res.jsonValue[jsonPtr]["ProcessorType"] = "Thread";
    aResp->res.jsonValue[jsonPtr]["Id"] = threadId;

    aResp->res.jsonValue[jsonPtr]["Status"]["State"] = "Enabled";
    aResp->res.jsonValue[jsonPtr]["Status"]["Health"] = "OK";

    bool present = false;
    bool functional = false;

    dbus::utility::MapperServiceMap serviceMap;
    for (const auto& [parsedObjectPath, parsedServiceMap] : subtree)
    {
        if (threadPath == parsedObjectPath)
        {
            serviceMap = parsedServiceMap;
            break;
        }
    }

    for (const auto& [serviceName, interfaceList] : serviceMap)
    {
        auto iter = managedObjectsMap.find(serviceName);
        if (iter == managedObjectsMap.end())
        {
            BMCWEB_LOG_DEBUG << "Thread data not available for serviceName "
                             << serviceName;
            continue;
        }

        for (const auto& interface : interfaceList)
        {
            dbus::utility::DBusPropertiesMap properties;
            if (interface == "xyz.openbmc_project.State."
                             "Decorator.OperationalStatus")
            {
                const bool* propertyFunctional = nullptr;
                dbus_utils::getPropertiesFromManagedObjects(
                    iter->second, threadPath, interface, properties);
                const bool success = sdbusplus::unpackPropertiesNoThrow(
                    dbus_utils::UnpackErrorPrinter(), properties, "Functional",
                    propertyFunctional);
                if (!success || propertyFunctional == nullptr)
                {
                    continue;
                }
                functional = *propertyFunctional;
            }
            else if (interface == "xyz.openbmc_project.Inventory.Item")
            {
                const bool* propertyPresent = nullptr;
                const std::string* propertyPrettyName = nullptr;
                dbus_utils::getPropertiesFromManagedObjects(
                    iter->second, threadPath, interface, properties);
                const bool success = sdbusplus::unpackPropertiesNoThrow(
                    dbus_utils::UnpackErrorPrinter(), properties, "Present",
                    propertyPresent, "PrettyName", propertyPrettyName);
                if (!success)
                {
                    continue;
                }

                if (propertyPresent != nullptr)
                {
                    present = *propertyPresent;
                }

                if (propertyPrettyName != nullptr)
                {
                    aResp->res.jsonValue[jsonPtr]["Name"] = *propertyPrettyName;
                }
            }
            else if (interface ==
                     "xyz.openbmc_project.Inventory.Item.CpuThread")
            {
                const uint32_t* propertyMicrocode = nullptr;
                dbus_utils::getPropertiesFromManagedObjects(
                    iter->second, threadPath, interface, properties);
                const bool success = sdbusplus::unpackPropertiesNoThrow(
                    dbus_utils::UnpackErrorPrinter(), properties, "Microcode",
                    propertyMicrocode);
                if (!success)
                {
                    continue;
                }

                if (propertyMicrocode != nullptr)
                {
                    aResp->res
                        .jsonValue[jsonPtr]["ProcessorId"]["MicrocodeInfo"] =
                        "0x" + intToHexString(*propertyMicrocode, 8);
                }
            }
        }
    }

    if (!present)
    {
        aResp->res.jsonValue[jsonPtr]["Status"]["State"] = "Absent";
    }

    if (!functional)
    {
        aResp->res.jsonValue[jsonPtr]["Status"]["Health"] = "Critical";
    }

    if (expandLevel > 0)
    {
        nlohmann::json::json_pointer metricsPtr = jsonPtr / "Metrics";
        handleGetCpuCoreThreadMetrics(aResp, metricsPtr, processorId, coreId,
                                      threadId);
    }
    else
    {
        // Inserting the "Metrics" JSON stanza
        std::string metricsUrl = aResp->res.jsonValue[jsonPtr]["@odata.id"];
        metricsUrl += "/ProcessorMetrics";
        nlohmann::json::object_t metricsObj;
        metricsObj["@odata.id"] = std::move(metricsUrl);
        aResp->res.jsonValue[jsonPtr]["Metrics"] = std::move(metricsObj);
    }
}

inline void getSubProcessorThreadData(
    const std::shared_ptr<bmcweb::AsyncResp>& aResp,
    const std::string& processorId, const std::string& coreId,
    const std::string& threadId, const boost::system::error_code ec,
    const std::string& corePath)
{
    if (ec)
    {
        BMCWEB_LOG_DEBUG << "DBUS response error, ec: " << ec.value();
        // No sub processor thread objects found by mapper
        if (ec.value() == boost::system::errc::io_error)
        {
            messages::resourceNotFound(aResp->res,
                                       "#Processor.v1_11_0.Processor", coreId);
            return;
        }

        messages::internalError(aResp->res);
        return;
    }
    aResp->res.addHeader(
        boost::beast::http::field::link,
        "</redfish/v1/JsonSchemas/Processor/Processor.json>; rel=describedby");

    managedStore::ManagedObjectStoreContext context(aResp);
    managedStore::GetManagedObjectStore()->getSubTree(
        corePath, 0, subProcessorThreadInterfaces, context,
        [aResp{aResp}, processorId, coreId, threadId,
         context](const boost::system::error_code& ec2,
                  const dbus::utility::MapperGetSubTreeResponse& subtree) {
        if (ec2)
        {
            BMCWEB_LOG_DEBUG << "DBUS response error, ec2: " << ec2.value();
            // No sub processor core objects found by mapper
            if (ec2.value() == boost::system::errc::io_error)
            {
                messages::resourceNotFound(
                    aResp->res, "#Processor.v1_11_0.Processor", coreId);
                return;
            }

            messages::internalError(aResp->res);
            return;
        }

        std::vector<std::string> serviceNames =
            dbus_utils::getServiceNamesFromSubtree(subtree);

        sdbusplus::message::object_path path("/xyz/openbmc_project/inventory");
        dbus_utils::getManagedObjectsInEachService(
            std::move(serviceNames), path, context,
            [aResp{aResp}, subtree, processorId, coreId, threadId](
                const ManagedObjectByServiceMap& managedObjectsByService) {
            if (managedObjectsByService.empty())
            {
                messages::internalError(aResp->res);
                return;
            }

            for (const auto& [objectPath, serviceMap] : subtree)
            {
                if (sdbusplus::message::object_path(objectPath).filename() !=
                    threadId)
                {
                    continue;
                }

                getCoreThreadData(aResp, ""_json_pointer, 0, processorId,
                                  coreId, threadId, objectPath, subtree,
                                  managedObjectsByService);
                return;
            }

            // Object not found
            messages::resourceNotFound(
                aResp->res, "#Processor.v1_11_0.Processor", threadId);
        });
    });
}

inline void getSubProcessorThreadMembers(
    const std::shared_ptr<bmcweb::AsyncResp>& aResp,
    const std::string& processorId, const std::string& coreId,
    const boost::system::error_code ec, const std::string& corePath)
{
    if (ec)
    {
        BMCWEB_LOG_DEBUG << "DBUS response error, ec: " << ec.value();
        // No sub processor core objects found by mapper
        if (ec.value() == boost::system::errc::io_error)
        {
            messages::resourceNotFound(aResp->res,
                                       "#Processor.v1_11_0.Processor", coreId);
            return;
        }

        messages::internalError(aResp->res);
        return;
    }

    aResp->res.addHeader(
        boost::beast::http::field::link,
        "</redfish/v1/JsonSchemas/ProcessorCollection/ProcessorCollection.json>; rel=describedby");
    aResp->res.jsonValue["@odata.type"] =
        "#ProcessorCollection.ProcessorCollection";
    aResp->res.jsonValue["@odata.id"] = crow::utility::urlFromPieces(
        "redfish", "v1", "Systems", "system", "Processors", processorId,
        "SubProcessors", coreId, "SubProcessors");
    aResp->res.jsonValue["Name"] = "SubProcessor Collection";

    const boost::urls::url& subProcessorsPath = crow::utility::urlFromPieces(
        "redfish", "v1", "Systems", "system", "Processors", processorId,
        "SubProcessors", coreId, "SubProcessors");

    constexpr std::array<std::string_view, 1> interfaces{
        "xyz.openbmc_project.Inventory.Item.CpuThread"};

    collection_util::getCollectionMembers(aResp, subProcessorsPath, interfaces,
                                          corePath.c_str());
}

inline void
    getCpuCoreData(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
                   const nlohmann::json::json_pointer& jsonPtr,
                   uint8_t expandLevel, const std::string& processorId,
                   const std::string& coreId, const std::string& corePath,
                   const dbus::utility::MapperGetSubTreeResponse& subtree,
                   const ManagedObjectByServiceMap& managedObjectsMap)
{
    aResp->res.jsonValue[jsonPtr]["@odata.type"] =
        "#Processor.v1_11_0.Processor";
    aResp->res.jsonValue[jsonPtr]["@odata.id"] = crow::utility::urlFromPieces(
        "redfish", "v1", "Systems", "system", "Processors", processorId,
        "SubProcessors", coreId);

    aResp->res.jsonValue[jsonPtr]["Name"] = "SubProcessor";
    aResp->res.jsonValue[jsonPtr]["ProcessorType"] = "Core";
    aResp->res.jsonValue[jsonPtr]["Id"] = coreId;

    if (expandLevel > 0)
    {
        nlohmann::json::json_pointer subProcessorPtr =
            jsonPtr / "SubProcessors";
        getSubProcessorThreadCollectionWithExpand(
            aResp, subProcessorPtr, expandLevel - 1, processorId, coreId,
            corePath, subtree, managedObjectsMap);
    }
    else
    {
        aResp->res.jsonValue[jsonPtr]["SubProcessors"]["@odata.id"] =
            crow::utility::urlFromPieces(
                "redfish", "v1", "Systems", "system", "Processors", processorId,
                "SubProcessors", coreId, "SubProcessors");
    }

    aResp->res.jsonValue[jsonPtr]["Status"]["State"] = "Enabled";
    aResp->res.jsonValue[jsonPtr]["Status"]["Health"] = "OK";

    bool present = false;
    bool functional = false;

    dbus::utility::MapperServiceMap serviceMap;
    for (const auto& [parsedObjectPath, parsedServiceMap] : subtree)
    {
        if (corePath == parsedObjectPath)
        {
            serviceMap = parsedServiceMap;
            break;
        }
    }

    for (const auto& [serviceName, interfaceList] : serviceMap)
    {
        auto iter = managedObjectsMap.find(serviceName);
        if (iter == managedObjectsMap.end())
        {
            BMCWEB_LOG_DEBUG << "Cpu data not available for serviceName "
                             << serviceName;
            continue;
        }

        for (const auto& interface : interfaceList)
        {
            dbus::utility::DBusPropertiesMap properties;
            if (interface == "xyz.openbmc_project.State."
                             "Decorator.OperationalStatus")
            {
                const bool* propertyFunctional = nullptr;
                dbus_utils::getPropertiesFromManagedObjects(
                    iter->second, corePath, interface, properties);
                const bool success = sdbusplus::unpackPropertiesNoThrow(
                    dbus_utils::UnpackErrorPrinter(), properties, "Functional",
                    propertyFunctional);

                if (!success)
                {
                    continue;
                }

                if (propertyFunctional != nullptr)
                {
                    functional = *propertyFunctional;
                }
            }
            else if (interface == "xyz.openbmc_project.Inventory.Item")
            {
                const bool* propertyPresent = nullptr;
                const std::string* propertyPrettyName = nullptr;
                dbus_utils::getPropertiesFromManagedObjects(
                    iter->second, corePath, interface, properties);
                const bool success = sdbusplus::unpackPropertiesNoThrow(
                    dbus_utils::UnpackErrorPrinter(), properties, "Present",
                    propertyPresent, "PrettyName", propertyPrettyName);

                if (!success)
                {
                    continue;
                }

                if (propertyPresent != nullptr)
                {
                    present = *propertyPresent;
                }

                if (propertyPrettyName != nullptr)
                {
                    aResp->res.jsonValue[jsonPtr]["Name"] = *propertyPrettyName;
                }
            }
            else if (interface == "xyz.openbmc_project.Inventory.Item.CpuCore")
            {
                const uint32_t* propertyMicrocode = nullptr;
                dbus_utils::getPropertiesFromManagedObjects(
                    iter->second, corePath, interface, properties);
                const bool success = sdbusplus::unpackPropertiesNoThrow(
                    dbus_utils::UnpackErrorPrinter(), properties, "Microcode",
                    propertyMicrocode);
                if (!success)
                {
                    continue;
                }

                if (propertyMicrocode != nullptr)
                {
                    aResp->res
                        .jsonValue[jsonPtr]["ProcessorId"]["MicrocodeInfo"] =
                        "0x" + intToHexString(*propertyMicrocode, 8);
                }
            }
        }
    }

    if (!present)
    {
        aResp->res.jsonValue[jsonPtr]["Status"]["State"] = "Absent";
    }

    if (!functional)
    {
        aResp->res.jsonValue[jsonPtr]["Status"]["Health"] = "Critical";
    }

    // The "Metrics" stanza is deliberately omitted at the Core layer
}

inline void getSubProcessorCoreData(
    const std::shared_ptr<bmcweb::AsyncResp>& aResp,
    const std::string& processorId, const std::string& coreId,
    const boost::system::error_code ec, const std::string& cpuPath)
{
    if (ec)
    {
        BMCWEB_LOG_DEBUG << "DBUS response error, ec: " << ec.value();
        // No processor objects found by mapper
        if (ec.value() == boost::system::errc::io_error)
        {
            messages::resourceNotFound(
                aResp->res, "#Processor.v1_11_0.Processor", processorId);
            return;
        }

        messages::internalError(aResp->res);
        return;
    }
    aResp->res.addHeader(
        boost::beast::http::field::link,
        "</redfish/v1/JsonSchemas/Processor/Processor.json>; rel=describedby");

    std::array<std::string_view, 1> interfaces{
        "xyz.openbmc_project.Inventory.Item.CpuCore"};
    managedStore::ManagedObjectStoreContext context(aResp);
    managedStore::GetManagedObjectStore()->getSubTree(
        cpuPath, 0, interfaces, context,
        [aResp{aResp}, processorId, coreId,
         context](const boost::system::error_code& ec2,
                  const dbus::utility::MapperGetSubTreeResponse& subtree) {
        if (ec2)
        {
            BMCWEB_LOG_DEBUG << "DBUS response error, ec2: " << ec2.value();
            // No processor objects found by mapper
            if (ec2.value() == boost::system::errc::io_error)
            {
                messages::resourceNotFound(
                    aResp->res, "#Processor.v1_11_0.Processor", processorId);
                return;
            }

            messages::internalError(aResp->res);
            return;
        }

        std::vector<std::string> serviceNames =
            dbus_utils::getServiceNamesFromSubtree(subtree);

        sdbusplus::message::object_path path("/xyz/openbmc_project/inventory");
        dbus_utils::getManagedObjectsInEachService(
            std::move(serviceNames), path, context,
            [aResp{aResp}, subtree, processorId,
             coreId](const ManagedObjectByServiceMap& managedObjectsByService) {
            if (managedObjectsByService.empty())
            {
                messages::internalError(aResp->res);
                return;
            }

            for (const auto& [objectPath, serviceMap] : subtree)
            {
                if (sdbusplus::message::object_path(objectPath).filename() !=
                    coreId)
                {
                    continue;
                }
                getCpuCoreData(aResp, ""_json_pointer, 0, processorId, coreId,
                               objectPath, subtree, managedObjectsByService);
                return;
            }

            // Object not found
            messages::resourceNotFound(aResp->res,
                                       "#Processor.v1_11_0.Processor", coreId);
        });
    });
}

inline void
    getSubProcessorCoreMembers(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
                               const std::string& processorId,
                               const boost::system::error_code ec,
                               const std::string& cpuPath)
{
    if (ec)
    {
        BMCWEB_LOG_DEBUG << "DBUS response error, ec: " << ec.value();
        // No processor objects found by mapper
        if (ec.value() == boost::system::errc::io_error)
        {
            messages::resourceNotFound(
                aResp->res, "#Processor.v1_11_0.Processor", processorId);
            return;
        }

        messages::internalError(aResp->res);
        return;
    }

    aResp->res.addHeader(
        boost::beast::http::field::link,
        "</redfish/v1/JsonSchemas/ProcessorCollection/ProcessorCollection.json>; rel=describedby");
    aResp->res.jsonValue["@odata.type"] =
        "#ProcessorCollection.ProcessorCollection";
    aResp->res.jsonValue["@odata.id"] = crow::utility::urlFromPieces(
        "redfish", "v1", "Systems", "system", "Processors", processorId,
        "SubProcessors");
    aResp->res.jsonValue["Name"] = "SubProcessor Collection";

    const boost::urls::url& subProcessorsPath = crow::utility::urlFromPieces(
        "redfish", "v1", "Systems", "system", "Processors", processorId,
        "SubProcessors");

    constexpr std::array<std::string_view, 1> interfaces{
        "xyz.openbmc_project.Inventory.Item.CpuCore"};

    collection_util::getCollectionMembers(aResp, subProcessorsPath, interfaces,
                                          cpuPath.c_str());
}

inline void getSubProcessorThreadCollectionWithExpand(
    const std::shared_ptr<bmcweb::AsyncResp>& aResp,
    const nlohmann::json::json_pointer& jsonPtr, uint8_t expandLevel,
    const std::string& processorId, const std::string& coreId,
    const std::string& corePath,
    const dbus::utility::MapperGetSubTreeResponse& subtree,
    const ManagedObjectByServiceMap& managedObjectsMap)
{
    aResp->res.jsonValue[jsonPtr]["Name"] = "SubProcessor Collection";
    aResp->res.jsonValue[jsonPtr]["@odata.type"] =
        "#ProcessorCollection.ProcessorCollection";
    aResp->res.jsonValue[jsonPtr]["@odata.id"] = crow::utility::urlFromPieces(
        "redfish", "v1", "Systems", "system", "Processors", processorId,
        "SubProcessors", coreId, "SubProcessors");

    // Maps thread ID to threadObjectPath
    std::map<std::string, std::string, AlphanumLess<std::string>>
        threadIdToObjectPath;

    for (const auto& [objectPath, serviceMap] : subtree)
    {
        if (!objectPath.starts_with(corePath) ||
            !dbus_utils::findInterfacesInServiceMap(
                serviceMap, subProcessorThreadInterfaces))
        {
            continue;
        }
        sdbusplus::message::object_path threadPath(objectPath);
        const std::string& threadId = threadPath.filename();
        threadIdToObjectPath.insert({threadId, threadPath});
    }

    BMCWEB_LOG_DEBUG << "Core path: " << corePath
                     << " thread count: " << threadIdToObjectPath.size();

    if (threadIdToObjectPath.empty())
    {
        BMCWEB_LOG_WARNING << "D-Bus CPU thread count was somehow empty";
        aResp->res.jsonValue[jsonPtr]["Members@odata.count"] = 0;
        aResp->res.jsonValue[jsonPtr]["Members"] = nlohmann::json::array();
        return;
    }

    size_t threadMemberCount = 0;
    for (const auto& [threadId, _] : threadIdToObjectPath)
    {
        nlohmann::json::json_pointer threadMemberPtr =
            jsonPtr / "Members" / threadMemberCount;
        if (expandLevel > 0)
        {
            getCoreThreadData(aResp, threadMemberPtr, expandLevel - 1,
                              processorId, coreId, threadId,
                              threadIdToObjectPath[threadId], subtree,
                              managedObjectsMap);
        }
        else
        {
            aResp->res.jsonValue[threadMemberPtr]["@odata.id"] =
                crow::utility::urlFromPieces("redfish", "v1", "Systems",
                                             "system", "Processors",
                                             processorId, "SubProcessors",
                                             coreId, "SubProcessors", threadId);
        }
        threadMemberCount++;
    }
    aResp->res.jsonValue[jsonPtr]["Members@odata.count"] = threadMemberCount;
}

inline void getSubProcessorCoreCollectionWithExpand(
    const std::shared_ptr<bmcweb::AsyncResp>& aResp,
    const nlohmann::json::json_pointer& jsonPtr, uint8_t expandLevel,
    const std::string& processorId, const std::string& cpuPath,
    const dbus::utility::MapperGetSubTreeResponse& subtree,
    const ManagedObjectByServiceMap& managedObjectsMap)
{
    aResp->res.jsonValue[jsonPtr]["@odata.type"] =
        "#ProcessorCollection.ProcessorCollection";
    aResp->res.jsonValue[jsonPtr]["Name"] = "SubProcessor Collection";
    aResp->res.jsonValue[jsonPtr]["@odata.id"] = crow::utility::urlFromPieces(
        "redfish", "v1", "Systems", "system", "Processors", processorId,
        "SubProcessors");

    // Maps core ID to coreObjectPath
    std::map<std::string, std::string, AlphanumLess<std::string>>
        coreIdToObjectPath;

    for (const auto& [objectPath, serviceMap] : subtree)
    {
        if (!objectPath.starts_with(cpuPath) ||
            !dbus_utils::findInterfacesInServiceMap(serviceMap,
                                                    subProcessorCoreInterfaces))
        {
            continue;
        }
        sdbusplus::message::object_path corePath(objectPath);
        const std::string& coreId = corePath.filename();
        coreIdToObjectPath.insert({coreId, objectPath});
    }

    if (coreIdToObjectPath.empty())
    {
        BMCWEB_LOG_WARNING << "D-Bus CPU core count was somehow empty";
        aResp->res.jsonValue[jsonPtr]["Members@odata.count"] = 0;
        aResp->res.jsonValue[jsonPtr]["Members"] = nlohmann::json::array();
        return;
    }

    size_t coreMemberCount = 0;
    for (const auto& [coreId, _] : coreIdToObjectPath)
    {
        nlohmann::json::json_pointer coreMemberPtr =
            jsonPtr / "Members" / coreMemberCount;
        if (expandLevel > 0)
        {
            getCpuCoreData(aResp, coreMemberPtr, expandLevel - 1, processorId,
                           coreId, coreIdToObjectPath[coreId], subtree,
                           managedObjectsMap);
        }
        else
        {
            aResp->res.jsonValue[coreMemberPtr]["@odata.id"] =
                crow::utility::urlFromPieces(
                    "redfish", "v1", "Systems", "system", "Processors",
                    processorId, "SubProcessors", coreId);
        }
        coreMemberCount++;
    }

    aResp->res.jsonValue[jsonPtr]["Members@odata.count"] = coreMemberCount;
}

inline void getProcessorCollectionWithExpand(
    const std::shared_ptr<bmcweb::AsyncResp>& aResp,
    const dbus::utility::MapperGetSubTreeResponse& subtree,
    const ManagedObjectByServiceMap& managedObjectsMap, uint8_t expandLevel,
    const std::string& systemPath)
{
    BMCWEB_LOG_DEBUG << "Get processor collection with expand.";

    const bool multiHost = !systemPath.empty();

    // Maps cpu ID to cpuObjectPath.
    std::map<std::string, std::string, AlphanumLess<std::string>>
        cpuNameToObjectPath;

    for (const auto& [objectPath, serviceMap] : subtree)
    {

        if (!dbus_utils::findInterfacesInServiceMap(serviceMap,
                                                    processorInterfaces))
        {
            continue;
        }
        sdbusplus::message::object_path cpuPath(objectPath);

        // For multi-host systems, the object path of the cpu must be a
        // descendant of the systemPath. (e.g. if systemPath = /a/b, then
        // objectPath must be some pattern like /a/b/..)
        if (multiHost && !objectPath.starts_with(systemPath))
        {
            continue;
        }

        const std::string& cpuId = cpuPath.filename();
        cpuNameToObjectPath.insert({cpuId, cpuPath});
    }

    // If no cpus found, return
    if (cpuNameToObjectPath.empty())
    {
        BMCWEB_LOG_WARNING << "D-Bus CPU count was somehow empty";
        aResp->res.jsonValue["Members@odata.count"] = 0;
        aResp->res.jsonValue["Members"] = nlohmann::json::array();
        return;
    }

    size_t cpuMemberCount = 0;
    for (const auto& [cpu, _] : cpuNameToObjectPath)
    {
        nlohmann::json::json_pointer cpuMemberPtr =
            "/Members"_json_pointer / cpuMemberCount;
        getProcessorData(aResp, cpuMemberPtr, expandLevel - 1, cpu, systemPath,
                         cpuNameToObjectPath[cpu], subtree, managedObjectsMap);
        cpuMemberCount++;
    }

    aResp->res.jsonValue["Members@odata.count"] = cpuMemberCount;
    aResp->res.jsonValue["Name"] = "Processor Collection";
}

/**
 * Request all the properties for the given D-Bus object and fill out the
 * related entries in the Redfish OperatingConfig response.
 *
 * @param[in,out]   aResp       Async HTTP response.
 * @param[in]       service     D-Bus service name to query.
 * @param[in]       objPath     D-Bus object to query.
 */
inline void
    getOperatingConfigData(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
                           const std::string& service,
                           const std::string& objPath)
{
    managedStore::ManagedObjectStoreContext context(aResp);
    managedStore::GetManagedObjectStore()->getAllProperties(
        service, objPath,
        "xyz.openbmc_project.Inventory.Item.Cpu.OperatingConfig", context,
        [aResp](const boost::system::error_code& ec,
                const dbus::utility::DBusPropertiesMap& properties) {
        if (ec)
        {
            BMCWEB_LOG_WARNING << "D-Bus error: " << ec << ", " << ec.message();
            messages::internalError(aResp->res);
            return;
        }

        const size_t* availableCoreCount = nullptr;
        const uint32_t* baseSpeed = nullptr;
        const uint32_t* maxJunctionTemperature = nullptr;
        const uint32_t* maxSpeed = nullptr;
        const uint32_t* powerLimit = nullptr;
        const TurboProfileProperty* turboProfile = nullptr;
        const BaseSpeedPrioritySettingsProperty* baseSpeedPrioritySettings =
            nullptr;

        const bool success = sdbusplus::unpackPropertiesNoThrow(
            dbus_utils::UnpackErrorPrinter(), properties, "AvailableCoreCount",
            availableCoreCount, "BaseSpeed", baseSpeed,
            "MaxJunctionTemperature", maxJunctionTemperature, "MaxSpeed",
            maxSpeed, "PowerLimit", powerLimit, "TurboProfile", turboProfile,
            "BaseSpeedPrioritySettings", baseSpeedPrioritySettings);

        if (!success)
        {
            messages::internalError(aResp->res);
            return;
        }

        nlohmann::json& json = aResp->res.jsonValue;

        if (availableCoreCount != nullptr)
        {
            json["TotalAvailableCoreCount"] = *availableCoreCount;
        }

        if (baseSpeed != nullptr)
        {
            json["BaseSpeedMHz"] = *baseSpeed;
        }

        if (maxJunctionTemperature != nullptr)
        {
            json["MaxJunctionTemperatureCelsius"] = *maxJunctionTemperature;
        }

        if (maxSpeed != nullptr)
        {
            json["MaxSpeedMHz"] = *maxSpeed;
        }

        if (powerLimit != nullptr)
        {
            json["TDPWatts"] = *powerLimit;
        }

        if (turboProfile != nullptr)
        {
            nlohmann::json& turboArray = json["TurboProfile"];
            turboArray = nlohmann::json::array();
            for (const auto& [turboSpeed, coreCount] : *turboProfile)
            {
                nlohmann::json::object_t turbo;
                turbo["ActiveCoreCount"] = coreCount;
                turbo["MaxSpeedMHz"] = turboSpeed;
                turboArray.emplace_back(std::move(turbo));
            }
        }

        if (baseSpeedPrioritySettings != nullptr)
        {
            nlohmann::json& baseSpeedArray = json["BaseSpeedPrioritySettings"];
            baseSpeedArray = nlohmann::json::array();
            for (const auto& [baseSpeedMhz, coreList] :
                 *baseSpeedPrioritySettings)
            {
                nlohmann::json::object_t speed;
                speed["CoreCount"] = coreList.size();
                speed["CoreIDs"] = coreList;
                speed["BaseSpeedMHz"] = baseSpeedMhz;
                baseSpeedArray.emplace_back(std::move(speed));
            }
        }
    });
}

/**
 * Handle the D-Bus response from attempting to set the CPU's AppliedConfig
 * property. Main task is to translate error messages into Redfish errors.
 *
 * @param[in,out]   resp    HTTP response.
 * @param[in]       setPropVal  Value which we attempted to set.
 * @param[in]       ec      D-Bus response error code.
 * @param[in]       msg     D-Bus response message.
 */
inline void
    handleAppliedConfigResponse(const std::shared_ptr<bmcweb::AsyncResp>& resp,
                                const std::string& setPropVal,
                                const boost::system::error_code& ec,
                                const sdbusplus::message_t& msg)
{
    if (!ec)
    {
        BMCWEB_LOG_DEBUG << "Set Property succeeded";
        return;
    }

    BMCWEB_LOG_DEBUG << "Set Property failed: " << ec;

    const sd_bus_error* dbusError = msg.get_error();
    if (dbusError == nullptr)
    {
        messages::internalError(resp->res);
        return;
    }

    // The asio error code doesn't know about our custom errors, so we have to
    // parse the error string. Some of these D-Bus -> Redfish translations are a
    // stretch, but it's good to try to communicate something vaguely useful.
    if (strcmp(dbusError->name,
               "xyz.openbmc_project.Common.Error.InvalidArgument") == 0)
    {
        // Service did not like the object_path we tried to set.
        messages::propertyValueIncorrect(
            resp->res, "AppliedOperatingConfig/@odata.id", setPropVal);
    }
    else if (strcmp(dbusError->name,
                    "xyz.openbmc_project.Common.Error.NotAllowed") == 0)
    {
        // Service indicates we can never change the config for this processor.
        messages::propertyNotWritable(resp->res, "AppliedOperatingConfig");
    }
    else if (strcmp(dbusError->name,
                    "xyz.openbmc_project.Common.Error.Unavailable") == 0)
    {
        // Service indicates the config cannot be changed right now, but maybe
        // in a different system state.
        messages::resourceInStandby(resp->res);
    }
    else
    {
        messages::internalError(resp->res);
    }
}

/**
 * Handle the PATCH operation of the AppliedOperatingConfig property. Do basic
 * validation of the input data, and then set the D-Bus property.
 *
 * @param[in,out]   resp            Async HTTP response.
 * @param[in]       processorId     Processor's Id.
 * @param[in]       appliedConfigUri    New property value to apply.
 * @param[in]       cpuObjectPath   Path of CPU object to modify.
 * @param[in]       serviceMap      Service map for CPU object.
 */
inline void patchAppliedOperatingConfig(
    const std::shared_ptr<bmcweb::AsyncResp>& resp,
    const std::string& processorId, const std::string& appliedConfigUri,
    const std::string& cpuObjectPath,
    const dbus::utility::MapperGetSubTreeResponse& subtree,
    [[maybe_unused]] const ManagedObjectByServiceMap& managedObjectsMap)
{
    // Get Service map for the object path.
    dbus::utility::MapperServiceMap serviceMap;
    for (const auto& [parsedObjectPath, parsedServiceMap] : subtree)
    {
        if (cpuObjectPath == parsedObjectPath)
        {
            serviceMap = parsedServiceMap;
            break;
        }
    }

    // Check that the property even exists by checking for the interface
    const std::string* controlService = nullptr;
    for (const auto& [serviceName, interfaceList] : serviceMap)
    {
        if (std::find(interfaceList.begin(), interfaceList.end(),
                      "xyz.openbmc_project.Control.Processor."
                      "CurrentOperatingConfig") != interfaceList.end())
        {
            controlService = &serviceName;
            break;
        }
    }

    if (controlService == nullptr)
    {
        messages::internalError(resp->res);
        return;
    }

    // Check that the config URI is a child of the cpu URI being patched.
    std::string expectedPrefix("/redfish/v1/Systems/system/Processors/");
    expectedPrefix += processorId;
    expectedPrefix += "/OperatingConfigs/";
    if (!appliedConfigUri.starts_with(expectedPrefix) ||
        expectedPrefix.size() == appliedConfigUri.size())
    {
        messages::propertyValueIncorrect(
            resp->res, "AppliedOperatingConfig/@odata.id", appliedConfigUri);
        return;
    }

    // Generate the D-Bus path of the OperatingConfig object, by assuming it's a
    // direct child of the CPU object.
    // Strip the expectedPrefix from the config URI to get the "filename", and
    // append to the CPU's path.
    std::string configBaseName = appliedConfigUri.substr(expectedPrefix.size());
    sdbusplus::message::object_path configPath(cpuObjectPath);
    configPath /= configBaseName;

    BMCWEB_LOG_INFO << "Setting config to " << configPath.str;

    // Set the property, with handler to check error responses
    managedStore::GetManagedObjectStore()->PostDbusCallToIoContextThreadSafe(
        resp->strand_,
        [resp, appliedConfigUri](const boost::system::error_code& ec,
                                 const sdbusplus::message_t& msg) {
        handleAppliedConfigResponse(resp, appliedConfigUri, ec, msg);
    },
        *controlService, cpuObjectPath, "org.freedesktop.DBus.Properties",
        "Set", "xyz.openbmc_project.Control.Processor.CurrentOperatingConfig",
        "AppliedConfig", dbus::utility::DbusVariantType(std::move(configPath)));
}

inline void handleSubProcessorThreadHead(
    crow::App& app, const crow::Request& req,
    const std::shared_ptr<bmcweb::AsyncResp>& aResp,
    const std::string& /* systemName */, const std::string& /* processorId */,
    const std::string& /* coreId */, const std::string& /* threadId */)
{
    if (!redfish::setUpRedfishRoute(app, req, aResp))
    {
        return;
    }
    aResp->res.addHeader(
        boost::beast::http::field::link,
        "</redfish/v1/JsonSchemas/Processor/Processor.json>; rel=describedby");
}

inline void handleSubProcessorThreadCollectionHead(
    crow::App& app, const crow::Request& req,
    const std::shared_ptr<bmcweb::AsyncResp>& aResp,
    const std::string& /* systemName */, const std::string& /* processorId */,
    const std::string& /* coreId */)
{
    if (!redfish::setUpRedfishRoute(app, req, aResp))
    {
        return;
    }
    aResp->res.addHeader(
        boost::beast::http::field::link,
        "</redfish/v1/JsonSchemas/ProcessorCollection/ProcessorCollection.json>; rel=describedby");
}

inline void
    handleSubProcessorCoreHead(crow::App& app, const crow::Request& req,
                               const std::shared_ptr<bmcweb::AsyncResp>& aResp,
                               const std::string& /* systemName */,
                               const std::string& /* processorId */,
                               const std::string& /* coreId */)
{
    if (!redfish::setUpRedfishRoute(app, req, aResp))
    {
        return;
    }
    aResp->res.addHeader(
        boost::beast::http::field::link,
        "</redfish/v1/JsonSchemas/Processor/Processor.json>; rel=describedby");
}

inline void handleSubProcessorCoreCollectionHead(
    crow::App& app, const crow::Request& req,
    const std::shared_ptr<bmcweb::AsyncResp>& aResp,
    const std::string& /* systemName */, const std::string& /* processorId */)
{
    if (!redfish::setUpRedfishRoute(app, req, aResp))
    {
        return;
    }
    aResp->res.addHeader(
        boost::beast::http::field::link,
        "</redfish/v1/JsonSchemas/ProcessorCollection/ProcessorCollection.json>; rel=describedby");
}

inline void handleProcessorHead(crow::App& app, const crow::Request& req,
                                const std::shared_ptr<bmcweb::AsyncResp>& aResp,
                                const std::string& /* systemName */,
                                const std::string& /* processorId */)
{
    if (!redfish::setUpRedfishRoute(app, req, aResp))
    {
        return;
    }
    aResp->res.addHeader(
        boost::beast::http::field::link,
        "</redfish/v1/JsonSchemas/Processor/Processor.json>; rel=describedby");
}

inline void handleProcessorCollectionHead(
    crow::App& app, const crow::Request& req,
    const std::shared_ptr<bmcweb::AsyncResp>& aResp,
    const std::string& /* systemName */)
{
    if (!redfish::setUpRedfishRoute(app, req, aResp))
    {
        return;
    }
    aResp->res.addHeader(
        boost::beast::http::field::link,
        "</redfish/v1/JsonSchemas/ProcessorCollection/ProcessorCollection.json>; rel=describedby");
}

inline void parseSubtreeForProcessorCollection(
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const dbus::utility::MapperGetSubTreeResponse& subtree,
    const query_param::Query& delegated, const std::string& systemPath)
{
    const bool multiHost = !systemPath.empty();

    // Default systemName is system and change if system is multi-host
    std::string systemName = "system";

    if (multiHost)
    {
        systemName = sdbusplus::message::object_path(systemPath).filename();
    }

    if (delegated.expandLevel == 0 ||
        delegated.expandType == query_param::ExpandType::None)
    {
        BMCWEB_LOG_DEBUG << "Use default processor expand handler";
        collection_util::getCollectionMembersFromSubtree(
            asyncResp,
            boost::urls::url("/redfish/v1/Systems/" + systemName +
                             "/Processors"),
            processorInterfaces, subtree);
        return;
    }
    BMCWEB_LOG_DEBUG << "Use efficient processor expand handler";

    std::vector<std::string> serviceNames =
        dbus_utils::getServiceNamesFromSubtree(subtree);
    if (serviceNames.empty())
    {
        BMCWEB_LOG_DEBUG << "Can't retrieve service names from subtree";
        asyncResp->res.jsonValue["Members@odata.count"] = 0;
        asyncResp->res.jsonValue["Members"] = nlohmann::json::array();
        return;
    }

    managedStore::ManagedObjectStoreContext context(asyncResp);
    // Get managed objects from each service in subtree to proactively
    // fetch all dbus data needed to serve requests for subordinate
    // resources.
    sdbusplus::message::object_path path("/xyz/openbmc_project/inventory");
    dbus_utils::getManagedObjectsInEachService(
        std::move(serviceNames), path, context,
        [asyncResp{asyncResp}, subtree, delegated,
         systemPath](const ManagedObjectByServiceMap& managedObjectsByService) {
        if (managedObjectsByService.empty())
        {
            BMCWEB_LOG_DEBUG << "Cannot get managed objects.";
            messages::internalError(asyncResp->res);
            return;
        }
        getProcessorCollectionWithExpand(asyncResp, subtree,
                                         managedObjectsByService,
                                         delegated.expandLevel, systemPath);
    });
}

inline void handleProcessorCollection(
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const query_param::Query& delegated, const std::string& systemPath)
{
    const bool multiHost = !systemPath.empty();

    // Default systemName is system and change if system is multi-host
    std::string systemName = "system";
    // The subtree to query for Dimms changes if single or multi-host
    std::string subtreeRoot = "/xyz/openbmc_project/inventory";

    if (multiHost)
    {
        systemName = sdbusplus::message::object_path(systemPath).filename();
        subtreeRoot = systemPath;
    }

    asyncResp->res.addHeader(
        boost::beast::http::field::link,
        "</redfish/v1/JsonSchemas/ProcessorCollection/ProcessorCollection.json>; rel=describedby");

    asyncResp->res.jsonValue["@odata.type"] =
        "#ProcessorCollection.ProcessorCollection";
    asyncResp->res.jsonValue["Name"] = "Processor Collection";

    asyncResp->res.jsonValue["@odata.id"] =
        "/redfish/v1/Systems/" + systemName + "/Processors";

    // Get dbus interfaces based on expand level.
    auto interfaces = getInterfacesForProcessorSubtree(delegated.expandLevel);

    if (interfaces.empty())
    {
        BMCWEB_LOG_ERROR << "Can't get interface list for expand level "
                         << delegated.expandLevel;
        messages::internalError(asyncResp->res);
        return;
    }

    // Get subtree information to serve requests for both processor
    // collection and, if expand is requested, for all requested subordinate
    // resources.
    managedStore::ManagedObjectStoreContext requestContext(asyncResp);
    managedStore::GetManagedObjectStore()->getSubTree(
        subtreeRoot, 0, interfaces, requestContext,
        [asyncResp{asyncResp}, delegated,
         systemPath](const boost::system::error_code& ec,
                     const dbus::utility::MapperGetSubTreeResponse& subtree) {
        if (ec == boost::system::errc::io_error)
        {
            asyncResp->res.jsonValue["Members"] = nlohmann::json::array();
            asyncResp->res.jsonValue["Members@odata.count"] = 0;
            return;
        }

        if (ec)
        {
            BMCWEB_LOG_DEBUG << "DBUS response error " << ec.value();
            messages::internalError(asyncResp->res);
            return;
        }
        parseSubtreeForProcessorCollection(asyncResp, subtree, delegated,
                                           systemPath);
    });
}

inline void handleOperatingConfigCollectionGet(
    App& app, const crow::Request& req,
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const std::string& cpuName)
{
    if (!redfish::setUpRedfishRoute(app, req, asyncResp))
    {
        return;
    }
    asyncResp->res.jsonValue["@odata.type"] =
        "#OperatingConfigCollection.OperatingConfigCollection";
    asyncResp->res.jsonValue["@odata.id"] =
        crow::utility::urlFromPieces("redfish", "v1", "Systems", "system",
                                     "Processors", cpuName, "OperatingConfigs");
    asyncResp->res.jsonValue["Name"] = "Operating Config Collection";

    // First find the matching CPU object so we know how to
    // constrain our search for related Config objects.
    const std::array<std::string_view, 1> interfaces = {
        "xyz.openbmc_project.Control.Processor.CurrentOperatingConfig"};
    managedStore::ManagedObjectStoreContext requestContext(asyncResp);
    managedStore::GetManagedObjectStore()->getSubTreePaths(
        "/xyz/openbmc_project/inventory", 0, interfaces, requestContext,
        [asyncResp,
         cpuName](const boost::system::error_code& ec,
                  const dbus::utility::MapperGetSubTreePathsResponse& objects) {
        if (ec)
        {
            BMCWEB_LOG_WARNING << "D-Bus error: " << ec << ", " << ec.message();
            messages::internalError(asyncResp->res);
            return;
        }

        for (const std::string& object : objects)
        {
            if (!object.ends_with(cpuName))
            {
                continue;
            }

            // Not expected that there will be multiple matching
            // CPU objects, but if there are just use the first
            // one.

            // Use the common search routine to construct the
            // Collection of all Config objects under this CPU.
            constexpr std::array<std::string_view, 1> interface{
                "xyz.openbmc_project.Inventory.Item.Cpu.OperatingConfig"};
            collection_util::getCollectionMembers(
                asyncResp,
                crow::utility::urlFromPieces("redfish", "v1", "Systems",
                                             "system", "Processors", cpuName,
                                             "OperatingConfigs"),
                interface, object.c_str());
            return;
        }
    });
}

inline void requestRoutesOperatingConfigCollection(App& app)
{
    BMCWEB_ROUTE(
        app, "/redfish/v1/Systems/system/Processors/<str>/OperatingConfigs/")
        .privileges(redfish::privileges::getOperatingConfigCollection)
        .methods(boost::beast::http::verb::get)(
            std::bind_front(handleOperatingConfigCollectionGet, std::ref(app)));
}

inline void handleOperatingConfigGet(
    App& app, const crow::Request& req,
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const std::string& cpuName, const std::string& configName)
{
    if (!redfish::setUpRedfishRoute(app, req, asyncResp))
    {
        return;
    }
    // Ask for all objects implementing OperatingConfig so we can search
    // for one with a matching name
    constexpr std::array<std::string_view, 1> interfaces = {
        "xyz.openbmc_project.Inventory.Item.Cpu.OperatingConfig"};
    managedStore::ManagedObjectStoreContext requestContext(asyncResp);
    managedStore::GetManagedObjectStore()->getSubTree(
        "/xyz/openbmc_project/inventory", 0, interfaces, requestContext,
        [asyncResp, cpuName,
         configName](const boost::system::error_code& ec,
                     const dbus::utility::MapperGetSubTreeResponse& subtree) {
        if (ec)
        {
            BMCWEB_LOG_WARNING << "D-Bus error: " << ec << ", " << ec.message();
            messages::internalError(asyncResp->res);
            return;
        }
        const std::string expectedEnding = cpuName + '/' + configName;
        for (const auto& [objectPath, serviceMap] : subtree)
        {
            // Ignore any configs without matching cpuX/configY
            if (!objectPath.ends_with(expectedEnding) || serviceMap.empty())
            {
                continue;
            }

            nlohmann::json& json = asyncResp->res.jsonValue;
            json["@odata.type"] = "#OperatingConfig.v1_0_0.OperatingConfig";
            json["@odata.id"] = crow::utility::urlFromPieces(
                "redfish", "v1", "Systems", "system", "Processors", cpuName,
                "OperatingConfigs", configName);
            json["Name"] = "Processor Profile";
            json["Id"] = configName;

            // Just use the first implementation of the object - not
            // expected that there would be multiple matching
            // services
            getOperatingConfigData(asyncResp, serviceMap.begin()->first,
                                   objectPath);
            return;
        }
        messages::resourceNotFound(asyncResp->res, "OperatingConfig",
                                   configName);
    });
}

inline void requestRoutesOperatingConfig(App& app)
{
    BMCWEB_ROUTE(
        app,
        "/redfish/v1/Systems/system/Processors/<str>/OperatingConfigs/<str>/")
        .privileges(redfish::privileges::getOperatingConfig)
        .methods(boost::beast::http::verb::get)(
            std::bind_front(handleOperatingConfigGet, std::ref(app)));
}

inline int countProcessors()
{
    // TODO(): This is a STUB
    // For now, this is OK, since it is only used for syntax validation.
    // However, when and if writing (POST, PATCH, etc.) is allowed,
    // we will need to have better bounds-checking here,
    // otherwise it will be trivial for a writer to DoS all the storage.
    return 16;
}

inline int countCores(int cpuIndex)
{
    // TODO(): This is a STUB, see above comment
    (void)cpuIndex;
    return 256;
}

inline int countThreads(int cpuIndex, int coreIndex)
{
    // TODO(): This is a STUB, see above comment
    (void)cpuIndex;
    (void)coreIndex;
    return 16;
}

inline int prefixStrToInt(const std::string& prefix, const std::string& str)
{
    size_t lenPrefix = prefix.size();
    size_t lenStr = str.size();

    // Content following prefix must be within 1 to 9 characters in length
    if (lenStr < (lenPrefix + 1))
    {
        BMCWEB_LOG_ERROR << "Index number too short";
        return -1;
    }
    if (lenStr > (lenPrefix + 9))
    {
        // This length limit prevents 32-bit rollover attacks
        BMCWEB_LOG_ERROR << "Index number too long";
        return -1;
    }

    if (str.substr(0, lenPrefix) != prefix)
    {
        // Prefix does not match
        BMCWEB_LOG_ERROR << "Index number wrong prefix";
        return -1;
    }

    std::string numText = str.substr(lenPrefix);
    size_t lenText = numText.size();
    size_t lenCheck = std::strlen(numText.c_str());
    if (lenText != lenCheck)
    {
        // This comparison prevents 0x00 string truncation attacks
        BMCWEB_LOG_ERROR << "Index number wrong length";
        return -1;
    }

    // Cannot use std::stoi because stoi throws
    char* endptr = nullptr;
    int64_t value = std::strtol(numText.c_str(), &endptr, 10);
    if (*endptr != '\0')
    {
        // The number was followed by extra content
        BMCWEB_LOG_ERROR << "Index number wrong content";
        return -1;
    }

    int result = static_cast<int>(value);
    return result;
}

inline int extractIndexFromArg(const std::string& arg)
{
    const std::string index =
        arg.substr(arg.find_last_not_of("0123456789") + 1);
    if (index.empty())
    {
        BMCWEB_LOG_ERROR << "Unable to extract index from arg";
        return -1;
    }
    // use std::strtol since std::stoi can throw
    char* enptr = nullptr;
    int64_t value = std::strtol(index.c_str(), &enptr, 10);
    return static_cast<int>(value);
}

inline int cpuArgToIndex(const std::string& cpuArg)
{
    int bound = countProcessors();
    int num = extractIndexFromArg(cpuArg);
    if (num >= bound)
    {
        BMCWEB_LOG_ERROR << "Processor index out of range";
        return -1;
    }
    return num;
}

inline int coreArgToIndex(const std::string& coreArg, int cpuIndex)
{

    int bound = countCores(cpuIndex);
    int num = prefixStrToInt("core", coreArg);
    if (num >= bound)
    {
        BMCWEB_LOG_ERROR << "Subprocessor core index out of range";
        return -1;
    }
    return num;
}

inline int threadArgToIndex(const std::string& threadArg, int cpuIndex,
                            int coreIndex)
{

    int bound = countThreads(cpuIndex, coreIndex);
    int num = prefixStrToInt("thread", threadArg);
    if (num >= bound)
    {
        BMCWEB_LOG_ERROR << "Subprocessor thread index out of range";
        return -1;
    }
    return num;
}

inline int validateCpu(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
                       const std::string& cpuArg)
{
    int cpuIndex = cpuArgToIndex(cpuArg);
    if (cpuIndex < 0)
    {
        messages::resourceNotFound(asyncResp->res, "Processor", cpuArg);
    }
    return cpuIndex;
}

inline int validateCpuCore(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
                           const std::string& cpuArg,
                           const std::string& coreArg)
{
    int cpuIndex = validateCpu(asyncResp, cpuArg);
    if (cpuIndex < 0)
    {
        return cpuIndex;
    }
    int coreIndex = coreArgToIndex(coreArg, cpuIndex);
    if (coreIndex < 0)
    {
        messages::resourceNotFound(asyncResp->res, "Core", coreArg);
    }
    return coreIndex;
}

inline int
    validateCpuCoreThread(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
                          const std::string& cpuArg, const std::string& coreArg,
                          const std::string& threadArg)
{
    int cpuIndex = validateCpu(asyncResp, cpuArg);
    if (cpuIndex < 0)
    {
        return cpuIndex;
    }
    int coreIndex = validateCpuCore(asyncResp, cpuArg, coreArg);
    if (coreIndex < 0)
    {
        return coreIndex;
    }
    int threadIndex = threadArgToIndex(threadArg, cpuIndex, coreIndex);
    if (threadIndex < 0)
    {
        messages::resourceNotFound(asyncResp->res, "Thread", threadArg);
    }
    return threadIndex;
}

// Creates a generic ExternalStorer hook, should be 2 directories above
// Each hook contains instances, each instance contains entries
// Omit the leading "/redfish/v1" from pathBase, and no trailing slash
inline external_storer::Hook makeExternalStorerHook(const std::string& pathBase)
{
    const std::string emptyString;
    const std::vector<std::string> emptyList;

    return {pathBase, emptyString, emptyList, emptyList};
}

// Creates a generic ExternalStorer instance within the given hook
// The content will be minimal, just enough to create filename on disk
// Returns true if successful
inline bool makeExternalStorerInstance(
    const std::shared_ptr<external_storer::Hook>& hook, const std::string& id)
{
    // External storer NEVER sends dbus calls, so you will never leave this thread.
    auto respGet = std::make_shared<bmcweb::AsyncResp>(nullptr);

    hook->handleGetInstance(respGet, id);
    if (respGet->res.result() == boost::beast::http::status::ok)
    {
        // Already exists, nothing more needs to be done
        return true;
    }

    boost::beast::http::request<boost::beast::http::string_body> upBody;
    std::error_code ec;

    // Create instance, with given ID, which will become filename on disk
    auto upJson = nlohmann::json::object();
    upJson["Id"] = id;

    // Must supply 4th argument to avoid throwing exceptions
    upBody.body() =
        upJson.dump(-1, ' ', false, nlohmann::json::error_handler_t::replace);
    crow::Request reqCreate{upBody, ec};

    // External storer NEVER sends dbus calls, so you will never leave this thread.
    auto respCreate = std::make_shared<bmcweb::AsyncResp>(nullptr);

    hook->handleCreateInstance(reqCreate, respCreate);
    if (respCreate->res.result() != boost::beast::http::status::created)
    {
        BMCWEB_LOG_ERROR << "Problem creating ExternalStorer instance " << id;
        return false;
    }

    return true;
}

// Remembers toplevel Processors hook, there is only one
// Each instance in it represents a CPU and is named like cpuArg
// Each instance contains only one entry, "ProcessorMetrics"
inline std::shared_ptr<external_storer::Hook>
    rememberProcessorHook(const std::string& cpuArg)
{
    static std::shared_ptr<external_storer::Hook> hookProcessor = nullptr;

    if (!hookProcessor)
    {
        // If not already remembered by static variable, create hook
        hookProcessor = std::make_shared<external_storer::Hook>(
            makeExternalStorerHook("Systems/system/Processors"));
    }

    if (!(makeExternalStorerInstance(hookProcessor, cpuArg)))
    {
        BMCWEB_LOG_ERROR << "Problem remembering hook for " << cpuArg;
        return nullptr;
    }

    return hookProcessor;
}

// Remembers lowest-level SubProcessors hook
// There is one hook for each unique (CPU, thread) tuple
// Each instance in it represents a thread and is named like threadArg
// Each instance contains only one entry, "ProcessorMetrics"
inline std::shared_ptr<external_storer::Hook>
    rememberThreadHook(const std::string& cpuArg, const std::string& coreArg,
                       const std::string& threadArg)
{
    static std::map<
        std::string,
        std::map<std::string, std::shared_ptr<external_storer::Hook>>>
        hookMaps;

    auto findCpu = hookMaps.find(cpuArg);
    if (findCpu == hookMaps.end())
    {
        hookMaps[cpuArg] = {};
        findCpu = hookMaps.find(cpuArg);
    }

    auto findCore = findCpu->second.find(coreArg);
    if (findCore == findCpu->second.end())
    {
        (findCpu->second)[coreArg] = {};
        findCore = findCpu->second.find(coreArg);
    }

    std::shared_ptr<external_storer::Hook> hookThread = findCore->second;

    if (!hookThread)
    {
        std::string path = "Systems/system/Processors/" + cpuArg +
                           "/SubProcessors/" + coreArg + "/SubProcessors";
        hookThread = std::make_shared<external_storer::Hook>(
            makeExternalStorerHook(path));
        findCore->second = hookThread;
    }

    if (!(makeExternalStorerInstance(hookThread, threadArg)))
    {
        BMCWEB_LOG_ERROR << "Problem remembering hook for " << threadArg;
        return nullptr;
    }

    return hookThread;
}

inline nlohmann::json fakeProcessorMetrics(const std::string& cpu,
                                           const std::string& core,
                                           const std::string& thread)
{
    nlohmann::json::object_t metricsObj;

    metricsObj["Id"] = "Metrics";
    metricsObj["Name"] = "Processor Metrics";

    // The different levels have slightly different default content
    if (!thread.empty())
    {
        // Thread level
        metricsObj["CorrectableCoreErrorCount"] = 0;
        metricsObj["UncorrectableCoreErrorCount"] = 0;
    }
    metricsObj["CorrectableOtherErrorCount"] = 0;
    metricsObj["UncorrectableOtherErrorCount"] = 0;

    // ExternalStorer would normally apply this as invariant if successful
    // The caller already applies "@odata.type" as invariant no matter what
    std::string url = "/redfish/v1/Systems/system/Processors/";
    url += cpu;
    if (!core.empty())
    {
        url += "/SubProcessors/";
        url += core;
    }
    if (!thread.empty())
    {
        url += "/SubProcessors/";
        url += thread;
    }
    url += "/ProcessorMetrics";

    metricsObj["@odata.id"] = std::move(url);

    return metricsObj;
}

inline void
    handleGetCpuMetrics(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
                        const nlohmann::json::json_pointer& jsonPtr,
                        const std::string& cpuArg)
{
    if (validateCpu(asyncResp, cpuArg) < 0)
    {
        // Error reply already composed
        return;
    }

    std::shared_ptr<external_storer::Hook> hook = rememberProcessorHook(cpuArg);
    if (!hook)
    {
        messages::resourceNotFound(asyncResp->res, "Processor", cpuArg);
        return;
    }

    std::string emptyString;
    hook->handleGetEntry(asyncResp, jsonPtr, cpuArg, emptyString,
                         "ProcessorMetrics");
    if (asyncResp->res.result() == boost::beast::http::status::not_found)
    {
        // Fake up a synthetic response to replace only the 404 error
        asyncResp->res.jsonValue[jsonPtr] =
            fakeProcessorMetrics(cpuArg, "", "");
        asyncResp->res.result(boost::beast::http::status::ok);
    }
    if (asyncResp->res.result() != boost::beast::http::status::ok)
    {
        // Error reply already composed
        return;
    }

    // Apply invariants, to override whatever might have been in the file
    asyncResp->res.jsonValue[jsonPtr]["@odata.type"] =
        "#ProcessorMetrics.v1_5_0.ProcessorMetrics";
}

inline void handleGetCpuCoreThreadMetrics(
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const nlohmann::json::json_pointer& jsonPtr, const std::string& cpuArg,
    const std::string& coreArg, const std::string& threadArg)
{
    if (validateCpuCoreThread(asyncResp, cpuArg, coreArg, threadArg) < 0)
    {
        return;
    }

    std::shared_ptr<external_storer::Hook> hook =
        rememberThreadHook(cpuArg, coreArg, threadArg);
    if (!hook)
    {
        messages::resourceNotFound(asyncResp->res, "Thread", threadArg);
        return;
    }

    std::string emptyString;
    hook->handleGetEntry(asyncResp, jsonPtr, threadArg, emptyString,
                         "ProcessorMetrics");
    if (asyncResp->res.result() == boost::beast::http::status::not_found)
    {
        // Fake up a synthetic response to replace only the 404 error
        asyncResp->res.jsonValue[jsonPtr] =
            fakeProcessorMetrics(cpuArg, coreArg, threadArg);
        asyncResp->res.result(boost::beast::http::status::ok);
    }
    if (asyncResp->res.result() != boost::beast::http::status::ok)
    {
        // Error reply already composed
        return;
    }

    // Apply invariants, to override whatever might have been in the file
    asyncResp->res.jsonValue[jsonPtr]["@odata.type"] =
        "#ProcessorMetrics.v1_5_0.ProcessorMetrics";
}

// The glue layers are already handled by these functions elsewhere:
// Processors = requestRoutesProcessorCollection()
// Processors/cpuX = requestRoutesProcessor()
// Processors/cpuX/SubProcessors = requestRoutesSubProcessorCoreCollection()
// Processors/cpuX/SubProcessors/coreY = requestRoutesSubProcessorCore()
// Processors/cpuX/SubProcessors/coreY/SubProcessors =
// requestRoutesSubProcessorThreadCollection()
// Processors/cpuX/SubProcessors/coreY/SubProcessors/threadZ =
// requestRoutesSubProcessorThread()

// The "ProcessorMetrics" endpoints are below those glue layers:
// Processors/cpuX/ProcessorMetrics = handled here
// Processors/cpuX/SubProcessors/coreY/ProcessorMetrics = intentionally
// omitted
// Processors/cpuX/SubProcessors/coreY/SubProcessors/threadZ/ProcessorMetrics
// = handled here
inline void requestRoutesProcessorMetricsViaExternalStorer(App& app)
{
    BMCWEB_ROUTE(
        app, "/redfish/v1/Systems/system/Processors/<str>/ProcessorMetrics/")
        .privileges(redfish::privileges::getProcessor)
        .methods(boost::beast::http::verb::get)(
            [&app](const crow::Request& req,
                   const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
                   const std::string& cpuArg) {
        if (!redfish::setUpRedfishRoute(app, req, asyncResp))
        {
            return;
        }
        handleGetCpuMetrics(asyncResp, ""_json_pointer, cpuArg);
    });

    BMCWEB_ROUTE(
        app,
        "/redfish/v1/Systems/system/Processors/<str>/SubProcessors/<str>/SubProcessors/<str>/ProcessorMetrics/")
        .privileges(redfish::privileges::getProcessor)
        .methods(boost::beast::http::verb::get)(
            [&app](const crow::Request& req,
                   const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
                   const std::string& cpuArg, const std::string& coreArg,
                   const std::string& threadArg) {
        if (!redfish::setUpRedfishRoute(app, req, asyncResp))
        {
            return;
        }
        handleGetCpuCoreThreadMetrics(asyncResp, ""_json_pointer, cpuArg,
                                      coreArg, threadArg);
    });

    // TODO(): Implement corresponding PATCH methods
    // The POST method is not correct to use here,
    // as the result location is already well-known name "ProcessorMetrics".
    // and from the user point of view it always exists,
    // so the creation operation is not the correct operation.
    // The PUT method also might not be correct to use here,
    // as it would fully replace all content at the result location,
    // but the expectation is to only selectively replace some content.
}

inline void requestRoutesProcessorCollection(App& app)
{
    /**
     * Functions triggers appropriate requests on DBus
     */
    BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/Processors/")
        .privileges(redfish::privileges::headProcessorCollection)
        .methods(boost::beast::http::verb::head)(
            std::bind_front(handleProcessorCollectionHead, std::ref(app)));

    BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/Processors/")
        .privileges(redfish::privileges::getProcessorCollection)
        .methods(boost::beast::http::verb::get)(
            [&app](const crow::Request& req,
                   const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
                   const std::string& systemName) {
        query_param::Query delegated;
        query_param::QueryCapabilities capabilities = {
#ifdef EFFICIENT_EXPAND_ENABLED
            .canDelegateExpandLevel = 6,
#else
            .canDelegateExpandLevel = 0,
#endif
        };
        if (!redfish::setUpRedfishRouteWithDelegation(app, req, asyncResp,
                                                      delegated, capabilities))
        {
            return;
        }

        redfish::system_utils::getSystemInformation(
            asyncResp, systemName,
            [delegated](const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
                        const std::string& systemPath) {
            handleProcessorCollection(asyncResp, delegated, systemPath);
        });
    });
}

inline void getProcessorStateCollection(
    App& app, const crow::Request& req,
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const std::string& systemName, const std::string& processorId)
{
    if (!redfish::setUpRedfishRoute(app, req, asyncResp))
    {
        return;
    }
    constexpr std::array<std::string_view, 1> procStateIntf = {
        "xyz.openbmc_project.Inventory.Item.ProcessorState"};
    collection_util::getCollectionMembers(
        asyncResp,
        crow::utility::urlFromPieces("redfish", "v1", "Systems", systemName,
                                     "Processors", processorId, "Oem", "Google",
                                     "ProcessorStates"),
        procStateIntf);
}

inline void
    handleProcessorGet(App& app, const crow::Request& req,
                       const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
                       const std::string& systemName,
                       const std::string& processorId)
{
    if (!redfish::setUpRedfishRoute(app, req, asyncResp))
    {
        return;
    }

    redfish::system_utils::getSystemInformation(
        asyncResp, systemName,
        [processorId](const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
                      const std::string& systemPath) {
        getProcessorObject(asyncResp, processorId, systemPath,
                           std::bind_front(getProcessorData, asyncResp,
                                           ""_json_pointer, 0, processorId,
                                           systemPath));
    });
}

inline void
    handleProcessorPatch(App& app, const crow::Request& req,
                         const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
                         const std::string& systemName,
                         const std::string& processorId)
{
    if (!redfish::setUpRedfishRoute(app, req, asyncResp))
    {
        return;
    }
    if (systemName != "system")
    {
        messages::resourceNotFound(asyncResp->res, "ComputerSystem",
                                   systemName);
        return;
    }

    std::optional<nlohmann::json> appliedConfigJson;
    if (!json_util::readJsonPatch(req, asyncResp->res, "AppliedOperatingConfig",
                                  appliedConfigJson))
    {
        return;
    }

    if (appliedConfigJson)
    {
        std::string appliedConfigUri;
        if (!json_util::readJson(*appliedConfigJson, asyncResp->res,
                                 "@odata.id", appliedConfigUri))
        {
            return;
        }

        redfish::system_utils::getSystemInformation(
            asyncResp, systemName,
            [processorId, appliedConfigUri](
                const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
                const std::string& systemPath) {
            // Check for 404 and find matching D-Bus object, then run
            // property patch handlers if that all succeeds.
            getProcessorObject(asyncResp, processorId, systemPath,
                               std::bind_front(patchAppliedOperatingConfig,
                                               asyncResp, processorId,
                                               appliedConfigUri));
        });
    }
}

inline void requestRoutesProcessor(App& app)
{
    /**
     * Functions triggers appropriate requests on DBus
     */

    BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/Processors/<str>/")
        .privileges(redfish::privileges::headProcessor)
        .methods(boost::beast::http::verb::head)(
            std::bind_front(handleProcessorHead, std::ref(app)));

    BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/Processors/<str>/")
        .privileges(redfish::privileges::getProcessor)
        .methods(boost::beast::http::verb::get)(
            std::bind_front(handleProcessorGet, std::ref(app)));

    BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/Processors/<str>/")
        .privileges(redfish::privileges::patchProcessor)
        .methods(boost::beast::http::verb::patch)(
            std::bind_front(handleProcessorPatch, std::ref(app)));

    BMCWEB_ROUTE(
        app,
        "/redfish/v1/Systems/<str>/Processors/<str>/Oem/Google/ProcessorStates/")
        .privileges(redfish::privileges::getProcessor)
        .methods(boost::beast::http::verb::get)(
            std::bind_front(getProcessorStateCollection, std::ref(app)));

    BMCWEB_ROUTE(
        app,
        "/redfish/v1/Systems/<str>/Processors/<str>/Oem/Google/ProcessorStates/<str>/")
        .privileges(redfish::privileges::getProcessor)
        .methods(boost::beast::http::verb::get)(
            std::bind_front(getProcessorStateData, std::ref(app)));
}

inline void requestRoutesSubProcessorCoreCollection(App& app)
{
    BMCWEB_ROUTE(app,
                 "/redfish/v1/Systems/<str>/Processors/<str>/SubProcessors/")
        .privileges(redfish::privileges::headProcessorCollection)
        .methods(boost::beast::http::verb::head)(std::bind_front(
            handleSubProcessorCoreCollectionHead, std::ref(app)));

    BMCWEB_ROUTE(app,
                 "/redfish/v1/Systems/<str>/Processors/<str>/SubProcessors/")
        .privileges(redfish::privileges::getProcessorCollection)
        .methods(boost::beast::http::verb::get)(
            [&app](const crow::Request& req,
                   const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
                   const std::string& systemName,
                   const std::string& processorId) {
        if (!redfish::setUpRedfishRoute(app, req, asyncResp))
        {
            return;
        }
        if (systemName != "system")
        {
            messages::resourceNotFound(asyncResp->res, "ComputerSystem",
                                       systemName);
            return;
        }

        BMCWEB_LOG_DEBUG << "Get available system sub processor core members.";

        getProcessorPaths(asyncResp, processorId,
                          std::bind_front(getSubProcessorCoreMembers, asyncResp,
                                          processorId));
    });
}

inline void requestRoutesSubProcessorCore(App& app)
{
    BMCWEB_ROUTE(
        app, "/redfish/v1/Systems/<str>/Processors/<str>/SubProcessors/<str>/")
        .privileges(redfish::privileges::headProcessor)
        .methods(boost::beast::http::verb::head)(
            std::bind_front(handleSubProcessorCoreHead, std::ref(app)));

    BMCWEB_ROUTE(
        app, "/redfish/v1/Systems/<str>/Processors/<str>/SubProcessors/<str>/")
        .privileges(redfish::privileges::getProcessor)
        .methods(boost::beast::http::verb::get)(
            [&app](const crow::Request& req,
                   const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
                   const std::string& systemName,
                   const std::string& processorId, const std::string& coreId) {
        if (!redfish::setUpRedfishRoute(app, req, asyncResp))
        {
            return;
        }
        if (systemName != "system")
        {
            messages::resourceNotFound(asyncResp->res, "ComputerSystem",
                                       systemName);
            return;
        }

        BMCWEB_LOG_DEBUG
            << "Get available system sub processor core resources.";

        getProcessorPaths(asyncResp, processorId,
                          std::bind_front(getSubProcessorCoreData, asyncResp,
                                          processorId, coreId));
    });
}

inline void requestRoutesSubProcessorThreadCollection(App& app)
{
    BMCWEB_ROUTE(
        app,
        "/redfish/v1/Systems/<str>/Processors/<str>/SubProcessors/<str>/SubProcessors/")
        .privileges(redfish::privileges::headProcessorCollection)
        .methods(boost::beast::http::verb::head)(std::bind_front(
            handleSubProcessorThreadCollectionHead, std::ref(app)));
    BMCWEB_ROUTE(
        app,
        "/redfish/v1/Systems/<str>/Processors/<str>/SubProcessors/<str>/SubProcessors/")
        .privileges(redfish::privileges::getProcessorCollection)
        .methods(boost::beast::http::verb::get)(
            [&app](const crow::Request& req,
                   const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
                   const std::string& systemName,
                   const std::string& processorId, const std::string& coreId) {
        if (!redfish::setUpRedfishRoute(app, req, asyncResp))
        {
            return;
        }
        if (systemName != "system")
        {
            messages::resourceNotFound(asyncResp->res, "ComputerSystem",
                                       systemName);
            return;
        }

        getSubProcessorCorePaths(asyncResp, processorId, coreId,
                                 std::bind_front(getSubProcessorThreadMembers,
                                                 asyncResp, processorId,
                                                 coreId));
    });
}

inline void requestRoutesSubProcessorThread(App& app)
{
    BMCWEB_ROUTE(
        app,
        "/redfish/v1/Systems/<str>/Processors/<str>/SubProcessors/<str>/SubProcessors/<str>/")
        .privileges(redfish::privileges::headProcessor)
        .methods(boost::beast::http::verb::head)(
            std::bind_front(handleSubProcessorThreadHead, std::ref(app)));
    BMCWEB_ROUTE(
        app,
        "/redfish/v1/Systems/<str>/Processors/<str>/SubProcessors/<str>/SubProcessors/<str>/")
        .privileges(redfish::privileges::getProcessor)
        .methods(boost::beast::http::verb::get)(
            [&app](const crow::Request& req,
                   const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
                   const std::string& systemName,
                   const std::string& processorId, const std::string& coreId,
                   const std::string& threadId) {
        if (!redfish::setUpRedfishRoute(app, req, asyncResp))
        {
            return;
        }
        if (systemName != "system")
        {
            messages::resourceNotFound(asyncResp->res, "ComputerSystem",
                                       systemName);
            return;
        }

        getSubProcessorCorePaths(asyncResp, processorId, coreId,
                                 std::bind_front(getSubProcessorThreadData,
                                                 asyncResp, processorId, coreId,
                                                 threadId));
    });
}

} // namespace redfish
