pdr: Update D-Bus mapping structure
For most PDR types, the D-Bus object structure(paths, interfaces, and
properties) should be defined in the JSON file instead of hard-coded.
Tested with JSON files:
https://gist.github.com/lxwinspur/2c3fd68cdb35e06480c4a5f7890e3a06#file-effecter_pdr-json.
pldmtool platform GetPDR -d 1
Encode request successfully
Request Message:
08 01 80 02 51 01 00 00 00 00 00 00 00 01 80 00 00 00
Success in creating the socket : RC = 3
Success in connecting to socket : RC = 0
Success in sending message type as pldm to mctp : RC = 0
Write to socket successful : RC = 18
Total length:18
Loopback response message:
08 01 80 02 51 01 00 00 00 00 00 00 00 01 80 00 00 00
On first recv(),response == request : RC = 0
Total length: 46
Shutdown Socket successful : RC = 0
Response Message:
08 01 00 02 51 00 02 00 00 00 00 00 00 00 01 1d 00 01 00 00 00 01 0b 00 00 13 00 00 00 01 00 21 00 00 00 00 00 00 00 00 00 01 c4 00 01 06
Parsed Response Msg:
nextRecordHandle: 2
responseCount: 29
recordHandle: 1
PDRHeaderVersion: 1
PDRType: 11
recordChangeNumber: 0
dataLength: 19
PLDMTerminusHandle: 0
effecterID: 1
entityType: 33
entityInstanceNumber: 0
containerID: 0
effecterSemanticID: 0
effecterInit: 0
effecterDescriptionPDR: false
compositeEffecterCount: 1
stateSetID: 196
possibleStatesSize: 1
possibleStates: 6
Signed-off-by: George Liu <liuxiwei@inspur.com>
Change-Id: Ifc0cd1540b08e9b73e03d99d71a0980ef6353e72
diff --git a/libpldmresponder/platform.hpp b/libpldmresponder/platform.hpp
index 8c9e45c..9c8860e 100644
--- a/libpldmresponder/platform.hpp
+++ b/libpldmresponder/platform.hpp
@@ -21,8 +21,13 @@
namespace platform
{
-using DbusPath = std::string;
-using EffecterObjs = std::vector<DbusPath>;
+using namespace pldm::utils;
+using namespace pldm::responder::pdr_utils;
+
+using EffecterId = uint16_t;
+using DbusMappings = std::vector<DBusMapping>;
+using DbusValMaps = std::vector<StatestoDbusVal>;
+using DbusObjMaps = std::map<EffecterId, std::tuple<DbusMappings, DbusValMaps>>;
class Handler : public CmdHandler
{
@@ -42,15 +47,31 @@
});
}
- const EffecterObjs& getEffecterObjs(uint16_t effecterId) const
+ pdr_utils::Repo& getRepo()
{
- return effecterObjs.at(effecterId);
+ return this->pdrRepo;
}
- void addEffecterObjs(uint16_t effecterId, EffecterObjs&& paths)
- {
- effecterObjs.emplace(effecterId, std::move(paths));
- }
+ /** @brief Add D-Bus mapping and value mapping(stateId to D-Bus) for the
+ * effecterId. If the same id is added, the previous dbusObjs will
+ * be "over-written".
+ *
+ * @param[in] effecterId - effecter id
+ * @param[in] dbusObj - list of D-Bus object structure and list of D-Bus
+ * property value to attribute value
+ */
+ void addDbusObjMaps(uint16_t effecterId,
+ std::tuple<DbusMappings, DbusValMaps> dbusObj);
+
+ /** @brief Retrieve an effecter id -> D-Bus objects mapping
+ *
+ * @param[in] effecterId - effecter id
+ *
+ * @return std::tuple<DbusMappings, DbusValMaps> - list of D-Bus object
+ * structure and list of D-Bus property value to attribute value
+ */
+ const std::tuple<DbusMappings, DbusValMaps>&
+ getDbusObjMaps(uint16_t effecterId) const;
uint16_t getNextEffecterId()
{
@@ -103,37 +124,32 @@
{
using namespace pldm::responder::pdr;
using namespace pldm::utils;
- using namespace std::string_literals;
- using DBusProperty = std::variant<std::string, bool>;
- using StateSetId = uint16_t;
using StateSetNum = uint8_t;
- using PropertyMap =
- std::map<StateSetId, std::map<StateSetNum, DBusProperty>>;
- static const PropertyMap stateNumToDbusProp = {
- {PLDM_BOOT_PROGRESS_STATE,
- {{PLDM_BOOT_NOT_ACTIVE,
- "xyz.openbmc_project.State.OperatingSystem.Status.OSStatus."
- "Standby"s},
- {PLDM_BOOT_COMPLETED,
- "xyz.openbmc_project.State.OperatingSystem.Status.OSStatus."
- "BootComplete"s}}},
- {PLDM_SYSTEM_POWER_STATE,
- {{PLDM_OFF_SOFT_GRACEFUL,
- "xyz.openbmc_project.State.Chassis.Transition.Off"s}}}};
- using namespace pldm::responder::pdr;
state_effecter_possible_states* states = nullptr;
pldm_state_effecter_pdr* pdr = nullptr;
uint8_t compEffecterCnt = stateField.size();
+
+ std::unique_ptr<pldm_pdr, decltype(&pldm_pdr_destroy)>
+ stateEffecterPdrRepo(pldm_pdr_init(), pldm_pdr_destroy);
+ Repo stateEffecterPDRs(stateEffecterPdrRepo.get());
+ getRepoByType(pdrRepo, stateEffecterPDRs, PLDM_STATE_EFFECTER_PDR);
+ if (stateEffecterPDRs.empty())
+ {
+ std::cerr << "Failed to get record by PDR type\n";
+ return PLDM_PLATFORM_INVALID_EFFECTER_ID;
+ }
+
PdrEntry pdrEntry{};
- auto pdrRecord = pdrRepo.getFirstRecord(pdrEntry);
+ auto pdrRecord = stateEffecterPDRs.getFirstRecord(pdrEntry);
while (pdrRecord)
{
pdr = reinterpret_cast<pldm_state_effecter_pdr*>(pdrEntry.data);
if (pdr->effecter_id != effecterId)
{
pdr = nullptr;
- pdrRecord = pdrRepo.getNextRecord(pdrRecord, pdrEntry);
+ pdrRecord =
+ stateEffecterPDRs.getNextRecord(pdrRecord, pdrEntry);
continue;
}
@@ -155,152 +171,77 @@
return PLDM_PLATFORM_INVALID_EFFECTER_ID;
}
- std::map<StateSetId, std::function<int(const std::string& objPath,
- const uint8_t currState)>>
- effecterToDbusEntries = {
- {PLDM_BOOT_PROGRESS_STATE,
- [&](const std::string& objPath, const uint8_t currState) {
- auto stateSet =
- stateNumToDbusProp.find(PLDM_BOOT_PROGRESS_STATE);
- if (stateSet == stateNumToDbusProp.end())
- {
- std::cerr << "Couldn't find D-Bus mapping for "
- << "PLDM_BOOT_PROGRESS_STATE, EFFECTER_ID="
- << effecterId << "\n";
- return PLDM_ERROR;
- }
- auto iter = stateSet->second.find(
- stateField[currState].effecter_state);
- if (iter == stateSet->second.end())
- {
- std::cerr << "Invalid state field passed or field not "
- << "found for PLDM_BOOT_PROGRESS_STATE, "
- "EFFECTER_ID="
- << effecterId << " FIELD="
- << stateField[currState].effecter_state
- << " OBJECT_PATH=" << objPath.c_str()
- << "\n";
- return PLDM_ERROR_INVALID_DATA;
- }
- PropertyValue value{std::get<std::string>(iter->second)};
- DBusMapping dbusMapping{
- objPath,
- "xyz.openbmc_project.State.OperatingSystem.Status",
- "OperatingSystemState", "string"};
- try
- {
- dBusIntf.setDbusProperty(dbusMapping, value);
- }
- catch (const std::exception& e)
- {
- std::cerr
- << "Error setting property, ERROR=" << e.what()
- << " PROPERTY=" << dbusMapping.propertyName
- << " INTERFACE="
- << dbusMapping.interface << " PATH="
- << dbusMapping.objectPath << "\n";
- return PLDM_ERROR;
- }
- return PLDM_SUCCESS;
- }},
- {PLDM_SYSTEM_POWER_STATE,
- [&](const std::string& objPath, const uint8_t currState) {
- auto stateSet =
- stateNumToDbusProp.find(PLDM_SYSTEM_POWER_STATE);
- if (stateSet == stateNumToDbusProp.end())
- {
- std::cerr << "Couldn't find D-Bus mapping for "
- << "PLDM_SYSTEM_POWER_STATE, EFFECTER_ID="
- << effecterId << "\n";
- return PLDM_ERROR;
- }
- auto iter = stateSet->second.find(
- stateField[currState].effecter_state);
- if (iter == stateSet->second.end())
- {
- std::cerr << "Invalid state field passed or field not "
- << "found for PLDM_SYSTEM_POWER_STATE, "
- "EFFECTER_ID="
- << effecterId << " FIELD="
- << stateField[currState].effecter_state
- << " OBJECT_PATH=" << objPath.c_str()
- << "\n";
- return PLDM_ERROR_INVALID_DATA;
- }
- PropertyValue value{std::get<std::string>(iter->second)};
- DBusMapping dbusMapping{
- objPath, "xyz.openbmc_project.State.Chassis",
- "RequestedPowerTransition", "string"};
- try
- {
- dBusIntf.setDbusProperty(dbusMapping, value);
- }
- catch (const std::exception& e)
- {
- std::cerr
- << "Error setting property, ERROR=" << e.what()
- << " PROPERTY=" << dbusMapping.propertyName
- << " INTERFACE="
- << dbusMapping.interface << " PATH="
- << dbusMapping.objectPath << "\n";
- return PLDM_ERROR;
- }
- return PLDM_SUCCESS;
- }}};
-
int rc = PLDM_SUCCESS;
- const auto& paths = getEffecterObjs(effecterId);
- for (uint8_t currState = 0; currState < compEffecterCnt; ++currState)
+ try
{
- std::vector<StateSetNum> allowed{};
- // computation is based on table 79 from DSP0248 v1.1.1
- uint8_t bitfieldIndex = stateField[currState].effecter_state / 8;
- uint8_t bit =
- stateField[currState].effecter_state - (8 * bitfieldIndex);
- if (states->possible_states_size < bitfieldIndex ||
- !(states->states[bitfieldIndex].byte & (1 << bit)))
+ const auto& [dbusMappings, dbusValMaps] =
+ dbusObjMaps.at(effecterId);
+ for (uint8_t currState = 0; currState < compEffecterCnt;
+ ++currState)
{
- std::cerr << "Invalid state set value, EFFECTER_ID="
- << effecterId
- << " VALUE=" << stateField[currState].effecter_state
- << " COMPOSITE_EFFECTER_ID=" << currState
- << " DBUS_PATH=" << paths[currState].c_str() << "\n";
- rc = PLDM_PLATFORM_SET_EFFECTER_UNSUPPORTED_SENSORSTATE;
- break;
- }
- auto iter = effecterToDbusEntries.find(states->state_set_id);
- if (iter == effecterToDbusEntries.end())
- {
- uint16_t setId = states->state_set_id;
- std::cerr << "Did not find the state set for the"
- << " state effecter pdr, STATE=" << setId
- << " EFFECTER_ID=" << effecterId << "\n";
- rc = PLDM_PLATFORM_INVALID_STATE_VALUE;
- break;
- }
- if (stateField[currState].set_request == PLDM_REQUEST_SET)
- {
- rc = iter->second(paths[currState], currState);
- if (rc != PLDM_SUCCESS)
+ std::vector<StateSetNum> allowed{};
+ // computation is based on table 79 from DSP0248 v1.1.1
+ uint8_t bitfieldIndex =
+ stateField[currState].effecter_state / 8;
+ uint8_t bit =
+ stateField[currState].effecter_state - (8 * bitfieldIndex);
+ if (states->possible_states_size < bitfieldIndex ||
+ !(states->states[bitfieldIndex].byte & (1 << bit)))
{
+ std::cerr
+ << "Invalid state set value, EFFECTER_ID=" << effecterId
+ << " VALUE=" << stateField[currState].effecter_state
+ << " COMPOSITE_EFFECTER_ID=" << currState
+ << " DBUS_PATH=" << dbusMappings[currState].objectPath
+ << "\n";
+ rc = PLDM_PLATFORM_SET_EFFECTER_UNSUPPORTED_SENSORSTATE;
break;
}
+ const DBusMapping& dbusMapping = dbusMappings[currState];
+ const StatestoDbusVal& dbusValToMap = dbusValMaps[currState];
+
+ if (stateField[currState].set_request == PLDM_REQUEST_SET)
+ {
+ try
+ {
+ dBusIntf.setDbusProperty(
+ dbusMapping,
+ dbusValToMap.at(
+ stateField[currState].effecter_state));
+ }
+ catch (const std::exception& e)
+ {
+ std::cerr
+ << "Error setting property, ERROR=" << e.what()
+ << " PROPERTY=" << dbusMapping.propertyName
+ << " INTERFACE="
+ << dbusMapping.interface << " PATH="
+ << dbusMapping.objectPath << "\n";
+ return PLDM_ERROR;
+ }
+ }
+ uint8_t* nextState =
+ reinterpret_cast<uint8_t*>(states) +
+ sizeof(state_effecter_possible_states) -
+ sizeof(states->states) +
+ (states->possible_states_size * sizeof(states->states));
+ states = reinterpret_cast<state_effecter_possible_states*>(
+ nextState);
}
- uint8_t* nextState =
- reinterpret_cast<uint8_t*>(states) +
- sizeof(state_effecter_possible_states) -
- sizeof(states->states) +
- (states->possible_states_size * sizeof(states->states));
- states =
- reinterpret_cast<state_effecter_possible_states*>(nextState);
}
+ catch (const std::out_of_range& e)
+ {
+ std::cerr << "the effecterId does not exist. effecter id: "
+ << effecterId << e.what() << '\n';
+ }
+
return rc;
}
private:
pdr_utils::Repo pdrRepo;
uint16_t nextEffecterId{};
- std::map<uint16_t, EffecterObjs> effecterObjs{};
+ DbusObjMaps dbusObjMaps{};
};
} // namespace platform