#include "NVMeFeatureStore.hpp"

#include "nvme_features.pb.h"

#include <endian.h>

#include <boost/asio/async_result.hpp>
#include <boost/asio/post.hpp>
#include <phosphor-logging/lg2.hpp>

#include <algorithm>
#include <cstring>
#include <iomanip>
#include <map>
#include <sstream>
#include <tuple>
#include <utility>
#include <vector>

static constexpr uint32_t nvmeGetFeaturesCapSaveable = 0x1;
static constexpr uint32_t nvmeGetFeaturesCapChangeable = 0x4;

struct FeatureMeta
{
    uint8_t fid;            ///< NVMe Feature Identifier
    std::string protoClass; ///< Fully qualified Protobuf class name
    FeatureScope scope;     ///< Applicability scope
};

/**
 * @brief Map of P0 features defined in the design document.
 */
static const std::map<std::string, FeatureMeta> supportedFeatures = {
    {"Arbitration",
     {0x01, "google.gbmc.nvme.base.Arbitration", FeatureScope::Controller}},
    {"PowerManagement",
     {0x02, "google.gbmc.nvme.base.PowerManagement", FeatureScope::Controller}},
    {"TemperatureThreshold",
     {0x04, "google.gbmc.nvme.base.TemperatureThreshold",
      FeatureScope::Controller}},
    {"ErrorRecovery",
     {0x05, "google.gbmc.nvme.base.ErrorRecovery", FeatureScope::Namespace}},
    {"VolatileWriteCache",
     {0x06, "google.gbmc.nvme.base.VolatileWriteCache",
      FeatureScope::Controller}},
    {"NumberOfQueues",
     {0x07, "google.gbmc.nvme.base.NumberOfQueues", FeatureScope::Controller}},
    {"InterruptCoalescing",
     {0x08, "google.gbmc.nvme.base.InterruptCoalescing",
      FeatureScope::Controller}},
    {"InterruptVectorConfiguration",
     {0x09, "google.gbmc.nvme.base.InterruptVectorConfiguration",
      FeatureScope::Controller}},
    {"WriteAtomicityNormal",
     {0x0A, "google.gbmc.nvme.base.WriteAtomicityNormal",
      FeatureScope::Controller}},
    {"AsynchronousEventConfiguration",
     {0x0B, "google.gbmc.nvme.base.AsynchronousEventConfiguration",
      FeatureScope::Controller}},
};

template <typename T>
static T parseProto(const std::vector<uint8_t>& data)
{
    T msg;
    if (!msg.ParseFromArray(data.data(), static_cast<int>(data.size())))
    {
        throw sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument();
    }
    return msg;
}

// Helper for async_initiate
static std::tuple<nvme_ex_ptr, uint32_t, std::vector<uint8_t>>
    asyncAdminGetFeatures(boost::asio::io_context& io,
                          const std::shared_ptr<NVMeMiIntf>& nvmeIntf,
                          nvme_mi_ctrl_t ctrl,
                          const NVMeMiIntf::GetFeaturesRequest& req,
                          boost::asio::yield_context yield)
{
    return boost::asio::async_initiate<boost::asio::yield_context,
                                       void(nvme_ex_ptr, uint32_t,
                                            std::vector<uint8_t>)>(
        [&io](auto&& callback, const std::shared_ptr<NVMeMiIntf>& nvmeIntf,
              nvme_mi_ctrl_t ctrl, const NVMeMiIntf::GetFeaturesRequest& req) {
        auto sharedCb = std::make_shared<std::decay_t<decltype(callback)>>(
            std::forward<decltype(callback)>(callback));
        nvmeIntf->adminGetFeatures(
            ctrl, req,
            [sharedCb, &io](nvme_ex_ptr ex, uint32_t resp,
                            std::span<uint8_t> data) mutable {
            std::vector<uint8_t> dataCopy(data.begin(), data.end());
            boost::asio::post(io, [sharedCb = std::move(sharedCb), ex, resp,
                                   dataCopy = std::move(dataCopy)]() mutable {
                (*sharedCb)(ex, resp, dataCopy);
            });
        });
    },
        yield, nvmeIntf, ctrl, req);
}

