Implement PDR.FindStateEffecterPDR DBus API
This commit implements a DBus API defined at
https://gerrit.openbmc-project.xyz/c/openbmc/phosphor-dbus-interfaces/+/31774
to find the stateEffecterPDR based on the entity ID
and stateSetID.
Tested: Unit tests and in witherspoon system
busctl call :1.187 /xyz/openbmc_project/pldm xyz.openbmc_project.PLDM.PDR FindStateEffecterPDR yqq 1 33 196
aay 1 29 1 0 0 0 1 11 0 0 19 0 0 0 1 0 33 0 0 0 0 0 0 0 0 0 1 196 0 1 6
busctl call :1.187 /xyz/openbmc_project/pldm xyz.openbmc_project.PLDM.PDR FindStateEffecterPDR yqq 1 31 129
aay 1 29 3 0 0 0 1 11 0 0 19 0 0 0 3 0 31 0 0 0 0 0 0 0 0 0 1 129 0 1 64
Change-Id: I5c15be5303b511465c36914f5b60a0957cd3857e
Signed-off-by: Pavithra Barithaya <pbaritha@in.ibm.com>
diff --git a/dbus_impl_pdr.cpp b/dbus_impl_pdr.cpp
new file mode 100644
index 0000000..c35e422
--- /dev/null
+++ b/dbus_impl_pdr.cpp
@@ -0,0 +1,33 @@
+#include "dbus_impl_pdr.hpp"
+
+#include "utils.hpp"
+#include "xyz/openbmc_project/Common/error.hpp"
+
+#include <iostream>
+
+#include "libpldm/pdr.h"
+#include "libpldm/pldm_types.h"
+
+using namespace sdbusplus::xyz::openbmc_project::Common::Error;
+
+namespace pldm
+{
+namespace dbus_api
+{
+
+std::vector<std::vector<uint8_t>> Pdr::findStateEffecterPDR(uint8_t tid,
+ uint16_t entityID,
+ uint16_t stateSetId)
+{
+ auto pdrs =
+ pldm::utils::findStateEffecterPDR(tid, entityID, stateSetId, pdrRepo);
+
+ if (pdrs.empty())
+ {
+ throw ResourceNotFound();
+ }
+
+ return pdrs;
+}
+} // namespace dbus_api
+} // namespace pldm
diff --git a/dbus_impl_pdr.hpp b/dbus_impl_pdr.hpp
new file mode 100644
index 0000000..7033526
--- /dev/null
+++ b/dbus_impl_pdr.hpp
@@ -0,0 +1,60 @@
+#pragma once
+
+#include "xyz/openbmc_project/PLDM/PDR/server.hpp"
+
+#include <sdbusplus/bus.hpp>
+#include <sdbusplus/server/object.hpp>
+#include <vector>
+
+#include "libpldm/pdr.h"
+#include "libpldm/platform.h"
+
+namespace pldm
+{
+namespace dbus_api
+{
+
+using PdrIntf = sdbusplus::server::object::object<
+ sdbusplus::xyz::openbmc_project::PLDM::server::PDR>;
+
+/** @class Pdr
+ * @brief OpenBMC PLDM.PDR Implementation
+ * @details A concrete implementation for the
+ * xyz.openbmc_project.PLDM.PDR DBus APIs.
+ */
+class Pdr : public PdrIntf
+{
+ public:
+ Pdr() = delete;
+ Pdr(const Pdr&) = delete;
+ Pdr& operator=(const Pdr&) = delete;
+ Pdr(Pdr&&) = delete;
+ Pdr& operator=(Pdr&&) = delete;
+ virtual ~Pdr() = default;
+
+ /** @brief Constructor to put object onto bus at a dbus path.
+ * @param[in] bus - Bus to attach to.
+ * @param[in] path - Path to attach at.
+ * @param[in] repo - pointer to BMC's primary PDR repo
+ */
+ Pdr(sdbusplus::bus::bus& bus, const std::string& path,
+ const pldm_pdr* repo) :
+ PdrIntf(bus, path.c_str(), repo),
+ pdrRepo(repo){};
+
+ /** @brief Implementation for PdrIntf.FindStateEffecterPDR
+ * @param[in] tid - PLDM terminus ID.
+ * @param[in] entityID - entity that can be associated with PLDM State set.
+ * @param[in] stateSetId - value that identifies PLDM State set.
+ */
+ std::vector<std::vector<uint8_t>>
+ findStateEffecterPDR(uint8_t tid, uint16_t entityID,
+ uint16_t stateSetId) override;
+
+ private:
+ /** @brief pointer to BMC's primary PDR repo */
+ const pldm_pdr* pdrRepo;
+};
+
+} // namespace dbus_api
+} // namespace pldm
diff --git a/meson.build b/meson.build
index 88fe1d2..4d2f1ec 100644
--- a/meson.build
+++ b/meson.build
@@ -69,6 +69,7 @@
'pldmd.cpp',
'dbus_impl_requester.cpp',
'instance_id.cpp',
+ 'dbus_impl_pdr.cpp',
implicit_include_directories: false,
dependencies: deps,
install: true,
diff --git a/pldmd.cpp b/pldmd.cpp
index d1ca6fa..4bc8943 100644
--- a/pldmd.cpp
+++ b/pldmd.cpp
@@ -1,3 +1,4 @@
+#include "dbus_impl_pdr.hpp"
#include "dbus_impl_requester.hpp"
#include "host_pdr_handler.hpp"
#include "invoker.hpp"
@@ -218,6 +219,7 @@
exit(EXIT_FAILURE);
}
+ dbus_api::Pdr dbusImplPdr(bus, "/xyz/openbmc_project/pldm", pdrRepo.get());
auto callback = [verbose, &invoker, &dbusImplReq](IO& /*io*/, int fd,
uint32_t revents) {
if (!(revents & EPOLLIN))
diff --git a/test/pldm_utils_test.cpp b/test/pldm_utils_test.cpp
index c880c20..4af91d1 100644
--- a/test/pldm_utils_test.cpp
+++ b/test/pldm_utils_test.cpp
@@ -1,5 +1,7 @@
#include "utils.hpp"
+#include "libpldm/platform.h"
+
#include <gtest/gtest.h>
using namespace pldm::utils;
@@ -77,3 +79,404 @@
EXPECT_EQ(effecterField, std::nullopt);
}
+
+TEST(FindStateEffecterPDR, testOneMatch)
+{
+
+ auto repo = pldm_pdr_init();
+ uint8_t tid = 1;
+ uint16_t entityID = 33;
+ uint16_t stateSetId = 196;
+
+ std::vector<uint8_t> pdr(sizeof(struct pldm_state_effecter_pdr) -
+ sizeof(uint8_t) +
+ sizeof(struct state_effecter_possible_states));
+
+ auto rec = reinterpret_cast<pldm_state_effecter_pdr*>(pdr.data());
+
+ auto state =
+ reinterpret_cast<state_effecter_possible_states*>(rec->possible_states);
+
+ rec->hdr.type = 11;
+ rec->hdr.record_handle = 1;
+ rec->entity_type = 33;
+ rec->container_id = 0;
+ rec->composite_effecter_count = 1;
+ state->state_set_id = 196;
+ state->possible_states_size = 1;
+
+ pldm_pdr_add(repo, pdr.data(), pdr.size(), 0, false);
+
+ auto record = findStateEffecterPDR(tid, entityID, stateSetId, repo);
+
+ EXPECT_EQ(pdr, record[0]);
+
+ pldm_pdr_destroy(repo);
+}
+
+TEST(FindStateEffecterPDR, testNoMatch)
+{
+
+ auto repo = pldm_pdr_init();
+ uint8_t tid = 1;
+ uint16_t entityID = 44;
+ uint16_t stateSetId = 196;
+
+ std::vector<uint8_t> pdr(sizeof(struct pldm_state_effecter_pdr) -
+ sizeof(uint8_t) +
+ sizeof(struct state_effecter_possible_states));
+
+ auto rec = reinterpret_cast<pldm_state_effecter_pdr*>(pdr.data());
+
+ auto state =
+ reinterpret_cast<state_effecter_possible_states*>(rec->possible_states);
+
+ rec->hdr.type = 11;
+ rec->hdr.record_handle = 1;
+ rec->entity_type = 33;
+ rec->container_id = 0;
+ rec->composite_effecter_count = 1;
+ state->state_set_id = 196;
+ state->possible_states_size = 1;
+
+ pldm_pdr_add(repo, pdr.data(), pdr.size(), 0, false);
+
+ auto record = findStateEffecterPDR(tid, entityID, stateSetId, repo);
+
+ EXPECT_EQ(record.empty(), true);
+
+ pldm_pdr_destroy(repo);
+}
+
+TEST(FindStateEffecterPDR, testEmptyRepo)
+{
+
+ auto repo = pldm_pdr_init();
+ uint8_t tid = 1;
+ uint16_t entityID = 33;
+ uint16_t stateSetId = 196;
+
+ std::vector<uint8_t> pdr(sizeof(struct pldm_state_effecter_pdr) -
+ sizeof(uint8_t) +
+ sizeof(struct state_effecter_possible_states));
+
+ auto record = findStateEffecterPDR(tid, entityID, stateSetId, repo);
+
+ EXPECT_EQ(record.empty(), true);
+
+ pldm_pdr_destroy(repo);
+}
+
+TEST(FindStateEffecterPDR, testMoreMatch)
+{
+
+ auto repo = pldm_pdr_init();
+ uint8_t tid = 1;
+
+ std::vector<uint8_t> pdr(sizeof(struct pldm_state_effecter_pdr) -
+ sizeof(uint8_t) +
+ sizeof(struct state_effecter_possible_states));
+
+ auto rec = reinterpret_cast<pldm_state_effecter_pdr*>(pdr.data());
+
+ auto state =
+ reinterpret_cast<state_effecter_possible_states*>(rec->possible_states);
+
+ rec->hdr.type = 11;
+ rec->hdr.record_handle = 1;
+ rec->entity_type = 31;
+ rec->container_id = 0;
+ rec->composite_effecter_count = 1;
+ state->state_set_id = 129;
+ state->possible_states_size = 1;
+
+ pldm_pdr_add(repo, pdr.data(), pdr.size(), 0, false);
+
+ std::vector<uint8_t> pdr_second(
+ sizeof(struct pldm_state_effecter_pdr) - sizeof(uint8_t) +
+ sizeof(struct state_effecter_possible_states));
+
+ auto rec_second =
+ reinterpret_cast<pldm_state_effecter_pdr*>(pdr_second.data());
+
+ auto state_second = reinterpret_cast<state_effecter_possible_states*>(
+ rec_second->possible_states);
+
+ rec_second->hdr.type = 11;
+ rec_second->hdr.record_handle = 2;
+ rec_second->entity_type = 31;
+ rec_second->container_id = 0;
+ rec_second->composite_effecter_count = 1;
+ state_second->state_set_id = 129;
+ state_second->possible_states_size = 1;
+
+ pldm_pdr_add(repo, pdr_second.data(), pdr_second.size(), 0, false);
+
+ uint16_t entityID_ = 31;
+ uint16_t stateSetId_ = 129;
+
+ auto record = findStateEffecterPDR(tid, entityID_, stateSetId_, repo);
+
+ EXPECT_EQ(pdr, record[0]);
+ EXPECT_EQ(pdr_second, record[1]);
+
+ pldm_pdr_destroy(repo);
+}
+
+TEST(FindStateEffecterPDR, testManyNoMatch)
+{
+
+ auto repo = pldm_pdr_init();
+ uint8_t tid = 1;
+ uint16_t entityID = 33;
+ uint16_t stateSetId = 196;
+
+ std::vector<uint8_t> pdr(sizeof(struct pldm_state_effecter_pdr) -
+ sizeof(uint8_t) +
+ sizeof(struct state_effecter_possible_states));
+
+ auto rec = reinterpret_cast<pldm_state_effecter_pdr*>(pdr.data());
+
+ auto state =
+ reinterpret_cast<state_effecter_possible_states*>(rec->possible_states);
+
+ rec->hdr.type = 11;
+ rec->hdr.record_handle = 1;
+ rec->entity_type = 34;
+ rec->container_id = 0;
+ rec->composite_effecter_count = 1;
+ state->state_set_id = 198;
+ state->possible_states_size = 1;
+
+ pldm_pdr_add(repo, pdr.data(), pdr.size(), 0, false);
+
+ std::vector<uint8_t> pdr_second(
+ sizeof(struct pldm_state_effecter_pdr) - sizeof(uint8_t) +
+ sizeof(struct state_effecter_possible_states));
+
+ auto rec_second =
+ reinterpret_cast<pldm_state_effecter_pdr*>(pdr_second.data());
+
+ auto state_second = reinterpret_cast<state_effecter_possible_states*>(
+ rec_second->possible_states);
+
+ rec_second->hdr.type = 11;
+ rec_second->hdr.record_handle = 2;
+ rec_second->entity_type = 39;
+ rec_second->container_id = 0;
+ rec_second->composite_effecter_count = 1;
+ state_second->state_set_id = 169;
+ state_second->possible_states_size = 1;
+
+ pldm_pdr_add(repo, pdr_second.data(), pdr_second.size(), 0, false);
+
+ auto record = findStateEffecterPDR(tid, entityID, stateSetId, repo);
+
+ EXPECT_EQ(record.empty(), true);
+
+ pldm_pdr_destroy(repo);
+}
+
+TEST(FindStateEffecterPDR, testOneMatchOneNoMatch)
+{
+ auto repo = pldm_pdr_init();
+ uint8_t tid = 1;
+ uint16_t entityID = 67;
+ uint16_t stateSetId = 192;
+
+ std::vector<uint8_t> pdr(sizeof(struct pldm_state_effecter_pdr) -
+ sizeof(uint8_t) +
+ sizeof(struct state_effecter_possible_states));
+
+ auto rec = reinterpret_cast<pldm_state_effecter_pdr*>(pdr.data());
+
+ auto state =
+ reinterpret_cast<state_effecter_possible_states*>(rec->possible_states);
+
+ rec->hdr.type = 11;
+ rec->hdr.record_handle = 1;
+ rec->entity_type = 32;
+ rec->container_id = 0;
+ rec->composite_effecter_count = 1;
+ state->state_set_id = 198;
+ state->possible_states_size = 1;
+
+ pldm_pdr_add(repo, pdr.data(), pdr.size(), 0, false);
+
+ std::vector<uint8_t> pdr_second(
+ sizeof(struct pldm_state_effecter_pdr) - sizeof(uint8_t) +
+ sizeof(struct state_effecter_possible_states));
+
+ auto rec_second =
+ reinterpret_cast<pldm_state_effecter_pdr*>(pdr_second.data());
+
+ auto state_second = reinterpret_cast<state_effecter_possible_states*>(
+ rec_second->possible_states);
+
+ rec_second->hdr.type = 11;
+ rec_second->hdr.record_handle = 2;
+ rec_second->entity_type = 67;
+ rec_second->container_id = 0;
+ rec_second->composite_effecter_count = 1;
+ state_second->state_set_id = 192;
+ state_second->possible_states_size = 1;
+
+ pldm_pdr_add(repo, pdr_second.data(), pdr_second.size(), 0, false);
+
+ auto record = findStateEffecterPDR(tid, entityID, stateSetId, repo);
+
+ EXPECT_EQ(pdr_second, record[0]);
+ EXPECT_EQ(record.size(), 1);
+
+ pldm_pdr_destroy(repo);
+}
+
+TEST(FindStateEffecterPDR, testOneMatchManyNoMatch)
+{
+ auto repo = pldm_pdr_init();
+ uint8_t tid = 1;
+ uint16_t entityID = 67;
+ uint16_t stateSetId = 192;
+
+ std::vector<uint8_t> pdr(sizeof(struct pldm_state_effecter_pdr) -
+ sizeof(uint8_t) +
+ sizeof(struct state_effecter_possible_states));
+
+ auto rec = reinterpret_cast<pldm_state_effecter_pdr*>(pdr.data());
+
+ auto state =
+ reinterpret_cast<state_effecter_possible_states*>(rec->possible_states);
+
+ rec->hdr.type = 11;
+ rec->hdr.record_handle = 1;
+ rec->entity_type = 32;
+ rec->container_id = 0;
+ rec->composite_effecter_count = 1;
+ state->state_set_id = 198;
+ state->possible_states_size = 1;
+
+ pldm_pdr_add(repo, pdr.data(), pdr.size(), 0, false);
+
+ std::vector<uint8_t> pdr_second(
+ sizeof(struct pldm_state_effecter_pdr) - sizeof(uint8_t) +
+ sizeof(struct state_effecter_possible_states));
+
+ auto rec_second =
+ reinterpret_cast<pldm_state_effecter_pdr*>(pdr_second.data());
+
+ auto state_second = reinterpret_cast<state_effecter_possible_states*>(
+ rec_second->possible_states);
+
+ rec_second->hdr.type = 11;
+ rec_second->hdr.record_handle = 2;
+ rec_second->entity_type = 67;
+ rec_second->container_id = 0;
+ rec_second->composite_effecter_count = 1;
+ state_second->state_set_id = 192;
+ state_second->possible_states_size = 1;
+
+ pldm_pdr_add(repo, pdr_second.data(), pdr_second.size(), 0, false);
+
+ std::vector<uint8_t> pdr_third(
+ sizeof(struct pldm_state_effecter_pdr) - sizeof(uint8_t) +
+ sizeof(struct state_effecter_possible_states));
+
+ auto rec_third =
+ reinterpret_cast<pldm_state_effecter_pdr*>(pdr_third.data());
+
+ auto state_third = reinterpret_cast<state_effecter_possible_states*>(
+ rec_third->possible_states);
+
+ rec_third->hdr.type = 11;
+ rec_third->hdr.record_handle = 3;
+ rec_third->entity_type = 69;
+ rec_third->container_id = 0;
+ rec_third->composite_effecter_count = 1;
+ state_third->state_set_id = 199;
+ state_third->possible_states_size = 1;
+
+ auto record = findStateEffecterPDR(tid, entityID, stateSetId, repo);
+
+ EXPECT_EQ(pdr_second, record[0]);
+ EXPECT_EQ(record.size(), 1);
+
+ pldm_pdr_destroy(repo);
+}
+
+TEST(FindStateEffecterPDR, testCompositeEffecter)
+{
+ auto repo = pldm_pdr_init();
+ uint8_t tid = 1;
+ uint16_t entityID = 67;
+ uint16_t stateSetId = 192;
+
+ std::vector<uint8_t> pdr(sizeof(struct pldm_state_effecter_pdr) -
+ sizeof(uint8_t) +
+ sizeof(struct state_effecter_possible_states));
+
+ auto rec = reinterpret_cast<pldm_state_effecter_pdr*>(pdr.data());
+
+ auto state =
+ reinterpret_cast<state_effecter_possible_states*>(rec->possible_states);
+
+ rec->hdr.type = 11;
+ rec->hdr.record_handle = 1;
+ rec->entity_type = 67;
+ rec->container_id = 0;
+ rec->composite_effecter_count = 3;
+ state->state_set_id = 198;
+ state->possible_states_size = 1;
+
+ state->state_set_id = 193;
+ state->possible_states_size = 1;
+
+ state->state_set_id = 192;
+ state->possible_states_size = 1;
+
+ pldm_pdr_add(repo, pdr.data(), pdr.size(), 0, false);
+
+ auto record = findStateEffecterPDR(tid, entityID, stateSetId, repo);
+
+ EXPECT_EQ(pdr, record[0]);
+
+ pldm_pdr_destroy(repo);
+}
+
+TEST(FindStateEffecterPDR, testNoMatchCompositeEffecter)
+{
+ auto repo = pldm_pdr_init();
+ uint8_t tid = 1;
+ uint16_t entityID = 67;
+ uint16_t stateSetId = 192;
+
+ std::vector<uint8_t> pdr(sizeof(struct pldm_state_effecter_pdr) -
+ sizeof(uint8_t) +
+ sizeof(struct state_effecter_possible_states));
+
+ auto rec = reinterpret_cast<pldm_state_effecter_pdr*>(pdr.data());
+
+ auto state =
+ reinterpret_cast<state_effecter_possible_states*>(rec->possible_states);
+
+ rec->hdr.type = 11;
+ rec->hdr.record_handle = 1;
+ rec->entity_type = 34;
+ rec->container_id = 0;
+ rec->composite_effecter_count = 3;
+ state->state_set_id = 198;
+ state->possible_states_size = 1;
+
+ state->state_set_id = 193;
+ state->possible_states_size = 1;
+
+ state->state_set_id = 123;
+ state->possible_states_size = 1;
+
+ pldm_pdr_add(repo, pdr.data(), pdr.size(), 0, false);
+
+ auto record = findStateEffecterPDR(tid, entityID, stateSetId, repo);
+
+ EXPECT_EQ(record.empty(), true);
+
+ pldm_pdr_destroy(repo);
+}
diff --git a/utils.cpp b/utils.cpp
index 6a93d99..27fda03 100644
--- a/utils.cpp
+++ b/utils.cpp
@@ -10,6 +10,9 @@
#include <vector>
#include <xyz/openbmc_project/Common/error.hpp>
+#include "libpldm/pdr.h"
+#include "libpldm/pldm_types.h"
+
namespace pldm
{
namespace utils
@@ -20,6 +23,59 @@
constexpr auto mapperInterface = "xyz.openbmc_project.ObjectMapper";
constexpr auto eidPath = "/usr/share/pldm/host_eid";
+std::vector<std::vector<uint8_t>> findStateEffecterPDR(uint8_t /*tid*/,
+ uint16_t entityID,
+ uint16_t stateSetId,
+ const pldm_pdr* repo)
+{
+ uint8_t* outData = nullptr;
+ uint32_t size{};
+ const pldm_pdr_record* record{};
+ std::vector<std::vector<uint8_t>> pdrs;
+ try
+ {
+ do
+ {
+ record = pldm_pdr_find_record_by_type(repo, PLDM_STATE_EFFECTER_PDR,
+ record, &outData, &size);
+ if (record)
+ {
+ auto pdr = reinterpret_cast<pldm_state_effecter_pdr*>(outData);
+ auto compositeEffecterCount = pdr->composite_effecter_count;
+
+ for (auto effecters = 0x00; effecters < compositeEffecterCount;
+ effecters++)
+ {
+ auto possibleStates =
+ reinterpret_cast<state_effecter_possible_states*>(
+ pdr->possible_states);
+ auto setId = possibleStates->state_set_id;
+ auto possibleStateSize =
+ possibleStates->possible_states_size;
+
+ if (pdr->entity_type == entityID && setId == stateSetId)
+ {
+ std::vector<uint8_t> effecter_pdr(&outData[0],
+ &outData[size]);
+ pdrs.emplace_back(std::move(effecter_pdr));
+ break;
+ }
+ possibleStates += possibleStateSize + sizeof(setId) +
+ sizeof(possibleStateSize);
+ }
+ }
+
+ } while (record);
+ }
+ catch (const std::exception& e)
+ {
+ std::cerr << " Failed to obtain a record. ERROR =" << e.what()
+ << std::endl;
+ }
+
+ return pdrs;
+}
+
uint8_t readHostEID()
{
uint8_t eid{};
diff --git a/utils.hpp b/utils.hpp
index abf525b..0814de2 100644
--- a/utils.hpp
+++ b/utils.hpp
@@ -259,5 +259,17 @@
PropertyValue jsonEntryToDbusVal(std::string_view type,
const nlohmann::json& value);
+/** @brief Find State Effecter PDR
+ * @param[in] tid - PLDM terminus ID.
+ * @param[in] entityID - entity that can be associated with PLDM State set.
+ * @param[in] stateSetId - value that identifies PLDM State set.
+ * @param[in] repo - pointer to BMC's primary PDR repo.
+ * @return array[array[uint8_t]] - StateEffecterPDRs
+ */
+std::vector<std::vector<uint8_t>> findStateEffecterPDR(uint8_t tid,
+ uint16_t entityID,
+ uint16_t stateSetId,
+ const pldm_pdr* repo);
+
} // namespace utils
} // namespace pldm