#include "NVMeMi.hpp"

#include "NVMeError.hpp"
#include "NVMeUtil.hpp"

#include <endian.h>

#include <boost/endian.hpp>
#include <phosphor-logging/lg2.hpp>

#include <cassert>
#include <cerrno>
#include <deque>
#include <fstream>
#include <stdexcept>

namespace common_err = sdbusplus::xyz::openbmc_project::Common::Error;

// NVMe Admin Opcode for Lockdown (Opcode 0x24 in NVMe Base Spec 2.0a)
constexpr uint8_t nvmeAdminOpcLockdown = 0x24;
// Opcode for Vendor Unique Lockdown
constexpr uint8_t nvmeAdminOpcSamsungVULockdown = 0xCC;

// NVMe Lockdown Scope values (CDW10, bits [3:0])
constexpr uint8_t lockdownScopeAdminCmd = 0x0;
constexpr uint8_t lockdownScopeFeatureId = 0x2;
constexpr uint8_t lockdownScopeLogPage = 0x5;

// CDW10 Bit Masks and Shifts
constexpr uint8_t lockdownPrhbtMask = 0x1;
constexpr uint8_t lockdownPrhbtShift = 4;

constexpr uint8_t lockdownIfcMask = 0x3;
constexpr uint8_t lockdownIfcShift = 5;

constexpr uint8_t lockdownScopeMask = 0xF;
constexpr uint8_t lockdownScopeShift = 0;

constexpr uint8_t lockdownOfiShift = 8;

// Default Interface Field (IFC) value: 00b = Admin Submission Queue (ASQ) only
constexpr uint8_t lockdownIfcAsq = 0x00;

static inline std::string scopeToString(uint8_t scope)
{
    switch (scope)
    {
        case 0x0:
            return "AdminCmd";
        case 0x2:
            return "FeatureCmd";
        case 0x5:
            return "LogPageCmd";
        default:
            return "Unknown";
    }
}
// libnvme-mi root service
nvme_root_t NVMeMi::nvmeRoot = nvme_mi_create_root(stderr, DEFAULT_LOGLEVEL);

constexpr size_t maxNVMeMILength = 4096;
constexpr int tcgDefaultTimeoutMS = 20 * 1000;
constexpr int namespaceDefaultTimeoutMS = 20 * 1000;
constexpr int sanitizeDefaultTimeoutMS = 20 * 1000;
constexpr int downloadDefaultTimeoutMS = 10 * 1000;
constexpr int initCmdTimeoutMS = 1000;

NVMeMi::NVMeMi(boost::asio::io_context& io,
               const std::shared_ptr<sdbusplus::asio::connection>& conn,
               const std::shared_ptr<const MctpDevice>& device,
               const std::shared_ptr<NVMeMiWorker>& worker,
               PowerState readState) :
    io(io), device(device), readState(readState), mctpStatus(Status::Reset),
    mtu(64), nvmeEP(nullptr), restart(false), worker(worker)
{
    // set update the worker thread
    if (nvmeRoot == nullptr)
    {
        throw std::runtime_error("invalid NVMe root");
    }

    // setup the power state
    if (readState == PowerState::on || readState == PowerState::biosPost ||
        readState == PowerState::chassisOn)
    {
        // life time of the callback is binding to the NVMeMi instance, so only
        // this capture is required.
        powerCallback = setupPowerMatchCallback(conn, [this](PowerState, bool) {
            if (!::readingStateGood(this->readState))
            {
                recover();
            }
        });
    }
}

void NVMeMi::epReset()
{
    switch (mctpStatus)
    {
        case Status::Reset:
            return;
        case Status::Initiated:
            if (optimizeTimer)
            {
                lg2::info("Cancel the optimization Timer for the endpoint",
                          "ENDPOINT", endpoint->describe());
                optimizeTimer->cancel();
            }
            [[fallthrough]];
        case Status::Connected:
            if (nvmeEP == nullptr)
            {
                throw std::logic_error(
                    "nvmeEP was unpopulated in Status::Initiated state");
            }
            mctpStatus = Status::Terminating;
            lg2::info("start MCTP closure", "ENDPOINT", endpoint->describe());
            // Immediately reset endpoint so that we can capture the parameter
            // from a subsequent invocation of start() while in
            // Status::Terminating
            endpoint.reset();
            // Invoke nvme_mi_close() via a lambda that we schedule via
            // flushOperations(). Using flushOperations() ensures that any
            // outstanding tasks are executed before nvme_mi_close() is invoked,
            // invalidating their controller reference.
            flushOperations([self{shared_from_this()}]() {
                nvme_mi_close(self->nvmeEP);
                self->mtu = 64;
                self->nvmeEP = nullptr;
                self->mctpStatus = Status::Reset;
                lg2::info("end MCTP closure", "DEVICE",
                          self->device->describe());
                if (self->restart)
                {
                    // If restart is true then we've captured the updated
                    // endpoint. We pass it to start() to recreate the
                    // connection.
                    self->restart = false;
                    self->start(self->endpoint);
                }
            });
            return;
        case Status::Terminating:
            return;
    }
    throw std::logic_error("Unreachable");
}

bool NVMeMi::epConnect(int lnid, uint8_t leid)
{
    switch (mctpStatus)
    {
        case Status::Reset:
            if (nvmeEP != nullptr)
            {
                throw std::logic_error(
                    "nvmeEP populated in Status::Reset state");
            }
            nvmeEP = nvme_mi_open_mctp(nvmeRoot, lnid, leid);
            if (nvmeEP != nullptr)
            {
                mctpStatus = Status::Initiated;
                return true;
            }
            return false;
        case Status::Initiated:
        case Status::Connected:
            return true;
        case Status::Terminating:
            // This isn't an error so much as we're just not ready yet
            return false;
    }
    throw std::logic_error("Unreachable");
}

void NVMeMi::epOptimize()
{
    switch (mctpStatus)
    {
        case Status::Reset:
            throw std::logic_error("optimize called from Status::Reset");
        case Status::Initiated:
            /* Continue with optimization below */
            break;
        case Status::Connected:
            /* Already optimized */
            return;
        case Status::Terminating:
            throw std::logic_error("optimize called from Status::Terminating");
    }

    // If the device is behind a bridge (so not directly I2C accessible), we
    // skip MTU and SMBus frequency configuration.
    if (!endpoint->isI2cAccessible())
    {
        mctpStatus = Status::Connected;
        return;
    }

    optimizeTimer = std::make_shared<boost::asio::steady_timer>(
        io, std::chrono::milliseconds(500));
    optimizeTimer->async_wait([this](boost::system::error_code ec) {
        if (ec)
        {
            lg2::error("Endpoint optimize timer error: {ERROR}", "ERROR",
                       ec.what());
            return;
        }
        miSetMCTPConfiguration(
            [self{shared_from_this()}](const std::error_code& ec) {
            self->optimizeTimer = nullptr;
            if (ec)
            {
                lg2::error("Failed setting up MTU for the MCTP endpoint.",
                           "DEVICE", self->device->describe());
                self->recover();
                return;
            }
            self->configureLocalRouteMtu([self](const std::error_code& ec) {
                if (ec)
                {
                    self->recover();
                    return;
                }
                self->mctpStatus = Status::Connected;
            });
        });
    });
}

void NVMeMi::recover()
{
    switch (mctpStatus)
    {
        case Status::Reset:
            return;
        case Status::Initiated:
        case Status::Connected:
            endpoint->recover();
            return;
        case Status::Terminating:
            return;
    }
    throw std::logic_error("Unreachable");
}

void NVMeMi::start(const std::shared_ptr<MctpEndpoint>& ep)
{
    if (mctpStatus == Status::Terminating)
    {
        endpoint = ep;
        this->restart = true;
        return;
    }

    if (mctpStatus == Status::Reset)
    {
        endpoint = ep;
        // open mctp endpoint
        if (!epConnect(endpoint->network(), endpoint->eid()))
        {
            epReset();
            lg2::error("can't open MCTP endpoint", "ENDPOINT", ep->describe());
            return;
        }
    }

    if (mctpStatus == Status::Initiated)
    {
        epOptimize();
    }
}

void NVMeMi::stop()
{
    restart = false;
    epReset();
}

std::optional<std::error_code> NVMeMi::isEndpointDegraded() const
{
    switch (mctpStatus)
    {
        case Status::Reset:
            return std::make_error_code(std::errc::no_such_device);
        case Status::Initiated:
            return std::make_error_code(std::errc::not_connected);
        case Status::Connected:
            return std::nullopt;
        case Status::Terminating:
            return std::make_error_code(std::errc::not_connected);
    }
    throw std::logic_error("Unreachable");
}

NVMeMiWorker::NVMeMiWorker()
{ // start worker thread
    thread = std::thread([&io = workerIO, &stop = workerStop, &mtx = workerMtx,
                          &cv = workerCv, &isNotified = workerIsNotified]() {
        // With BOOST_ASIO_DISABLE_THREADS, boost::asio::executor_work_guard
        // issues null_event across the thread, which caused invalid invokation.
        // We implement a simple invoke machenism based std::condition_variable.
        while (true)
        {
            io.run();
            io.restart();
            {
                std::unique_lock<std::mutex> lock(mtx);
                cv.wait(lock, [&]() { return isNotified; });
                isNotified = false;

                if (stop)
                {
                    // exhaust all tasks and exit
                    io.run();
                    break;
                }
            }
        }
    });
}

