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/CMakeLists.txt b/CMakeLists.txt
index 441b320..398f396 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -7,6 +7,8 @@
target_include_directories(peci PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
set_target_properties(peci PROPERTIES VERSION "1.0" SOVERSION "1")
+option(DBUS_RAW_PECI "Add the raw PECI D-Bus daemon to the build." OFF)
+
set(
CMAKE_C_FLAGS
"${CMAKE_C_FLAGS} \
@@ -38,3 +40,28 @@
RUNTIME DESTINATION bin
LIBRARY DESTINATION lib
ARCHIVE DESTINATION lib/static)
+
+if(${DBUS_RAW_PECI})
+ add_executable(raw-peci dbus_raw_peci.cpp)
+ add_dependencies(raw-peci peci)
+
+ find_package(Boost 1.73 REQUIRED)
+ include_directories(${BOOST_SRC_DIR})
+
+ add_definitions(-DBOOST_ERROR_CODE_HEADER_ONLY)
+ add_definitions(-DBOOST_SYSTEM_NO_DEPRECATED)
+ add_definitions(-DBOOST_ALL_NO_LIB)
+ add_definitions(-DBOOST_NO_RTTI)
+ add_definitions(-DBOOST_NO_TYPEID)
+
+ target_link_libraries(raw-peci peci -lsystemd sdbusplus)
+
+ install(TARGETS raw-peci
+ RUNTIME DESTINATION bin
+ LIBRARY DESTINATION lib
+ ARCHIVE DESTINATION lib/static)
+
+ set(SERVICE_FILES ${PROJECT_SOURCE_DIR}/service_files/com.intel.peci.service)
+
+ install(FILES ${SERVICE_FILES} DESTINATION /lib/systemd/system/)
+endif()
\ No newline at end of file
diff --git a/README.md b/README.md
index bc825ec..a6a1374 100644
--- a/README.md
+++ b/README.md
@@ -10,3 +10,9 @@
This repo also includes a peci_cmds command-line utility with functions that
map to the libpeci APIs. It can be used to test PECI functionality across
the library, driver, and hardware.
+
+## dbus_raw_peci
+This repo also includes dbus_raw_peci which provides a raw-peci daemon that
+exposes a raw PECI interface that is accessible over D-Bus. It can be used
+when an application needs to send a raw PECI command without loading the full
+PECI library.
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
diff --git a/service_files/com.intel.peci.service b/service_files/com.intel.peci.service
new file mode 100644
index 0000000..88c7025
--- /dev/null
+++ b/service_files/com.intel.peci.service
@@ -0,0 +1,11 @@
+[Unit]
+Description=Intel CPU Raw PECI interface
+
+[Service]
+Restart=always
+ExecStart=/usr/bin/raw-peci
+Type=dbus
+BusName=com.intel.peci
+
+[Install]
+WantedBy=multi-user.target