static std::tuple<nvme_ex_ptr, uint32_t> asyncAdminSetFeatures(
    boost::asio::io_context& io, const std::shared_ptr<NVMeMiIntf>& nvmeIntf,
    nvme_mi_ctrl_t ctrl, const NVMeMiIntf::SetFeaturesRequest& req,
    boost::asio::yield_context yield)
{
    return boost::asio::async_initiate<boost::asio::yield_context,
                                       void(nvme_ex_ptr, uint32_t)>(
        [&io](auto&& callback, const std::shared_ptr<NVMeMiIntf>& nvmeIntf,
              nvme_mi_ctrl_t ctrl, const NVMeMiIntf::SetFeaturesRequest& req) {
        auto sharedCb = std::make_shared<std::decay_t<decltype(callback)>>(
            std::forward<decltype(callback)>(callback));
        nvmeIntf->adminSetFeatures(
            ctrl, req, [sharedCb, &io](nvme_ex_ptr ex, uint32_t resp) mutable {
            boost::asio::post(io, [sharedCb = std::move(sharedCb), ex,
                                   resp]() mutable { (*sharedCb)(ex, resp); });
        });
    },
        yield, nvmeIntf, ctrl, req);
}

static std::tuple<nvme_ex_ptr, std::vector<uint8_t>> asyncAdminIdentify(
    boost::asio::io_context& io, const std::shared_ptr<NVMeMiIntf>& nvmeIntf,
    nvme_mi_ctrl_t ctrl, nvme_identify_cns cns, uint32_t nsid, uint16_t cntid,
    boost::asio::yield_context yield)
{
    return boost::asio::async_initiate<boost::asio::yield_context,
                                       void(nvme_ex_ptr, std::vector<uint8_t>)>(
        [&io](auto&& callback, const std::shared_ptr<NVMeMiIntf>& nvmeIntf,
              nvme_mi_ctrl_t ctrl, nvme_identify_cns cns, uint32_t nsid,
              uint16_t cntid) {
        auto sharedCb = std::make_shared<std::decay_t<decltype(callback)>>(
            std::forward<decltype(callback)>(callback));
        nvmeIntf->adminIdentify(
            ctrl, cns, nsid, cntid,
            [sharedCb, &io](nvme_ex_ptr ex, std::span<uint8_t> data) mutable {
            std::vector<uint8_t> dataCopy(data.begin(), data.end());
            boost::asio::post(io, [sharedCb = std::move(sharedCb), ex,
                                   dataCopy = std::move(dataCopy)]() mutable {
                (*sharedCb)(ex, dataCopy);
            });
        });
    },
        yield, nvmeIntf, ctrl, cns, nsid, cntid);
}

static std::tuple<std::error_code, std::vector<uint8_t>> asyncAdminGetLogPage(
    boost::asio::io_context& io, const std::shared_ptr<NVMeMiIntf>& nvmeIntf,
    nvme_mi_ctrl_t ctrl, nvme_cmd_get_log_lid lid, uint32_t nsid, uint8_t lsp,
    uint16_t lsi, boost::asio::yield_context yield)
{
    return boost::asio::async_initiate<boost::asio::yield_context,
                                       void(std::error_code,
                                            std::vector<uint8_t>)>(
        [&io](auto&& callback, const std::shared_ptr<NVMeMiIntf>& nvmeIntf,
              nvme_mi_ctrl_t ctrl, nvme_cmd_get_log_lid lid, uint32_t nsid,
              uint8_t lsp, uint16_t lsi) {
        auto sharedCb = std::make_shared<std::decay_t<decltype(callback)>>(
            std::forward<decltype(callback)>(callback));
        nvmeIntf->adminGetLogPage(
            ctrl, lid, nsid, lsp, lsi,
            [sharedCb, &io](const std::error_code& ec,
                            std::span<uint8_t> data) mutable {
            std::vector<uint8_t> dataCopy(data.begin(), data.end());
            boost::asio::post(io, [sharedCb = std::move(sharedCb), ec,
                                   dataCopy = std::move(dataCopy)]() mutable {
                (*sharedCb)(ec, dataCopy);
            });
        });
    },
        yield, nvmeIntf, ctrl, lid, nsid, lsp, lsi);
}