NVMeMiWorker::~NVMeMiWorker()
{
    // close worker
    workerStop = true;
    {
        std::unique_lock<std::mutex> lock(workerMtx);
        workerIsNotified = true;
        workerCv.notify_all();
    }
    thread.join();
}

NVMeMi::~NVMeMi()
{
    // If we're being destructed the only thing left to do is to clean up the
    // endpoint connection. We're in the destructor because the last shared
    // reference has been dropped, which means it must be the case that no
    // worker jobs remain queued that reference the instance.
    //
    // We can't call epReset() here via stop() as was originally the case.
    // epReset() prepares the NVMeMi instance for a subsequent epConnect() using
    // shared_from_this(), which will yield a std::bad_weak_ptr now that we're
    // in the destructor. Moreover, a subsequent epConnect() is not possible
    // beyond this point.
    if (nvmeEP != nullptr)
    {
        nvme_mi_close(nvmeEP);
    }
}

void NVMeMiWorker::post(std::function<void(void)>&& func)
{
    if (!workerStop)
    {
        std::unique_lock<std::mutex> lock(workerMtx);
        if (!workerStop)
        {
            workerIsNotified = true;
            boost::asio::post(workerIO, std::move(func));
            workerCv.notify_all();
            return;
        }
    }
    throw std::runtime_error("NVMeMi has been stopped");
}

void NVMeMi::post(std::function<void(void)>&& func)
{
    worker->post([func{std::move(func)}]() { func(); });
}

// Calls .post(), catching runtime_error and returning an error code on failure.
std::error_code NVMeMi::tryPost(std::function<void(void)>&& func)
{
    try
    {
        post([self{shared_from_this()}, func{std::move(func)}]() { func(); });
    }
    catch (const std::runtime_error& e)
    {
        lg2::error("{ERROR}", "DEVICE", device->describe(), "ERROR", e.what());
        return std::make_error_code(std::errc::no_such_device);
    }
    return {};
}

void NVMeMi::miConfigureSMBusFrequency(
    uint8_t portId, uint8_t /*maxSupportedFreq*/,
    std::function<void(const std::error_code&)>&& cb)
{
    if (mctpStatus == Status::Reset || mctpStatus == Status::Terminating)
    {
        lg2::error("nvme endpoint is invalid", "DEVICE", device->describe());
        boost::asio::post(io, [cb{std::move(cb)}]() {
            cb(std::make_error_code(std::errc::no_such_device));
        });
        return;
    }
    try
    {
        post([portId, ep{endpoint}, self{shared_from_this()},
              cb{std::move(cb)}]() mutable {
            enum nvme_mi_config_smbus_freq smbusFreq = {};
            auto rc = nvme_mi_mi_config_get_smbus_freq(self->nvmeEP, portId,
                                                       &smbusFreq);
            if (rc != 0)
            {
                lg2::error("failed to get the SMBus frequency", "ENDPOINT",
                           ep->describe());
            }
            else if (smbusFreq == NVME_MI_CONFIG_SMBUS_FREQ_100kHz)
            {
                lg2::info("Setting the SMBus frequency to 400kHz", "ENDPOINT",
                          ep->describe());
                rc = nvme_mi_mi_config_set_smbus_freq(
                    self->nvmeEP, portId, NVME_MI_CONFIG_SMBUS_FREQ_400kHz);
                if (rc != 0)
                {
                    lg2::error("failed to set the SMBus frequency", "ENDPOINT",
                               ep->describe());
                }
            }
            if (rc != 0)
            {
                boost::asio::post(self->io, [cb{std::move(cb)}]() {
                    cb(std::make_error_code(std::errc::bad_message));
                });
                return;
            }
            boost::asio::post(self->io, [cb{std::move(cb)}]() { cb({}); });
        });
    }
    catch (const std::runtime_error& e)
    {
        lg2::error("{ERROR}", "DEVICE", device->describe(), "ERROR", e.what());
        return;
    }
}

void NVMeMi::miConfigureRemoteMCTP(
    uint8_t port, uint16_t mtu, uint8_t maxSupportedFreq,
    std::function<void(const std::error_code&)>&& cb)
{
    if (mctpStatus == Status::Reset || mctpStatus == Status::Terminating)
    {
        lg2::error("nvme endpoint is invalid", "DEVICE", device->describe());
        boost::asio::post(io, [cb{std::move(cb)}]() {
            cb(std::make_error_code(std::errc::no_such_device));
        });
        return;
    }
    try
    {
        post([port, mtu, maxSupportedFreq, self{shared_from_this()},
              cb{std::move(cb)}]() mutable {
            unsigned timeout = nvme_mi_ep_get_timeout(self->nvmeEP);
            nvme_mi_ep_set_timeout(self->nvmeEP, initCmdTimeoutMS);
            auto rc = nvme_mi_mi_config_set_mctp_mtu(self->nvmeEP, port, mtu);
            nvme_mi_ep_set_timeout(self->nvmeEP, timeout);

            if (rc != 0)
            {
                lg2::error("failed to set remote MCTP MTU for port: {PORT}",
                           "DEVICE", self->device->describe(), "PORT", port);
                boost::asio::post(self->io, [cb{std::move(cb)}]() {
                    cb(std::make_error_code(std::errc::bad_message));
                });
                return;
            }
            self->mtu = mtu;
            if (maxSupportedFreq >= 2)
            {
                boost::asio::post(self->io, [self, port, maxSupportedFreq,
                                             cb{std::move(cb)}]() mutable {
                    self->miConfigureSMBusFrequency(port, maxSupportedFreq,
                                                    std::move(cb));
                });
                return;
            }
            boost::asio::post(self->io, [cb{std::move(cb)}]() { cb({}); });
        });
    }
    catch (const std::runtime_error& e)
    {
        lg2::error("{ERROR}", "DEVICE", device->describe(), "ERROR", e.what());
        boost::asio::post(io, [cb{std::move(cb)}]() {
            cb(std::make_error_code(std::errc::no_such_device));
        });
        return;
    }
}

void NVMeMi::miSetMCTPConfiguration(
    std::function<void(const std::error_code&)>&& cb)
{
    if (mctpStatus == Status::Reset || mctpStatus == Status::Terminating)
    {
        lg2::error("nvme endpoint is invalid", "DEVICE", device->describe());
        boost::asio::post(io, [cb{std::move(cb)}]() {
            cb(std::make_error_code(std::errc::no_such_device));
        });
        return;
    }
    try
    {
        post([cb{std::move(cb)}, self{shared_from_this()}]() mutable {
            unsigned timeout = nvme_mi_ep_get_timeout(self->nvmeEP);
            nvme_mi_ep_set_timeout(self->nvmeEP, initCmdTimeoutMS);
            struct nvme_mi_read_nvm_ss_info ssInfo = {};
            auto rc = nvme_mi_mi_read_mi_data_subsys(self->nvmeEP, &ssInfo);
            nvme_mi_ep_set_timeout(self->nvmeEP, timeout);
            if (rc != 0)
            {
                lg2::error("Failed reading subsystem info failing", "DEVICE",
                           self->device->describe());
                boost::asio::post(self->io, [cb{std::move(cb)}]() {
                    cb(std::make_error_code(std::errc::bad_message));
                });
                return;
            }

            for (uint8_t portId = 0; portId <= ssInfo.nump; portId++)
            {
                struct nvme_mi_read_port_info portInfo = {};
                auto rc = nvme_mi_mi_read_mi_data_port(self->nvmeEP, portId,
                                                       &portInfo);
                if (rc != 0)
                {
                    /* PCIe port might not be ready right after AC/DC cycle. */
                    lg2::error("failed reading port info for port_id: {PORT}",
                               "DEVICE", self->device->describe(), "PORT",
                               portId);
                }
                else if (portInfo.portt == 0x2) // SMBus ports = 0x2
                {
                    uint16_t supportedMtu = portInfo.mmctptus;
                    uint8_t supportedFreq = portInfo.smb.mme_freq; // NOLINT
                    boost::asio::post(self->io, [self, portId, supportedMtu,
                                                 supportedFreq,
                                                 cb{std::move(cb)}]() mutable {
                        self->miConfigureRemoteMCTP(
                            portId, supportedMtu, supportedFreq, std::move(cb));
                    });
                    return;
                }
            }
            // Didn't find the SMbus port
            boost::asio::post(self->io, [cb{std::move(cb)}]() {
                cb(std::make_error_code(std::errc::no_such_device));
            });
        });
    }
    catch (const std::runtime_error& e)
    {
        lg2::error("{ERROR}", "DEVICE", device->describe(), "ERROR", e.what());
        boost::asio::post(io, [cb{std::move(cb)}]() {
            cb(std::make_error_code(std::errc::no_such_device));
        });
        return;
    }
}

