#include "NVMeController.hpp"

#include "dbus-sensor_config.h"

#include "AsioHelper.hpp"
#include "NVMeCacheImpl.hpp"
#include "NVMeError.hpp"
#include "NVMePlugin.hpp"
#include "NVMeSubsys.hpp"
#include "Utils.hpp"

#include <boost/asio/async_result.hpp>
#include <boost/asio/spawn.hpp>
#include <phosphor-logging/lg2.hpp>
#include <sdbusplus/exception.hpp>
#include <sdbusplus/message/native_types.hpp>
#include <xyz/openbmc_project/Common/File/error.hpp>
#include <xyz/openbmc_project/Common/error.hpp>

#include <cstdint>
#include <cstdio>
#include <filesystem>
#include <fstream>
#include <system_error>
#include <tuple>
#include <vector>

// using sdbusplus::xyz::openbmc_project::Inventory::Item::server::
//     StorageController;
using sdbusplus::xyz::openbmc_project::NVMe::server::NVMeAdmin;
using SchedulerClockType = std::chrono::steady_clock;

constexpr uint32_t kMinNvmeVerLogLid00hSupport = 0x020000;
constexpr int kDiscoverLogsMaxRetries =
    6; // exponentially backoff ~6.3s (100ms to 3.2s)
constexpr int kDiscoverLogsBaseBackoffMs = 100;
constexpr uint64_t kDefaultDA1IntervalSeconds = 60;
constexpr uint64_t kDefaultDAIntervalSeconds = 86400;

inline std::optional<std::string> findPluginName(const SensorData& config)
{
    // find base configuration
    auto sensorBase = config.find(configInterfaceName(nvme::sensorType));
    if (sensorBase == config.end())
    {
        return {};
    }
    const SensorBaseConfigMap& sensorConfig = sensorBase->second;
    auto findPlugin = sensorConfig.find("Plugin");
    if (findPlugin == sensorConfig.end())
    {
        return std::nullopt;
    }
    return std::get<std::string>(findPlugin->second);
}

inline std::vector<std::string> findHostInitiatedLog(const SensorData& config)
{
    auto sensorBase = config.find(configInterfaceName(nvme::sensorType));
    if (sensorBase == config.end())
    {
        return {};
    }
    const SensorBaseConfigMap& sensorConfig = sensorBase->second;
    auto findHostInitLog = sensorConfig.find("HostInitiatedLog");
    if (findHostInitLog == sensorConfig.end())
    {
        return {};
    }
    if (std::holds_alternative<std::vector<std::string>>(
            findHostInitLog->second))
    {
        return std::get<std::vector<std::string>>(findHostInitLog->second);
    }
    return {};
}

inline std::optional<uint64_t> findDAPollingRate(const SensorData& config,
                                                 const std::string& key)
{
    auto sensorBase = config.find(configInterfaceName(nvme::sensorType));
    if (sensorBase == config.end())
    {
        return {};
    }
    const SensorBaseConfigMap& sensorConfig = sensorBase->second;
    auto findRate = sensorConfig.find(key);
    if (findRate == sensorConfig.end())
    {
        return {};
    }

    if (std::holds_alternative<uint64_t>(findRate->second))
    {
        return std::get<uint64_t>(findRate->second);
    }
    if (std::holds_alternative<double>(findRate->second))
    {
        return static_cast<uint64_t>(std::get<double>(findRate->second));
    }
    if (std::holds_alternative<uint32_t>(findRate->second))
    {
        return std::get<uint32_t>(findRate->second);
    }

    return {};
}

std::shared_ptr<NVMeControllerEnabled>
    NVMeControllerEnabled::create(NVMeController&& nvmeController)
{
    auto self = std::shared_ptr<NVMeControllerEnabled>(
        new NVMeControllerEnabled(std::move(nvmeController)));
    self->init();
    return self;
}

NVMeControllerEnabled::NVMeControllerEnabled(NVMeController&& nvmeController) :
    NVMeController(nvmeController),
    NVMeAdmin(*this->NVMeController::conn, this->NVMeController::path.c_str(),
              {{"FirmwareCommitStatus", {FwCommitStatus::Ready}},
               {"FirmwareDownloadStatus", {FwDownloadStatus::Ready}}}),
    SoftwareExtVersion(dynamic_cast<sdbusplus::bus_t&>(*conn), path.c_str()),
    SoftwareVersion(dynamic_cast<sdbusplus::bus_t&>(*conn), path.c_str())
{}