FeatureStore::FeatureStore(
    boost::asio::io_context& io, sdbusplus::asio::object_server& objServer,
    const std::shared_ptr<sdbusplus::asio::connection>& conn,
    const std::string& objectPath, std::shared_ptr<NVMeMiIntf> nvmeIntf,
    nvme_mi_ctrl_t ctrl, uint32_t nsid, FeatureScope scope) :
    io(io), objServer(objServer), conn(conn), objectPath(objectPath),
    nvmeIntf(std::move(nvmeIntf)), ctrl(ctrl), nsid(nsid), scope(scope)
{}

void FeatureStore::registerDbusInterface()
{
    dbusIntf = objServer.add_interface(objectPath,
                                       "xyz.openbmc_project.NVMe.FeatureStore");

    dbusIntf->register_property("ProtoLibraryVersion", std::string("2.0"),
                                sdbusplus::asio::PropertyPermission::readOnly);
    dbusIntf->register_property("FeatureCollection", featureCollection,
                                sdbusplus::asio::PropertyPermission::readOnly);
    dbusIntf->register_method(
        "GetFeature",
        [weakSelf = weak_from_this()](const boost::asio::yield_context& yield,
                                      const std::string& featureName) {
        auto self = weakSelf.lock();
        if (!self)
        {
            throw sdbusplus::xyz::openbmc_project::Common::Error::Unavailable();
        }
        return self->getFeature(yield, featureName);
    });

    dbusIntf->register_method(
        "SetFeature",
        [weakSelf = weak_from_this()](const boost::asio::yield_context& yield,
                                      const std::string& featureName,
                                      const std::vector<uint8_t>& data) {
        auto self = weakSelf.lock();
        if (!self)
        {
            throw sdbusplus::xyz::openbmc_project::Common::Error::Unavailable();
        }
        self->setFeature(yield, featureName, data);
    });

    dbusIntf->initialize();
}

void FeatureStore::init(std::function<void(const std::error_code&)>&& cb)
{
    (void)boost::asio::spawn(
        io, [self{shared_from_this()}, cb{std::move(cb)}](
                const boost::asio::yield_context& yield) mutable {
        self->fetchIdentifyData(yield);
        self->registerDbusInterface();
        cb({});
    });
}

void FeatureStore::fetchIdentifyData(const boost::asio::yield_context& yield)
{
    std::string path = this->objectPath;
    auto [ex, data] = asyncAdminIdentify(
        io, nvmeIntf, ctrl, NVME_IDENTIFY_CNS_CTRL, NVME_NSID_NONE, 0, yield);

    if (ex)
    {
        lg2::error(
            "[{PATH}]Identify Controller failed during FeatureStore init: {ERROR}",
            "PATH", path, "ERROR", ex->what());
        discoverFeatures(yield);
        return;
    }

    if (data.size() < sizeof(nvme_id_ctrl))
    {
        lg2::error("[{PATH}]Identify Controller returned insufficient data",
                   "PATH", path);
        discoverFeatures(yield);
        return;
    }
    nvme_id_ctrl idCtrl = {};
    std::memcpy(&idCtrl, data.data(), sizeof(nvme_id_ctrl));
    vwcSupported = (idCtrl.vwc & NVME_CTRL_VWC_PRESENT) != 0;
    oncs = le16toh(idCtrl.oncs);

    if (!vwcSupported)
    {
        lg2::info(
            "[{PATH}]Volatile Write Cache (FID 0x06) not supported by hardware",
            "PATH", path);
    }

    discoverFeatures(yield);
}

