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),