void NVMeControllerEnabled::init()
{
    createAssociation();

    passthruInterface =
        objServer.add_interface(path, "xyz.openbmc_project.NVMe.Passthru");

    passthruInterface->register_method(
        "AdminNonDataCmd",
        [selfWeak{weak_from_this()}](
            boost::asio::yield_context yield, uint8_t opcode, uint32_t cdw1,
            uint32_t cdw2, uint32_t cdw3, uint32_t cdw10, uint32_t cdw11,
            uint32_t cdw12, uint32_t cdw13, uint32_t cdw14, uint32_t cdw15) {
        auto self = selfWeak.lock();
        if (!self)
        {
            checkLibNVMeError(std::make_error_code(std::errc::no_such_device),
                              -1, "AdminNonDataCmd");
            return std::tuple<uint32_t, uint32_t, uint32_t>{0, 0, 0};
        }

        if (self->status != Status::Enabled)
        {
            lg2::error("[{PATH}]Controller has been disabled", "PATH",
                       self->path);
            throw sdbusplus::xyz::openbmc_project::Common::Error::Unavailable();
        }
        return self->adminNonDataCmdMethod(std::move(yield), opcode, cdw1, cdw2,
                                           cdw3, cdw10, cdw11, cdw12, cdw13,
                                           cdw14, cdw15);
    });
    passthruInterface->initialize();

    securityInterface = objServer.add_interface(
        path, "xyz.openbmc_project.Inventory.Item.StorageControllerSecurity");
    securityInterface->register_method(
        "SecuritySend", [selfWeak{weak_from_this()}](
                            boost::asio::yield_context yield, uint8_t proto,
                            uint16_t protoSpecific, std::vector<uint8_t> data) {
        auto self = selfWeak.lock();
        if (!self)
        {
            checkLibNVMeError(std::make_error_code(std::errc::no_such_device),
                              -1, "SecuritySend");
            return;
        }

        if (self->status != Status::Enabled)
        {
            lg2::error("[{PATH}]Controller has been disabled", "PATH",
                       self->path);
            throw sdbusplus::xyz::openbmc_project::Common::Error::Unavailable();
        }

        return self->securitySendMethod(std::move(yield), proto, protoSpecific,
                                        data);
    });
    securityInterface->register_method(
        "SecurityReceive",
        [selfWeak{weak_from_this()}](boost::asio::yield_context yield,
                                     uint8_t proto, uint16_t protoSpecific,
                                     uint32_t transferLength) {
        auto self = selfWeak.lock();
        if (!self)
        {
            checkLibNVMeError(std::make_error_code(std::errc::no_such_device),
                              -1, "SecurityReceive");
            return std::vector<uint8_t>{};
        }

        if (self->status != Status::Enabled)
        {
            lg2::error("[{PATH}]Controller has been disabled", "PATH",
                       self->path);
            throw sdbusplus::xyz::openbmc_project::Common::Error::Unavailable();
        }

        return self->securityReceiveMethod(std::move(yield), proto,
                                           protoSpecific, transferLength);
    });

    if (this->featureLockdownEnabled)
    {
        lockdownInterface =
            objServer.add_interface(path, "xyz.openbmc_project.NVMe.Lockdown");

        lockdownInterface->register_method(
            "LockdownInband",
            [selfWeak{weak_from_this()}](boost::asio::yield_context yield,
                                         uint8_t prohibit,
                                         const std::vector<uint8_t>& adminCmds,
                                         const std::vector<uint8_t>& features,
                                         const std::vector<uint8_t>& logPages) {
            auto self = selfWeak.lock();
            if (!self)
            {
                checkLibNVMeError(
                    std::make_error_code(std::errc::no_such_device), -1,
                    "LockdownInband");
                return std::tuple<uint32_t, uint32_t, uint32_t, std::string,
                                  uint32_t>{0, 0, 0, "", 0};
            }

            if (self->status != Status::Enabled)
            {
                lg2::error("[{PATH}]Controller has been disabled", "PATH",
                           self->path);
                throw sdbusplus::xyz::openbmc_project::Common::Error::
                    Unavailable();
            }

            return self->lockdownInbandMethod(std::move(yield), prohibit,
                                              adminCmds, features, logPages);
        });
        lockdownInterface->initialize();
    }

    // StorageController interface is implemented manually to allow
    // async methods
    ctrlInterface = objServer.add_interface(
        path, "xyz.openbmc_project.Inventory.Item.StorageController");
    ctrlInterface->register_method(
        "AttachVolume", [selfWeak{weak_from_this()}](
                            boost::asio::yield_context yield,
                            const sdbusplus::message::object_path& volPath) {
        auto self = selfWeak.lock();
        if (!self)
        {
            checkLibNVMeError(std::make_error_code(std::errc::no_such_device),
                              -1, "SecurityReceive");
            return;
        }

        if (self->status != Status::Enabled)
        {
            lg2::error("[{PATH}]Controller has been disabled", "PATH",
                       self->path);
            throw sdbusplus::xyz::openbmc_project::Common::Error::Unavailable();
        }

        return self->attachVolume(std::move(yield), volPath);
    });
    ctrlInterface->register_method(
        "DetachVolume", [selfWeak{weak_from_this()}](
                            boost::asio::yield_context yield,
                            const sdbusplus::message::object_path& volPath) {
        auto self = selfWeak.lock();
        if (!self)
        {
            checkLibNVMeError(std::make_error_code(std::errc::no_such_device),
                              -1, "SecurityReceive");
            return;
        }

        if (self->status != Status::Enabled)
        {
            lg2::error("[{PATH}]Controller has been disabled", "PATH",
                       self->path);
            throw sdbusplus::xyz::openbmc_project::Common::Error::Unavailable();
        }

        return self->detachVolume(std::move(yield), volPath);
    });

    ctrlInterface->initialize();

    securityInterface->initialize();
    // StorageController::emit_added();

    NVMeAdmin::emit_added();
    SoftwareExtVersion::emit_added();
    SoftwareVersion::emit_added();
}

void NVMeControllerEnabled::initializeMetricStore()
{
    // if metric store feature is disabled then create empty metric store
    // the dbus interface will be there but with no metrics
    if (!isMetricStoreEnabled())
    {
        this->metricStore.emplace(this->NVMeController::io,
                                  this->NVMeController::conn,
                                  this->NVMeController::path);
        return;
    }

    lg2::info("[{PATH}] NVMe version for controller: {VERSION}", "PATH", path,
              "VERSION", lg2::hex, nvmeVersion);

    discoverSupportedLogPages();
}

