#ifndef THIRD_PARTY_GBMCWEB_REDFISH_CORE_LIB_PROCESSOR_H_
#define THIRD_PARTY_GBMCWEB_REDFISH_CORE_LIB_PROCESSOR_H_

/*
// 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.
*/

#include <systemd/sd-bus.h>

#include <algorithm>
#include <array>
#include <cstddef>
#include <cstdint>
#include <cstring>
#include <functional>
#include <limits>
#include <map>
#include <memory>
#include <optional>
#include <string>
#include <string_view>
#include <system_error>  // NOLINT
#include <tuple>
#include <unordered_map>
#include <utility>
#include <variant>
#include <vector>

#include "absl/strings/match.h"
#include "absl/strings/numbers.h"
#include "absl/strings/str_cat.h"
#include "boost/container/flat_map.hpp"  // NOLINT
#include "boost/system/error_code.hpp"  // NOLINT
#include "app.hpp"
#include "http_request.hpp"
#include "logging.hpp"
#include "utility.hpp"
#include "async_resp.hpp"
#include "dbus_utility.hpp"
#include "human_sort.hpp"
#include "error_messages.hpp"
#include "query.hpp"
#include "registries/privilege_registry.hpp"
#include "collection.hpp"
#include "dbus_utils.hpp"
#include "hex_utils.hpp"
#include "json_utils.hpp"
#include "location_utils.hpp"
#include "system_utils.hpp"
#include "external_storer.hpp"
#include "health.hpp"
#include <nlohmann/json.hpp>
#include "managed_store.hpp"
#include "managed_store_types.hpp"
#include "sdbusplus/message.hpp"
#include "sdbusplus/message/native_types.hpp"
#include "sdbusplus/unpack_properties.hpp"

#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& systemName, 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& systemName, 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& systemName,
    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& systemName,
    const std::string& cpuArg);

inline bool isValidSystemServicePair(const std::string& systemName,
                                     const std::string& service);

/**
 * @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 Check if the given system name and service name are a valid pair.
 *
 * @param[in] systemName The name of the system.
 * @param[in] service The name of the service.
 *
 * @return True if the pair is valid, false otherwise.
 */
inline bool isValidSystemServicePair(const std::string& systemName,
                                     const std::string& service) {
  static const std::unordered_map<std::string, std::string>
      validSystemServices = {{"system1", "xyz.openbmc_project.pldm0"},
                             {"system2", "xyz.openbmc_project.pldm1"},
                             {"system", "xyz.openbmc_project.pldm"}};

  auto it = validSystemServices.find(systemName);
  return (it != validSystemServices.end() && it->second == service);
}

/**
 *
 * @param[in,out] aResp   Async HTTP response.
 * @param[in] processorPath The D-Bus path of the processor.
 * @param[in] jsonPtr     json pointer to index the response fields.
 * @param[in] systemName  system name
 */