void NVMeMi::configureLocalRouteMtu(
    std::function<void(const std::error_code& ec)>&& completed, int retries)
{
    const uint32_t mctpMtu = mtu + 4;
    std::function<void(const std::error_code& ec)> retry =
        [this, cb{std::move(completed)},
         retries](const std::error_code& ec) mutable {
        if (!endpoint)
        {
            lg2::error("failed to set MCTP path MTU: Status::Terminating",
                       "DEVICE", device->describe());
            cb(ec);
            return;
        }

        if (!ec)
        {
            lg2::info("Finished MCTP initialization. MTU: {MTU}", "ENDPOINT",
                      endpoint->describe(), "MTU", mtu);
            cb(ec);
            return;
        }

        retries--;
        if (retries == 0)
        {
            lg2::error("failed to set MCTP path MTU: {ERROR}", "ENDPOINT",
                       endpoint->describe(), "ERROR", ec.message());
            cb(ec);
            return;
        }

        lg2::warning("retry to set MCTP path MTU", "ENDPOINT",
                     endpoint->describe());
        configureLocalRouteMtu(std::move(cb), retries);
    };
    endpoint->setMtu(mctpMtu, std::move(retry));
}

void NVMeMi::miSubsystemHealthStatusPoll(
    std::function<void(const std::error_code&, nvme_mi_nvm_ss_health_status*)>&&
        cb)
{
    if (auto degraded = isEndpointDegraded())
    {
        lg2::error("MCTP connection is not established", "DEVICE",
                   device->describe());

        boost::asio::post(io, [cb{std::move(cb)}, errc{degraded.value()}]() {
            cb(errc, nullptr);
        });
        return;
    }

    try
    {
        post([self{shared_from_this()}, ep{endpoint}, cb{std::move(cb)}]() {
            nvme_mi_nvm_ss_health_status ssHealth = {};
            auto rc = nvme_mi_mi_subsystem_health_status_poll(self->nvmeEP,
                                                              true, &ssHealth);
            if (rc < 0)
            {
                lg2::error("fail to subsystem_health_status_poll: {ERROR}",
                           "ENDPOINT", ep->describe(), "ERROR",
                           strerror(errno));
                boost::asio::post(self->io,
                                  [cb{cb}, lastErrno{errno}]() mutable {
                    cb(std::make_error_code(static_cast<std::errc>(lastErrno)),
                       nullptr);
                });
                return;
            }
            if (rc > 0)
            {
                std::string_view errMsg =
                    statusToString(static_cast<nvme_mi_resp_status>(rc));
                lg2::error("fail to subsystem_health_status_poll: {ERROR}",
                           "ENDPOINT", ep->describe(), "ERROR", errMsg.data());
                boost::asio::post(self->io, [cb{cb}]() mutable {
                    cb(std::make_error_code(std::errc::bad_message), nullptr);
                });
                return;
            }

            boost::asio::post(self->io, [cb{cb}, ssHealth{ssHealth}]() mutable {
                cb({}, &ssHealth);
            });
        });
    }
    catch (const std::runtime_error& e)
    {
        lg2::error("{ERROR}", "DEVICE", device->describe(), "ERROR", e.what());
        boost::asio::post(io, [cb{std::move(cb)}]() {
            cb(std::make_error_code(std::errc::no_such_device), {});
        });
        return;
    }
}

void NVMeMi::miScanCtrl(std::function<void(const std::error_code&,
                                           const std::vector<nvme_mi_ctrl_t>&)>
                            cb)
{
    if (auto degraded = isEndpointDegraded())
    {
        lg2::error("MCTP connection is not established", "DEVICE",
                   device->describe());

        boost::asio::post(io, [cb{std::move(cb)}, errc{degraded.value()}]() {
            cb(errc, {});
        });
        return;
    }

    try
    {
        post([self{shared_from_this()}, ep{endpoint}, cb{std::move(cb)}]() {
            int rc = nvme_mi_scan_ep(self->nvmeEP, true);
            if (rc < 0)
            {
                lg2::error("fail to scan controllers: {ERROR}", "ENDPOINT",
                           ep->describe(), "ERROR", strerror(errno));
                boost::asio::post(self->io,
                                  [cb{cb}, lastErrno{errno}]() mutable {
                    cb(std::make_error_code(static_cast<std::errc>(lastErrno)),
                       {});
                });
                return;
            }
            if (rc > 0)
            {
                std::string_view errMsg =
                    statusToString(static_cast<nvme_mi_resp_status>(rc));
                lg2::error("fail to scan controllers: {ERROR}", "ENDPOINT",
                           ep->describe(), "ERROR", errMsg.data());
                boost::asio::post(self->io, [cb{cb}]() mutable {
                    cb(std::make_error_code(std::errc::bad_message), {});
                });
                return;
            }

            std::vector<nvme_mi_ctrl_t> list;
            nvme_mi_ctrl_t c = {};
            nvme_mi_for_each_ctrl(self->nvmeEP, c)
            {
                list.push_back(c);
            }
            boost::asio::post(
                self->io,
                [cb{cb}, list{std::move(list)}]() mutable { cb({}, list); });
        });
    }
    catch (const std::runtime_error& e)
    {
        lg2::error("{ERROR}", "ENDPOINT", endpoint->describe(), "ERROR",
                   e.what());
        boost::asio::post(io, [cb{std::move(cb)}]() {
            cb(std::make_error_code(std::errc::no_such_device), {});
        });
        return;
    }
}

bool NVMeMi::flushOperations(std::function<void()>&& cb)
{
    try
    {
        post([self{shared_from_this()}, cb{std::move(cb)}]() {
            boost::asio::post(self->io, cb);
        });

        return true;
    }
    catch (const std::runtime_error& e)
    {
        lg2::error("Runtime error: {ERROR}", "ERROR", e.what());
        return false;
    }
}

void NVMeMi::adminIdentify(
    nvme_mi_ctrl_t ctrl, nvme_identify_cns cns, uint32_t nsid, uint16_t cntid,
    std::function<void(nvme_ex_ptr, std::span<uint8_t>)>&& cb)
{
    if (auto degraded = isEndpointDegraded())
    {
        lg2::error("MCTP connection is not established", "DEVICE",
                   device->describe());
        boost::asio::post(io, [cb{std::move(cb)}, errc{degraded.value()}]() {
            cb(makeLibNVMeError("nvme endpoint is degraded"), {});
        });
        return;
    }
    try
    {
        post([ctrl, cns, nsid, cntid, self{shared_from_this()}, ep{endpoint},
              cb{std::move(cb)}]() {
            int rc = 0;
            std::vector<uint8_t> data;
            switch (cns)
            {
                case NVME_IDENTIFY_CNS_SECONDARY_CTRL_LIST:
                {
                    data.resize(sizeof(nvme_secondary_ctrl_list));
                    nvme_identify_args args{};
                    memset(&args, 0, sizeof(args));
                    args.result = nullptr;
                    args.data = data.data();
                    args.args_size = sizeof(args);
                    args.cns = cns;
                    args.csi = NVME_CSI_NVM;
                    args.nsid = nsid;
                    args.cntid = cntid;
                    args.cns_specific_id = NVME_CNSSPECID_NONE;
                    args.uuidx = NVME_UUID_NONE,

                    rc = nvme_mi_admin_identify_partial(ctrl, &args, 0,
                                                        data.size());

                    break;
                }

                default:
                {
                    data.resize(NVME_IDENTIFY_DATA_SIZE);
                    nvme_identify_args args{};
                    memset(&args, 0, sizeof(args));
                    args.result = nullptr;
                    args.data = data.data();
                    args.args_size = sizeof(args);
                    args.cns = cns;
                    args.csi = NVME_CSI_NVM;
                    args.nsid = nsid;
                    args.cntid = cntid;
                    args.cns_specific_id = NVME_CNSSPECID_NONE;
                    args.uuidx = NVME_UUID_NONE,

                    rc = nvme_mi_admin_identify(ctrl, &args);
                }
            }

            if (rc < 0)
            {
                lg2::error("fail to do nvme identify: {ERROR}", "ENDPOINT",
                           ep->describe(), "ERROR", strerror(errno));
            }
            else if (rc > 0)
            {
                std::string_view errMsg =
                    statusToString(static_cast<nvme_mi_resp_status>(rc));
                lg2::error("fail to do nvme identify: {ERROR}", "ENDPOINT",
                           ep->describe(), "ERROR", errMsg.data());
            }

            auto ex = makeLibNVMeError(errno, rc, "adminIdentify");
            if (ex)
            {
                lg2::error("fail to do nvme identify: {ERROR}", "ERROR",
                           ex->description());
            }

            boost::asio::post(self->io,
                              [cb{cb}, ex, data{std::move(data)}]() mutable {
                std::span<uint8_t> span{data.data(), data.size()};
                cb(ex, span);
            });
        });
    }
    catch (const std::runtime_error& e)
    {
        lg2::error("{ERROR}", "ENDPOINT", endpoint->describe(), "ERROR",
                   e.what());
        auto msg = std::string("Runtime error: ") + e.what();
        lg2::error("{MSG}", "MSG", msg);
        boost::asio::post(
            io, [cb{std::move(cb)}, msg]() { cb(makeLibNVMeError(msg), {}); });
        return;
    }
}

static int nvmeMiAdminGetLogTelemetryHostRae(nvme_mi_ctrl_t ctrl, bool /*rae*/,
                                             __u64 offset, __u32 len, void* log)
{
    return nvme_mi_admin_get_log_telemetry_host(ctrl, offset, len, log);
}