void NVMeControllerEnabled::populateMetricStore()
{
    auto scheduler = Scheduler<SchedulerClockType>::getScheduler(path);

    using IdentifyMetric =
        IdentifyMetric<NVME_IDENTIFY_CNS_CTRL, SchedulerClockType>;

    using ErrorInfoMetric =
        ControllerLogPageMetric<NVME_LOG_LID_ERROR, SchedulerClockType>;
    using SMARTMetric =
        ControllerLogPageMetric<NVME_LOG_LID_SMART, SchedulerClockType>;
    using FwSlotMetric =
        ControllerLogPageMetric<NVME_LOG_LID_FW_SLOT, SchedulerClockType>;
    using SelfTestMetric =
        ControllerLogPageMetric<NVME_LOG_LID_DEVICE_SELF_TEST,
                                SchedulerClockType>;
    using HostTelemetryMetric =
        ControllerLogPageMetric<NVME_LOG_LID_TELEMETRY_HOST,
                                SchedulerClockType>;
    using HostTelemetryMetricDA1 =
        ControllerLogPageMetric<NVME_LOG_LID_TELEMETRY_HOST, SchedulerClockType,
                                1>;
    using HostTelemetryMetricDA2 =
        ControllerLogPageMetric<NVME_LOG_LID_TELEMETRY_HOST, SchedulerClockType,
                                2>;
    using HostTelemetryMetricDA3 =
        ControllerLogPageMetric<NVME_LOG_LID_TELEMETRY_HOST, SchedulerClockType,
                                3>;
    using HostTelemetryMetricDA4 =
        ControllerLogPageMetric<NVME_LOG_LID_TELEMETRY_HOST, SchedulerClockType,
                                4>;
    using LockdownMetric =
        ControllerLogPageMetric<NVME_LOG_LID_CMD_AND_FEAT_LOCKDOWN,
                                SchedulerClockType>;

    auto defaultLogpageRefreshDuration =
        std::chrono::duration_cast<SchedulerClockType::duration>(
            std::chrono::seconds(60));

    auto identify = std::make_shared<IdentifyMetric>(
        shared_from_this(), scheduler,
        // Mitigate solution before Knuckle FW fix for b/404610159
        defaultLogpageRefreshDuration);

    std::list<std::shared_ptr<MetricBase<SchedulerClockType>>> metrics;
    metrics.push_back(identify);

    // Standard core metrics are statically supported across all NVMe versions
    metrics.push_back(std::make_shared<ErrorInfoMetric>(
        this->weak_from_this(), scheduler, defaultLogpageRefreshDuration));
    metrics.push_back(std::make_shared<SMARTMetric>(
        this->weak_from_this(), scheduler, defaultLogpageRefreshDuration));
    metrics.push_back(std::make_shared<FwSlotMetric>(
        this->weak_from_this(), scheduler, defaultLogpageRefreshDuration));
    metrics.push_back(std::make_shared<SelfTestMetric>(
        this->weak_from_this(), scheduler, defaultLogpageRefreshDuration));

    auto pluginName = findPluginName(config);
    bool isOcp = pluginName == "OCP";
    auto hostInitLog = findHostInitiatedLog(config);

    if (!isOcp)
    {
        metrics.push_back(std::make_shared<HostTelemetryMetric>(
            this->weak_from_this(), scheduler,
            std::chrono::duration_cast<SchedulerClockType::duration>(
                std::chrono::seconds(900))));
    }

    for (const auto& dataArea : hostInitLog)
    {
        std::string configKey = "HostInitiatedLog" + dataArea + "Interval";
        auto rateOpt = findDAPollingRate(config, configKey);
        uint64_t durationSec = rateOpt.value_or(0);
        if (durationSec == 0)
        {
            durationSec = (dataArea == "DA1") ? kDefaultDA1IntervalSeconds
                                              : kDefaultDAIntervalSeconds;
        }

        if (dataArea == "DA1")
        {
            lg2::debug("{PATH}: applied polling interval {DURATION}s for DA1",
                       "PATH", path, "DURATION", durationSec);
            metrics.push_back(std::make_shared<HostTelemetryMetricDA1>(
                this->weak_from_this(), scheduler,
                std::chrono::duration_cast<SchedulerClockType::duration>(
                    std::chrono::seconds(durationSec))));
        }
        else if (dataArea == "DA2")
        {
            lg2::debug("{PATH}: applied polling interval {DURATION}s for DA2",
                       "PATH", path, "DURATION", durationSec);
            metrics.push_back(std::make_shared<HostTelemetryMetricDA2>(
                this->weak_from_this(), scheduler,
                std::chrono::duration_cast<SchedulerClockType::duration>(
                    std::chrono::seconds(durationSec))));
        }
        else if (dataArea == "DA3")
        {
            lg2::debug("{PATH}: applied polling interval {DURATION}s for DA3",
                       "PATH", path, "DURATION", durationSec);
            metrics.push_back(std::make_shared<HostTelemetryMetricDA3>(
                this->weak_from_this(), scheduler,
                std::chrono::duration_cast<SchedulerClockType::duration>(
                    std::chrono::seconds(durationSec))));
        }
        else if (dataArea == "DA4")
        {
            lg2::debug("{PATH}: applied polling interval {DURATION}s for DA4",
                       "PATH", path, "DURATION", durationSec);
            metrics.push_back(std::make_shared<HostTelemetryMetricDA4>(
                this->weak_from_this(), scheduler,
                std::chrono::duration_cast<SchedulerClockType::duration>(
                    std::chrono::seconds(durationSec))));
        }
    }

    // Command Lockdown (Log Page 14h) is dynamically registered only on
    // NVMe 2.0+ controllers that explicitly report support via Supported Log
    // Pages (00h) check.
    if (isLogPageSupported(NVME_LOG_LID_CMD_AND_FEAT_LOCKDOWN))
    {
        metrics.push_back(std::make_shared<LockdownMetric>(
            this->weak_from_this(), scheduler, defaultLogpageRefreshDuration));
    }

    this->metricStore.emplace(
        this->NVMeController::io, this->NVMeController::conn,
        this->NVMeController::path, metrics.begin(), metrics.end());
}

void NVMeControllerEnabled::discoverSupportedLogPages()
{
    if (nvmeVersion < kMinNvmeVerLogLid00hSupport)
    {
        populateMetricStore();
        return;
    }

    lg2::info(
        "[{PATH}] Querying Supported Log Pages (00h) for NVMe 2.0+ controller",
        "PATH", path);

    discoverLogsToken = std::make_shared<bool>();
    std::weak_ptr<bool> weakToken = discoverLogsToken;

    fetchSupportedLogPages(0, weakToken);
}

