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;
}