// Get Temetery Log header and return the size for hdr + data area (Area 1, 2,
// 3, or maybe 4)
int getTelemetryLogSize(nvme_mi_ctrl_t ctrl, bool host, uint32_t& size)
{
    int rc = 0;
    nvme_telemetry_log log = {};
    auto func = host ? nvmeMiAdminGetLogTelemetryHostRae
                     : nvme_mi_admin_get_log_telemetry_ctrl;

    // Only host telemetry log requires create.
    if (host)
    {
        rc = nvme_mi_admin_get_log_create_telemetry_host(ctrl, &log);
        if (rc != 0)
        {
            lg2::error("failed to create telemetry host log");
            return rc;
        }
    }

    rc = func(ctrl, false, 0, sizeof(log), &log);

    if (rc != 0)
    {
        lg2::error("failed to retain telemetry log for {TYPE}", "TYPE",
                   [host] { return host ? "host" : "ctrl"; }());
        return rc;
    }

    // Restrict the telemetry log to Data Area 1 and 2. Getting Data Area 3
    // OOB is not suitable due to its possible size. Data Area 3 can be up to
    // 30000 data blocks with each block being 512 bytes in size. Restricting
    // to Area 1 and 2.
    size = static_cast<uint32_t>(
               (boost::endian::little_to_native(log.dalb2) + 1)) *
           NVME_LOG_TELEM_BLOCK_SIZE;
    return rc;
}

void NVMeMi::getTelemetryLogChunk(
    nvme_mi_ctrl_t ctrl, bool host, uint64_t offset,
    std::vector<uint8_t>&& data,
    std::function<void(const std::error_code&, std::span<uint8_t>)>&& cb)
{
    if (offset >= data.size())
    {
        lg2::error(
            "get telemetry log: offset exceed the log size. offset: {OFFSET}, size: {SIZE}",
            "DEVICE", device->describe(), "OFFSET", offset, "SIZE",
            data.size());
        cb(std::make_error_code(std::errc::invalid_argument), {});
        return;
    }

    post([self{shared_from_this()}, ctrl, host, offset, data{std::move(data)},
          cb{std::move(cb)}]() mutable {
        int rc = 0;
        bool rae = true;
        auto func = host ? nvmeMiAdminGetLogTelemetryHostRae
                         : nvme_mi_admin_get_log_telemetry_ctrl;
        uint32_t size = 0;

        // final transaction
        if (offset + nvmeMiXferSize >= data.size())
        {
            rae = false;
        }
        size = std::min(static_cast<uint32_t>(nvmeMiXferSize),
                        static_cast<uint32_t>(data.size() - offset));

        rc = func(ctrl, rae, offset, size, data.data() + offset);

        if (rc < 0)
        {
            lg2::error("fail to get chunk for telemetry log: {ERROR}", "DEVICE",
                       self->device->describe(), "ERROR", strerror(errno));
            boost::asio::post(self->io,
                              [cb{std::move(cb)}, lastErrno{errno}]() {
                cb(std::make_error_code(static_cast<std::errc>(lastErrno)), {});
            });
            return;
        }
        if (rc > 0)
        {
            std::string_view errMsg =
                statusToString(static_cast<nvme_mi_resp_status>(rc));
            lg2::error("fail to get chunk for telemetry log: {ERROR}", "DEVICE",
                       self->device->describe(), "ERROR", errMsg.data());
            boost::asio::post(self->io, [cb{std::move(cb)}]() {
                cb(std::make_error_code(std::errc::bad_message), {});
            });
            return;
        }

        if (!rae)
        {
            boost::asio::post(
                self->io, [cb{std::move(cb)}, data{std::move(data)}]() mutable {
                std::span<uint8_t> span{data.data(), data.size()};
                cb({}, span);
            });
            return;
        }

        offset += size;
        boost::asio::post(self->io,
                          [self, ctrl, host, offset, data{std::move(data)},
                           cb{std::move(cb)}]() mutable {
            self->getTelemetryLogChunk(ctrl, host, offset, std::move(data),
                                       std::move(cb));
        });
    });
}

void NVMeMi::processNextLockdownCommand(
    nvme_mi_ctrl_t ctrl, uint8_t prohibit,
    std::deque<std::pair<uint8_t, uint8_t>> lockdownQueue,
    const std::function<void(const std::error_code&, int, uint32_t,
                             const std::string&, uint32_t)>& finalCb,
    int lastNvmeStatus, uint32_t lastCompletionDw0, int attempt,
    const std::string& lastFailureScope, uint32_t lastFailureId)
{
    if (lockdownQueue.empty())
    {
        // Propagates the final success status and the final propagated failure
        // state
        boost::asio::post(this->io, [finalCb, lastNvmeStatus, lastCompletionDw0,
                                     lastFailureScope, lastFailureId]() {
            finalCb(std::error_code(), lastNvmeStatus, lastCompletionDw0,
                    lastFailureScope, lastFailureId);
        });
        return;
    }

    // local variables to hold the result of the synchronous hardware call.
    uint32_t completionDw0 = 0;
    int nvmeStatus = 0;
    int currentErrno = 0;

    const auto& currentCmd = lockdownQueue.front();
    uint8_t itemCode = currentCmd.first;
    uint8_t scope = currentCmd.second;
    uint8_t opcode = 0;
    constexpr uint32_t lockdownTimeoutMs = 5 * 1000;

    if (scope == lockdownScopeLogPage)
    {
        opcode = nvmeAdminOpcSamsungVULockdown;
    }
    else
    {
        opcode = nvmeAdminOpcLockdown;
    }

    // CDW10 Construction is the same for both scopes
    // Bits 15:8 (OFI/PRTID): itemCode
    // Bits 6:5 (IFC): 00b (lockdownIfcAsq)
    // Bit 4 (PRHBT): prohibit
    // Bits 3:0 (SCP): scope
    uint32_t cdw10 =
        (((uint32_t)itemCode) << lockdownOfiShift) |
        (((uint32_t)(lockdownIfcAsq & lockdownIfcMask)) << lockdownIfcShift) |
        (((uint32_t)(prohibit & lockdownPrhbtMask)) << lockdownPrhbtShift) |
        (((uint32_t)(scope & lockdownScopeMask)) << lockdownScopeShift);

    nvmeStatus = nvme_mi_admin_admin_passthru(
        ctrl, opcode, 0, 0, 0, 0, 0, cdw10, 0, 0, 0, 0, 0, 0, nullptr, 0,
        nullptr, lockdownTimeoutMs, &completionDw0);

    if (nvmeStatus < 0)
    {
        currentErrno = errno;
    }
    else
    {
        currentErrno = 0;
    }

    // Success condition
    if (nvmeStatus == 0)
    {
        lockdownQueue.pop_front();

        this->post([self = shared_from_this(), ctrl, prohibit,
                    lockdownQueue = std::move(lockdownQueue), finalCb,
                    nvmeStatus, completionDw0, lastFailureScope,
                    lastFailureId]() mutable {
            self->processNextLockdownCommand(
                ctrl, prohibit, std::move(lockdownQueue), finalCb, nvmeStatus,
                completionDw0, 0, lastFailureScope, lastFailureId);
        });
        return;
    }

    // Failure condition and checking if reattempting is allowed
    if (attempt == 0)
    {
        this->post([self = shared_from_this(), ctrl, prohibit,
                    lockdownQueue = std::move(lockdownQueue), finalCb,
                    nvmeStatus, completionDw0, lastFailureScope,
                    lastFailureId]() mutable {
            self->processNextLockdownCommand(
                ctrl, prohibit, std::move(lockdownQueue), finalCb, nvmeStatus,
                completionDw0, 1, lastFailureScope, lastFailureId);
        });
        return;
    }

    // The device failed this command, so its details become the final error
    // payload.
    std::string failureScope = scopeToString(currentCmd.second);
    uint32_t failureId = currentCmd.first;

    // Call the final D-Bus callback with the specific failure context (current
    // status is the error status).
    boost::asio::post(this->io, [finalCb, currentErrno, nvmeStatus,
                                 completionDw0, failureScope, failureId]() {
        finalCb(std::make_error_code(static_cast<std::errc>(currentErrno)),
                nvmeStatus, completionDw0, failureScope, failureId);
    });
}