void NVMeControllerEnabled::fetchSupportedLogPages(
    int retryCount, const std::weak_ptr<bool>& weakToken)
{
    std::weak_ptr<NVMeControllerEnabled> weakSelf = weak_from_this();

    nvmeIntf->adminGetLogPage(
        nvmeCtrl, NVME_LOG_LID_SUPPORTED_LOG_PAGES, NVME_NSID_NONE, 0, 0,
        [weakSelf, retryCount, weakToken, path = this->path](
            const std::error_code& ec, std::span<uint8_t> data) mutable {
        auto self = weakSelf.lock();
        if (!self || weakToken.expired())
        {
            lg2::info(
                "[{PATH}]Skipping fetchSupportedLogPages as token expired "
                "or controller destroyed",
                "PATH", path);
            return;
        }

        if (ec)
        {
            if (retryCount < kDiscoverLogsMaxRetries)
            {
                // Adaptive timer: exponential backoff
                int discoverLogsBackoffMs = kDiscoverLogsBaseBackoffMs
                                            << retryCount;
                self->discoverLogsRetryTimer =
                    std::make_shared<boost::asio::steady_timer>(self->io);
                self->discoverLogsRetryTimer->expires_after(
                    std::chrono::milliseconds(discoverLogsBackoffMs));
                self->discoverLogsRetryTimer->async_wait(
                    [weakSelf, retryCount, weakToken,
                     path](const boost::system::error_code& timerEc) {
                    auto self = weakSelf.lock();
                    if (!self || weakToken.expired() ||
                        timerEc == boost::asio::error::operation_aborted)
                    {
                        lg2::info(
                            "[{PATH}]Skipping fetchSupportedLogPages as token "
                            "expired or timer canceled or controller "
                            "destroyed",
                            "PATH", path);
                        return; // Destructed or cancelled naturally!
                    }
                    self->fetchSupportedLogPages(retryCount + 1, weakToken);
                });
                return;
            }

            lg2::error(
                "[{PATH}] Failed to get Supported Log Pages (00h): {ERROR}",
                "PATH", path, "ERROR", ec.message());
            self->supportedLogPages.clear();
            self->populateMetricStore();
            return;
        }

        if (data.size() < 1024)
        {
            lg2::error(
                "[{PATH}] Undersized Supported Log Pages payload ({SIZE} bytes)",
                "PATH", path, "SIZE", data.size());
            self->supportedLogPages.clear();
            self->populateMetricStore();
            return;
        }

        self->supportedLogPages.assign(data.begin(), data.end());
        self->populateMetricStore();
    });
}

void NVMeControllerEnabled::initializeFeatureStore()
{
    if (featureStore)
    {
        return;
    }

    this->featureStore =
        std::make_shared<FeatureStore>(io, objServer, conn, path, nvmeIntf,
                                       nvmeCtrl, 0, FeatureScope::Controller);

    this->featureStore->init([path = this->path](const std::error_code& ec) {
        if (ec)
        {
            lg2::error("[{PATH}]Failed to initialize feature store: {ERROR}",
                       "PATH", path, "ERROR", ec.message());
        }
    });
}
void NVMeControllerEnabled::start(
    const std::shared_ptr<NVMeControllerPlugin>& nvmePlugin)
{
    this->NVMeController::start(nvmePlugin);

    status = Status::Enabled;

    if (isPrimary)
    {
        this->initializeMetricStore();
        this->initializeFeatureStore();
    }
}

void NVMeControllerEnabled::stop()
{
    status = Status::Disabled;

    // Resetting the discovery token here instantly revokes it, guaranteeing
    // that any stale async callbacks from fetchSupportedLogPages still pending
    // in the ASIO queue are invalidated upon execution.
    discoverLogsToken.reset();
    this->metricStore.reset();
    if (discoverLogsRetryTimer)
    {
        discoverLogsRetryTimer->cancel();
    }
    this->featureStore.reset();
}

void NVMeController::createAssociation()
{
    assocIntf = objServer.add_interface(path, association::interface);
    assocIntf->register_property("Associations", makeAssociation());
    assocIntf->initialize();
}

void NVMeController::updateAssociation()
{
    if (assocIntf)
    {
        assocIntf->set_property("Associations", makeAssociation());
    }
}

std::vector<Association> NVMeController::makeAssociation() const
{
    std::vector<Association> associations;
    std::filesystem::path p(path);

    auto s = subsys.lock();
    if (!s)
    {
        lg2::error("[{PATH}]makeAssociation() after shutdown", "PATH", path);
        return associations;
    }

    associations.emplace_back("storage", "storage_controller", s->path);

    for (const auto& cntrl : secondaryControllers)
    {
        associations.emplace_back("secondary", "primary", cntrl);
    }

    for (uint32_t nsid : s->attachedVolumes(getCntrlId()))
    {
        auto p = s->volumePath(nsid);
        associations.emplace_back("attaching", "attached", p);
    }

    return associations;
}

