bool CmisFirmwareUpgrader::cmisModuleFirmwareDownload()

in fboss/lib/i2c/FirmwareUpgrader.cpp [92:327]


bool CmisFirmwareUpgrader::cmisModuleFirmwareDownload(
    const uint8_t* imageBuf,
    int imageLen) {
  uint8_t startCommandPayloadSize = 0;
  bool status;
  int imageOffset, imageChunkLen;
  bool eplSupported = false;

  XLOG(INFO) << folly::sformat(
      "cmisModuleFirmwareDownload: Mod{:d}: Starting to download the image with length {:d}",
      moduleId_,
      imageLen);

  // Set the password to let the privileged operation of firmware download
  bus_->moduleWrite(
      moduleId_,
      {TransceiverI2CApi::ADDR_QSFP, kModulePasswordEntryReg, 4},
      msaPassword_.data());

  CdbCommandBlock commandBlockBuf;
  CdbCommandBlock* commandBlock = &commandBlockBuf;

  // Basic validation first. Check if the firmware download is allowed by
  // issuing the Query command to CDB
  commandBlock->createCdbCmdModuleQuery();
  // Run the CDB command
  status = commandBlock->cmisRunCdbCommand(bus_, moduleId_);
  if (status) {
    // Query result will be in LPL memory at byte offset 2
    if (commandBlock->getCdbRlplLength() >= 3) {
      if (commandBlock->getCdbLplFlatMemory()[2] == 0) {
        // This should not happen because before calling this function
        // we supply the password to module to allow priviledged
        // operation. But still download feature is not available here
        // so return false here
        XLOG(INFO) << folly::sformat(
            "cmisModuleFirmwareDownload: Mod{:d}: The firmware download feature is locked by vendor",
            moduleId_);
        return false;
      }
    }
  } else {
    // The QUERY command can fail if the module is in bootloader mode
    // Not able to determine CDB module status but don't return from here
    XLOG(INFO) << folly::sformat(
        "cmisModuleFirmwareDownload: Mod{:d}: Could not get result from CDB Query command",
        moduleId_);
  }

  // Step 0: Retrieve the Start Command Payload Size (the image header size)
  // Done by sending Firmware upgrade feature command to CDB
  commandBlock->createCdbCmdGetFwFeatureInfo();
  // Run the CDB command
  status = commandBlock->cmisRunCdbCommand(bus_, moduleId_);

  // If the CDB command is successfull then the Start Command Payload Size is
  // returned by CDB in LPL memory at offset 2

  if (status && commandBlock->getCdbRlplLength() >= 3) {
    // Get the firmware header size from CDB
    startCommandPayloadSize = commandBlock->getCdbLplFlatMemory()[2];

    // Check if EPL memory is supported
    if (commandBlock->getCdbLplFlatMemory()[5] == 0x10 ||
        commandBlock->getCdbLplFlatMemory()[5] == 0x11) {
      eplSupported = true;
      XLOG(INFO) << folly::sformat(
          "cmisModuleFirmwareDownload: Mod{:d} will use EPL memory for firmware download",
          moduleId_);
    }
  } else {
    XLOG(INFO) << folly::sformat(
        "cmisModuleFirmwareDownload: Mod{:d}: Could not get result from CDB Firmware Update Feature command",
        moduleId_);

    // Sometime when the optics is  in boot loader mode, this CDB command
    // fails. So fill in the header size if it is a known optics otherwise
    // return false
    startCommandPayloadSize = imageHeaderLen_;
    XLOG(INFO) << folly::sformat(
        "cmisModuleFirmwareDownload: Mod{:d}: Setting the module startCommandPayloadSize as {:d}",
        moduleId_,
        startCommandPayloadSize);
  }

  XLOG(INFO) << folly::sformat(
      "cmisModuleFirmwareDownload: Mod{:d}: Step 0: Got Start Command Payload Size as {:d}",
      moduleId_,
      startCommandPayloadSize);

  // Validate if the image length is greater than this. If not then our new
  // image is bad
  if (imageLen < startCommandPayloadSize) {
    XLOG(INFO) << folly::sformat(
        "cmisModuleFirmwareDownload: Mod{:d}: The image length {:d} is smaller than startCommandPayloadSize {:d}",
        moduleId_,
        imageLen,
        startCommandPayloadSize);
    return false;
  }

  // Step 1: Issue CDB command: Firmware Download start
  imageChunkLen = startCommandPayloadSize;
  commandBlock->createCdbCmdFwDownloadStart(
      startCommandPayloadSize, imageLen, imageOffset, imageBuf);

  // Run the CDB command
  status = commandBlock->cmisRunCdbCommand(bus_, moduleId_);
  if (!status) {
    // DOWNLOAD_START command failed
    XLOG(INFO) << folly::sformat(
        "cmisModuleFirmwareDownload: Mod{:d}: Could not run the CDB Firmware Download Start command",
        moduleId_);
    return false;
  }

  XLOG(INFO) << folly::sformat(
      "cmisModuleFirmwareDownload: Mod{:d}: Step 1: Issued Firmware download start command successfully",
      moduleId_);

  // Step 2: Issue CDB command: Firmware Download image

  XLOG(INFO) << folly::sformat(
      "cmisModuleFirmwareDownload: Mod{:d}: Step 2: Issuing Firmware Download Image command. Starting offset: {:d}",
      moduleId_,
      imageOffset);

  while (imageOffset < imageLen) {
    if (!eplSupported) {
      // Create CDB command block using internal LPL memory
      commandBlock->createCdbCmdFwDownloadImageLpl(
          startCommandPayloadSize,
          imageLen,
          imageBuf,
          imageOffset,
          imageChunkLen);
    } else {
      // Create CDB command block assuming external EPL memory
      commandBlock->createCdbCmdFwDownloadImageEpl(
          startCommandPayloadSize, imageLen, imageOffset, imageChunkLen);

      // Write the image payload to external EPL before invoking the command
      commandBlock->writeEplPayload(
          bus_, moduleId_, imageBuf, imageOffset, imageChunkLen);
    }

    // Run the CDB command
    status = commandBlock->cmisRunCdbCommand(bus_, moduleId_);
    if (!status) {
      // DOWNLOAD_IMAGE command failed
      XLOG(INFO) << folly::sformat(
          "cmisModuleFirmwareDownload: Mod{:d}: Could not run the CDB Firmware Download Image command",
          moduleId_);
      return false;
    }
    XLOG(INFO) << folly::sformat(
        "cmisModuleFirmwareDownload: Mod{:d}: Image wrote, offset: {:d} .. {:d}",
        moduleId_,
        imageOffset - imageChunkLen,
        imageOffset);
  }
  XLOG(INFO) << folly::sformat(
      "cmisModuleFirmwareDownload: Mod{:d}: Step 2: Issued Firmware Download Image successfully. Downloaded file size {:d}",
      moduleId_,
      imageOffset);

  // Step 3: Issue CDB command: Firmware download complete
  commandBlock->createCdbCmdFwDownloadComplete();

  // Run the CDB command
  status = commandBlock->cmisRunCdbCommand(bus_, moduleId_);
  if (!status) {
    // DOWNLOAD_COMPLETE command failed
    XLOG(INFO) << folly::sformat(
        "cmisModuleFirmwareDownload: Mod{:d}: Could not run the CDB Firmware Download Complete command",
        moduleId_);
    // Send the DOWNLOAD_ABORT command to CDB and return.
    return false;
  }

  XLOG(INFO) << folly::sformat(
      "cmisModuleFirmwareDownload: Mod{:d}: Step 3: Issued Firmware download complete command successfully",
      moduleId_);

  // Non App images like DSP image don't need last 2 steps (Run, Commit) for the
  // firmware download
  if (!appImage_) {
    return true;
  }

  // Step 4: Issue CDB command: Run the downloaded firmware
  commandBlock->createCdbCmdFwImageRun();

  // Run the CDB command
  // No need to check status because RUN command issues soft reset to CDB
  // so we can't check status here
  status = commandBlock->cmisRunCdbCommand(bus_, moduleId_);

  XLOG(INFO) << folly::sformat(
      "cmisModuleFirmwareDownload: Mod{:d}: Step 4: Issued Firmware download Run command successfully",
      moduleId_);

  usleep(2 * moduleDatapathInitDurationUsec);

  // Set the password to let the privileged operation of firmware download
  bus_->moduleWrite(
      moduleId_,
      {TransceiverI2CApi::ADDR_QSFP, kModulePasswordEntryReg, 4},
      msaPassword_.data());

  // Step 5: Issue CDB command: Commit the downloaded firmware
  commandBlock->createCdbCmdFwCommit();

  // Run the CDB command
  status = commandBlock->cmisRunCdbCommand(bus_, moduleId_);

  if (!status) {
    XLOG(INFO) << folly::sformat(
        "cmisModuleFirmwareDownload: Mod{:d}: Step 5: Issued Firmware commit command failed",
        moduleId_);
  } else {
    XLOG(INFO) << folly::sformat(
        "cmisModuleFirmwareDownload: Mod{:d}: Step 5: Issued Firmware commit command successful",
        moduleId_);
  }

  usleep(10 * moduleDatapathInitDurationUsec);

  // Set the password to let the privileged operation of firmware download
  bus_->moduleWrite(
      moduleId_,
      {TransceiverI2CApi::ADDR_QSFP, kModulePasswordEntryReg, 4},
      msaPassword_.data());

  return true;
}