void FeatureStore::discoverFeatures(const boost::asio::yield_context& yield)
{
    std::string path = this->objectPath;
    bool oncsBit4 = (oncs & (1 << 4)) != 0;

    featureCollection.clear();

    std::vector<std::pair<std::string, FeatureMeta>> featuresToCheck;
    for (const auto& [name, meta] : supportedFeatures)
    {
        if (meta.scope == scope)
        {
            if (name == "VolatileWriteCache" && !vwcSupported)
            {
                continue;
            }
            featuresToCheck.emplace_back(name, meta);
        }
    }

    // Fetch Log Page 12h (Feature Identifiers Supported and Effects)
    std::vector<uint8_t> fidSupportedEffects;
    auto [ec, logData] = asyncAdminGetLogPage(
        io, nvmeIntf, ctrl, NVME_LOG_LID_FID_SUPPORTED_EFFECTS, NVME_NSID_NONE,
        0, 0, yield);
    if (!ec)
    {
        if (logData.size() == sizeof(struct nvme_fid_supported_effects_log))
        {
            fidSupportedEffects = std::move(logData);
        }
        else
        {
            lg2::error(
                "[{PATH}]Log Page 12h size mismatch: expected {EXPECTED}, got {GOT}",
                "PATH", path, "EXPECTED",
                sizeof(struct nvme_fid_supported_effects_log), "GOT",
                logData.size());
        }
    }
    else
    {
        lg2::error("[{PATH}]Failed to fetch Log Page 12h: {ERROR}", "PATH",
                   path, "ERROR", ec.message());
    }

    for (const auto& [name, meta] : featuresToCheck)
    {
        if (!fidSupportedEffects.empty())
        {
            size_t offset = static_cast<size_t>(meta.fid) * 4;
            if (offset + sizeof(uint32_t) <= fidSupportedEffects.size())
            {
                uint32_t entry = 0;
                std::memcpy(&entry, fidSupportedEffects.data() + offset,
                            sizeof(entry));
                entry = le32toh(entry);
                if ((entry & 0x1) == 0) // FSUPP bit
                {
                    lg2::info(
                        "[{PATH}]Feature {NAME} (FID {FID}) not supported per Log Page 12h",
                        "PATH", path, "NAME", name, "FID", meta.fid);
                    continue;
                }
            }
            else
            {
                lg2::error("[{PATH}]Log Page 12h data too short for FID {FID}",
                           "PATH", path, "FID", meta.fid);
                continue;
            }
        }
        std::stringstream ss;
        ss << "0x" << std::setfill('0') << std::setw(2) << std::hex
           << static_cast<int>(meta.fid);
        std::string fidStr = ss.str();

        if (!oncsBit4)
        {
            featureCollection.emplace_back(name + "_Current", fidStr,
                                           meta.protoClass);
            continue;
        }

        NVMeMiIntf::GetFeaturesRequest args{};
        args.fid = meta.fid;
        args.sel = NVME_GET_FEATURES_SEL_SUPPORTED; // 011b
        args.nsid = (scope == FeatureScope::Namespace) ? nsid : NVME_NSID_NONE;
        args.cdw11 = 0;
        args.data_len = 0;

        auto [ex, cdw0, data] = asyncAdminGetFeatures(io, nvmeIntf, ctrl, args,
                                                      yield);

        if (ex)
        {
            lg2::info(
                "[{PATH}]Feature {NAME} (FID {FID}) capabilities query failed (unsupported): {ERROR}",
                "PATH", path, "NAME", name, "FID", meta.fid, "ERROR",
                ex->what());
            continue;
        }

        featureCaps[meta.fid] = cdw0;

        featureCollection.emplace_back(name + "_Current", fidStr,
                                       meta.protoClass);

        if ((cdw0 & nvmeGetFeaturesCapChangeable) != 0)
        {
            featureCollection.emplace_back(name + "_Default", fidStr,
                                           meta.protoClass);
        }

        if ((cdw0 & nvmeGetFeaturesCapSaveable) != 0)
        {
            featureCollection.emplace_back(name + "_Saved", fidStr,
                                           meta.protoClass);
        }
    }
}