sdbusplus::message::unix_fd NVMeControllerEnabled::getLogPage(uint8_t lid,
                                                              uint32_t nsid,
                                                              uint8_t lsp,
                                                              uint16_t lsi)
{
    if (status != Status::Enabled)
    {
        lg2::error("[{PATH}]Controller has been disabled", "PATH", path);
        throw sdbusplus::xyz::openbmc_project::Common::Error::Unavailable();
    }

    std::array<int, 2> pipe{};
    if (::pipe(pipe.data()) < 0)
    {
        lg2::error("[{PATH}]GetLogPage fails to open pipe: {ERROR}", "PATH",
                   path, "ERROR", strerror(errno));
        throw sdbusplus::xyz::openbmc_project::Common::File::Error::Open();
    }

    // standard NVMe Log IDs
    if (lid < uint8_t{0xC0})
    {
        nvmeIntf->adminGetLogPage(
            nvmeCtrl, static_cast<nvme_cmd_get_log_lid>(lid), nsid, lsp, lsi,
            [pipe, &io = this->io, path = this->path](const std::error_code& ec,
                                                      std::span<uint8_t> data) {
            if (ec)
            {
                lg2::error("[{PATH}]fail to GetLogPage: {ERROR}", "PATH", path,
                           "ERROR", ec.message());
                close(pipe[1]);
                close(pipe[0]);
                return;
            }

            // async write to pipe
            auto asyncPipe =
                std::make_shared<boost::asio::posix::stream_descriptor>(
                    io, pipe[1]);
            std::weak_ptr<boost::asio::posix::stream_descriptor> weakPipe =
                asyncPipe;

            auto asyncBuffer = std::make_shared<std::vector<uint8_t>>(
                data.begin(), data.end());
            boost::asio::async_write(*asyncPipe,
                                     boost::asio::buffer(*asyncBuffer),
                                     [asyncPipe, asyncBuffer, path](
                                         const boost::system::error_code& error,
                                         std::size_t /* transferredSize */) {
                if (error)
                {
                    lg2::error("[{PATH}]GetLogPage fails to write fd: {ERROR}",
                               "PATH", path, "ERROR", error.message());
                }
            });

            // set a timer of 5 second for the client to read the telemetry.
            auto timer = std::make_shared<boost::asio::steady_timer>(io);
            timer->expires_after(std::chrono::seconds(5));
            timer->async_wait([timer, fd{pipe[0]}, weakPipe](
                                  const boost::system::error_code& /* ec */) {
                auto pipe = weakPipe.lock();
                if (pipe)
                {
                    pipe->cancel();
                }
                close(fd);
            });
        });
    }
    // vendor Log IDs
    else if (!plugin.expired())
    {
        auto nvmePlugin = plugin.lock();
        auto handler = nvmePlugin->getGetLogPageHandler();
        if (handler)
        {
            std::function<void(const std::error_code&, std::span<uint8_t>)> cb =
                [pipe, &io = this->io, path = this->path](
                    std::error_code ec, std::span<uint8_t> data) {
                if (ec)
                {
                    lg2::error("[{PATH}]fail to GetLogPage: {ERROR}", "PATH",
                               path, "ERROR", ec.message());
                    close(pipe[1]);
                    close(pipe[0]);
                    return;
                }

                // async write to pipe
                auto asyncPipe =
                    std::make_shared<boost::asio::posix::stream_descriptor>(
                        io, pipe[1]);
                std::weak_ptr<boost::asio::posix::stream_descriptor> weakPipe =
                    asyncPipe;

                auto asyncBuffer = std::make_shared<std::vector<uint8_t>>(
                    data.begin(), data.end());
                boost::asio::async_write(
                    *asyncPipe, boost::asio::buffer(*asyncBuffer),
                    [asyncPipe, asyncBuffer,
                     path](const boost::system::error_code& error,
                           std::size_t /* transferredSize */) {
                    if (error)
                    {
                        lg2::error(
                            "[{PATH}]GetLogPage fails to write fd: {ERROR}",
                            "PATH", path, "ERROR", error.message());
                    }
                });

                // set a timer of 5 second for the client to read the telemetry.
                auto timer = std::make_shared<boost::asio::steady_timer>(io);
                timer->expires_after(std::chrono::seconds(5));
                timer->async_wait(
                    [timer, fd{pipe[0]},
                     weakPipe](const boost::system::error_code& /* ec */) {
                    auto pipe = weakPipe.lock();
                    if (pipe)
                    {
                        pipe->cancel();
                    }
                    close(fd);
                });
            };
            handler(lid, nsid, lsp, lsi, std::move(cb));
        }
        else // No VU LogPage handler
        {
            close(pipe[1]);
            close(pipe[0]);
            throw sdbusplus::xyz::openbmc_project::Common::Error::
                InvalidArgument();
        }
    }
    else // No VU plugin
    {
        close(pipe[0]);
        close(pipe[1]);
        throw sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument();
    }
    return sdbusplus::message::unix_fd{pipe[0]};
}

sdbusplus::message::unix_fd
    NVMeControllerEnabled::identify(uint8_t cns, uint32_t nsid, uint16_t cntid)
{
    if (status != Status::Enabled)
    {
        lg2::error("[{PATH}]Controller has been disabled", "PATH", path);
        throw sdbusplus::xyz::openbmc_project::Common::Error::Unavailable();
    }

    std::array<int, 2> pipe{};
    if (::pipe(pipe.data()) < 0)
    {
        lg2::error("[{PATH}]Identify fails to open pipe: {ERROR}", "PATH", path,
                   "ERROR", strerror(errno));
        throw sdbusplus::xyz::openbmc_project::Common::File::Error::Open();
    }

    nvmeIntf->adminIdentify(
        nvmeCtrl, static_cast<nvme_identify_cns>(cns), nsid, cntid,
        [pipe, &io = this->io, path = this->path](const nvme_ex_ptr& ex,
                                                  std::span<uint8_t> data) {
        if (ex)
        {
            lg2::error("[{PATH}]fail to Identify: {ERROR}", "PATH", path,
                       "ERROR", ex->what());
            close(pipe[1]);
            close(pipe[0]);
            return;
        }

        // async write to pipe
        auto asyncPipe =
            std::make_shared<boost::asio::posix::stream_descriptor>(io,
                                                                    pipe[1]);
        std::weak_ptr<boost::asio::posix::stream_descriptor> weakPipe =
            asyncPipe;

        auto asyncBuffer = std::make_shared<std::vector<uint8_t>>(data.begin(),
                                                                  data.end());
        boost::asio::async_write(*asyncPipe, boost::asio::buffer(*asyncBuffer),
                                 [asyncPipe, asyncBuffer,
                                  path](const boost::system::error_code& error,
                                        std::size_t /* transferredSize */) {
            if (error)
            {
                lg2::error("[{PATH}]Identify fails to write fd: {ERROR}",
                           "PATH", path, "ERROR", error.message());
            }
        });

        // set a timer of 5 second for the client to read the telemetry.
        auto timer = std::make_shared<boost::asio::steady_timer>(io);
        timer->expires_after(std::chrono::seconds(5));
        timer->async_wait([timer, fd{pipe[0]}, weakPipe](
                              const boost::system::error_code& /* ec */) {
            auto pipe = weakPipe.lock();
            if (pipe)
            {
                pipe->cancel();
            }
            close(fd);
        });
    });
    return sdbusplus::message::unix_fd{pipe[0]};
}

