image_info BmcCpldComponent::check_image()

in meta-facebook/meta-fby3/recipes-fby3/fw-util/files/bmc_cpld.cpp [18:183]


image_info BmcCpldComponent::check_image(string image, bool force) {
const string board_type[] = {"Unknown", "EVT", "DVT", "PVT", "MP"};
  string flash_image = image;
  uint8_t bmc_location = 0;
  string fru_name = fru();
  string slot_str = "slot";
  string bmc_str = "bmc";
  size_t slot_found = fru_name.find(slot_str);
  size_t bmc_found = fru_name.find(bmc_str);
  uint8_t slot_id = 0;
  int ret = -1;
  uint8_t board_rev = 0;
  uint8_t hsc_det = 0;
  
  int board_type_index = 0;
  bool board_rev_is_invalid = false;

  image_info image_sts = {"", false};

  if ( fby3_common_get_bmc_location(&bmc_location) < 0 ) {
    printf("Failed to initialize the fw-util\n");
    exit(EXIT_FAILURE);
  }

  //create a new tmp file
  image_sts.new_path = image + "-tmp";

  //open the binary
  int fd_r = open(image.c_str(), O_RDONLY);
  if (fd_r < 0) {
    cerr << "Cannot open " << image << " for reading" << endl;
    return image_sts;
  }

  // create a tmp file for writing.
  int fd_w = open(image_sts.new_path.c_str(), O_WRONLY | O_CREAT, 0666);
  if (fd_w < 0) {
    cerr << "Cannot write to " << image_sts.new_path << endl;
    close(fd_r);
    return image_sts;
  }

  uint8_t *memblock = new uint8_t [image_size + 1];//data_size + signed byte
  uint8_t signed_byte = 0;
  size_t r_b = read(fd_r, memblock, image_size + 1);
  size_t w_b = 0;

  //it's an old image
  if ( r_b == image_size ) {
    signed_byte = 0x0;
  } else if ( r_b == (image_size + 1) ) {
    signed_byte = memblock[image_size] & 0xff;
    r_b = r_b - 1;  //only write data to tmp file
  }

  w_b = write(fd_w, memblock, r_b);

  //check size
  if ( r_b != w_b ) {
    cerr << "Cannot create the tmp file - " << image_sts.new_path << endl;
    cerr << "Read: " << r_b << " Write: " << w_b << endl;
    image_sts.result = false;
  }
  
  if ( force == false ) {
    // Read Board Revision from CPLD
    if ( ((bmc_location == BB_BMC) || (bmc_location == DVT_BB_BMC)) && (bmc_found != string::npos)) {
      if ( fby3_common_get_bb_board_rev(&board_rev) ) {
        cout << "Failed to get bb board rev" << endl;
        return image_sts;
      }
      // respin board, Need to process BOARD_REV through HSC_DETECT, keeping the original logic work
      if ( fby3_common_get_hsc_bb_detect(&hsc_det) ) {
        cout << "Failed to get bb board rev" << endl;
        return image_sts;
      }
      if ( hsc_det == HSC_DET_ADM1278 ) {
        // old board, BOARD_REV_ID3 is floating.
        board_rev &= 0x7;
      } else {
        // new respin board is the MP stage,
        // rise bit3 to keep "if (board_type_index < CPLD_BOARD_PVT_REV)" work.
        board_rev |= 0x8;
      }
    } else if (slot_found != string::npos) {
      bic_gpio_t gpio = {0};
      
      slot_id = fru_name.at(4) - '0';
      if ( fby3_common_get_sb_board_rev(slot_id, &board_rev) ) {
        cout << "Failed to get sb board rev" << endl;
        return image_sts;
      }
      // respin board, Need to process BOARD_REV through HSC_DETECT, keeping the original logic work
      ret = bic_get_gpio(slot_id, &gpio, NONE_INTF);
      if ( ret < 0 ) {
        printf("%s() bic_get_gpio returns %d\n", __func__, ret);
        return image_sts;
      }
      hsc_det |= ((BIT_VALUE(gpio, 77)) << 0); // 77    HSC_DETECT0
      hsc_det |= ((BIT_VALUE(gpio, 78)) << 1); // 78    HSC_DETECT1
      hsc_det |= ((BIT_VALUE(gpio, 79)) << 2); // 79    HSC_DETECT2
      if ( hsc_det == HSC_DET_ADM1278 ) {
        // old board, BOARD_REV_ID3 is floating.
        board_rev &= 0x7;
      } else {
        // new respin board is the MP stage,
        // rise bit3 to keep "if (board_type_index < CPLD_BOARD_PVT_REV)" work.
        board_rev |= 0x8;
      }
    }

    board_type_index = board_rev - 1;
    if (board_type_index < 0) {
      board_type_index = 0;
    }

    // PVT & MP firmware could be used in common
    if (board_type_index < CPLD_BOARD_PVT_REV) {
      if (REVISION_ID(signed_byte) != board_type_index) {
        board_rev_is_invalid = true;
      }
    } else {
      if (REVISION_ID(signed_byte) < CPLD_BOARD_PVT_REV) {
        board_rev_is_invalid = true;
      }
    }

    //CPLD is located on class 2(NIC_EXP)
    if ( bmc_location == NIC_BMC ) {
      if ( (COMPONENT_ID(signed_byte) == NICEXP) && (bmc_found != string::npos) ) {
        image_sts.result = true;
      } else if ( !board_rev_is_invalid && (COMPONENT_ID(signed_byte) == BICDL) && (slot_found != string::npos)) {
        image_sts.result = true;
      } else {
        if (board_rev_is_invalid && (slot_found != string::npos)) {
             cout << "To prevent this update on " << fru_name <<", please use the f/w of "
             << board_type[board_type_index].c_str() <<" on the " << board_type[board_type_index].c_str() <<" system." << endl;
             cout << "To force the update, please use the --force option." << endl;
        }

        cout << "image is not a valid CPLD image for " << fru_name << endl;
      }
    } else if ( (bmc_location == BB_BMC) || (bmc_location == DVT_BB_BMC) ) {
      if ( !board_rev_is_invalid && (COMPONENT_ID(signed_byte) == BICBB) && (bmc_found != string::npos) ) {
        image_sts.result = true;
      } else if ( !board_rev_is_invalid && (COMPONENT_ID(signed_byte) == BICDL) && (slot_found != string::npos) ) {
        image_sts.result = true;
      } else {
        if (board_rev_is_invalid) {
             cout << "To prevent this update on " << fru_name <<", please use the f/w of "
             << board_type[board_type_index].c_str() <<" on the " << board_type[board_type_index].c_str() <<" system." << endl;
             cout << "To force the update, please use the --force option." << endl;
        }

        cout << "image is not a valid CPLD image for " << fru_name << endl;
      }
    }
  }

  //release the resource
  close(fd_r);
  close(fd_w);
  delete[] memblock;

  return image_sts;
}