inline void getProcessorMaxTDP(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
                               const std::string& processorPath,
                               const nlohmann::json::json_pointer& jsonPtr,
                               const std::string& systemName) {
  constexpr std::array<std::string_view, 1> interfaces = {
      "xyz.openbmc_project.Effecter.Value"};

  managedStore::ManagedObjectStoreContext pldmContext(aResp);

  // Get all PLDM effecters using the ManagedObjectStore
  managedStore::GetManagedObjectStore()->getSubTree(
      "/xyz/openbmc_project/pldm", 0, interfaces, pldmContext,
      [aResp, processorPath, jsonPtr, systemName](
          const boost::system::error_code& ec,
          const dbus::utility::MapperGetSubTreeResponse& subtree) {
        if (ec) {
          BMCWEB_LOG_ERROR << "DBUS response error for pldm effecters: " << ec;
          // It's not a fatal error if PLDM isn't present, so just return.
          return;
        }

        // Iterate through the PLDM services (CN0, CN1, etc.)
        for (const auto& [effecterPath, serviceMap] : subtree) {
          if (serviceMap.empty()) {
            continue;
          }

          // 2. Inner loop iterates over the key-value pairs in 'serviceMap'.
          for (const auto& servicePair : serviceMap) {
            // 3. We only use '.first' to get the service name (the key).
            const std::string& service = servicePair.first;
            BMCWEB_LOG_DEBUG << "Service Name: " << service
                             << "Effecter Path: " << effecterPath;

            // Inverted condition to skip invalid pairs first
            if (!isValidSystemServicePair(systemName, service)) {
              continue;
            }

            // The effecter object path looks like:
            // /xyz/openbmc_project/pldm/4/effecter/power/SOC_TDP_4.
            // This object implements the
            // xyz.openbmc_project.Effecter.Value interface, which
            // stores the configured MaxTDPWatts field. The object name
            // can be same for both pldm services on muti CN systems
            if (absl::StrContains(effecterPath, "SOC_TDP")) {
              // Get the MaxTDPWatts value
              managedStore::ManagedObjectStoreContext valueContext(aResp);
              dbus_utils::getProperty<double>(
                  service, effecterPath, "xyz.openbmc_project.Effecter.Value",
                  "Value", valueContext,
                  [aResp, jsonPtr, effecterPath](
                      const boost::system::error_code& ec3,
                      const double& value) {
                    if (ec3) {
                      BMCWEB_LOG_ERROR
                          << "DBUS response error for effecterPath: "
                          << effecterPath << " ,Error: " << ec3.message();
                      return;
                    }
                    aResp->res.jsonValue[jsonPtr]["MaxTDPWatts"] = value;
                  });
              return;
            }
          }
        }
      });
}

/**
 * @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);
#ifdef HEALTH_POPULATE
      auto health = std::make_shared<HealthPopulate>(
          aResp, "/redfish/v1/Systems/system/Processors/" + cpuId, objPath,
          "Processor", cpuId);
#endif /* HEALTH_POPULATE */
    } 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";
#ifdef HEALTH_POPULATE
  auto healthObj = std::make_shared<HealthPopulate>(
      aResp, "/redfish/v1/Systems/system/Processors/" + acclrtrId, objPath,
      "Processor", acclrtrId);
#endif /* HEALTH_POPULATE */
}

// 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,
    const nlohmann::json::json_pointer& jsonPtr) {
  managedStore::ManagedObjectStoreContext requestContext(asyncResp);
  dbus_utils::getProperty<bool>(
      service, objPath, "xyz.openbmc_project.Inventory.Item", "Present",
      requestContext,
      [asyncResp, objPath, jsonPtr](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[jsonPtr]["Status"]["State"] =
            present ? "Enabled" : "Absent";
      });
}

inline void getProcessorStateData(
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const std::string& systemName, const std::string& processorId,
    const std::string& procStateId,
    const nlohmann::json::json_pointer& jsonPtr) {
  BMCWEB_LOG_DEBUG << "Processor State Id: " << procStateId;
  asyncResp->res.jsonValue[jsonPtr]["@odata.id"] = crow::utility::urlFromPieces(
      "redfish", "v1", "Systems", systemName, "Processors", processorId, "Oem",
      "Google", "ProcessorStates", procStateId);
  asyncResp->res.jsonValue[jsonPtr]["@odata.type"] =
      "#GoogleProcessorState.GoogleProcessorState";
  asyncResp->res.jsonValue[jsonPtr]["Id"] = procStateId;
  asyncResp->res.jsonValue[jsonPtr]["Name"] = "Processor";
  getProcessorState(asyncResp, "xyz.openbmc_project.EntityManager",
                    absl::StrCat("/xyz/openbmc_project/inventory/", systemName,
                                 "/processorstate/", procStateId),
                    jsonPtr);
}

inline void handleGetProcessorState(
    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;
  }
  getProcessorStateData(asyncResp, systemName, processorId, procStateId,
                        ""_json_pointer);
}