NVMeAdmin::FwCommitStatus NVMeControllerEnabled::firmwareCommitStatus(
    NVMeAdmin::FwCommitStatus status)
{
    auto commitStatus = this->NVMeAdmin::firmwareCommitStatus();
    // The function is only allowed to reset the status back to ready
    if (status != FwCommitStatus::Ready ||
        commitStatus == FwCommitStatus::Ready ||
        commitStatus == FwCommitStatus::InProgress)
    {
        throw sdbusplus::xyz::openbmc_project::Common::Error::NotAllowed{};
    }
    return this->NVMeAdmin::firmwareCommitStatus(status);
}

void NVMeControllerEnabled::firmwareCommitAsync(uint8_t commitAction,
                                                uint8_t firmwareSlot, bool bpid)
{
    auto commitStatus = this->NVMeAdmin::firmwareCommitStatus();
    if (commitStatus != FwCommitStatus::Ready)
    {
        throw sdbusplus::xyz::openbmc_project::Common::Error::NotAllowed();
    }

    if (status != Status::Enabled)
    {
        lg2::error("[{PATH}]Controller has been disabled", "PATH", path);
        throw sdbusplus::xyz::openbmc_project::Common::Error::Unavailable();
    }

    this->NVMeAdmin::firmwareCommitStatus(FwCommitStatus::InProgress);
    nvmeIntf->adminFwCommit(
        nvmeCtrl, static_cast<nvme_fw_commit_ca>(commitAction & 0b111),
        firmwareSlot, bpid,
        [self{shared_from_this()}, path = this->path](
            const std::error_code& ec, nvme_status_field status) {
        if (ec)
        {
            lg2::error("[{PATH}]firmware commit failed: {ERROR}", "PATH", path,
                       "ERROR", ec.message());
            self->NVMeAdmin::firmwareCommitStatus(FwCommitStatus::Failed);
            return;
        }
        if (status != NVME_SC_SUCCESS)
        {
            lg2::error(
                "[{PATH}]firmware commit status is not success: {STATUS}",
                "PATH", path, "STATUS", status);
            self->NVMeAdmin::firmwareCommitStatus(FwCommitStatus::RequireReset);
            return;
        }

        self->NVMeAdmin::firmwareCommitStatus(FwCommitStatus::Success);
    });
}

NVMeAdmin::FwDownloadStatus NVMeControllerEnabled::firmwareDownloadStatus(
    NVMeAdmin::FwDownloadStatus status)
{
    auto downloadStatus = this->NVMeAdmin::firmwareDownloadStatus();
    // The function is only allowed to reset the status back to ready
    if (status != FwDownloadStatus::Ready ||
        downloadStatus == FwDownloadStatus::Ready ||
        downloadStatus == FwDownloadStatus::InProgress)
    {
        throw sdbusplus::xyz::openbmc_project::Common::Error::NotAllowed{};
    }
    return this->NVMeAdmin::firmwareDownloadStatus(status);
}

void NVMeControllerEnabled::firmwareDownloadAsync(std::string pathToImage)
{
    auto downloadStatus = this->NVMeAdmin::firmwareDownloadStatus();
    if (downloadStatus != FwDownloadStatus::Ready)
    {
        throw sdbusplus::xyz::openbmc_project::Common::Error::NotAllowed();
    }
    if (std::filesystem::exists(pathToImage))
    {
        this->NVMeAdmin::firmwareDownloadStatus(FwDownloadStatus::InProgress);
        nvmeIntf->adminFwDownload(
            nvmeCtrl, pathToImage,
            [self{shared_from_this()}](const std::error_code& ec,
                                       nvme_status_field status) {
            if (ec || status != NVME_SC_SUCCESS)
            {
                self->NVMeAdmin::firmwareDownloadStatus(
                    FwDownloadStatus::Failed);
                return;
            }
            self->NVMeAdmin::firmwareDownloadStatus(FwDownloadStatus::Success);
        });
    }
    else
    {
        throw sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument();
    }
}

NVMeControllerEnabled::~NVMeControllerEnabled()
{
    if (discoverLogsRetryTimer)
    {
        discoverLogsRetryTimer->cancel();
    }
    objServer.remove_interface(securityInterface);
    objServer.remove_interface(passthruInterface);
    if (lockdownInterface)
    {
        objServer.remove_interface(lockdownInterface);
    }
    SoftwareVersion::emit_removed();
    SoftwareExtVersion::emit_removed();
    NVMeAdmin::emit_removed();
    // StorageController::emit_removed();
    objServer.remove_interface(ctrlInterface);
}

NVMeController::NVMeController(
    boost::asio::io_context& io, sdbusplus::asio::object_server& objServer,
    std::shared_ptr<sdbusplus::asio::connection> conn, std::string path,
    const SensorData& configData, std::shared_ptr<NVMeMiIntf> nvmeIntf,
    nvme_mi_ctrl_t ctrl, std::weak_ptr<NVMeSubsystem> subsys,
    bool enableFeatureLockdown) :
    isPrimary(true), io(io), objServer(objServer), conn(std::move(conn)),
    path(std::move(path)), config(configData), nvmeIntf(std::move(nvmeIntf)),
    nvmeCtrl(ctrl), subsys(std::move(subsys)),
    featureLockdownEnabled(enableFeatureLockdown)
{}

NVMeController::~NVMeController()
{
    objServer.remove_interface(assocIntf);
}

void NVMeController::start(
    const std::shared_ptr<NVMeControllerPlugin>& nvmePlugin)
{
    plugin = nvmePlugin;
}

void NVMeController::stop() {}

void NVMeController::setSecAssoc(
    const std::vector<std::shared_ptr<NVMeController>>& secCntrls)
{
    secondaryControllers.clear();

    if (secCntrls.empty())
    {
        return;
    }

    for (const auto& cntrl : secCntrls)
    {
        secondaryControllers.push_back(cntrl->path);
    }
    updateAssociation();
}