bool FeatureStore::isFeatureSupported(const std::string& featureName) const
{
    return std::any_of(featureCollection.begin(), featureCollection.end(),
                       [&featureName](const auto& item) {
        return std::get<0>(item) == featureName;
    });
}

std::vector<uint8_t>
    FeatureStore::getFeature(const boost::asio::yield_context& yield,
                             const std::string& featureName)
{
    std::string path = this->objectPath;
    if (!isFeatureSupported(featureName))
    {
        throw sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument();
    }
    size_t lastUnderscore = featureName.find_last_of('_');
    if (lastUnderscore == std::string::npos)
    {
        throw sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument();
    }

    std::string baseName = featureName.substr(0, lastUnderscore);
    std::string selectStr = featureName.substr(lastUnderscore + 1);

    auto it = supportedFeatures.find(baseName);
    if (it == supportedFeatures.end() || it->second.scope != scope)
    {
        throw sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument();
    }

    uint8_t fid = it->second.fid;
    uint8_t sel = 0;
    if (selectStr == "Current")
    {
        sel = 0;
    }
    else if (selectStr == "Default")
    {
        sel = 1;
    }
    else if (selectStr == "Saved")
    {
        sel = 2;
    }
    else
    {
        throw sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument();
    }

    NVMeMiIntf::GetFeaturesRequest args{};
    args.fid = fid;
    args.sel = sel;
    args.nsid = (scope == FeatureScope::Namespace) ? nsid : NVME_NSID_NONE;
    args.cdw11 = 0;
    args.data_len = 0;

    auto [ex, cdw0, data] = asyncAdminGetFeatures(io, nvmeIntf, ctrl, args,
                                                  yield);

    if (ex)
    {
        lg2::error("[{PATH}]NVMe Get Features (FID {FID}) failed: {ERROR}",
                   "PATH", path, "FID", fid, "ERROR", ex->what());
        throw sdbusplus::xyz::openbmc_project::Common::Error::Unavailable();
    }

    std::vector<uint8_t> protoData;

    switch (fid)
    {
        case 0x01:
        {
            google::gbmc::nvme::base::Arbitration msg;
            msg.set_arbitration_burst(cdw0 & 0xFF);
            msg.set_low_priority_weight((cdw0 >> 8) & 0xFF);
            msg.set_medium_priority_weight((cdw0 >> 16) & 0xFF);
            msg.set_high_priority_weight((cdw0 >> 24) & 0xFF);
            protoData.resize(msg.ByteSizeLong());
            if (!msg.SerializeToArray(protoData.data(),
                                      static_cast<int>(protoData.size())))
            {
                lg2::error("[{PATH}]Failed to serialize Arbitration", "PATH",
                           path);
            }
            break;
        }
        case 0x02:
        {
            google::gbmc::nvme::base::PowerManagement msg;
            msg.set_power_state(cdw0 & 0x1F);
            msg.set_workload_hint((cdw0 >> 8) & 0x7);
            protoData.resize(msg.ByteSizeLong());
            if (!msg.SerializeToArray(protoData.data(),
                                      static_cast<int>(protoData.size())))
            {
                lg2::error("[{PATH}]Failed to serialize PowerManagement",
                           "PATH", path);
            }
            break;
        }
        case 0x04:
        {
            google::gbmc::nvme::base::TemperatureThreshold msg;
            msg.set_temperature_threshold(cdw0 & 0xFFFF);
            msg.set_threshold_temperature_select((cdw0 >> 16) & 0xF);
            msg.set_threshold_type_select(
                static_cast<google::gbmc::nvme::base::
                                TemperatureThreshold_ThresholdType>(
                    (cdw0 >> 20) & 0x3));
            protoData.resize(msg.ByteSizeLong());
            if (!msg.SerializeToArray(protoData.data(),
                                      static_cast<int>(protoData.size())))
            {
                lg2::error("[{PATH}]Failed to serialize TemperatureThreshold",
                           "PATH", path);
            }
            break;
        }
        case 0x05:
        {
            google::gbmc::nvme::base::ErrorRecovery msg;
            msg.set_tler(cdw0 & 0xFFFF);
            msg.set_dulbe_enable(
                static_cast<google::gbmc::nvme::base::ErrorRecovery_State>(
                    (cdw0 >> 16) & 0x1));
            protoData.resize(msg.ByteSizeLong());
            if (!msg.SerializeToArray(protoData.data(),
                                      static_cast<int>(protoData.size())))
            {
                lg2::error("[{PATH}]Failed to serialize ErrorRecovery", "PATH",
                           path);
            }
            break;
        }
        case 0x06:
        {
            google::gbmc::nvme::base::VolatileWriteCache msg;
            msg.set_write_cache_enable(
                static_cast<google::gbmc::nvme::base::VolatileWriteCache_State>(
                    cdw0 & 0x1));
            protoData.resize(msg.ByteSizeLong());
            if (!msg.SerializeToArray(protoData.data(),
                                      static_cast<int>(protoData.size())))
            {
                lg2::error("[{PATH}]Failed to serialize VolatileWriteCache",
                           "PATH", path);
            }
            break;
        }
        case 0x07:
        {
            google::gbmc::nvme::base::NumberOfQueues msg;
            msg.set_number_of_submission_queues(cdw0 & 0xFFFF);
            msg.set_number_of_completion_queues((cdw0 >> 16) & 0xFFFF);
            protoData.resize(msg.ByteSizeLong());
            if (!msg.SerializeToArray(protoData.data(),
                                      static_cast<int>(protoData.size())))
            {
                lg2::error("[{PATH}]Failed to serialize NumberOfQueues", "PATH",
                           path);
            }
            break;
        }
        case 0x08:
        {
            google::gbmc::nvme::base::InterruptCoalescing msg;
            msg.set_aggregation_threshold(cdw0 & 0xFF);
            msg.set_aggregation_time((cdw0 >> 8) & 0xFF);
            protoData.resize(msg.ByteSizeLong());
            if (!msg.SerializeToArray(protoData.data(),
                                      static_cast<int>(protoData.size())))
            {
                lg2::error("[{PATH}]Failed to serialize Interrupt Coalescing",
                           "PATH", path);
            }
            break;
        }
        case 0x09:
        {
            google::gbmc::nvme::base::InterruptVectorConfiguration msg;
            msg.set_interrupt_vector(cdw0 & 0xFFFF);
            msg.set_coalescing_disable(
                static_cast<google::gbmc::nvme::base::
                                InterruptVectorConfiguration_CoalescingState>(
                    (cdw0 >> 16) & 0x1));
            protoData.resize(msg.ByteSizeLong());
            if (!msg.SerializeToArray(protoData.data(),
                                      static_cast<int>(protoData.size())))
            {
                lg2::error(
                    "[{PATH}]Failed to serialize InterruptVectorConfiguration",
                    "PATH", path);
            }
            break;
        }
        case 0x0A:
        {
            google::gbmc::nvme::base::WriteAtomicityNormal msg;
            msg.set_disable_normal(
                static_cast<google::gbmc::nvme::base::
                                WriteAtomicityNormal_NormalWriteAtomicityState>(
                    cdw0 & 0x1));
            protoData.resize(msg.ByteSizeLong());
            if (!msg.SerializeToArray(protoData.data(),
                                      static_cast<int>(protoData.size())))
            {
                lg2::error("[{PATH}]Failed to serialize WriteAtomicityNormal",
                           "PATH", path);
            }
            break;
        }
        case 0x0B:
        {
            google::gbmc::nvme::base::AsynchronousEventConfiguration msg;
            msg.set_smart_critical_warning_config(cdw0 & 0xFF);
            protoData.resize(msg.ByteSizeLong());
            if (!msg.SerializeToArray(protoData.data(),
                                      static_cast<int>(protoData.size())))
            {
                lg2::error(
                    "[{PATH}]Failed to serialize AsynchronousEventConfiguration",
                    "PATH", path);
            }
            break;
        }
        default:
            break;
    }

    return protoData;
}