void NVMeMi::adminGetLogPage(
    nvme_mi_ctrl_t ctrl, nvme_cmd_get_log_lid lid, uint32_t nsid, uint8_t lsp,
    uint16_t /*lsi*/,
    std::function<void(const std::error_code&, std::span<uint8_t>)>&& cb)
{
    if (auto degraded = isEndpointDegraded())
    {
        lg2::error("MCTP connection is not established", "DEVICE",
                   device->describe());
        boost::asio::post(io, [cb{std::move(cb)}, errc{degraded.value()}]() {
            cb(errc, {});
        });
        return;
    }

    try
    {
        post([ctrl, nsid, lid, lsp, self{shared_from_this()}, ep{endpoint},
              cb{std::move(cb)}]() {
            std::vector<uint8_t> data;
            std::function<void(void)> logHandler;
            int rc = 0;
            int logId = lid;
            switch (logId)
            {
                case NVME_LOG_LID_ERROR:
                {
                    data.resize(nvmeMiXferSize);
                    // The number of entries for most recent error logs.
                    // Currently we only do one nvme mi transfer for the
                    // error log to avoid blocking other tasks
                    static constexpr int num = nvmeMiXferSize /
                                               sizeof(nvme_error_log_page);
                    nvme_error_log_page* log =
                        // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
                        reinterpret_cast<nvme_error_log_page*>(data.data());

                    rc = nvme_mi_admin_get_log_error(ctrl, num, false, log);
                    if (rc != 0)
                    {
                        lg2::error("fail to get error log", "ENDPOINT",
                                   ep->describe());
                        break;
                    }
                }
                break;
                case NVME_LOG_LID_SMART:
                {
                    data.resize(sizeof(nvme_smart_log));
                    nvme_smart_log* log =
                        // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
                        reinterpret_cast<nvme_smart_log*>(data.data());
                    rc = nvme_mi_admin_get_log_smart(ctrl, nsid, false, log);
                    if (rc != 0)
                    {
                        lg2::error("fail to get smart log", "ENDPOINT",
                                   ep->describe());
                        break;
                    }
                }
                break;
                    /* Begin of patch context
                     *
                     *
                     *
                     */
                    /*
                     *
                     *
                     * End of patch context
                     */
                case NVME_LOG_LID_FW_SLOT:
                {
                    data.resize(sizeof(nvme_firmware_slot));
                    nvme_firmware_slot* log =
                        // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
                        reinterpret_cast<nvme_firmware_slot*>(data.data());
                    rc = nvme_mi_admin_get_log_fw_slot(ctrl, false, log);
                    if (rc != 0)
                    {
                        lg2::error("fail to get firmware slot", "ENDPOINT",
                                   ep->describe());
                        break;
                    }
                }
                break;
                case NVME_LOG_LID_CMD_EFFECTS:
                {
                    data.resize(sizeof(nvme_cmd_effects_log));
                    nvme_cmd_effects_log* log =
                        // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
                        reinterpret_cast<nvme_cmd_effects_log*>(data.data());

                    // nvme rev 1.3 doesn't support csi,
                    // set to default csi = NVME_CSI_NVM
                    rc = nvme_mi_admin_get_log_cmd_effects(ctrl, NVME_CSI_NVM,
                                                           log);
                    if (rc != 0)
                    {
                        lg2::error("fail to get cmd supported and effects log",
                                   "ENDPOINT", ep->describe());
                        break;
                    }
                }
                break;
                case NVME_LOG_LID_DEVICE_SELF_TEST:
                {
                    data.resize(sizeof(nvme_self_test_log));
                    nvme_self_test_log* log =
                        // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
                        reinterpret_cast<nvme_self_test_log*>(data.data());
                    rc = nvme_mi_admin_get_log_device_self_test(ctrl, log);
                    if (rc != 0)
                    {
                        lg2::error("fail to get device self test log",
                                   "ENDPOINT", ep->describe());
                        break;
                    }
                }
                break;
                case NVME_LOG_LID_CHANGED_NS:
                {
                    data.resize(sizeof(nvme_ns_list));
                    nvme_ns_list* log =
                        // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
                        reinterpret_cast<nvme_ns_list*>(data.data());
                    rc = nvme_mi_admin_get_log_changed_ns_list(ctrl, false,
                                                               log);
                    if (rc != 0)
                    {
                        lg2::error("fail to get changed namespace list",
                                   "ENDPOINT", ep->describe());
                        break;
                    }
                }
                break;
                case NVME_LOG_LID_TELEMETRY_HOST:
                // fall through to NVME_LOG_LID_TELEMETRY_CTRL
                case NVME_LOG_LID_TELEMETRY_CTRL:
                {
                    bool host = lid == NVME_LOG_LID_TELEMETRY_HOST;

                    uint32_t size = 0;
                    rc = getTelemetryLogSize(ctrl, host, size);
                    if (rc == 0)
                    {
                        data.resize(size);
                        logHandler = [self, ctrl, host, data{data},
                                      cb{cb}]() mutable {
                            self->getTelemetryLogChunk(
                                ctrl, host, 0, std::move(data), std::move(cb));
                        };
                    }
                }
                break;
                case NVME_LOG_LID_CMD_AND_FEAT_LOCKDOWN:
                {
                    data.resize(sizeof(nvme_lockdown_log));
                    nvme_lockdown_log* log =
                        // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
                        reinterpret_cast<nvme_lockdown_log*>(data.data());

                    int rc = nvme_mi_admin_get_log_lockdown(ctrl, lsp, log);
                    if (rc != 0)
                    {
                        lg2::error(
                            "fail to get command and feature lockdown log",
                            "ENDPOINT", ep->describe());
                        break;
                    }
                }
                break;
                case NVME_LOG_LID_RESERVATION:
                {
                    data.resize(sizeof(nvme_resv_notification_log));
                    nvme_resv_notification_log* log =
                        // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
                        reinterpret_cast<nvme_resv_notification_log*>(
                            data.data());

                    int rc = nvme_mi_admin_get_log_reservation(ctrl, false,
                                                               log);
                    if (rc != 0)
                    {
                        lg2::error("fail to get reservation notification log",
                                   "ENDPOINT", ep->describe());
                        break;
                    }
                }
                break;
                case NVME_LOG_LID_SANITIZE:
                {
                    data.resize(sizeof(nvme_sanitize_log_page));
                    nvme_sanitize_log_page* log =
                        // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
                        reinterpret_cast<nvme_sanitize_log_page*>(data.data());

                    int rc = nvme_mi_admin_get_log_sanitize(ctrl, false, log);
                    if (rc != 0)
                    {
                        lg2::error("fail to get sanitize status log",
                                   "ENDPOINT", ep->describe());
                        break;
                    }
                }
                break;
                default:
                {
                    lg2::error("unknown lid for GetLogPage", "ENDPOINT",
                               ep->describe());
                    rc = -1;
                    errno = EINVAL;
                }
            }

            if (rc < 0)
            {
                lg2::error("fail to get log page: {ERROR}", "ENDPOINT",
                           ep->describe(), "ERROR", strerror(errno));
                logHandler = [cb{cb}, lastErrno{errno}]() mutable {
                    cb(std::make_error_code(static_cast<std::errc>(lastErrno)),
                       {});
                };
            }
            else if (rc > 0)
            {
                std::string_view errMsg =
                    statusToString(static_cast<nvme_mi_resp_status>(rc));
                lg2::error("fail to get log page: {ERROR}", "ENDPOINT",
                           ep->describe(), "ERROR", errMsg.data());
                logHandler = [cb{cb}]() mutable {
                    cb(std::make_error_code(std::errc::bad_message), {});
                };
            }

            if (!logHandler)
            {
                logHandler = [cb{cb}, data{std::move(data)}]() mutable {
                    std::span<uint8_t> span{data.data(), data.size()};
                    cb({}, span);
                };
            }
            boost::asio::post(self->io, logHandler);
        });
    }
    catch (const std::runtime_error& e)
    {
        lg2::error("NVMeMi adminGetLogPage throws: {ERROR}", "ENDPOINT",
                   endpoint->describe(), "ERROR", e.what());
        boost::asio::post(io, [cb{std::move(cb)}]() {
            cb(std::make_error_code(std::errc::no_such_device), {});
        });
        return;
    }
}

void NVMeMi::adminLockdownInband(
    nvme_mi_ctrl_t ctrl, uint8_t prohibit,
    const std::vector<uint8_t>& adminCmds, const std::vector<uint8_t>& features,
    const std::vector<uint8_t>& logPages,
    std::function<void(const std::error_code&, int nvmeStatus,
                       uint32_t comptionDw0, const std::string& failureScope,
                       uint32_t failureId)>&& cb)
{
    // Flatten all command sets into a deque of {itemCode, scope} pairs
    std::deque<std::pair<uint8_t, uint8_t>> lockdownQueue;

    for (uint8_t cmd : adminCmds)
    {
        lockdownQueue.emplace_back(cmd, lockdownScopeAdminCmd);
    }
    for (uint8_t feature : features)
    {
        lockdownQueue.emplace_back(feature, lockdownScopeFeatureId);
    }
    for (uint8_t logPage : logPages)
    {
        lockdownQueue.emplace_back(logPage, lockdownScopeLogPage);
    }
    std::error_code postErr =
        tryPost([self{shared_from_this()}, ctrl, prohibit,
                 lockdownQueue = std::move(lockdownQueue), cb{cb}]() mutable {
        self->processNextLockdownCommand(
            ctrl, prohibit, std::move(lockdownQueue), cb, 0, 0, 0, "", 0);
    });

    if (postErr)
    {
        lg2::error("adminLockdownInband post failed: {ERROR}", "DEVICE",
                   device->describe(), "ERROR", postErr.message());

        boost::asio::post(
            io, [cb{std::move(cb)}, postErr]() { cb(postErr, -1, 0, "", 0); });
    }
}