void NVMeControllerEnabled::securitySendMethod(boost::asio::yield_context yield,
                                               uint8_t proto,
                                               uint16_t protoSpecific,
                                               std::span<uint8_t> data)
{
    if (status != Status::Enabled)
    {
        lg2::error("[{PATH}]Controller has been disabled", "PATH", path);
        throw sdbusplus::xyz::openbmc_project::Common::Error::Unavailable();
    }

    using callback_t = void(std::tuple<std::error_code, int>);
    auto [err, nvmeStatus] =
        boost::asio::async_initiate<boost::asio::yield_context, callback_t>(
            [intf{nvmeIntf}, ctrl{nvmeCtrl}, proto, protoSpecific,
             &data](auto&& handler) {
        auto h = asio_helper::CopyableCallback(
            std::forward<decltype(handler)>(handler));

        intf->adminSecuritySend(
            ctrl, proto, protoSpecific, data,
            [h](const std::error_code& err, int nvmeStatus) mutable {
            h(std::make_tuple(err, nvmeStatus));
        });
    },
            yield);

    // exception must be thrown outside of the async block
    checkLibNVMeError(err, nvmeStatus, "SecuritySend");
}

std::vector<uint8_t> NVMeControllerEnabled::securityReceiveMethod(
    boost::asio::yield_context yield, uint8_t proto, uint16_t protoSpecific,
    uint32_t transferLength)
{
    if (status != Status::Enabled)
    {
        lg2::error("[{PATH}]Controller has been disabled", "PATH", path);
        throw sdbusplus::xyz::openbmc_project::Common::Error::Unavailable();
    }

    using callback_t =
        void(std::tuple<std::error_code, int, std::vector<uint8_t>>);
    auto [err, nvmeStatus, data] =
        boost::asio::async_initiate<boost::asio::yield_context, callback_t>(
            [intf{nvmeIntf}, ctrl{nvmeCtrl}, proto, protoSpecific,
             transferLength](auto&& handler) {
        auto h = asio_helper::CopyableCallback(
            std::forward<decltype(handler)>(handler));

        intf->adminSecurityReceive(ctrl, proto, protoSpecific, transferLength,
                                   [h](const std::error_code& err,
                                       int nvmeStatus,
                                       std::span<uint8_t> data) mutable {
            std::vector<uint8_t> d(data.begin(), data.end());
            h(std::make_tuple(err, nvmeStatus, d));
        });
    },
            yield);

    // exception must be thrown outside of the async block
    checkLibNVMeError(err, nvmeStatus, "SecurityReceive");
    return data;
}

std::tuple<uint32_t, uint32_t, uint32_t>
    NVMeControllerEnabled::adminNonDataCmdMethod(
        boost::asio::yield_context yield, uint8_t opcode, uint32_t cdw1,
        uint32_t cdw2, uint32_t cdw3, uint32_t cdw10, uint32_t cdw11,
        uint32_t cdw12, uint32_t cdw13, uint32_t cdw14, uint32_t cdw15)
{
    using callback_t = void(std::tuple<std::error_code, int, uint32_t>);
    auto [err, nvmeStatus, completionDw0] =
        boost::asio::async_initiate<boost::asio::yield_context, callback_t>(
            [intf{nvmeIntf}, ctrl{nvmeCtrl}, opcode, cdw1, cdw2, cdw3, cdw10,
             cdw11, cdw12, cdw13, cdw14, cdw15](auto&& handler) {
        auto h = asio_helper::CopyableCallback(
            std::forward<decltype(handler)>(handler));

        intf->adminNonDataCmd(ctrl, opcode, cdw1, cdw2, cdw3, cdw10, cdw11,
                              cdw12, cdw13, cdw14, cdw15,
                              [h](const std::error_code& err, int nvmeStatus,
                                  uint32_t completionDw0) mutable {
            h(std::make_tuple(err, nvmeStatus, completionDw0));
        });
    },
            yield);

    lg2::debug("[{PATH}]nvme_status:{STATUS}, dw0:{DW0}", "PATH", path,
               "STATUS", nvmeStatus, "DW0", completionDw0);
    if (nvmeStatus < 0)
    {
        throw sdbusplus::exception::SdBusError(err.value(),
                                               "adminNonDataCmdMethod");
    }

    // Parse MI status Or MI status from nvme_status
    uint32_t miStatus = 0;
    uint32_t adminStatus = 0;
    if (nvme_status_get_type(nvmeStatus) == NVME_STATUS_TYPE_MI)
    {
        // there is no Admin status and dw0 if MI layer failed.
        miStatus = nvme_status_get_value(nvmeStatus);
        adminStatus = 0;
        completionDw0 = 0;
    }
    else
    {
        miStatus = 0;
        adminStatus = nvme_status_get_value(nvmeStatus);
    }
    return {miStatus, adminStatus, completionDw0};
}