void FeatureStore::setFeature(const boost::asio::yield_context& yield,
                              const std::string& featureName,
                              const std::vector<uint8_t>& data)
{
    std::string path = this->objectPath;
    if (!isFeatureSupported(featureName))
    {
        throw sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument();
    }
    size_t lastUnderscore = featureName.find_last_of('_');
    if (lastUnderscore == std::string::npos)
    {
        throw sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument();
    }

    std::string baseName = featureName.substr(0, lastUnderscore);
    std::string selectStr = featureName.substr(lastUnderscore + 1);

    auto it = supportedFeatures.find(baseName);
    if (it == supportedFeatures.end() || it->second.scope != scope)
    {
        throw sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument();
    }

    if (selectStr == "Default")
    {
        // Default endpoint is read-only
        throw sdbusplus::xyz::openbmc_project::Common::Error::NotAllowed();
    }
    if (selectStr != "Current" && selectStr != "Saved")
    {
        throw sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument();
    }

    uint8_t fid = it->second.fid;
    bool save = (selectStr == "Saved");

    auto capIt = featureCaps.find(fid);
    if (capIt != featureCaps.end())
    {
        uint32_t caps = capIt->second;
        bool changeable = (caps & nvmeGetFeaturesCapChangeable) != 0;
        bool saveable = (caps & nvmeGetFeaturesCapSaveable) != 0;

        if (save && !saveable)
        {
            lg2::error(
                "[{PATH}]SetFeature: FID {FID} is not saveable per SEL=011b",
                "PATH", path, "FID", lg2::hex, fid);
            throw sdbusplus::xyz::openbmc_project::Common::Error::NotAllowed();
        }

        if (!save && !changeable)
        {
            lg2::error(
                "[{PATH}]SetFeature: FID {FID} is not changeable per SEL=011b",
                "PATH", path, "FID", lg2::hex, fid);
            throw sdbusplus::xyz::openbmc_project::Common::Error::NotAllowed();
        }
    }

    uint32_t cdw11 = 0;

    switch (fid)
    {
        case 0x01:
        {
            auto msg = parseProto<google::gbmc::nvme::base::Arbitration>(data);
            if (msg.arbitration_burst() > 0xFF ||
                msg.low_priority_weight() > 0xFF ||
                msg.medium_priority_weight() > 0xFF ||
                msg.high_priority_weight() > 0xFF)
            {
                throw sdbusplus::xyz::openbmc_project::Common::Error::
                    InvalidArgument();
            }
            cdw11 = (msg.arbitration_burst() & 0xFF) |
                    ((msg.low_priority_weight() & 0xFF) << 8) |
                    ((msg.medium_priority_weight() & 0xFF) << 16) |
                    ((msg.high_priority_weight() & 0xFF) << 24);
            break;
        }
        case 0x02:
        {
            auto msg =
                parseProto<google::gbmc::nvme::base::PowerManagement>(data);
            if (msg.power_state() > 0x1F || msg.workload_hint() > 0x7)
            {
                throw sdbusplus::xyz::openbmc_project::Common::Error::
                    InvalidArgument();
            }
            cdw11 = (msg.power_state() & 0x1F) |
                    ((msg.workload_hint() & 0x7) << 8);
            break;
        }
        case 0x04:
        {
            auto msg =
                parseProto<google::gbmc::nvme::base::TemperatureThreshold>(
                    data);
            if (msg.temperature_threshold() > 0xFFFF ||
                msg.threshold_temperature_select() > 0xF)
            {
                throw sdbusplus::xyz::openbmc_project::Common::Error::
                    InvalidArgument();
            }
            cdw11 = (msg.temperature_threshold() & 0xFFFF) |
                    ((msg.threshold_temperature_select() & 0xF) << 16) |
                    ((static_cast<uint32_t>(msg.threshold_type_select()) & 0x3)
                     << 20);
            break;
        }
        case 0x05:
        {
            auto msg =
                parseProto<google::gbmc::nvme::base::ErrorRecovery>(data);
            if (msg.tler() > 0xFFFF)
            {
                throw sdbusplus::xyz::openbmc_project::Common::Error::
                    InvalidArgument();
            }
            cdw11 = (msg.tler() & 0xFFFF) |
                    ((static_cast<uint32_t>(msg.dulbe_enable()) & 0x1) << 16);
            break;
        }
        case 0x06:
        {
            auto msg =
                parseProto<google::gbmc::nvme::base::VolatileWriteCache>(data);
            cdw11 = static_cast<uint32_t>(msg.write_cache_enable()) & 0x1;
            break;
        }
        case 0x07:
        {
            auto msg =
                parseProto<google::gbmc::nvme::base::NumberOfQueues>(data);
            if (msg.number_of_submission_queues() > 0xFFFF ||
                msg.number_of_completion_queues() > 0xFFFF)
            {
                throw sdbusplus::xyz::openbmc_project::Common::Error::
                    InvalidArgument();
            }
            cdw11 = (msg.number_of_submission_queues() & 0xFFFF) |
                    ((msg.number_of_completion_queues() & 0xFFFF) << 16);
            break;
        }
        case 0x08:
        {
            auto msg =
                parseProto<google::gbmc::nvme::base::InterruptCoalescing>(data);
            if (msg.aggregation_threshold() > 0xFF ||
                msg.aggregation_time() > 0xFF)
            {
                throw sdbusplus::xyz::openbmc_project::Common::Error::
                    InvalidArgument();
            }
            cdw11 = (msg.aggregation_threshold() & 0xFF) |
                    ((msg.aggregation_time() & 0xFF) << 8);
            break;
        }
        case 0x09:
        {
            auto msg = parseProto<
                google::gbmc::nvme::base::InterruptVectorConfiguration>(data);
            if (msg.interrupt_vector() > 0xFFFF)
            {
                throw sdbusplus::xyz::openbmc_project::Common::Error::
                    InvalidArgument();
            }
            cdw11 = (msg.interrupt_vector() & 0xFFFF) |
                    ((static_cast<uint32_t>(msg.coalescing_disable()) & 0x1)
                     << 16);
            break;
        }
        case 0x0A:
        {
            auto msg =
                parseProto<google::gbmc::nvme::base::WriteAtomicityNormal>(
                    data);
            cdw11 = static_cast<uint32_t>(msg.disable_normal()) & 0x1;
            break;
        }
        case 0x0B:
        {
            auto msg = parseProto<
                google::gbmc::nvme::base::AsynchronousEventConfiguration>(data);
            if (msg.smart_critical_warning_config() > 0xFF)
            {
                throw sdbusplus::xyz::openbmc_project::Common::Error::
                    InvalidArgument();
            }
            cdw11 = msg.smart_critical_warning_config() & 0xFF;
            break;
        }
        default:
            break;
    }

    NVMeMiIntf::SetFeaturesRequest args{};
    args.fid = fid;
    args.save = save;
    args.cdw11 = cdw11;
    args.nsid = (scope == FeatureScope::Namespace) ? nsid : NVME_NSID_NONE;
    args.data = {};

    auto [ex, resp] = asyncAdminSetFeatures(io, nvmeIntf, ctrl, args, yield);

    if (ex)
    {
        lg2::error("[{PATH}]NVMe Set Features (FID {FID}) failed: {ERROR}",
                   "PATH", path, "FID", fid, "ERROR", ex->what());
        throw sdbusplus::xyz::openbmc_project::Common::Error::Unavailable();
    }
}