void NVMeMi::adminXfer(
    nvme_mi_ctrl_t ctrl, const nvme_mi_admin_req_hdr& adminReq,
    std::span<uint8_t> data, unsigned int timeoutMs,
    std::function<void(const std::error_code&, const nvme_mi_admin_resp_hdr&,
                       std::span<uint8_t>)>&& cb)
{
    if (auto degraded = isEndpointDegraded())
    {
        lg2::error("MCTP connection is not established", "DEVICE",
                   device->describe());
        boost::asio::post(io, [cb{std::move(cb)}, errc{degraded.value()}]() {
            cb(errc, {}, {});
        });
        return;
    }

    try
    {
        std::vector<uint8_t> req(sizeof(nvme_mi_admin_req_hdr) + data.size());
        memcpy(req.data(), &adminReq, sizeof(nvme_mi_admin_req_hdr));
        memcpy(req.data() + sizeof(nvme_mi_admin_req_hdr), data.data(),
               data.size());
        post([ctrl, req{std::move(req)}, self{shared_from_this()}, ep{endpoint},
              timeoutMs, cb{std::move(cb)}]() mutable {
            int rc = 0;

            nvme_mi_admin_req_hdr* reqHeader =
                // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
                reinterpret_cast<nvme_mi_admin_req_hdr*>(req.data());
            // set response data size == req DL. Only if data passed is empty
            size_t respDataSize = 0;
            if (req.size() == sizeof(nvme_mi_admin_req_hdr))
            {
                respDataSize =
                    boost::endian::little_to_native<size_t>(reqHeader->dlen);
            }
            off_t respDataOffset =
                boost::endian::little_to_native<off_t>(reqHeader->doff);
            size_t bufSize = sizeof(nvme_mi_admin_resp_hdr) + respDataSize;
            std::vector<uint8_t> buf(bufSize);
            nvme_mi_admin_resp_hdr* respHeader =
                // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
                reinterpret_cast<nvme_mi_admin_resp_hdr*>(buf.data());

            // set timeout
            unsigned timeout = nvme_mi_ep_get_timeout(self->nvmeEP);
            nvme_mi_ep_set_timeout(self->nvmeEP, timeoutMs);

            rc = nvme_mi_admin_xfer(ctrl, reqHeader,
                                    req.size() - sizeof(nvme_mi_admin_req_hdr),
                                    respHeader, respDataOffset, &respDataSize);
            // revert to previous timeout
            nvme_mi_ep_set_timeout(self->nvmeEP, timeout);

            if (rc < 0)
            {
                lg2::error("failed to nvme_mi_admin_xfer", "ENDPOINT",
                           ep->describe());
                boost::asio::post(self->io,
                                  [cb{std::move(cb)}, lastErrno{errno}]() {
                    cb(std::make_error_code(static_cast<std::errc>(lastErrno)),
                       {}, {});
                });
                return;
            }
            // the MI interface will only consume protocol/io errors
            // The client will take the reponsibility to deal with nvme-mi
            // status flag and nvme status field(cwd3). cmd specific return
            // value (cdw0) is also client's job.

            buf.resize(sizeof(nvme_mi_admin_resp_hdr) + respDataSize);
            boost::asio::post(
                self->io, [cb{std::move(cb)}, data{std::move(buf)}]() mutable {
                std::span<uint8_t> span(
                    data.begin() + sizeof(nvme_mi_admin_resp_hdr), data.end());
                // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
                cb({}, *reinterpret_cast<nvme_mi_admin_resp_hdr*>(data.data()),
                   span);
            });
        });
    }
    catch (const std::runtime_error& e)
    {
        lg2::error("{ERROR}", "ENDPOINT", endpoint->describe(), "ERROR",
                   e.what());
        boost::asio::post(io, [cb{std::move(cb)}]() {
            cb(std::make_error_code(std::errc::no_such_device), {}, {});
        });
        return;
    }
}

void NVMeMi::adminFwCommit(
    nvme_mi_ctrl_t ctrl, nvme_fw_commit_ca action, uint8_t slot, bool bpid,
    std::function<void(const std::error_code&, nvme_status_field)>&& cb)
{
    if (auto degraded = isEndpointDegraded())
    {
        lg2::error("MCTP connection is not established", "DEVICE",
                   device->describe());
        boost::asio::post(io, [cb{std::move(cb)}, errc{degraded.value()}]() {
            cb(errc, nvme_status_field::NVME_SC_MASK);
        });
        return;
    }
    try
    {
        nvme_fw_commit_args args{};
        memset(&args, 0, sizeof(args));
        args.args_size = sizeof(args);
        args.action = action;
        args.slot = slot;
        args.bpid = bpid;
        boost::asio::post(io, [ctrl, args, cb{std::move(cb)}, ep{endpoint},
                               self{shared_from_this()}]() mutable {
            int rc = nvme_mi_admin_fw_commit(ctrl, &args);
            if (rc < 0)
            {
                lg2::error("fail to nvme_mi_admin_fw_commit: {ERROR}",
                           "ENDPOINT", ep->describe(), "ERROR",
                           strerror(errno));
                boost::asio::post(self->io,
                                  [cb{std::move(cb)}, lastErrno{errno}]() {
                    cb(std::make_error_code(static_cast<std::errc>(lastErrno)),
                       nvme_status_field::NVME_SC_MASK);
                });
                return;
            }
            if (rc >= 0)
            {
                switch (rc & 0x7ff)
                {
                    case NVME_SC_SUCCESS:
                    case NVME_SC_FW_NEEDS_CONV_RESET:
                    case NVME_SC_FW_NEEDS_SUBSYS_RESET:
                    case NVME_SC_FW_NEEDS_RESET:
                        boost::asio::post(self->io, [rc, cb{std::move(cb)}]() {
                            cb({}, static_cast<nvme_status_field>(rc));
                        });
                        break;
                    default:
                        std::string_view errMsg = statusToString(
                            static_cast<nvme_mi_resp_status>(rc));
                        lg2::error("fail to nvme_mi_admin_fw_commit: {ERROR}",
                                   "ERROR", errMsg.data());
                        boost::asio::post(self->io, [rc, cb{std::move(cb)}]() {
                            cb(std::make_error_code(std::errc::bad_message),
                               static_cast<nvme_status_field>(rc));
                        });
                }
                return;
            }
        });
    }
    catch (const std::runtime_error& e)
    {
        lg2::error("{ERROR}", "ENDPOINT", endpoint->describe(), "ERROR",
                   e.what());
        boost::asio::post(io, [cb{std::move(cb)}]() {
            cb(std::make_error_code(std::errc::no_such_device),
               nvme_status_field::NVME_SC_MASK);
        });
        return;
    }
}

void NVMeMi::adminFwDownloadChunk(
    nvme_mi_ctrl_t ctrl, const std::string& firmwarefile, size_t size,
    size_t offset, int attemptCount,
    std::function<void(const std::error_code&, nvme_status_field)>&& cb)
{
    if (auto degraded = isEndpointDegraded())
    {
        lg2::error("MCTP connection is not established", "DEVICE",
                   device->describe());
        boost::asio::post(io, [cb{std::move(cb)}, errc{degraded.value()}]() {
            cb(errc, nvme_status_field::NVME_SC_MASK);
        });
        return;
    }
    try
    {
        post([ctrl, firmwarefile, size, offset, attemptCount, cb{std::move(cb)},
              self{shared_from_this()}]() mutable {
            std::array<char, nvmeMiXferSize> data = {};
            std::ifstream fwFile(firmwarefile, std::ios::in | std::ios::binary);
            if (fwFile.fail())
            {
                lg2::error("fail to open fw image file: {FILE}, {ERROR}",
                           "FILE", firmwarefile, "ERROR", strerror(errno));
                boost::asio::post(self->io, [cb{std::move(cb)}]() {
                    cb(std::make_error_code(static_cast<std::errc>(errno)),
                       nvme_status_field::NVME_SC_MASK);
                });
                return;
            }
            fwFile.seekg(static_cast<int64_t>(offset), std::ios::beg);
            nvme_fw_download_args args = {};
            memset(&args, 0, sizeof(args));
            args.args_size = sizeof(args);
            int dataLen =
                static_cast<int>(std::min(size - offset, nvmeMiXferSize));
            fwFile.read((char*)data.data(), dataLen);
            fwFile.close();
            args.offset = offset;
            args.data_len = dataLen;
            args.data = (char*)data.data();
            unsigned timeout = nvme_mi_ep_get_timeout(self->nvmeEP);
            nvme_mi_ep_set_timeout(self->nvmeEP, downloadDefaultTimeoutMS);
            int rc = nvme_mi_admin_fw_download(ctrl, &args);
            nvme_mi_ep_set_timeout(self->nvmeEP, timeout);
            if (rc < 0)
            {
                if (attemptCount > 0)
                {
                    lg2::warning(
                        "Retrying the firmware chunk. With Offset: {OFFSET}, Total firmware Size: {SIZE}",
                        "OFFSET", offset, "SIZE", size);
                    attemptCount = attemptCount - 1;
                }
                else
                {
                    lg2::error("fail to nvme_mi_admin_fw_download: {ERROR}",
                               "ERROR", strerror(errno));
                    boost::asio::post(self->io, [cb{std::move(cb)}]() {
                        cb(std::make_error_code(static_cast<std::errc>(errno)),
                           nvme_status_field::NVME_SC_MASK);
                    });
                    return;
                }
            }
            else
            {
                attemptCount = 3; /* Reset the attempt count*/
                offset = offset + args.data_len;
            }
            if (offset >= size)
            {
                lg2::info(
                    "Successfully transferred the firmware. Transfer Size: {XFER}, Total Size: {SIZE}",
                    "XFER", offset, "SIZE", size);
                boost::asio::post(self->io, [rc, cb{std::move(cb)}]() {
                    cb({}, static_cast<nvme_status_field>(rc));
                });
                return;
            }
            boost::asio::post(self->io,
                              [self, ctrl, firmwarefile, size, offset,
                               attemptCount, cb{std::move(cb)}]() mutable {
                self->adminFwDownloadChunk(ctrl, firmwarefile, size, offset,
                                           attemptCount, std::move(cb));
            });
        });
    }
    catch (const std::runtime_error& e)
    {
        lg2::error("{ERROR}", "ERROR", e.what());
        boost::asio::post(io, [cb{std::move(cb)}]() {
            cb(std::make_error_code(std::errc::no_such_device),
               nvme_status_field::NVME_SC_MASK);
        });
        return;
    }
}