std::tuple<uint32_t, uint32_t, uint32_t, std::string, uint32_t>
    NVMeControllerEnabled::lockdownInbandMethod(
        boost::asio::yield_context yield, uint8_t prohibit,
        const std::vector<uint8_t>& adminCmds,
        const std::vector<uint8_t>& features,
        const std::vector<uint8_t>& logPages)
{
    using callback_t =
        void(std::tuple<std::error_code, int, uint32_t, std::string, uint32_t>);

    auto [err, nvmeStatus, completionDw0, failureScope, failureId] =
        boost::asio::async_initiate<boost::asio::yield_context, callback_t>(
            [intf{nvmeIntf}, ctrl{nvmeCtrl}, prohibit, adminCmds, features,
             logPages](auto&& handler) {
        auto h = asio_helper::CopyableCallback(
            std::forward<decltype(handler)>(handler));

        intf->adminLockdownInband(ctrl, prohibit, adminCmds, features, logPages,
                                  [h](const std::error_code& err,
                                      int nvmeStatus, uint32_t completionDw0,
                                      const std::string& scope,
                                      uint32_t id) mutable {
            h(std::make_tuple(err, nvmeStatus, completionDw0, scope, id));
        });
    },
            yield);

    lg2::debug("[{PATH}]NVMe command result: status={STATUS}, dw0={DW0}",
               "PATH", path, "STATUS", nvmeStatus, "DW0", completionDw0);
    if (nvmeStatus < 0)
    {
        throw sdbusplus::exception::SdBusError(err.value(),
                                               "lockdownInbandMethod");
    }

    uint32_t miStatus = 0;
    uint32_t adminStatus = 0;
    if (nvme_status_get_type(nvmeStatus) == NVME_STATUS_TYPE_MI)
    {
        // If it's an MI status (e.g., protocol failure), Admin status is 0.
        miStatus = nvme_status_get_value(nvmeStatus);
        adminStatus = 0;
        completionDw0 = 0;
    }
    else
    {
        // If it's an Admin status (e.g., command failed on the drive), MI
        // status is 0.
        miStatus = 0;
        adminStatus = nvme_status_get_value(nvmeStatus);
    }

    // Returns the standardized tuple for the D-Bus client
    return {miStatus, adminStatus, completionDw0, failureScope, failureId};
}

void NVMeControllerEnabled::attachVolume(
    boost::asio::yield_context yield,
    const sdbusplus::message::object_path& volumePath)
{
    if (status != Status::Enabled)
    {
        lg2::error("[{PATH}]Controller has been disabled", "PATH", path);
        throw sdbusplus::xyz::openbmc_project::Common::Error::Unavailable();
    }

    uint32_t nsid = 0;
    if (auto s = subsys.lock())
    {
        auto vol = s->getVolume(volumePath);
        if (!vol)
        {
            throw sdbusplus::exception::SdBusError(ENOENT, "attachVolume");
        }
        nsid = vol->namespaceId();
    }
    else
    {
        return;
    }

    using callback_t = void(std::tuple<std::error_code, int>);
    uint16_t ctrlid = getCntrlId();
    auto [err, nvmeStatus] =
        boost::asio::async_initiate<boost::asio::yield_context, callback_t>(
            [intf{nvmeIntf}, ctrl{nvmeCtrl}, ctrlid, nsid](auto&& handler) {
        auto h = asio_helper::CopyableCallback(
            std::forward<decltype(handler)>(handler));

        intf->adminAttachDetachNamespace(
            ctrl, ctrlid, nsid, true,
            [h](const std::error_code& err, int nvmeStatus) mutable {
            h(std::make_tuple(err, nvmeStatus));
        });
    }, yield);

    // exception must be thrown outside of the async block
    checkLibNVMeError(err, nvmeStatus, "attachVolume");

    if (status == Status::Enabled)
    {
        if (auto s = subsys.lock())
        {
            try
            {
                s->attachCtrlVolume(getCntrlId(), nsid);
            }
            catch (const std::exception& e)
            {
                lg2::error(
                    "[{PATH}]Fail to attach NS({NSID}) to controller: {ERROR}",
                    "PATH", path, "NSID", nsid, "ERROR", e.what());
                throw sdbusplus::xyz::openbmc_project::Common::Error::
                    InternalFailure();
            }
        }
        updateAssociation();
    }
}

void NVMeControllerEnabled::detachVolume(
    boost::asio::yield_context yield,
    const sdbusplus::message::object_path& volumePath)
{
    if (status != Status::Enabled)
    {
        lg2::error("[{PATH}]Controller has been disabled", "PATH", path);
        throw sdbusplus::xyz::openbmc_project::Common::Error::Unavailable();
    }

    uint32_t nsid = 0;
    if (auto s = subsys.lock())
    {
        auto vol = s->getVolume(volumePath);
        if (!vol)
        {
            throw sdbusplus::exception::SdBusError(ENOENT, "detachVolume");
        }
        nsid = vol->namespaceId();
    }
    else
    {
        return;
    }

    using callback_t = void(std::tuple<std::error_code, int>);
    uint16_t ctrlid = getCntrlId();
    auto [err, nvmeStatus] =
        boost::asio::async_initiate<boost::asio::yield_context, callback_t>(
            [intf{nvmeIntf}, ctrl{nvmeCtrl}, ctrlid, nsid](auto&& handler) {
        auto h = asio_helper::CopyableCallback(
            std::forward<decltype(handler)>(handler));

        intf->adminAttachDetachNamespace(
            ctrl, ctrlid, nsid, false,
            [h](const std::error_code& err, int nvmeStatus) mutable {
            h(std::make_tuple(err, nvmeStatus));
        });
    }, yield);

    // exception must be thrown outside of the async block
    checkLibNVMeError(err, nvmeStatus, "detachVolume");

    if (status == Status::Enabled)
    {
        if (auto s = subsys.lock())
        {
            try
            {
                s->detachCtrlVolume(getCntrlId(), nsid);
            }
            catch (const std::exception& e)
            {
                lg2::error(
                    "[{PATH}]Fail to detach NS({NSID}) from controller: {ERROR}",
                    "PATH", path, "NSID", nsid, "ERROR", e.what());
                throw sdbusplus::xyz::openbmc_project::Common::Error::
                    InternalFailure();
            }
        }
        updateAssociation();
    }
}

void NVMeController::setNvmeVersion(uint32_t version)
{
    nvmeVersion = version;
}

bool NVMeController::isLogPageSupported(uint8_t lid) const
{
    if (nvmeVersion < kMinNvmeVerLogLid00hSupport)
    {
        return false;
    }

    if (lid == 0x00)
    {
        return true;
    }

    if (supportedLogPages.size() < 1024)
    {
        return false; // Under-sized payload or error condition
    }

    size_t byteOffset = static_cast<size_t>(lid) * 4;
    if (byteOffset >= supportedLogPages.size())
    {
        return false;
    }

    return (supportedLogPages[byteOffset] & 0x01) != 0;
}