using Mapper = dbus::utility::MapperGetSubTreePathsResponse;
inline void getProcessorStateLinksOrExpand(
    const std::shared_ptr<bmcweb::AsyncResp>& aResp,
    const std::string& processorId, const nlohmann::json::json_pointer& jsonPtr,
    const std::string& systemName, uint8_t expandLevel,
    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;
  size_t stateCount = 0;
  for (const std::string& procState : procStatePaths) {
    std::string procStateId =
        sdbusplus::message::object_path(procState).filename();
    nlohmann::json::json_pointer processorStatePtr =
        jsonPtr / "Oem" / "Google" / "ProcessorStates" / stateCount++;
    if (expandLevel > 0) {
      getProcessorStateData(aResp, systemName, processorId, procStateId,
                            processorStatePtr);
    } else {
      nlohmann::json::object_t procStateObj;
      aResp->res.jsonValue[processorStatePtr]["@odata.id"] =
          crow::utility::urlFromPieces(
              "redfish", "v1", "Systems", systemName, "Processors", processorId,
              "Oem", "Google", "ProcessorStates", procStateId);
    }
  }
}

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;
      }
    }
  }
  getProcessorMaxTDP(aResp, objectPath, jsonPtr, systemName);
  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(getProcessorStateLinksOrExpand, aResp, processorId,
                      jsonPtr, systemName, expandLevel));

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

  if (!multiHost) {
    if (expandLevel > 0) {
      nlohmann::json::json_pointer metricsPtr = jsonPtr / "Metrics";
      handleGetCpuMetrics(aResp, metricsPtr, systemName, processorId);
    } else {
      // Inserting the "Metrics" JSON stanza
      std::string metricsUrl = aResp->res.jsonValue[jsonPtr]["@odata.id"];
      absl::StrAppend(&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& systemPath,
                              const std::string& processorId,
                              Handler&& handler) {
  std::array<std::string_view, 1> interfaces{
      "xyz.openbmc_project.Inventory.Item.Cpu"};

  std::string subtreeRoot = "/xyz/openbmc_project/inventory";
  if (!systemPath.empty()) {
    subtreeRoot = systemPath;
  }

  managedStore::ManagedObjectStoreContext requestContext(aResp);
  managedStore::GetManagedObjectStore()->getSubTreePaths(
      subtreeRoot, 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& systemPath, const std::string& processorId,
    const std::string& coreId, Handler&& handler) {
  std::array<std::string_view, 1> interfaces{
      "xyz.openbmc_project.Inventory.Item.Cpu"};

  std::string subtreeRoot = "/xyz/openbmc_project/inventory";
  if (!systemPath.empty()) {
    subtreeRoot = systemPath;
  }

  managedStore::ManagedObjectStoreContext requestContext(aResp);
  managedStore::GetManagedObjectStore()->getSubTreePaths(
      subtreeRoot, 0, interfaces, requestContext,
      [processorId, coreId, aResp{aResp},
       handler{std::forward<Handler>(handler)}, subtreeRoot,
       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(
              subtreeRoot, 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& systemName,
    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", systemName, "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 (systemName == "system") {
    if (expandLevel > 0) {
      nlohmann::json::json_pointer metricsPtr = jsonPtr / "Metrics";
      handleGetCpuCoreThreadMetrics(aResp, metricsPtr, systemName, processorId,
                                    coreId, threadId);
    } else {
      // Inserting the "Metrics" JSON stanza
      std::string metricsUrl = aResp->res.jsonValue[jsonPtr]["@odata.id"];
      absl::StrAppend(&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& systemName, 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}, systemName, 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, systemName, 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, systemName,
                                  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& systemName, 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", systemName, "Processors", processorId,
      "SubProcessors", coreId, "SubProcessors");
  aResp->res.jsonValue["Name"] = "SubProcessor Collection";

  const boost::urls::url& subProcessorsPath = crow::utility::urlFromPieces(
      "redfish", "v1", "Systems", systemName, "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& systemName, 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", systemName, "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, systemName, processorId,
        coreId, corePath, subtree, managedObjectsMap);
  } else {
    aResp->res.jsonValue[jsonPtr]["SubProcessors"]["@odata.id"] =
        crow::utility::urlFromPieces("redfish", "v1", "Systems", systemName,
                                     "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& systemName, 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}, systemName, 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, systemName, 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, systemName,
                               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& systemName, 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", systemName,
                                   "Processors", processorId, "SubProcessors");
  aResp->res.jsonValue["Name"] = "SubProcessor Collection";

  const boost::urls::url& subProcessorsPath =
      crow::utility::urlFromPieces("redfish", "v1", "Systems", systemName,
                                   "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& systemName, 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", systemName, "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, systemName,
                        processorId, coreId, threadId,
                        threadIdToObjectPath[threadId], subtree,
                        managedObjectsMap);
    } else {
      aResp->res.jsonValue[threadMemberPtr]["@odata.id"] =
          crow::utility::urlFromPieces(
              "redfish", "v1", "Systems", systemName, "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& systemName, 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", systemName,
                                   "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, systemName,
                     processorId, coreId, coreIdToObjectPath[coreId], subtree,
                     managedObjectsMap);
    } else {
      aResp->res.jsonValue[coreMemberPtr]["@odata.id"] =
          crow::utility::urlFromPieces("redfish", "v1", "Systems", systemName,
                                       "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;
  }

  int64_t value = 0;
  if (!absl::SimpleAtoi(numText, &value)) {
    BMCWEB_LOG_ERROR << "Index number wrong content:" << numText;
    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;
  }

  int64_t value = 0;
  if (!absl::SimpleAtoi(index, &value)) {
    BMCWEB_LOG_ERROR << "Index number from arg invalid content:" << index;
    return -1;
  }

  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 per systemName
// 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& systemName, const std::string& cpuArg) {
  if (systemName != "system") {
    return nullptr;
  }
  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, scoped by systemName
// There is one hook for each unique (System, 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& systemName, const std::string& cpuArg,
    const std::string& coreArg, const std::string& threadArg) {
  if (systemName != "system") {
    return nullptr;
  }
  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& systemName,
                                           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 =
      absl::StrCat("/redfish/v1/Systems/", systemName, "/Processors/", cpu);
  if (!core.empty()) {
    absl::StrAppend(&url, "/SubProcessors/", core);
  }
  if (!thread.empty()) {
    absl::StrAppend(&url, "/SubProcessors/", thread);
  }
  absl::StrAppend(&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& systemName,
    const std::string& cpuArg) {
  if (validateCpu(asyncResp, cpuArg) < 0) {
    // Error reply already composed
    return;
  }

  std::shared_ptr<external_storer::Hook> hook =
      rememberProcessorHook(systemName, 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(systemName, 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& systemName,
    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(systemName, 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(systemName, 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, "system", 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,
                                          "system", 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_PROCESSORS_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(handleGetProcessorState, 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;
            }

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

            redfish::system_utils::getSystemInformation(
                asyncResp, systemName,
                [processorId, systemName](
                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
                    const std::string& systemPath) {
                  getProcessorPaths(
                      asyncResp, systemPath, processorId,
                      std::bind_front(getSubProcessorCoreMembers, asyncResp,
                                      systemName, 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;
            }

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

            redfish::system_utils::getSystemInformation(
                asyncResp, systemName,
                [processorId, coreId, systemName](
                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
                    const std::string& systemPath) {
                  getProcessorPaths(
                      asyncResp, systemPath, processorId,
                      std::bind_front(getSubProcessorCoreData, asyncResp,
                                      systemName, 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;
            }

            redfish::system_utils::getSystemInformation(
                asyncResp, systemName,
                [processorId, coreId, systemName](
                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
                    const std::string& systemPath) {
                  getSubProcessorCorePaths(
                      asyncResp, systemPath, processorId, coreId,
                      std::bind_front(getSubProcessorThreadMembers, asyncResp,
                                      systemName, 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;
            }

            redfish::system_utils::getSystemInformation(
                asyncResp, systemName,
                [processorId, coreId, threadId, systemName](
                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
                    const std::string& systemPath) {
                  getSubProcessorCorePaths(
                      asyncResp, systemPath, processorId, coreId,
                      std::bind_front(getSubProcessorThreadData, asyncResp,
                                      systemName, processorId, coreId,
                                      threadId));
                });
          });
}

}  // namespace redfish

#endif  // THIRD_PARTY_GBMCWEB_REDFISH_CORE_LIB_PROCESSOR_H_
