Add D-Bus Raw PECI Daemon

This adds a new D-Bus daemon to handle raw PECI requests over
D-Bus.

The D-Bus interface provides a Send method that takes a
vector of byte vectors where each byte vector contains the raw
data for a single PECI command.  This allows sending an array
of raw PECI commands to execute in bulk to avoid issues with
network latency when sending multiple commands.

The method returns a vector of raw PECI responses corresponding
to the vector of raw commands.

Tested:
Confirmed that a single and multiple PECI commands correctly
execute and return when SendRawPeci is called.

Change-Id: I6b2d0f81366ea77057e70d69c72be90ba4c4aeb9
Signed-off-by: Jason M. Bills <jason.m.bills@linux.intel.com>
diff --git a/dbus_raw_peci.cpp b/dbus_raw_peci.cpp
new file mode 100644
index 0000000..49e1c5d
--- /dev/null
+++ b/dbus_raw_peci.cpp
@@ -0,0 +1,82 @@
+/*
+// Copyright (c) 2021 Intel Corporation
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+*/
+#include <peci.h>
+
+#include <boost/asio/io_service.hpp>
+#include <iostream>
+#include <sdbusplus/asio/object_server.hpp>
+
+int main()
+{
+    boost::asio::io_service io;
+    std::shared_ptr<sdbusplus::asio::connection> conn;
+    std::shared_ptr<sdbusplus::asio::object_server> server;
+
+    // setup connection to dbus
+    conn = std::make_shared<sdbusplus::asio::connection>(io);
+
+    conn->request_name("com.intel.peci");
+    server = std::make_shared<sdbusplus::asio::object_server>(conn);
+
+    // Send Raw PECI Interface
+    std::shared_ptr<sdbusplus::asio::dbus_interface> ifaceRawPeci =
+        server->add_interface("/com/intel/peci", "com.intel.Protocol.PECI.Raw");
+
+    // Send a Raw PECI command
+    ifaceRawPeci->register_method(
+        "Send", [](const std::string& peciDev,
+                   const std::vector<std::vector<uint8_t>>& rawCmds) {
+            peci_SetDevName(const_cast<char*>(peciDev.c_str()));
+            // D-Bus will time out after too long, so set a deadline for when to
+            // abort the PECI commands (at 25s, it mostly times out, at 24s it
+            // doesn't, so use 23s to be safe)
+            constexpr int peciTimeout = 23;
+            std::chrono::steady_clock::time_point peciDeadline =
+                std::chrono::steady_clock::now() +
+                std::chrono::duration<int>(peciTimeout);
+            std::vector<std::vector<uint8_t>> rawResp;
+            rawResp.resize(rawCmds.size());
+            for (size_t i = 0; i < rawCmds.size(); i++)
+            {
+                const std::vector<uint8_t>& rawCmd = rawCmds[i];
+                // If the commands are taking too long, return early to avoid a
+                // D-Bus timeout
+                if (std::chrono::steady_clock::now() > peciDeadline)
+                {
+                    std::cerr << peciTimeout
+                              << " second deadline reached.  Aborting PECI "
+                                 "commands to avoid a timeout\n";
+                    break;
+                }
+
+                if (rawCmd.size() < 3)
+                {
+                    peci_SetDevName(NULL);
+                    throw std::invalid_argument("Command Length too short");
+                }
+                rawResp[i].resize(rawCmd[2]);
+                peci_raw(rawCmd[0], rawCmd[2], &rawCmd[3], rawCmd[1],
+                         rawResp[i].data(), rawResp[i].size());
+            }
+            peci_SetDevName(NULL);
+            return rawResp;
+        });
+    ifaceRawPeci->initialize();
+
+    io.run();
+
+    return 0;
+}
\ No newline at end of file