static int pldm_update_fw()

in common/recipes-core/ncsi-util/files/ncsi-util.c [305:535]


static int pldm_update_fw(char *path, int pldm_bufsize, uint8_t ch)
{
#define SLEEP_TIME_MS               20  // wait time per loop in ms
  NCSI_NL_MSG_T *nl_msg = NULL;
  NCSI_NL_RSP_T *nl_resp = NULL;
  pldm_fw_pkg_hdr_t *pkgHdr;
  pldm_cmd_req pldmReq = {0};
  pldm_response *pldmRes = NULL;
  int pldmCmdStatus = 0;
  int i = 0, j = 0;
  int ret = 0;
  int waitcycle = 0;
  int waitTOsec = 0;
  int currnet_state = -1, previous_state = -1;
  char value[64];
  struct timespec ts;
#define MAX_WAIT_CYCLE 1000

  clock_gettime(CLOCK_MONOTONIC, &ts);
  snprintf(value, sizeof(value), "%ld", ts.tv_sec + 600);
  kv_set("block_ncsi_xmit", value, 0, 0);

  nl_msg = calloc(1, sizeof(NCSI_NL_MSG_T));
  if (!nl_msg) {
    printf("%s, Error: failed nl_msg buffer allocation(%d)\n",
           __FUNCTION__, sizeof(NCSI_NL_MSG_T));
    ret = -1;
    goto free_exit;
  }
  memset(nl_msg, 0, sizeof(NCSI_NL_MSG_T));

  pldmRes = calloc(1, sizeof(pldm_response));
  if (!pldmRes) {
    printf("%s, Error: failed pldmRes buffer allocation(%d)\n",
           __FUNCTION__, sizeof(pldm_response));
    ret = -1;
    goto free_exit;
  }


  pkgHdr = pldm_parse_fw_pkg(path);
  if (!pkgHdr) {
    ret = -1;
    goto free_exit;
  }

  pldmCreateReqUpdateCmd(pkgHdr, &pldmReq, pldm_bufsize);
  printf("\n01 PldmRequestUpdateOp: payload_size=%d\n", pldmReq.payload_size);
  ret = create_ncsi_ctrl_pkt(nl_msg, ch, NCSI_PLDM_REQUEST, pldmReq.payload_size,
                       &(pldmReq.common[0]));
  if (ret) {
    goto free_exit;
  }

  if (sendPldmCmdAndCheckResp(nl_msg) != CC_SUCCESS) {
    ret = -1;
    goto free_exit;
  }

  for (i=0; i<pkgHdr->componentImageCnt; ++i) {
    memset(&pldmReq, 0, sizeof(pldm_cmd_req));
    pldmCreatePassComponentTblCmd(pkgHdr, i, &pldmReq);
    printf("\n02 PldmPassComponentTableOp[%d]: payload_size=%d\n", i,
            pldmReq.payload_size);
    ret = create_ncsi_ctrl_pkt(nl_msg, ch, NCSI_PLDM_REQUEST, pldmReq.payload_size,
                         &(pldmReq.common[0]));
    if (ret) {
      goto free_exit;
    }
    if (sendPldmCmdAndCheckResp(nl_msg) != CC_SUCCESS) {
      ret = -1;
      goto free_exit;
    }
  }



  for (i=0; i<pkgHdr->componentImageCnt; ++i) {
    memset(&pldmReq, 0, sizeof(pldm_cmd_req));
    pldmCreateUpdateComponentCmd(pkgHdr, i, &pldmReq);
    printf("\n03 PldmUpdateComponentOp[%d]: payload_size=%d\n", i,
            pldmReq.payload_size);
    ret = create_ncsi_ctrl_pkt(nl_msg, ch, NCSI_PLDM_REQUEST, pldmReq.payload_size,
                         &(pldmReq.common[0]));
    if (ret) {
      goto free_exit;
    }
    if (sendPldmCmdAndCheckResp(nl_msg) != CC_SUCCESS) {
      ret = -1;
      goto free_exit;
    }
  }

  // FW data transfer
  int loopCount = 0;
  int idleCnt = 0;
  int pldmCmd = 0;
  setPldmTimeout(CMD_UPDATE_COMPONENT, &waitTOsec);
  while (idleCnt < (waitTOsec * 1000 /SLEEP_TIME_MS) ) {
//    printf("\n04 QueryPendingNcPldmRequestOp, loop=%d\n", loopCount);
    ret = create_ncsi_ctrl_pkt(nl_msg, ch, NCSI_QUERY_PENDING_NC_PLDM_REQ, 0, NULL);
    if (ret) {
      goto free_exit;
    }
    nl_resp = send_nl_msg_retry(nl_msg);
    if (!nl_resp) {
      ret = -1;
      goto free_exit;
    }
    print_pldm_cmd_status(nl_resp);

    pldmCmd = ncsiGetPldmCmd(nl_resp, &pldmReq);
    free(nl_resp);
    nl_resp = NULL;
    if (pldmCmd == -1) {
  //    printf("No pending command, loop %d\n", idleCnt);
      msleep(SLEEP_TIME_MS); // wait some time and try again
      idleCnt++;
      continue;
    } else {
      idleCnt = 0;
    }

    if ( (pldmCmd == CMD_REQUEST_FIRMWARE_DATA) ||
         (pldmCmd == CMD_TRANSFER_COMPLETE) ||
         (pldmCmd == CMD_VERIFY_COMPLETE) ||
         (pldmCmd == CMD_APPLY_COMPLETE)) {
      setPldmTimeout(pldmCmd, &waitTOsec);
      loopCount++;
      waitcycle = 0;
      pldmCmdStatus = pldmFwUpdateCmdHandler(pkgHdr, &pldmReq, pldmRes);
      ret = create_ncsi_ctrl_pkt(nl_msg, ch, NCSI_SEND_NC_PLDM_REPLY,
                                 pldmRes->resp_size, pldmRes->common);
      if (ret) {
        goto free_exit;
      }
      nl_resp = send_nl_msg_retry(nl_msg);
      if (!nl_resp) {
        ret = -1;
        goto free_exit;
      }
      //print_ncsi_resp(nl_resp);
      free(nl_resp);
      nl_resp = NULL;
      if ((pldmCmd == CMD_APPLY_COMPLETE) || (pldmCmdStatus == -1))
        break;
      if (nl_conf == 0) // Linux 4.1
        msleep(10); // add dealy to reduce retry sending request to NIC
    } else {
      printf("unknown PLDM cmd 0x%x\n", pldmCmd);
      waitcycle++;
      if (waitcycle >= MAX_WAIT_CYCLE) {
        printf("max wait cycle exceeded, exit\n");
        break;
      }
    }
  }

  // only activate FW if update loop exists with good status
  if (!pldmCmdStatus && (pldmCmd == CMD_APPLY_COMPLETE)) {
    // update successful,  activate FW
    memset(&pldmReq, 0, sizeof(pldm_cmd_req));
    pldmCreateActivateFirmwareCmd(&pldmReq);
    printf("\n05 PldmActivateFirmwareOp\n");
    ret = create_ncsi_ctrl_pkt(nl_msg, ch, NCSI_PLDM_REQUEST, pldmReq.payload_size,
                         &(pldmReq.common[0]));
    if (ret) {
      goto free_exit;
    }
    if (sendPldmCmdAndCheckResp(nl_msg) != CC_SUCCESS) {
      for (j=0; j<5; j++) {
        sleep(2);
        memset(&pldmReq, 0, sizeof(pldm_cmd_req));
        pldmCreateGetStatusCmd(&pldmReq);
        ret = create_ncsi_ctrl_pkt(nl_msg, ch, NCSI_PLDM_REQUEST, pldmReq.payload_size,
                            &(pldmReq.common[0]));
        if (ret) {
          printf("\nPldmGetStatus fail ret=%d\n",ret);
          goto free_exit;
        }
        nl_resp = send_nl_msg(nl_msg);
        if (!nl_resp) {
          printf("\nPldmGetStatus send_nl_msg fail\n");
          ret = -1;
          goto free_exit;
        }
        print_pldm_cmd_status(nl_resp);
        print_pldm_resp_raw(nl_resp);
        currnet_state = nl_resp->msg_payload[8];
        previous_state = nl_resp->msg_payload[9];
        free(nl_resp);
        nl_resp = NULL;
        if (currnet_state == STATE_IDLE && previous_state == STATE_ACTIVATE) {
          ret = 0;
          break;
        } else {
          ret = -1;
        }
      }
    }
  } else {
    printf("PLDM cmd (%d) failed (status %d), abort update\n",
      pldmCmd, pldmCmdStatus);

    // send abort update cmd
    memset(&pldmReq, 0, sizeof(pldm_cmd_req));
    pldmCreateCancelUpdateCmd(&pldmReq);
    ret = create_ncsi_ctrl_pkt(nl_msg, ch, NCSI_PLDM_REQUEST, pldmReq.payload_size,
                              &(pldmReq.common[0]));
    if (ret) {
      ret = -1;
      goto free_exit;
    }
    // ignore the return status and exit since this is on the error path
    sendPldmCmdAndCheckResp(nl_msg);
    ret = -1;
  }

free_exit:
  if (pkgHdr)
    free_pldm_pkg_data(&pkgHdr);
  if (nl_resp)
    free(nl_resp);

  if (pldmRes)
    free(pldmRes);

  if (nl_msg)
    free(nl_msg);
  return ret;
}