Get ME status for lcd card

Send a get device command to ME and read a byte to find status
of ME if it is in operational mode. Display this status in LCD
debug card screen in system info page.

Tested: verified with lcd debug card screen.

Change-Id: I777a0d48f0a0538a80f5fd351a4eb47a0a07f52a
Signed-off-by: Vijay Khemka <vijaykhemka@fb.com>
diff --git a/src/usb-dbg.cpp b/src/usb-dbg.cpp
index 59dc566..19e7914 100644
--- a/src/usb-dbg.cpp
+++ b/src/usb-dbg.cpp
@@ -16,6 +16,7 @@
 
 #include <host-ipmid/ipmid-api.h>
 #include <nlohmann/json.hpp>
+#include <ipmid/api.hpp>
 #include <stdbool.h>
 #include <stdio.h>
 #include <sys/stat.h>
@@ -25,6 +26,7 @@
 #include <sstream>
 #include <iomanip>
 #include <phosphor-logging/log.hpp>
+#include <sdbusplus/asio/connection.hpp>
 #include <appcommands.hpp>
 
 namespace ipmi
@@ -72,6 +74,13 @@
 int getSensorUnit(std::string &, std::string &);
 } // namespace storage
 
+static constexpr bool DEBUG = false;
+static const uint8_t meAddress = 1;
+static constexpr uint8_t lun = 0;
+
+using IpmbMethodType =
+    std::tuple<int, uint8_t, uint8_t, uint8_t, uint8_t, std::vector<uint8_t>>;
+
 typedef struct _sensor_desc
 {
     char name[16];
@@ -871,6 +880,49 @@
     return -1;
 }
 
+static int getMeStatus(std::string &status)
+{
+    uint8_t cmd = 0x01;   // Get Device id command
+    uint8_t netFn = 0x06; // Netfn for APP
+    std::shared_ptr<sdbusplus::asio::connection> bus = getSdBus();
+    std::vector<uint8_t> cmdData;
+
+    auto method = bus->new_method_call("xyz.openbmc_project.Ipmi.Channel.Ipmb",
+                                       "/xyz/openbmc_project/Ipmi/Channel/Ipmb",
+                                       "org.openbmc.Ipmb", "sendRequest");
+    method.append(meAddress, netFn, lun, cmd, cmdData);
+
+    auto reply = bus->call(method);
+    if (reply.is_method_error())
+    {
+        std::cerr << "Error reading from ME\n";
+        return -1;
+    }
+
+    IpmbMethodType resp;
+    reply.read(resp);
+
+    std::vector<uint8_t> data;
+    data = std::get<5>(resp);
+
+    if (DEBUG)
+    {
+        std::cout << "ME Get ID: ";
+        for (size_t d : data)
+        {
+            std::cout << d << " ";
+        }
+        std::cout << "\n";
+    }
+
+    if (data[2] & 0x80)
+        status = "recovery mode";
+    else
+        status = "operation mode";
+
+    return 0;
+}
+
 static int udbg_get_info_page(uint8_t frame, uint8_t page, uint8_t *next,
                               uint8_t *count, uint8_t *buffer)
 {
@@ -939,9 +991,18 @@
             frame_info.append(biosVer.c_str(), 1);
         }
 
-        /* TBD: ME status and Board ID needs implementation */
         // ME status
+        std::string meStatus;
+        if (getMeStatus(meStatus) != 0)
+        {
+            phosphor::logging::log<phosphor::logging::level::WARNING>(
+                "Reading ME status failed");
+            meStatus = "unknown";
+        }
+        frame_info.append("ME_status:", 0);
+        frame_info.append(meStatus.c_str(), 1);
 
+        /* TBD: Board ID needs implementation */
         // Board ID
 
         // Battery - Use Escape sequence