pldmtool: oem: Implement GetAlertStatus command

Tested:
 pldmtool oem-ibm GetAlertStatus -i 0
 Encode request successfully
 Request Message:
 08 01 80 3f f0 00
 Success in creating the socket : RC = 4
 Success in connecting to socket : RC = 0
 Success in sending message type as pldm to mctp : RC = 0
 Write to socket successful : RC = 6
 Total length: 14
 Shutdown Socket successful :  RC = 0
 Response Message:
 08 01 00 3f f0 00 30 00 00 ff 30 80 00 00
 GetAlertStatus Success:
 rack entry: 0xff000030
 pri cec node: 0x00008030

Signed-off-by: George Liu <liuxiwei@inspur.com>
Change-Id: I5650591f547abb4ea5961e51ff11af8d1d20b4f2
diff --git a/tool/meson.build b/tool/meson.build
index 555856f..12daf0d 100644
--- a/tool/meson.build
+++ b/tool/meson.build
@@ -1,16 +1,20 @@
+libpldm_headers = ['.', './oem/ibm']
+
 sources = [
   'pldm_cmd_helper.cpp',
   'pldm_base_cmd.cpp',
   'pldm_platform_cmd.cpp',
   'pldm_bios_cmd.cpp',
   'pldm_fru_cmd.cpp',
-  'pldmtool.cpp'
+  'pldmtool.cpp',
+  'oem/ibm/pldm_host_cmd.cpp'
 ]
 
 executable(
   'pldmtool',
   sources,
   implicit_include_directories: false,
+  include_directories: include_directories(libpldm_headers),
   dependencies: [libpldm, libpldmutils, dependency('sdbusplus')],
   install: true,
   install_dir: get_option('bindir'))
diff --git a/tool/oem/ibm/pldm_host_cmd.cpp b/tool/oem/ibm/pldm_host_cmd.cpp
new file mode 100644
index 0000000..cb7e740
--- /dev/null
+++ b/tool/oem/ibm/pldm_host_cmd.cpp
@@ -0,0 +1,87 @@
+#include "pldm_host_cmd.hpp"
+
+#include "../../pldm_cmd_helper.hpp"
+
+#include "oem/ibm/libpldm/host.h"
+
+namespace pldmtool
+{
+
+namespace oem_ibm
+{
+namespace power_host
+{
+using namespace pldmtool::helper;
+
+std::vector<std::unique_ptr<CommandInterface>> commands;
+
+class GetAlertStatus : public CommandInterface
+{
+  public:
+    ~GetAlertStatus() = default;
+    GetAlertStatus() = delete;
+    GetAlertStatus(const GetAlertStatus&) = delete;
+    GetAlertStatus(GetAlertStatus&&) = default;
+    GetAlertStatus& operator=(const GetAlertStatus&) = delete;
+    GetAlertStatus& operator=(GetAlertStatus&&) = default;
+
+    explicit GetAlertStatus(const char* type, const char* name, CLI::App* app) :
+        CommandInterface(type, name, app)
+    {
+        app->add_option(
+               "-i, --id", versionId,
+               "Version of the command/response format. 0x00 for this format")
+            ->required();
+    }
+
+    std::pair<int, std::vector<uint8_t>> createRequestMsg() override
+    {
+        std::vector<uint8_t> requestMsg(sizeof(pldm_msg_hdr) +
+                                        PLDM_GET_ALERT_STATUS_REQ_BYTES);
+        auto request = reinterpret_cast<pldm_msg*>(requestMsg.data());
+
+        auto rc = encode_get_alert_status_req(instanceId, versionId, request,
+                                              PLDM_GET_ALERT_STATUS_REQ_BYTES);
+        return {rc, requestMsg};
+    }
+
+    void parseResponseMsg(pldm_msg* responsePtr, size_t payloadLength) override
+    {
+        uint8_t completionCode = 0;
+        uint32_t rack_entry = 0;
+        uint32_t pri_cec_node = 0;
+        auto rc = decode_get_alert_status_resp(responsePtr, payloadLength,
+                                               &completionCode, &rack_entry,
+                                               &pri_cec_node);
+
+        if (rc != PLDM_SUCCESS || completionCode != PLDM_SUCCESS)
+        {
+            std::cerr << "Response Message Error: "
+                      << "rc=" << rc << ",cc=" << (int)completionCode << "\n";
+            return;
+        }
+
+        std::cout << "GetAlertStatus Success: " << std::endl;
+        std::cout << "rack entry: 0x" << std::setfill('0') << std::setw(8)
+                  << std::hex << (int)rack_entry << std::endl;
+        std::cout << "pri cec node: 0x" << std::setfill('0') << std::setw(8)
+                  << std::hex << (int)pri_cec_node << std::endl;
+    }
+
+  private:
+    uint8_t versionId;
+};
+
+void registerCommand(CLI::App& app)
+{
+    auto oem_ibm = app.add_subcommand("oem-ibm", "oem type command");
+    oem_ibm->require_subcommand(1);
+
+    auto getAlertStatus = oem_ibm->add_subcommand(
+        "GetAlertStatus", "get alert status descriptor");
+    commands.push_back(std::make_unique<GetAlertStatus>(
+        "oem_ibm", "getAlertStatus", getAlertStatus));
+}
+} // namespace power_host
+} // namespace oem_ibm
+} // namespace pldmtool
diff --git a/tool/oem/ibm/pldm_host_cmd.hpp b/tool/oem/ibm/pldm_host_cmd.hpp
new file mode 100644
index 0000000..d57ccd4
--- /dev/null
+++ b/tool/oem/ibm/pldm_host_cmd.hpp
@@ -0,0 +1,19 @@
+#pragma once
+
+#include <CLI/CLI.hpp>
+
+namespace pldmtool
+{
+
+namespace oem_ibm
+{
+namespace power_host
+{
+
+void registerCommand(CLI::App& app);
+
+}
+
+} // namespace oem_ibm
+
+} // namespace pldmtool
diff --git a/tool/pldmtool.cpp b/tool/pldmtool.cpp
index 7e4e0e8..bbb222d 100644
--- a/tool/pldmtool.cpp
+++ b/tool/pldmtool.cpp
@@ -3,6 +3,7 @@
 #include "pldm_cmd_helper.hpp"
 #include "pldm_fru_cmd.hpp"
 #include "pldm_platform_cmd.hpp"
+#include "tool/oem/ibm/pldm_host_cmd.hpp"
 
 #include <CLI/CLI.hpp>
 
@@ -72,6 +73,7 @@
     pldmtool::bios::registerCommand(app);
     pldmtool::platform::registerCommand(app);
     pldmtool::fru::registerCommand(app);
+    pldmtool::oem_ibm::power_host::registerCommand(app);
 
     CLI11_PARSE(app, argc, argv);
     return 0;