1 #include "oem_ibm_handler.hpp" 2 3 #include "libpldm/entity.h" 4 #include "libpldm/requester/pldm.h" 5 6 #include "file_io_type_lid.hpp" 7 #include "libpldmresponder/file_io.hpp" 8 #include "libpldmresponder/pdr_utils.hpp" 9 namespace pldm 10 { 11 namespace responder 12 { 13 namespace oem_ibm_platform 14 { 15 16 int pldm::responder::oem_ibm_platform::Handler:: 17 getOemStateSensorReadingsHandler( 18 EntityType entityType, EntityInstance entityInstance, 19 StateSetId stateSetId, CompositeCount compSensorCnt, 20 std::vector<get_sensor_state_field>& stateField) 21 { 22 int rc = PLDM_SUCCESS; 23 stateField.clear(); 24 25 for (size_t i = 0; i < compSensorCnt; i++) 26 { 27 uint8_t sensorOpState{}; 28 if (entityType == PLDM_OEM_IBM_ENTITY_FIRMWARE_UPDATE && 29 stateSetId == PLDM_OEM_IBM_BOOT_STATE) 30 { 31 sensorOpState = fetchBootSide(entityInstance, codeUpdate); 32 } 33 else 34 { 35 rc = PLDM_PLATFORM_INVALID_STATE_VALUE; 36 break; 37 } 38 stateField.push_back({PLDM_SENSOR_ENABLED, PLDM_SENSOR_UNKNOWN, 39 PLDM_SENSOR_UNKNOWN, sensorOpState}); 40 } 41 return rc; 42 } 43 44 int pldm::responder::oem_ibm_platform::Handler:: 45 oemSetStateEffecterStatesHandler( 46 uint16_t entityType, uint16_t entityInstance, uint16_t stateSetId, 47 uint8_t compEffecterCnt, 48 std::vector<set_effecter_state_field>& stateField, 49 uint16_t /*effecterId*/) 50 { 51 int rc = PLDM_SUCCESS; 52 53 for (uint8_t currState = 0; currState < compEffecterCnt; ++currState) 54 { 55 if (stateField[currState].set_request == PLDM_REQUEST_SET) 56 { 57 if (entityType == PLDM_OEM_IBM_ENTITY_FIRMWARE_UPDATE && 58 stateSetId == PLDM_OEM_IBM_BOOT_STATE) 59 { 60 rc = setBootSide(entityInstance, currState, stateField, 61 codeUpdate); 62 } 63 else if (entityType == PLDM_OEM_IBM_ENTITY_FIRMWARE_UPDATE && 64 stateSetId == PLDM_OEM_IBM_FIRMWARE_UPDATE_STATE) 65 { 66 if (stateField[currState].effecter_state == 67 uint8_t(CodeUpdateState::START)) 68 { 69 codeUpdate->setCodeUpdateProgress(true); 70 startUpdateEvent = 71 std::make_unique<sdeventplus::source::Defer>( 72 event, 73 std::bind(std::mem_fn(&oem_ibm_platform::Handler:: 74 _processStartUpdate), 75 this, std::placeholders::_1)); 76 } 77 else if (stateField[currState].effecter_state == 78 uint8_t(CodeUpdateState::END)) 79 { 80 rc = PLDM_SUCCESS; 81 assembleImageEvent = std::make_unique< 82 sdeventplus::source::Defer>( 83 event, 84 std::bind( 85 std::mem_fn( 86 &oem_ibm_platform::Handler::_processEndUpdate), 87 this, std::placeholders::_1)); 88 89 // sendCodeUpdateEvent(effecterId, END, START); 90 } 91 else if (stateField[currState].effecter_state == 92 uint8_t(CodeUpdateState::ABORT)) 93 { 94 codeUpdate->setCodeUpdateProgress(false); 95 codeUpdate->clearDirPath(LID_STAGING_DIR); 96 auto sensorId = codeUpdate->getFirmwareUpdateSensor(); 97 sendStateSensorEvent(sensorId, PLDM_STATE_SENSOR_STATE, 0, 98 uint8_t(CodeUpdateState::ABORT), 99 uint8_t(CodeUpdateState::START)); 100 // sendCodeUpdateEvent(effecterId, ABORT, END); 101 } 102 else if (stateField[currState].effecter_state == 103 uint8_t(CodeUpdateState::ACCEPT)) 104 { 105 auto sensorId = codeUpdate->getFirmwareUpdateSensor(); 106 sendStateSensorEvent(sensorId, PLDM_STATE_SENSOR_STATE, 0, 107 uint8_t(CodeUpdateState::ACCEPT), 108 uint8_t(CodeUpdateState::END)); 109 // TODO Set new Dbus property provided by code update app 110 // sendCodeUpdateEvent(effecterId, ACCEPT, END); 111 } 112 else if (stateField[currState].effecter_state == 113 uint8_t(CodeUpdateState::REJECT)) 114 { 115 auto sensorId = codeUpdate->getFirmwareUpdateSensor(); 116 sendStateSensorEvent(sensorId, PLDM_STATE_SENSOR_STATE, 0, 117 uint8_t(CodeUpdateState::REJECT), 118 uint8_t(CodeUpdateState::END)); 119 // TODO Set new Dbus property provided by code update app 120 // sendCodeUpdateEvent(effecterId, REJECT, END); 121 } 122 } 123 else 124 { 125 rc = PLDM_PLATFORM_SET_EFFECTER_UNSUPPORTED_SENSORSTATE; 126 } 127 } 128 if (rc != PLDM_SUCCESS) 129 { 130 break; 131 } 132 } 133 return rc; 134 } 135 136 void buildAllCodeUpdateEffecterPDR(platform::Handler* platformHandler, 137 uint16_t entityInstance, uint16_t stateSetID, 138 pdr_utils::Repo& repo) 139 { 140 size_t pdrSize = 0; 141 pdrSize = sizeof(pldm_state_effecter_pdr) + 142 sizeof(state_effecter_possible_states); 143 std::vector<uint8_t> entry{}; 144 entry.resize(pdrSize); 145 pldm_state_effecter_pdr* pdr = 146 reinterpret_cast<pldm_state_effecter_pdr*>(entry.data()); 147 if (!pdr) 148 { 149 std::cerr << "Failed to get record by PDR type, ERROR:" 150 << PLDM_PLATFORM_INVALID_EFFECTER_ID << std::endl; 151 } 152 pdr->hdr.record_handle = 0; 153 pdr->hdr.version = 1; 154 pdr->hdr.type = PLDM_STATE_EFFECTER_PDR; 155 pdr->hdr.record_change_num = 0; 156 pdr->hdr.length = sizeof(pldm_state_effecter_pdr) - sizeof(pldm_pdr_hdr); 157 pdr->terminus_handle = pdr::BmcPldmTerminusHandle; 158 pdr->effecter_id = platformHandler->getNextEffecterId(); 159 pdr->entity_type = PLDM_OEM_IBM_ENTITY_FIRMWARE_UPDATE; 160 pdr->entity_instance = entityInstance; 161 pdr->container_id = 0; 162 pdr->effecter_semantic_id = 0; 163 pdr->effecter_init = PLDM_NO_INIT; 164 pdr->has_description_pdr = false; 165 pdr->composite_effecter_count = 1; 166 167 auto* possibleStatesPtr = pdr->possible_states; 168 auto possibleStates = 169 reinterpret_cast<state_effecter_possible_states*>(possibleStatesPtr); 170 possibleStates->state_set_id = stateSetID; 171 possibleStates->possible_states_size = 2; 172 auto state = 173 reinterpret_cast<state_effecter_possible_states*>(possibleStates); 174 if (stateSetID == PLDM_OEM_IBM_BOOT_STATE) 175 state->states[0].byte = 6; 176 else if (stateSetID == PLDM_OEM_IBM_FIRMWARE_UPDATE_STATE) 177 state->states[0].byte = 126; 178 pldm::responder::pdr_utils::PdrEntry pdrEntry{}; 179 pdrEntry.data = entry.data(); 180 pdrEntry.size = pdrSize; 181 repo.addRecord(pdrEntry); 182 } 183 184 void buildAllCodeUpdateSensorPDR(platform::Handler* platformHandler, 185 uint16_t entityType, uint16_t entityInstance, 186 uint16_t stateSetID, pdr_utils::Repo& repo) 187 { 188 size_t pdrSize = 0; 189 pdrSize = 190 sizeof(pldm_state_sensor_pdr) + sizeof(state_sensor_possible_states); 191 std::vector<uint8_t> entry{}; 192 entry.resize(pdrSize); 193 pldm_state_sensor_pdr* pdr = 194 reinterpret_cast<pldm_state_sensor_pdr*>(entry.data()); 195 if (!pdr) 196 { 197 std::cerr << "Failed to get record by PDR type, ERROR:" 198 << PLDM_PLATFORM_INVALID_SENSOR_ID << std::endl; 199 } 200 pdr->hdr.record_handle = 0; 201 pdr->hdr.version = 1; 202 pdr->hdr.type = PLDM_STATE_SENSOR_PDR; 203 pdr->hdr.record_change_num = 0; 204 pdr->hdr.length = sizeof(pldm_state_sensor_pdr) - sizeof(pldm_pdr_hdr); 205 pdr->terminus_handle = pdr::BmcPldmTerminusHandle; 206 pdr->sensor_id = platformHandler->getNextSensorId(); 207 pdr->entity_type = entityType; 208 pdr->entity_instance = entityInstance; 209 pdr->container_id = 0; 210 pdr->sensor_init = PLDM_NO_INIT; 211 pdr->sensor_auxiliary_names_pdr = false; 212 pdr->composite_sensor_count = 1; 213 214 auto* possibleStatesPtr = pdr->possible_states; 215 auto possibleStates = 216 reinterpret_cast<state_sensor_possible_states*>(possibleStatesPtr); 217 possibleStates->state_set_id = stateSetID; 218 possibleStates->possible_states_size = 2; 219 auto state = 220 reinterpret_cast<state_sensor_possible_states*>(possibleStates); 221 if ((stateSetID == PLDM_OEM_IBM_BOOT_STATE) || 222 (stateSetID == oem_ibm_platform::PLDM_OEM_IBM_VERIFICATION_STATE)) 223 state->states[0].byte = 6; 224 else if (stateSetID == PLDM_OEM_IBM_FIRMWARE_UPDATE_STATE) 225 state->states[0].byte = 126; 226 pldm::responder::pdr_utils::PdrEntry pdrEntry{}; 227 pdrEntry.data = entry.data(); 228 pdrEntry.size = pdrSize; 229 repo.addRecord(pdrEntry); 230 } 231 232 void pldm::responder::oem_ibm_platform::Handler::buildOEMPDR( 233 pdr_utils::Repo& repo) 234 { 235 buildAllCodeUpdateEffecterPDR(platformHandler, ENTITY_INSTANCE_0, 236 PLDM_OEM_IBM_BOOT_STATE, repo); 237 buildAllCodeUpdateEffecterPDR(platformHandler, ENTITY_INSTANCE_1, 238 PLDM_OEM_IBM_BOOT_STATE, repo); 239 buildAllCodeUpdateEffecterPDR(platformHandler, ENTITY_INSTANCE_0, 240 PLDM_OEM_IBM_FIRMWARE_UPDATE_STATE, repo); 241 242 buildAllCodeUpdateSensorPDR( 243 platformHandler, PLDM_OEM_IBM_ENTITY_FIRMWARE_UPDATE, ENTITY_INSTANCE_0, 244 PLDM_OEM_IBM_BOOT_STATE, repo); 245 buildAllCodeUpdateSensorPDR( 246 platformHandler, PLDM_OEM_IBM_ENTITY_FIRMWARE_UPDATE, ENTITY_INSTANCE_1, 247 PLDM_OEM_IBM_BOOT_STATE, repo); 248 buildAllCodeUpdateSensorPDR( 249 platformHandler, PLDM_OEM_IBM_ENTITY_FIRMWARE_UPDATE, ENTITY_INSTANCE_0, 250 PLDM_OEM_IBM_FIRMWARE_UPDATE_STATE, repo); 251 buildAllCodeUpdateSensorPDR( 252 platformHandler, PLDM_OEM_IBM_ENTITY_FIRMWARE_UPDATE, ENTITY_INSTANCE_0, 253 PLDM_OEM_IBM_VERIFICATION_STATE, repo); 254 auto sensorId = findStateSensorId( 255 repo.getPdr(), 0, PLDM_OEM_IBM_ENTITY_FIRMWARE_UPDATE, 256 ENTITY_INSTANCE_0, 0, PLDM_OEM_IBM_VERIFICATION_STATE); 257 codeUpdate->setMarkerLidSensor(sensorId); 258 sensorId = findStateSensorId( 259 repo.getPdr(), 0, PLDM_OEM_IBM_ENTITY_FIRMWARE_UPDATE, 260 ENTITY_INSTANCE_0, 0, PLDM_OEM_IBM_FIRMWARE_UPDATE_STATE); 261 codeUpdate->setFirmwareUpdateSensor(sensorId); 262 } 263 264 void pldm::responder::oem_ibm_platform::Handler::setPlatformHandler( 265 pldm::responder::platform::Handler* handler) 266 { 267 platformHandler = handler; 268 } 269 270 int pldm::responder::oem_ibm_platform::Handler::sendEventToHost( 271 std::vector<uint8_t>& requestMsg) 272 { 273 uint8_t* responseMsg = nullptr; 274 size_t responseMsgSize{}; 275 if (requestMsg.size()) 276 { 277 std::ostringstream tempStream; 278 for (int byte : requestMsg) 279 { 280 tempStream << std::setfill('0') << std::setw(2) << std::hex << byte 281 << " "; 282 } 283 std::cout << tempStream.str() << std::endl; 284 } 285 286 auto requesterRc = 287 pldm_send_recv(mctp_eid, mctp_fd, requestMsg.data(), requestMsg.size(), 288 &responseMsg, &responseMsgSize); 289 std::unique_ptr<uint8_t, decltype(std::free)*> responseMsgPtr{responseMsg, 290 std::free}; 291 if (requesterRc != PLDM_REQUESTER_SUCCESS) 292 { 293 std::cerr << "Failed to send message/receive response. RC = " 294 << requesterRc << ", errno = " << errno 295 << "for sending event to host \n"; 296 return requesterRc; 297 } 298 uint8_t completionCode{}; 299 uint8_t status{}; 300 auto responsePtr = reinterpret_cast<struct pldm_msg*>(responseMsgPtr.get()); 301 auto rc = decode_platform_event_message_resp( 302 responsePtr, responseMsgSize - sizeof(pldm_msg_hdr), &completionCode, 303 &status); 304 305 if (rc != PLDM_SUCCESS || completionCode != PLDM_SUCCESS) 306 { 307 std::cerr << "Failure in decode platform event message response, rc= " 308 << rc << " cc=" << static_cast<unsigned>(completionCode) 309 << "\n"; 310 return rc; 311 } 312 return rc; 313 } 314 315 int encodeEventMsg(uint8_t eventType, const std::vector<uint8_t>& eventDataVec, 316 std::vector<uint8_t>& requestMsg, uint8_t instanceId) 317 { 318 auto request = reinterpret_cast<pldm_msg*>(requestMsg.data()); 319 320 auto rc = encode_platform_event_message_req( 321 instanceId, 1 /*formatVersion*/, 0 /*tId*/, eventType, 322 eventDataVec.data(), eventDataVec.size(), request, 323 eventDataVec.size() + PLDM_PLATFORM_EVENT_MESSAGE_MIN_REQ_BYTES); 324 325 return rc; 326 } 327 328 void pldm::responder::oem_ibm_platform::Handler::sendStateSensorEvent( 329 uint16_t sensorId, enum sensor_event_class_states sensorEventClass, 330 uint8_t sensorOffset, uint8_t eventState, uint8_t prevEventState) 331 { 332 333 std::vector<uint8_t> sensorEventDataVec{}; 334 size_t sensorEventSize = PLDM_SENSOR_EVENT_DATA_MIN_LENGTH + 1; 335 sensorEventDataVec.resize(sensorEventSize); 336 auto eventData = reinterpret_cast<struct pldm_sensor_event_data*>( 337 sensorEventDataVec.data()); 338 eventData->sensor_id = sensorId; 339 eventData->sensor_event_class_type = sensorEventClass; 340 auto eventClassStart = eventData->event_class; 341 auto eventClass = 342 reinterpret_cast<struct pldm_sensor_event_state_sensor_state*>( 343 eventClassStart); 344 eventClass->sensor_offset = sensorOffset; 345 eventClass->event_state = eventState; 346 eventClass->previous_event_state = prevEventState; 347 auto instanceId = requester.getInstanceId(mctp_eid); 348 std::vector<uint8_t> requestMsg(sizeof(pldm_msg_hdr) + 349 PLDM_PLATFORM_EVENT_MESSAGE_MIN_REQ_BYTES + 350 sensorEventDataVec.size()); 351 auto rc = encodeEventMsg(PLDM_SENSOR_EVENT, sensorEventDataVec, requestMsg, 352 instanceId); 353 if (rc != PLDM_SUCCESS) 354 { 355 std::cerr << "Failed to encode state sensor event, rc = " << rc 356 << std::endl; 357 return; 358 } 359 rc = sendEventToHost(requestMsg); 360 if (rc != PLDM_SUCCESS) 361 { 362 std::cerr << "Failed to send event to host: " 363 << "rc=" << rc << std::endl; 364 } 365 requester.markFree(mctp_eid, instanceId); 366 return; 367 } 368 369 void pldm::responder::oem_ibm_platform::Handler::_processEndUpdate( 370 sdeventplus::source::EventBase& /*source */) 371 { 372 assembleImageEvent.reset(); 373 int retc = assembleCodeUpdateImage(); 374 if (retc != PLDM_SUCCESS) 375 { 376 codeUpdate->setCodeUpdateProgress(false); 377 auto sensorId = codeUpdate->getFirmwareUpdateSensor(); 378 sendStateSensorEvent(sensorId, PLDM_STATE_SENSOR_STATE, 0, 379 uint8_t(CodeUpdateState::FAIL), 380 uint8_t(CodeUpdateState::START)); 381 } 382 } 383 384 void pldm::responder::oem_ibm_platform::Handler::_processStartUpdate( 385 sdeventplus::source::EventBase& /*source */) 386 { 387 codeUpdate->deleteImage(); 388 CodeUpdateState state = CodeUpdateState::START; 389 auto rc = codeUpdate->setRequestedApplyTime(); 390 if (rc != PLDM_SUCCESS) 391 { 392 std::cerr << "setRequestedApplyTime failed \n"; 393 state = CodeUpdateState::FAIL; 394 } 395 auto sensorId = codeUpdate->getFirmwareUpdateSensor(); 396 sendStateSensorEvent(sensorId, PLDM_STATE_SENSOR_STATE, 0, uint8_t(state), 397 uint8_t(CodeUpdateState::END)); 398 } 399 400 } // namespace oem_ibm_platform 401 } // namespace responder 402 } // namespace pldm 403