void NVMeMi::adminFwDownload(
    nvme_mi_ctrl_t ctrl, std::string firmwarefile,
    std::function<void(const std::error_code&, nvme_status_field)>&& cb)
{
    size_t offset = 0;
    int tryCount = 3;
    std::ifstream imageFile(firmwarefile,
                            std::ios::in | std::ios::binary | std::ios::ate);
    if (imageFile.fail())
    {
        lg2::error("Can't open the firmware file: {ERROR}", "ERROR",
                   strerror(errno));
        boost::asio::post(io, [cb{cb}]() {
            cb(std::make_error_code(std::errc::no_such_device),
               nvme_status_field::NVME_SC_MASK);
        });
    }
    size_t size = imageFile.tellg();
    imageFile.close();
    adminFwDownloadChunk(ctrl, firmwarefile, size, offset, tryCount,
                         std::move(cb));
}

void NVMeMi::adminSecuritySend(
    nvme_mi_ctrl_t ctrl, uint8_t proto, uint16_t protoSpecific,
    std::span<uint8_t> data,
    std::function<void(const std::error_code&, int nvmeStatus)>&& cb)
{
    std::error_code postErr = tryPost(
        [self{shared_from_this()}, ctrl, proto, protoSpecific, data, cb{cb}]() {
        struct nvme_security_send_args args = {};
        memset(&args, 0x0, sizeof(args));
        args.secp = proto;
        args.spsp0 = protoSpecific & 0xff;
        args.spsp1 = protoSpecific >> 8;
        args.nssf = 0;
        args.data = data.data();
        args.data_len = data.size_bytes();
        args.args_size = sizeof(struct nvme_security_send_args);

        unsigned timeout = nvme_mi_ep_get_timeout(self->nvmeEP);
        nvme_mi_ep_set_timeout(self->nvmeEP, tcgDefaultTimeoutMS);
        int status = nvme_mi_admin_security_send(ctrl, &args);
        nvme_mi_ep_set_timeout(self->nvmeEP, timeout);

        boost::asio::post(self->io,
                          [cb{cb}, nvmeErrno{errno}, status]() mutable {
            auto err = std::make_error_code(static_cast<std::errc>(nvmeErrno));
            cb(err, status);
        });
    });
    if (postErr)
    {
        lg2::error("adminSecuritySend post failed: {ERROR}", "DEVICE",
                   device->describe(), "ERROR", postErr.message());
        boost::asio::post(io,
                          [cb{std::move(cb)}, postErr]() { cb(postErr, -1); });
    }
}

void NVMeMi::adminSecurityReceive(
    nvme_mi_ctrl_t ctrl, uint8_t proto, uint16_t protoSpecific,
    uint32_t transferLength,
    std::function<void(const std::error_code&, int nvmeStatus,
                       std::span<uint8_t> data)>&& cb)
{
    if (transferLength > maxNVMeMILength)
    {
        cb(std::make_error_code(std::errc::invalid_argument), -1, {});
        return;
    }

    std::error_code postErr =
        tryPost([self{shared_from_this()}, ctrl, proto, protoSpecific,
                 transferLength, cb{cb}]() {
        std::vector<uint8_t> data(transferLength);

        struct nvme_security_receive_args args = {};
        memset(&args, 0x0, sizeof(args));
        args.secp = proto;
        args.spsp0 = protoSpecific & 0xff;
        args.spsp1 = protoSpecific >> 8;
        args.nssf = 0;
        args.data = data.data();
        args.data_len = data.size();
        args.args_size = sizeof(struct nvme_security_receive_args);

        unsigned timeout = nvme_mi_ep_get_timeout(self->nvmeEP);
        nvme_mi_ep_set_timeout(self->nvmeEP, tcgDefaultTimeoutMS);
        int status = nvme_mi_admin_security_recv(ctrl, &args);
        nvme_mi_ep_set_timeout(self->nvmeEP, timeout);

        if (args.data_len > maxNVMeMILength)
        {
            lg2::error(
                "nvme_mi_admin_security_send returned excess data, {LEN}",
                "DEVICE", self->device->describe(), "LEN", args.data_len);
            boost::asio::post(self->io, [cb]() {
                cb(std::make_error_code(std::errc::protocol_error), -1, {});
            });
            return;
        }

        data.resize(args.data_len);
        boost::asio::post(self->io,
                          [cb{cb}, nvmeErrno{errno}, status, data]() mutable {
            std::span<uint8_t> span{data.data(), data.size()};
            auto err = std::make_error_code(static_cast<std::errc>(nvmeErrno));
            cb(err, status, span);
        });
    });
    if (postErr)
    {
        lg2::error("adminSecurityReceive post failed: {ERROR}", "DEVICE",
                   device->describe(), "ERROR", postErr.message());
        boost::asio::post(
            io, [cb{std::move(cb)}, postErr]() { cb(postErr, -1, {}); });
    }
}

void NVMeMi::adminNonDataCmd(
    nvme_mi_ctrl_t ctrl, 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,
    std::function<void(const std::error_code&, int nvmeStatus,
                       uint32_t comptionDw0)>&& cb)
{
    std::error_code postErr =
        tryPost([self{shared_from_this()}, ctrl, opcode, cdw1, cdw2, cdw3,
                 cdw10, cdw11, cdw12, cdw13, cdw14, cdw15, cb{cb}]() {
        uint32_t comptionDw0 = 0;
        int nvmeStatus = nvme_mi_admin_admin_passthru(
            ctrl, opcode, 0, 0, cdw1, cdw2, cdw3, cdw10, cdw11, cdw12, cdw13,
            cdw14, cdw15, 0, nullptr, 0, nullptr, 10 * 1000, &comptionDw0);
        boost::asio::post(self->io, [cb{cb}, nvmeErrno{errno}, nvmeStatus,
                                     comptionDw0]() mutable {
            auto err = std::make_error_code(static_cast<std::errc>(nvmeErrno));
            cb(err, nvmeStatus, comptionDw0);
        });
    });
    if (postErr)
    {
        lg2::error("adminNonDataCmd post failed: {ERROR}", "DEVICE",
                   device->describe(), "ERROR", postErr.message());
        boost::asio::post(
            io, [cb{std::move(cb)}, postErr]() { cb(postErr, -1, 0); });
    }
}

/* throws a nvme_ex_ptr on failure */
size_t NVMeMi::getBlockSize(nvme_mi_ctrl_t ctrl, size_t lbaFormat)
{
    struct nvme_id_ns id = {};
    lg2::debug("getblocksize");
    int status = nvme_mi_admin_identify_ns(ctrl, NVME_NSID_ALL, &id);
    auto e = makeLibNVMeError(errno, status, "getBlockSize");
    if (e)
    {
        // TODO: (b/375054188) Exception handling to be refactored
        // NOLINTNEXTLINE(cert-err09-cpp,cert-err60-cpp,cert-err61-cpp,misc-throw-by-value-catch-by-reference)
        throw e;
    }

    lg2::debug("nlbaf {NLBAF}, lbaf {LBAF}", "NLBAF", (int)id.nlbaf, "LBAF",
               (int)lbaFormat);

    // Sanity check for the value from the drive
    size_t maxLbaf = std::min(63, (int)id.nlbaf);

    // NLBAF is the maximum allowed index (not a count)
    if (lbaFormat > maxLbaf)
    {
        throw makeLibNVMeError("LBA format out of range, maximum is " +
                                   std::to_string(maxLbaf),
                               std::make_shared<common_err::InvalidArgument>());
    }

    return 1 << id.lbaf[lbaFormat].ds;
}

/*
 finished_cb will not be called if submitted_cb is called with a failure.
 */
