Nvmed: Add VU log page lockdown Added implementation for locking down multiple log pages using the samsung provided VU commands This is to support E1.S SSD left shift development Tested: https://paste.googleplex.com/5697255522828288 Google-Bug-Id: 445994713 Change-Id: Ie8f59a9274a5622f0f9347ce0b839f09fedf4673 Signed-off-by: Agrim Bharat <agrimbharat@google.com>
diff --git a/src/NVMeController.cpp b/src/NVMeController.cpp index 6c9e88f..537b748 100644 --- a/src/NVMeController.cpp +++ b/src/NVMeController.cpp
@@ -146,16 +146,17 @@ objServer.add_interface(path, "xyz.openbmc_project.NVMe.Lockdown"); lockdownInterface->register_method( - "LockDownInband", + "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>& 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"); + -1, "LockdownInband"); return std::tuple<uint32_t, uint32_t, uint32_t, std::string, uint32_t>{0, 0, 0, "", 0}; } @@ -166,8 +167,8 @@ throw sdbusplus::xyz::openbmc_project::Common::Error::Unavailable(); } - return self->lockDownInbandMethod(std::move(yield), prohibit, adminCmds, - features); + return self->lockdownInbandMethod(std::move(yield), prohibit, adminCmds, + features, logPages); }); lockdownInterface->initialize(); @@ -829,22 +830,23 @@ } std::tuple<uint32_t, uint32_t, uint32_t, std::string, uint32_t> - NVMeControllerEnabled::lockDownInbandMethod( + 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>& 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](auto&& handler) { + [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, + intf->adminLockdownInband(ctrl, prohibit, adminCmds, features, logPages, [h](const std::error_code& err, int nvmeStatus, uint32_t completionDw0, const std::string& scope, @@ -859,7 +861,7 @@ if (nvmeStatus < 0) { throw sdbusplus::exception::SdBusError(err.value(), - "lockDownInbandMethod"); + "lockdownInbandMethod"); } uint32_t miStatus = 0;
diff --git a/src/NVMeController.hpp b/src/NVMeController.hpp index afdc470..db0a515 100644 --- a/src/NVMeController.hpp +++ b/src/NVMeController.hpp
@@ -268,9 +268,10 @@ uint32_t cdw13, uint32_t cdw14, uint32_t cdw15); std::tuple<uint32_t, uint32_t, uint32_t, std::string, uint32_t> - lockDownInbandMethod(boost::asio::yield_context yield, uint8_t prohibit, + 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>& features, + const std::vector<uint8_t>& logPages); void attachVolume(boost::asio::yield_context yield, const sdbusplus::message::object_path& volumePath);
diff --git a/src/NVMeIntf.hpp b/src/NVMeIntf.hpp index f9992c5..48b55f5 100644 --- a/src/NVMeIntf.hpp +++ b/src/NVMeIntf.hpp
@@ -285,6 +285,7 @@ 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) = 0;
diff --git a/src/NVMeMi.cpp b/src/NVMeMi.cpp index b2c581c..06d7c2d 100644 --- a/src/NVMeMi.cpp +++ b/src/NVMeMi.cpp
@@ -18,10 +18,13 @@ // 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; @@ -46,6 +49,8 @@ return "AdminCmd"; case 0x2: return "FeatureCmd"; + case 0x5: + return "LogPageCmd"; default: return "Unknown"; } @@ -978,22 +983,32 @@ const auto& currentCmd = lockdownQueue.front(); uint8_t itemCode = currentCmd.first; uint8_t scope = currentCmd.second; - - // CDW10 Construction: PRHBT (Bit 4) | OFI (Bit 8) | SCP (Bit 0) - uint32_t cdw10 = (((uint32_t)itemCode) - << lockdownOfiShift) | // OFI (Bits 15:8) - (((uint32_t)(lockdownIfcAsq & lockdownIfcMask)) - << lockdownIfcShift) | // IFC (Bits 6:5) - (((uint32_t)(prohibit & lockdownPrhbtMask)) - << lockdownPrhbtShift) | // PRHBT (Bit 4) - (((uint32_t)(scope & lockdownScopeMask)) - << lockdownScopeShift); // SCP (Bits 3:0) - + 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, nvmeAdminOpcLockdown, 0, 0, 0, 0, 0, cdw10, 0, 0, 0, 0, 0, 0, - nullptr, 0, nullptr, lockdownTimeoutMs, &completionDw0); + ctrl, opcode, 0, 0, 0, 0, 0, cdw10, 0, 0, 0, 0, 0, 0, nullptr, 0, + nullptr, lockdownTimeoutMs, &completionDw0); if (nvmeStatus < 0) { @@ -1306,6 +1321,7 @@ 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) @@ -1321,7 +1337,10 @@ { 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 {
diff --git a/src/NVMeMi.hpp b/src/NVMeMi.hpp index 4fbc29a..e048c2f 100644 --- a/src/NVMeMi.hpp +++ b/src/NVMeMi.hpp
@@ -99,6 +99,7 @@ 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)
diff --git a/src/NVMeMiFake.hpp b/src/NVMeMiFake.hpp index ccd9f67..3766582 100644 --- a/src/NVMeMiFake.hpp +++ b/src/NVMeMiFake.hpp
@@ -435,6 +435,7 @@ [[maybe_unused]] nvme_mi_ctrl_t ctrl, [[maybe_unused]] uint8_t prohibit, [[maybe_unused]] const std::vector<uint8_t>& adminCmds, [[maybe_unused]] const std::vector<uint8_t>& features, + [[maybe_unused]] 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) override
diff --git a/tests/test_nvme_mi.cpp b/tests/test_nvme_mi.cpp index e8a231e..c7b1a81 100644 --- a/tests/test_nvme_mi.cpp +++ b/tests/test_nvme_mi.cpp
@@ -131,6 +131,7 @@ (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),