1557dfb00SDeepak Kodihalli 2557dfb00SDeepak Kodihalli #include "platform.hpp" 3557dfb00SDeepak Kodihalli 483409573SGeorge Liu #include "utils.hpp" 583409573SGeorge Liu 6557dfb00SDeepak Kodihalli namespace pldm 7557dfb00SDeepak Kodihalli { 8557dfb00SDeepak Kodihalli namespace responder 9557dfb00SDeepak Kodihalli { 10a2fa0709SSampa Misra namespace platform 11a2fa0709SSampa Misra { 12a2fa0709SSampa Misra 13c682fe2dSDeepak Kodihalli using InternalFailure = 14c682fe2dSDeepak Kodihalli sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure; 15c682fe2dSDeepak Kodihalli 16c682fe2dSDeepak Kodihalli void Handler::generateStateEffecterRepo(const Json& json, Repo& repo) 17c682fe2dSDeepak Kodihalli { 18c682fe2dSDeepak Kodihalli static const std::vector<Json> emptyList{}; 19c682fe2dSDeepak Kodihalli static const Json empty{}; 20c682fe2dSDeepak Kodihalli auto entries = json.value("entries", emptyList); 21c682fe2dSDeepak Kodihalli for (const auto& e : entries) 22c682fe2dSDeepak Kodihalli { 23c682fe2dSDeepak Kodihalli size_t pdrSize = 0; 24c682fe2dSDeepak Kodihalli auto effecters = e.value("effecters", emptyList); 25c682fe2dSDeepak Kodihalli static const Json empty{}; 26c682fe2dSDeepak Kodihalli for (const auto& effecter : effecters) 27c682fe2dSDeepak Kodihalli { 28c682fe2dSDeepak Kodihalli auto set = effecter.value("set", empty); 29c682fe2dSDeepak Kodihalli auto statesSize = set.value("size", 0); 30c682fe2dSDeepak Kodihalli if (!statesSize) 31c682fe2dSDeepak Kodihalli { 32c682fe2dSDeepak Kodihalli std::cerr << "Malformed PDR JSON return " 33c682fe2dSDeepak Kodihalli "pdrEntry;- no state set " 34c682fe2dSDeepak Kodihalli "info, TYPE=" 35c682fe2dSDeepak Kodihalli << PLDM_STATE_EFFECTER_PDR << "\n"; 36c682fe2dSDeepak Kodihalli throw InternalFailure(); 37c682fe2dSDeepak Kodihalli } 38c682fe2dSDeepak Kodihalli pdrSize += sizeof(state_effecter_possible_states) - 39c682fe2dSDeepak Kodihalli sizeof(bitfield8_t) + (sizeof(bitfield8_t) * statesSize); 40c682fe2dSDeepak Kodihalli } 41c682fe2dSDeepak Kodihalli pdrSize += sizeof(pldm_state_effecter_pdr) - sizeof(uint8_t); 42c682fe2dSDeepak Kodihalli 43c682fe2dSDeepak Kodihalli std::vector<uint8_t> entry{}; 44c682fe2dSDeepak Kodihalli entry.resize(pdrSize); 45c682fe2dSDeepak Kodihalli 46c682fe2dSDeepak Kodihalli pldm_state_effecter_pdr* pdr = 47c682fe2dSDeepak Kodihalli reinterpret_cast<pldm_state_effecter_pdr*>(entry.data()); 48c682fe2dSDeepak Kodihalli pdr->hdr.record_handle = 0; 49c682fe2dSDeepak Kodihalli pdr->hdr.version = 1; 50c682fe2dSDeepak Kodihalli pdr->hdr.type = PLDM_STATE_EFFECTER_PDR; 51c682fe2dSDeepak Kodihalli pdr->hdr.record_change_num = 0; 52c682fe2dSDeepak Kodihalli pdr->hdr.length = pdrSize - sizeof(pldm_pdr_hdr); 53c682fe2dSDeepak Kodihalli 54c682fe2dSDeepak Kodihalli pdr->terminus_handle = 0; 55c682fe2dSDeepak Kodihalli pdr->effecter_id = this->getNextEffecterId(); 56c682fe2dSDeepak Kodihalli pdr->entity_type = e.value("type", 0); 57c682fe2dSDeepak Kodihalli pdr->entity_instance = e.value("instance", 0); 58c682fe2dSDeepak Kodihalli pdr->container_id = e.value("container", 0); 59c682fe2dSDeepak Kodihalli pdr->effecter_semantic_id = 0; 60c682fe2dSDeepak Kodihalli pdr->effecter_init = PLDM_NO_INIT; 61c682fe2dSDeepak Kodihalli pdr->has_description_pdr = false; 62c682fe2dSDeepak Kodihalli pdr->composite_effecter_count = effecters.size(); 63c682fe2dSDeepak Kodihalli 64c682fe2dSDeepak Kodihalli EffecterObjs paths{}; 65c682fe2dSDeepak Kodihalli uint8_t* start = 66c682fe2dSDeepak Kodihalli entry.data() + sizeof(pldm_state_effecter_pdr) - sizeof(uint8_t); 67c682fe2dSDeepak Kodihalli for (const auto& effecter : effecters) 68c682fe2dSDeepak Kodihalli { 69c682fe2dSDeepak Kodihalli auto set = effecter.value("set", empty); 70c682fe2dSDeepak Kodihalli state_effecter_possible_states* possibleStates = 71c682fe2dSDeepak Kodihalli reinterpret_cast<state_effecter_possible_states*>(start); 72c682fe2dSDeepak Kodihalli possibleStates->state_set_id = set.value("id", 0); 73c682fe2dSDeepak Kodihalli possibleStates->possible_states_size = set.value("size", 0); 74c682fe2dSDeepak Kodihalli 75c682fe2dSDeepak Kodihalli start += sizeof(possibleStates->state_set_id) + 76c682fe2dSDeepak Kodihalli sizeof(possibleStates->possible_states_size); 77c682fe2dSDeepak Kodihalli static const std::vector<uint8_t> emptyStates{}; 78c682fe2dSDeepak Kodihalli auto states = set.value("states", emptyStates); 79c682fe2dSDeepak Kodihalli for (const auto& state : states) 80c682fe2dSDeepak Kodihalli { 81c682fe2dSDeepak Kodihalli auto index = state / 8; 82c682fe2dSDeepak Kodihalli auto bit = state - (index * 8); 83c682fe2dSDeepak Kodihalli bitfield8_t* bf = reinterpret_cast<bitfield8_t*>(start + index); 84c682fe2dSDeepak Kodihalli bf->byte |= 1 << bit; 85c682fe2dSDeepak Kodihalli } 86c682fe2dSDeepak Kodihalli start += possibleStates->possible_states_size; 87c682fe2dSDeepak Kodihalli 88c682fe2dSDeepak Kodihalli auto dbus = effecter.value("dbus", empty); 89c682fe2dSDeepak Kodihalli paths.emplace_back(std::move(dbus)); 90c682fe2dSDeepak Kodihalli } 91c682fe2dSDeepak Kodihalli addEffecterObjs(pdr->effecter_id, std::move(paths)); 92c682fe2dSDeepak Kodihalli PdrEntry pdrEntry{}; 93c682fe2dSDeepak Kodihalli pdrEntry.data = entry.data(); 94c682fe2dSDeepak Kodihalli pdrEntry.size = pdrSize; 95c682fe2dSDeepak Kodihalli repo.addRecord(pdrEntry); 96c682fe2dSDeepak Kodihalli } 97c682fe2dSDeepak Kodihalli } 98c682fe2dSDeepak Kodihalli 99c682fe2dSDeepak Kodihalli void Handler::generate(const std::string& dir, Repo& repo) 100c682fe2dSDeepak Kodihalli { 101c682fe2dSDeepak Kodihalli // A map of PDR type to a lambda that handles creation of that PDR type. 102c682fe2dSDeepak Kodihalli // The lambda essentially would parse the platform specific PDR JSONs to 103c682fe2dSDeepak Kodihalli // generate the PDR structures. This function iterates through the map to 104c682fe2dSDeepak Kodihalli // invoke all lambdas, so that all PDR types can be created. 105c682fe2dSDeepak Kodihalli const std::map<Type, std::function<void(const Json& json, Repo& repo)>> 106c682fe2dSDeepak Kodihalli generators = { 107c682fe2dSDeepak Kodihalli {PLDM_STATE_EFFECTER_PDR, [this](const auto& json, Repo& repo) { 108c682fe2dSDeepak Kodihalli generateStateEffecterRepo(json, repo); 109c682fe2dSDeepak Kodihalli }}}; 110c682fe2dSDeepak Kodihalli 111c682fe2dSDeepak Kodihalli Type pdrType{}; 112c682fe2dSDeepak Kodihalli for (const auto& dirEntry : fs::directory_iterator(dir)) 113c682fe2dSDeepak Kodihalli { 114c682fe2dSDeepak Kodihalli try 115c682fe2dSDeepak Kodihalli { 116c682fe2dSDeepak Kodihalli auto json = readJson(dirEntry.path().string()); 117c682fe2dSDeepak Kodihalli if (!json.empty()) 118c682fe2dSDeepak Kodihalli { 119c682fe2dSDeepak Kodihalli pdrType = json.value("pdrType", 0); 120c682fe2dSDeepak Kodihalli generators.at(pdrType)(json, repo); 121c682fe2dSDeepak Kodihalli } 122c682fe2dSDeepak Kodihalli } 123c682fe2dSDeepak Kodihalli catch (const InternalFailure& e) 124c682fe2dSDeepak Kodihalli { 125c682fe2dSDeepak Kodihalli std::cerr << "PDR config directory does not exist or empty, TYPE= " 126c682fe2dSDeepak Kodihalli << pdrType << "PATH= " << dirEntry 127c682fe2dSDeepak Kodihalli << " ERROR=" << e.what() << "\n"; 128c682fe2dSDeepak Kodihalli } 129c682fe2dSDeepak Kodihalli catch (const Json::exception& e) 130c682fe2dSDeepak Kodihalli { 131c682fe2dSDeepak Kodihalli std::cerr << "Failed parsing PDR JSON file, TYPE= " << pdrType 132c682fe2dSDeepak Kodihalli << " ERROR=" << e.what() << "\n"; 133c682fe2dSDeepak Kodihalli pldm::utils::reportError( 134c682fe2dSDeepak Kodihalli "xyz.openbmc_project.bmc.pldm.InternalFailure"); 135c682fe2dSDeepak Kodihalli } 136c682fe2dSDeepak Kodihalli catch (const std::exception& e) 137c682fe2dSDeepak Kodihalli { 138c682fe2dSDeepak Kodihalli std::cerr << "Failed parsing PDR JSON file, TYPE= " << pdrType 139c682fe2dSDeepak Kodihalli << " ERROR=" << e.what() << "\n"; 140c682fe2dSDeepak Kodihalli pldm::utils::reportError( 141c682fe2dSDeepak Kodihalli "xyz.openbmc_project.bmc.pldm.InternalFailure"); 142c682fe2dSDeepak Kodihalli } 143c682fe2dSDeepak Kodihalli } 144c682fe2dSDeepak Kodihalli } 145557dfb00SDeepak Kodihalli 146bc669f1bSDeepak Kodihalli Response Handler::getPDR(const pldm_msg* request, size_t payloadLength) 147557dfb00SDeepak Kodihalli { 148557dfb00SDeepak Kodihalli Response response(sizeof(pldm_msg_hdr) + PLDM_GET_PDR_MIN_RESP_BYTES, 0); 149557dfb00SDeepak Kodihalli auto responsePtr = reinterpret_cast<pldm_msg*>(response.data()); 150557dfb00SDeepak Kodihalli 151557dfb00SDeepak Kodihalli if (payloadLength != PLDM_GET_PDR_REQ_BYTES) 152557dfb00SDeepak Kodihalli { 153fb8611dcSGeorge Liu return CmdHandler::ccOnlyResponse(request, PLDM_ERROR_INVALID_LENGTH); 154557dfb00SDeepak Kodihalli } 155557dfb00SDeepak Kodihalli 156557dfb00SDeepak Kodihalli uint32_t recordHandle{}; 157557dfb00SDeepak Kodihalli uint32_t dataTransferHandle{}; 158557dfb00SDeepak Kodihalli uint8_t transferOpFlag{}; 159557dfb00SDeepak Kodihalli uint16_t reqSizeBytes{}; 160557dfb00SDeepak Kodihalli uint16_t recordChangeNum{}; 161557dfb00SDeepak Kodihalli 162fb8611dcSGeorge Liu auto rc = decode_get_pdr_req(request, payloadLength, &recordHandle, 163fb8611dcSGeorge Liu &dataTransferHandle, &transferOpFlag, 164fb8611dcSGeorge Liu &reqSizeBytes, &recordChangeNum); 165fb8611dcSGeorge Liu if (rc != PLDM_SUCCESS) 166fb8611dcSGeorge Liu { 167fb8611dcSGeorge Liu return CmdHandler::ccOnlyResponse(request, rc); 168fb8611dcSGeorge Liu } 169557dfb00SDeepak Kodihalli 170557dfb00SDeepak Kodihalli uint16_t respSizeBytes{}; 171557dfb00SDeepak Kodihalli uint8_t* recordData = nullptr; 172557dfb00SDeepak Kodihalli try 173557dfb00SDeepak Kodihalli { 174e53193faSGeorge Liu pdr_utils::PdrEntry e; 175e53193faSGeorge Liu auto record = pdr::getRecordByHandle(pdrRepo, recordHandle, e); 176e53193faSGeorge Liu if (record == NULL) 177e53193faSGeorge Liu { 178e53193faSGeorge Liu return CmdHandler::ccOnlyResponse( 179e53193faSGeorge Liu request, PLDM_PLATFORM_INVALID_RECORD_HANDLE); 180e53193faSGeorge Liu } 181e53193faSGeorge Liu 182557dfb00SDeepak Kodihalli if (reqSizeBytes) 183557dfb00SDeepak Kodihalli { 184e53193faSGeorge Liu respSizeBytes = e.size; 185557dfb00SDeepak Kodihalli if (respSizeBytes > reqSizeBytes) 186557dfb00SDeepak Kodihalli { 187557dfb00SDeepak Kodihalli respSizeBytes = reqSizeBytes; 188557dfb00SDeepak Kodihalli } 189e53193faSGeorge Liu recordData = e.data; 190557dfb00SDeepak Kodihalli } 191557dfb00SDeepak Kodihalli response.resize(sizeof(pldm_msg_hdr) + PLDM_GET_PDR_MIN_RESP_BYTES + 192557dfb00SDeepak Kodihalli respSizeBytes, 193557dfb00SDeepak Kodihalli 0); 194557dfb00SDeepak Kodihalli responsePtr = reinterpret_cast<pldm_msg*>(response.data()); 195*22b5a7d7SDeepak Kodihalli rc = encode_get_pdr_resp( 196*22b5a7d7SDeepak Kodihalli request->hdr.instance_id, PLDM_SUCCESS, e.handle.nextRecordHandle, 197*22b5a7d7SDeepak Kodihalli 0, PLDM_START_AND_END, respSizeBytes, recordData, 0, responsePtr); 198fb8611dcSGeorge Liu if (rc != PLDM_SUCCESS) 199fb8611dcSGeorge Liu { 200fb8611dcSGeorge Liu return ccOnlyResponse(request, rc); 201fb8611dcSGeorge Liu } 202557dfb00SDeepak Kodihalli } 203557dfb00SDeepak Kodihalli catch (const std::exception& e) 204557dfb00SDeepak Kodihalli { 205aa8ae72fSSampa Misra std::cerr << "Error accessing PDR, HANDLE=" << recordHandle 206aa8ae72fSSampa Misra << " ERROR=" << e.what() << "\n"; 207fb8611dcSGeorge Liu return CmdHandler::ccOnlyResponse(request, PLDM_ERROR); 208557dfb00SDeepak Kodihalli } 209557dfb00SDeepak Kodihalli return response; 210557dfb00SDeepak Kodihalli } 211557dfb00SDeepak Kodihalli 212bc669f1bSDeepak Kodihalli Response Handler::setStateEffecterStates(const pldm_msg* request, 213bc669f1bSDeepak Kodihalli size_t payloadLength) 214a2fa0709SSampa Misra { 215a2fa0709SSampa Misra Response response( 216a2fa0709SSampa Misra sizeof(pldm_msg_hdr) + PLDM_SET_STATE_EFFECTER_STATES_RESP_BYTES, 0); 217a2fa0709SSampa Misra auto responsePtr = reinterpret_cast<pldm_msg*>(response.data()); 218a2fa0709SSampa Misra uint16_t effecterId; 219a2fa0709SSampa Misra uint8_t compEffecterCnt; 220a2fa0709SSampa Misra constexpr auto maxCompositeEffecterCnt = 8; 221a2fa0709SSampa Misra std::vector<set_effecter_state_field> stateField(maxCompositeEffecterCnt, 222a2fa0709SSampa Misra {0, 0}); 223a2fa0709SSampa Misra 224a2fa0709SSampa Misra if ((payloadLength > PLDM_SET_STATE_EFFECTER_STATES_REQ_BYTES) || 225a2fa0709SSampa Misra (payloadLength < sizeof(effecterId) + sizeof(compEffecterCnt) + 226a2fa0709SSampa Misra sizeof(set_effecter_state_field))) 227a2fa0709SSampa Misra { 228fb8611dcSGeorge Liu return CmdHandler::ccOnlyResponse(request, PLDM_ERROR_INVALID_LENGTH); 229a2fa0709SSampa Misra } 230a2fa0709SSampa Misra 231a2fa0709SSampa Misra int rc = decode_set_state_effecter_states_req(request, payloadLength, 232a2fa0709SSampa Misra &effecterId, &compEffecterCnt, 233a2fa0709SSampa Misra stateField.data()); 234a2fa0709SSampa Misra 235fb8611dcSGeorge Liu if (rc != PLDM_SUCCESS) 236a2fa0709SSampa Misra { 237fb8611dcSGeorge Liu return CmdHandler::ccOnlyResponse(request, rc); 238fb8611dcSGeorge Liu } 23983409573SGeorge Liu 240fb8611dcSGeorge Liu stateField.resize(compEffecterCnt); 24183409573SGeorge Liu const pldm::utils::DBusHandler dBusIntf; 24283409573SGeorge Liu rc = setStateEffecterStatesHandler<pldm::utils::DBusHandler>( 24383409573SGeorge Liu dBusIntf, effecterId, stateField); 244fb8611dcSGeorge Liu if (rc != PLDM_SUCCESS) 245fb8611dcSGeorge Liu { 246fb8611dcSGeorge Liu return CmdHandler::ccOnlyResponse(request, rc); 247a2fa0709SSampa Misra } 248a2fa0709SSampa Misra 249fb8611dcSGeorge Liu rc = encode_set_state_effecter_states_resp(request->hdr.instance_id, rc, 250a2fa0709SSampa Misra responsePtr); 251fb8611dcSGeorge Liu if (rc != PLDM_SUCCESS) 252fb8611dcSGeorge Liu { 253fb8611dcSGeorge Liu return ccOnlyResponse(request, rc); 254fb8611dcSGeorge Liu } 255fb8611dcSGeorge Liu 256a2fa0709SSampa Misra return response; 257a2fa0709SSampa Misra } 258a2fa0709SSampa Misra 259bc669f1bSDeepak Kodihalli } // namespace platform 260557dfb00SDeepak Kodihalli } // namespace responder 261557dfb00SDeepak Kodihalli } // namespace pldm 262