void NVMeMi::createNamespace(
    nvme_mi_ctrl_t ctrl, uint64_t size, size_t lbaFormat, bool metadataAtEnd,
    std::function<void(nvme_ex_ptr ex)>&& submittedCb,
    std::function<void(nvme_ex_ptr ex, NVMeNSIdentify newid)>&& finishedCb)
{
    lg2::debug("createns {TID}", "TID", (int)gettid());
    std::error_code postErr = tryPost(
        [self{shared_from_this()}, ctrl, size, lbaFormat, metadataAtEnd,
         submittedCb{submittedCb}, finishedCb{std::move(finishedCb)}]() {
        size_t blockSize = 0;

        try
        {
            blockSize = NVMeMi::getBlockSize(ctrl, lbaFormat);
        }
        // TODO: (b/375054188) Exception handling to be refactored
        // NOLINTNEXTLINE(cert-err09-cpp,cert-err60-cpp,cert-err61-cpp,misc-throw-by-value-catch-by-reference)
        catch (nvme_ex_ptr e)
        {
            submittedCb(e);
            return;
        }

        if (size % blockSize != 0)
        {
            auto msg =
                std::string("Size must be a multiple of the block size ") +
                std::to_string(blockSize);
            submittedCb(makeLibNVMeError(
                msg, std::make_shared<common_err::InvalidArgument>()));
            return;
        }

        uint64_t blocks = size / blockSize;

        // TODO: this will become nvme_ns_mgmt_host_sw_specified in a newer
        // libnvme.
        struct nvme_id_ns data = {};
        uint32_t newNsid = 0;

        uint8_t flbas = 0;
        if (metadataAtEnd)
        {
            flbas |= (1 << 4);
        }
        // low 4 bits at 0:3
        flbas |= (lbaFormat & 0xf);
        // high 2 bits at 5:6
        flbas |= ((lbaFormat & 0x30) << 1);

        memset(&data, 0x0, sizeof(data));
        data.nsze = ::htole64(blocks);
        data.ncap = ::htole64(blocks);
        data.flbas = flbas;

        lg2::debug("verified {TID}", "TID", (int)gettid());

        // submission has been verified. Handle the cb in main thread
        // concurrently.
        boost::asio::post(self->io, [submittedCb{submittedCb}]() mutable {
            submittedCb(nvme_ex_ptr());
        });
        lg2::debug("after submitted_cb {TID}", "TID", (int)gettid());

        unsigned timeout = nvme_mi_ep_get_timeout(self->nvmeEP);
        nvme_mi_ep_set_timeout(self->nvmeEP, namespaceDefaultTimeoutMS);
        int status = nvme_mi_admin_ns_mgmt_create(ctrl, &data, 0, &newNsid);
        nvme_mi_ep_set_timeout(self->nvmeEP, timeout);

        nvme_ex_ptr e = makeLibNVMeError(errno, status, "createVolume");

        NVMeNSIdentify newns = {
            .namespaceId = newNsid,
            .size = size,
            .capacity = size,
            .blockSize = blockSize,
            .lbaFormat = lbaFormat,
            .metadataAtEnd = metadataAtEnd,
        };

        boost::asio::post(self->io,
                          [finishedCb{finishedCb}, e, newns]() mutable {
            finishedCb(e, newns);
        });

#if 0
        // TODO testing purposes
        static uint32_t counter = 20;

        printf("createNamespace top, sleeping 5 seconds\n");
        sleep(5);

        uint32_t new_ns = counter++;

        printf("create complete. ns %d\n", new_ns);

        auto err = std::make_error_code(static_cast<std::errc>(0));
        cb(err, 0, new_ns);
#endif
    });

    lg2::debug("submitted cb {TID}", "TID", (int)gettid());

    if (postErr)
    {
        lg2::error("createNamespace post failed: {ERROR}", "ERROR",
                   postErr.message());
        auto e = makeLibNVMeError(postErr, -1, "createVolume");
        boost::asio::post(
            io, [submittedCb{std::move(submittedCb)}, e]() { submittedCb(e); });
    }
}

// Deletes a namespace
void NVMeMi::adminDeleteNamespace(
    nvme_mi_ctrl_t ctrl, uint32_t nsid,
    std::function<void(const std::error_code&, int nvmeStatus)>&& cb)
{
    std::error_code postErr =
        tryPost([self{shared_from_this()}, ctrl, nsid, cb{cb}]() {
        unsigned timeout = nvme_mi_ep_get_timeout(self->nvmeEP);
        nvme_mi_ep_set_timeout(self->nvmeEP, namespaceDefaultTimeoutMS);
        int status = nvme_mi_admin_ns_mgmt_delete(ctrl, nsid);
        nvme_mi_ep_set_timeout(self->nvmeEP, timeout);

        boost::asio::post(self->io,
                          [cb{cb}, nvmeErrno{errno}, status]() mutable {
            auto err = std::make_error_code(static_cast<std::errc>(nvmeErrno));
            cb(err, status);
        });
    });
    if (postErr)
    {
        lg2::error("deleteNamespace post failed: {ERROR}", "ERROR",
                   postErr.message());
        boost::asio::post(io,
                          [cb{std::move(cb)}, postErr]() { cb(postErr, -1); });
    }
}

void NVMeMi::adminListNamespaces(
    nvme_mi_ctrl_t ctrl,
    std::function<void(nvme_ex_ptr, std::vector<uint32_t> ns)>&& cb)
{
    std::error_code postErr =
        tryPost([self{shared_from_this()}, ctrl, cb{cb}]() {
        int status = 0;
        int nvmeErrno = 0;
        std::vector<uint32_t> ns;
        // sanity in case of bad drives, allows for >1million NSes
        const int maxIter = 1000;

        for (int i = 0; i < maxIter; i++)
        {
            struct nvme_ns_list list = {};
            uint32_t start = NVME_NSID_NONE;
            if (!ns.empty())
            {
                start = ns.back() + 1;
            }
            status = nvme_mi_admin_identify_active_ns_list(ctrl, start, &list);
            nvmeErrno = errno;
            if (status != 0)
            {
                ns.clear();
                break;
            }

            // NOLINTNEXTLINE(modernize-loop-convert)
            for (size_t i = 0; i < NVME_ID_NS_LIST_MAX; i++)
            {
                if (list.ns[i] == 0U)
                {
                    break;
                }
                ns.push_back(list.ns[i]);
            }
            if (list.ns[NVME_ID_NS_LIST_MAX - 1] == 0)
            {
                // all entries read
                break;
            }
        }

        auto ex = makeLibNVMeError(nvmeErrno, status, "adminListNamespaces");
        boost::asio::post(self->io, [cb{cb}, ex, ns]() mutable { cb(ex, ns); });
    });
    if (postErr)
    {
        auto ex = makeLibNVMeError("post failed");
        boost::asio::post(
            io, [cb{std::move(cb)}, ex]() { cb(ex, std::vector<uint32_t>()); });
    }
}

// Attaches or detaches a namespace from a controller
void NVMeMi::adminAttachDetachNamespace(
    nvme_mi_ctrl_t ctrl, uint16_t ctrlid, uint32_t nsid, bool attach,
    std::function<void(const std::error_code&, int nvmeStatus)>&& cb)
{
    std::error_code postErr = tryPost(
        [self{shared_from_this()}, ctrl, nsid, attach, ctrlid, cb{cb}]() {
        struct nvme_ctrl_list ctrlList = {};
        struct nvme_ns_attach_args args = {};
        memset(&args, 0x0, sizeof(args));

        // TODO: add this to a newer libnvme
        // uint16_t ctrl_id = nvme_mi_ctrl_id(ctrl);
        uint16_t ctrlId = ctrlid;
        nvme_init_ctrl_list(&ctrlList, 1, &ctrlId);
        args.ctrlist = &ctrlList;
        args.nsid = nsid;
        if (attach)
        {
            args.sel = NVME_NS_ATTACH_SEL_CTRL_ATTACH;
        }
        else
        {
            args.sel = NVME_NS_ATTACH_SEL_CTRL_DEATTACH;
        }
        args.args_size = sizeof(args);

        unsigned timeout = nvme_mi_ep_get_timeout(self->nvmeEP);
        nvme_mi_ep_set_timeout(self->nvmeEP, namespaceDefaultTimeoutMS);
        int status = nvme_mi_admin_ns_attach(ctrl, &args);
        nvme_mi_ep_set_timeout(self->nvmeEP, timeout);
        boost::asio::post(self->io,
                          [cb{cb}, nvmeErrno{errno}, status]() mutable {
            auto err = std::make_error_code(static_cast<std::errc>(nvmeErrno));
            cb(err, status);
        });
    });
    if (postErr)
    {
        lg2::error("adminAttachDetachNamespace post failed: {ERROR}", "ERROR",
                   postErr.message());
        boost::asio::post(io,
                          [cb{std::move(cb)}, postErr]() { cb(postErr, -1); });
    }
}

void NVMeMi::adminSanitize(nvme_mi_ctrl_t ctrl,
                           enum nvme_sanitize_sanact sanact, uint8_t passes,
                           uint32_t /*pattern*/, bool invertPattern,
                           std::function<void(nvme_ex_ptr ex)>&& cb)
{
    std::error_code postErr = tryPost([self{shared_from_this()}, ctrl, sanact,
                                       passes, invertPattern, cb{cb}]() {
        struct nvme_sanitize_nvm_args args = {};
        memset(&args, 0x0, sizeof(args));
        args.args_size = sizeof(args);
        args.sanact = sanact;
        args.owpass = passes;
        args.oipbp = invertPattern;

        unsigned timeout = nvme_mi_ep_get_timeout(self->nvmeEP);
        nvme_mi_ep_set_timeout(self->nvmeEP, sanitizeDefaultTimeoutMS);
        int status = nvme_mi_admin_sanitize_nvm(ctrl, &args);
        nvme_mi_ep_set_timeout(self->nvmeEP, timeout);
        lg2::debug("san status {STATUS}, errno {ERRNO}", "STATUS", status,
                   "ERRNO", errno);

        auto ex = makeLibNVMeError(errno, status, "adminSanitize");
        boost::asio::post(self->io, [cb{cb}, ex]() mutable { cb(ex); });
    });
    if (postErr)
    {
        auto ex = makeLibNVMeError("post failed");
        boost::asio::post(io, [cb{std::move(cb)}, ex]() { cb(ex); });
    }
}
