1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 /* 28 * The reference for the functions in this file is the 29 * 30 * Mellanox HCA Flash Programming Application Note 31 * (Mellanox document number 2205AN) rev 1.45, 2007. 32 * Chapter 4 in particular. 33 */ 34 35 #include <stdio.h> 36 #include <stdlib.h> 37 #include <unistd.h> 38 #include <sys/types.h> 39 #include <sys/stat.h> 40 #include <sys/sysmacros.h> 41 #include <sys/queue.h> 42 #include <fcntl.h> 43 #include <ctype.h> 44 #include <string.h> 45 #include <strings.h> 46 47 #include <sys/byteorder.h> 48 49 #include <libintl.h> /* for gettext(3c) */ 50 51 #include <fwflash/fwflash.h> 52 #include "../../hdrs/hermon_ib.h" 53 54 char *devprefix = "/devices"; 55 char drivername[] = "hermon\0"; 56 char *devsuffix = ":devctl"; 57 58 extern di_node_t rootnode; 59 extern int errno; 60 extern struct fw_plugin *self; 61 extern struct vrfyplugin *verifier; 62 extern int fwflash_debug; 63 64 /* required functions for this plugin */ 65 int fw_readfw(struct devicelist *device, char *filename); 66 int fw_writefw(struct devicelist *device); 67 int fw_identify(int start); 68 int fw_devinfo(); 69 70 71 /* helper functions */ 72 static int cnx_identify(struct devicelist *thisdev); 73 static int cnx_get_guids(ib_cnx_encap_ident_t *handle); 74 static int cnx_close(struct devicelist *flashdev); 75 static int cnx_check_for_magic_pattern(ib_cnx_encap_ident_t *hdl, uint32_t adr); 76 static uint32_t cnx_get_log2_chunk_size_f_hdl(ib_cnx_encap_ident_t *handle, 77 int type); 78 static uint32_t cnx_get_log2_chunk_size(uint32_t chunk_size_word); 79 static uint32_t cnx_cont2phys(uint32_t log2_chunk_sz, uint32_t cont_addr, 80 int type); 81 static uint32_t cnx_get_image_size_f_hdl(ib_cnx_encap_ident_t *hdl, int type); 82 static void cnx_local_set_guid_crc_img(uint32_t offset, uint32_t guid_crc_size, 83 uint32_t guid_crc_offset); 84 static int cnx_read_image(ib_cnx_encap_ident_t *handle); 85 static int cnx_write_file(ib_cnx_encap_ident_t *handle, const char *filename); 86 static int cnx_verify_image(ib_cnx_encap_ident_t *handle, int type); 87 static int cnx_read_guids(ib_cnx_encap_ident_t *handle, int type); 88 static int cnx_set_guids(ib_cnx_encap_ident_t *handle, void *arg); 89 static int cnx_write_image(ib_cnx_encap_ident_t *handle, int type); 90 static int cnx_read_ioctl(ib_cnx_encap_ident_t *hdl, 91 hermon_flash_ioctl_t *info); 92 static int cnx_write_ioctl(ib_cnx_encap_ident_t *hdl, 93 hermon_flash_ioctl_t *info); 94 static int cnx_erase_sector_ioctl(ib_cnx_encap_ident_t *hdl, 95 hermon_flash_ioctl_t *info); 96 static int cnx_find_magic_n_chnk_sz(ib_cnx_encap_ident_t *handle, int type); 97 static int cnx_get_image_info(ib_cnx_encap_ident_t *handle); 98 99 100 int 101 fw_readfw(struct devicelist *flashdev, char *filename) 102 { 103 ib_cnx_encap_ident_t *manuf; 104 int rv = FWFLASH_SUCCESS; 105 106 logmsg(MSG_INFO, "hermon: fw_readfw: filename %s\n", filename); 107 108 manuf = (ib_cnx_encap_ident_t *)flashdev->ident->encap_ident; 109 if (CNX_I_CHECK_HANDLE(manuf)) { 110 logmsg(MSG_ERROR, gettext("hermon: Invalid Handle for " 111 "device %s! \n"), flashdev->access_devname); 112 return (FWFLASH_FAILURE); 113 } 114 115 logmsg(MSG_INFO, "hermon: fw_identify should have read the image. " 116 "state 0x%x\n", manuf->state); 117 118 rv = cnx_read_image(manuf); 119 if (rv != FWFLASH_SUCCESS) { 120 logmsg(MSG_ERROR, gettext("hermon: Failed to read any valid " 121 "image on device (%s)\n"), flashdev->access_devname); 122 logmsg(MSG_ERROR, gettext("Aborting read.\n")); 123 } else { 124 rv = cnx_write_file(manuf, filename); 125 } 126 127 cnx_close(flashdev); 128 return (rv); 129 } 130 131 132 /* 133 * If we're invoking fw_writefw, then flashdev is a valid, 134 * flashable device as determined by fw_identify(). 135 * 136 * If verifier is null, then we haven't been called following a firmware 137 * image verification load operation. 138 */ 139 int 140 fw_writefw(struct devicelist *flashdev) 141 { 142 ib_cnx_encap_ident_t *manuf; 143 int i, j, k; 144 145 logmsg(MSG_INFO, "hermon: fw_writefw\n"); 146 147 manuf = (ib_cnx_encap_ident_t *)flashdev->ident->encap_ident; 148 149 if (CNX_I_CHECK_HANDLE(manuf)) { 150 logmsg(MSG_ERROR, gettext("hermon: Invalid Handle for " 151 "device %s! \n"), flashdev->access_devname); 152 return (FWFLASH_FAILURE); 153 } 154 155 /* 156 * Try the primary first, then the secondary. 157 * If we get here, then the verifier has _already_ checked that 158 * the part number in the firmware image matches that in the HCA, 159 * so we only need this check if there's no hardware info available 160 * already after running through fw_identify(). 161 */ 162 if (manuf->pn_len == 0) { 163 int resp; 164 165 (void) fprintf(stderr, gettext("Unable to completely verify " 166 "that this firmware image (%s) is compatible with your " 167 "HCA %s"), verifier->imgfile, flashdev->access_devname); 168 (void) fprintf(stderr, gettext("Do you really want to " 169 "continue? (Y/N): ")); 170 (void) fflush(stdin); 171 resp = getchar(); 172 if (resp != 'Y' && resp != 'y') { 173 (void) fprintf(stderr, gettext("Not proceeding with " 174 "flash operation of %s on %s"), 175 verifier->imgfile, flashdev->access_devname); 176 return (FWFLASH_FAILURE); 177 } 178 } 179 180 logmsg(MSG_INFO, "hermon: fw_writefw: Using Existing GUIDs.\n"); 181 manuf->state |= 182 FWFLASH_IB_STATE_GUIDN | 183 FWFLASH_IB_STATE_GUID1 | 184 FWFLASH_IB_STATE_GUID2 | 185 FWFLASH_IB_STATE_GUIDS; 186 if (cnx_set_guids(manuf, manuf->ibguids) != FWFLASH_SUCCESS) { 187 logmsg(MSG_WARN, gettext("hermon: Failed to set GUIDs")); 188 } 189 190 /* 191 * Update both Primary and Secondary images 192 * 193 * For Failsafe firmware image update, if the current image (i.e. 194 * containing a magic pattern) on the Flash is stored on the Primary 195 * location, burn the new image to the Secondary location first, 196 * or vice versa. 197 */ 198 199 /* Note Current Image location. */ 200 j = manuf->state & 201 (FWFLASH_IB_STATE_IMAGE_PRI | FWFLASH_IB_STATE_IMAGE_SEC); 202 203 /* 204 * If we find that current image location is not found, no worries 205 * we shall default to PRIMARY, and proceed with burning anyway. 206 */ 207 if (j == 0) 208 j = FWFLASH_IB_STATE_IMAGE_PRI; 209 210 for (i = FWFLASH_FLASH_IMAGES; i > 0; i--) { 211 char *type; 212 213 if (i == 2) { 214 if (j == 2) 215 k = 1; /* Burn PRI First */ 216 else 217 k = 2; /* Burn SEC First */ 218 } else { 219 if (k == 2) 220 k = 1; /* Burn PRI next */ 221 else 222 k = 2; /* Burn SEC next */ 223 } 224 type = ((k == 1) ? "Primary" : "Secondary"); 225 226 logmsg(MSG_INFO, "hermon: fw_write: UPDATING %s image\n", type); 227 228 if (cnx_write_image(manuf, k) != FWFLASH_SUCCESS) { 229 (void) fprintf(stderr, 230 gettext("Failed to update %s image on device %s"), 231 type, flashdev->access_devname); 232 goto out; 233 } 234 235 logmsg(MSG_INFO, "hermon: fw_write: Verify %s image..\n", type); 236 if (cnx_verify_image(manuf, k) != FWFLASH_SUCCESS) { 237 (void) fprintf(stderr, 238 gettext("Failed to verify %s image for device %s"), 239 type, flashdev->access_devname); 240 goto out; 241 } 242 } 243 out: 244 /* final update marker to the user */ 245 (void) printf(" +\n"); 246 return (cnx_close(flashdev)); 247 } 248 249 250 /* 251 * The fw_identify() function walks the device tree trying to find 252 * devices which this plugin can work with. 253 * 254 * The parameter "start" gives us the starting index number 255 * to give the device when we add it to the fw_devices list. 256 * 257 * firstdev is allocated by us and we add space as necessary 258 */ 259 int 260 fw_identify(int start) 261 { 262 int rv = FWFLASH_FAILURE; 263 di_node_t thisnode; 264 struct devicelist *newdev; 265 char *devpath; 266 int idx = start; 267 int devlength = 0; 268 269 logmsg(MSG_INFO, "hermon: fw_identify\n"); 270 thisnode = di_drv_first_node(drivername, rootnode); 271 272 if (thisnode == DI_NODE_NIL) { 273 logmsg(MSG_INFO, gettext("No %s nodes in this system\n"), 274 drivername); 275 return (rv); 276 } 277 278 /* we've found one, at least */ 279 for (; thisnode != DI_NODE_NIL; thisnode = di_drv_next_node(thisnode)) { 280 281 devpath = di_devfs_path(thisnode); 282 283 if ((newdev = calloc(1, sizeof (struct devicelist))) == NULL) { 284 logmsg(MSG_ERROR, gettext("hermon: Unable to allocate " 285 "space for device entry\n")); 286 di_devfs_path_free(devpath); 287 return (FWFLASH_FAILURE); 288 } 289 290 /* calloc enough for /devices + devpath + ":devctl" + '\0' */ 291 devlength = strlen(devpath) + strlen(devprefix) + 292 strlen(devsuffix) + 2; 293 294 if ((newdev->access_devname = calloc(1, devlength)) == NULL) { 295 logmsg(MSG_ERROR, gettext("hermon: Unable to allocate " 296 "space for a devfs name\n")); 297 (void) free(newdev); 298 di_devfs_path_free(devpath); 299 return (FWFLASH_FAILURE); 300 } 301 snprintf(newdev->access_devname, devlength, 302 "%s%s%s", devprefix, devpath, devsuffix); 303 304 if ((newdev->ident = calloc(1, sizeof (struct vpr))) == NULL) { 305 logmsg(MSG_ERROR, gettext("hermon: Unable to allocate " 306 "space for a device identification record\n")); 307 (void) free(newdev->access_devname); 308 (void) free(newdev); 309 di_devfs_path_free(devpath); 310 return (FWFLASH_FAILURE); 311 } 312 313 /* CHECK VARIOUS IB THINGS HERE */ 314 rv = cnx_identify(newdev); 315 if (rv == FWFLASH_FAILURE) { 316 (void) free(newdev->ident); 317 (void) free(newdev->access_devname); 318 (void) free(newdev); 319 di_devfs_path_free(devpath); 320 continue; 321 } 322 323 if ((newdev->drvname = calloc(1, strlen(drivername) + 1)) 324 == NULL) { 325 logmsg(MSG_ERROR, gettext("hermon: Unable to allocate" 326 " space for a driver name\n")); 327 (void) free(newdev->ident); 328 (void) free(newdev->access_devname); 329 (void) free(newdev); 330 di_devfs_path_free(devpath); 331 return (FWFLASH_FAILURE); 332 } 333 334 (void) strlcpy(newdev->drvname, drivername, 335 strlen(drivername) + 1); 336 337 /* this next bit is backwards compatibility - "IB\0" */ 338 if ((newdev->classname = calloc(1, 3)) == NULL) { 339 logmsg(MSG_ERROR, gettext("hermon: Unable to allocate " 340 "space for a class name\n")); 341 (void) free(newdev->drvname); 342 (void) free(newdev->ident); 343 (void) free(newdev->access_devname); 344 (void) free(newdev); 345 di_devfs_path_free(devpath); 346 return (FWFLASH_FAILURE); 347 } 348 (void) strlcpy(newdev->classname, "IB", 3); 349 350 newdev->index = idx; 351 ++idx; 352 newdev->plugin = self; 353 354 di_devfs_path_free(devpath); 355 356 TAILQ_INSERT_TAIL(fw_devices, newdev, nextdev); 357 } 358 359 if (fwflash_debug != 0) { 360 struct devicelist *tempdev; 361 362 TAILQ_FOREACH(tempdev, fw_devices, nextdev) { 363 logmsg(MSG_INFO, "fw_identify: hermon:\n"); 364 logmsg(MSG_INFO, "\ttempdev @ 0x%lx\n" 365 "\t\taccess_devname: %s\n" 366 "\t\tdrvname: %s\tclassname: %s\n" 367 "\t\tident->vid: %s\n" 368 "\t\tident->pid: %s\n" 369 "\t\tident->revid: %s\n" 370 "\t\tindex: %d\n" 371 "\t\tguid0: %s\n" 372 "\t\tguid1: %s\n" 373 "\t\tguid2: %s\n" 374 "\t\tguid3: %s\n" 375 "\t\tplugin @ 0x%lx\n\n", 376 &tempdev, 377 tempdev->access_devname, 378 tempdev->drvname, newdev->classname, 379 tempdev->ident->vid, 380 tempdev->ident->pid, 381 tempdev->ident->revid, 382 tempdev->index, 383 tempdev->addresses[0], 384 tempdev->addresses[1], 385 tempdev->addresses[2], 386 tempdev->addresses[3], 387 tempdev->plugin); 388 } 389 } 390 391 return (FWFLASH_SUCCESS); 392 } 393 394 395 int 396 fw_devinfo(struct devicelist *thisdev) 397 { 398 ib_cnx_encap_ident_t *encap; 399 400 logmsg(MSG_INFO, "hermon: fw_devinfo\n"); 401 402 encap = (ib_cnx_encap_ident_t *)thisdev->ident->encap_ident; 403 if (CNX_I_CHECK_HANDLE(encap)) { 404 logmsg(MSG_ERROR, gettext("hermon: fw_devinfo: Invalid handle " 405 "for device %s! \n"), thisdev->access_devname); 406 return (FWFLASH_FAILURE); 407 } 408 409 /* Try the primary first, then the secondary */ 410 fprintf(stdout, gettext("Device[%d] %s\n"), 411 thisdev->index, thisdev->access_devname); 412 fprintf(stdout, gettext("Class [%s]\n"), thisdev->classname); 413 414 fprintf(stdout, "\t"); 415 416 /* Mellanox HCA Flash app note, p40, #4.2.3 table 9 */ 417 fprintf(stdout, gettext("GUID: System Image - %s\n"), 418 thisdev->addresses[3]); 419 fprintf(stdout, gettext("\t\tNode Image - %s\n"), 420 thisdev->addresses[0]); 421 fprintf(stdout, gettext("\t\tPort 1\t - %s\n"), 422 thisdev->addresses[1]); 423 fprintf(stdout, gettext("\t\tPort 2\t - %s\n"), 424 thisdev->addresses[2]); 425 426 fprintf(stdout, gettext("\tFirmware revision : %s\n"), 427 thisdev->ident->revid); 428 429 if (encap->pn_len != 0) { 430 if (strlen(encap->info.mlx_id)) 431 fprintf(stdout, gettext("\tProduct\t\t : %s (%s)\n"), 432 encap->info.mlx_pn, encap->info.mlx_id); 433 else 434 fprintf(stdout, gettext("\tProduct\t\t : %s \n"), 435 encap->info.mlx_pn); 436 437 if (strlen(encap->info.mlx_psid)) 438 fprintf(stdout, gettext("\tPSID\t\t : %s\n"), 439 encap->info.mlx_psid); 440 else if (strlen(thisdev->ident->pid)) 441 fprintf(stdout, gettext("\t%s\n"), thisdev->ident->pid); 442 } else { 443 fprintf(stdout, gettext("\t%s\n"), thisdev->ident->pid); 444 } 445 fprintf(stdout, "\n\n"); 446 447 return (cnx_close(thisdev)); 448 } 449 450 451 /* 452 * Helper functions lurk beneath this point 453 */ 454 455 456 /* 457 * Notes: 458 * 1. flash read is done in 32 bit quantities, and the driver returns 459 * data in host byteorder form. 460 * 2. flash write is done in 8 bit quantities by the driver. 461 * 3. data in the flash should be in network byteorder. 462 * 4. data in image files is in network byteorder form. 463 * 5. data in image structures in memory is kept in network byteorder. 464 * 6. the functions in this file deal with data in host byteorder form. 465 */ 466 467 static int 468 cnx_read_image(ib_cnx_encap_ident_t *handle) 469 { 470 hermon_flash_ioctl_t ioctl_info; 471 uint32_t phys_addr; 472 int ret, i; 473 int image_size; 474 int type; 475 476 type = handle->state & 477 (FWFLASH_IB_STATE_IMAGE_PRI | FWFLASH_IB_STATE_IMAGE_SEC); 478 logmsg(MSG_INFO, "cnx_read_image: type %lx\n", type); 479 480 if (type == 0) { 481 logmsg(MSG_ERROR, gettext("cnx_read_image: Must read in " 482 "image first\n")); 483 return (FWFLASH_FAILURE); 484 } 485 486 image_size = handle->fw_sz; 487 if (image_size <= 0) { 488 logmsg(MSG_ERROR, gettext("cnx_read_image: Invalid image size " 489 "0x%x for %s image\n"), 490 image_size, (type == 0x1 ? "Primary" : "Secondary")); 491 return (FWFLASH_FAILURE); 492 } 493 494 logmsg(MSG_INFO, "hermon: fw_size: 0x%x\n", image_size); 495 496 handle->fw = (uint32_t *)calloc(1, image_size); 497 if (handle->fw == NULL) { 498 logmsg(MSG_ERROR, gettext("cnx_read_image: Unable to allocate " 499 "memory for fw_img : (%s)\n"), strerror(errno)); 500 return (FWFLASH_FAILURE); 501 } 502 503 ioctl_info.af_type = HERMON_FLASH_READ_QUADLET; 504 for (i = 0; i < image_size; i += 4) { 505 phys_addr = cnx_cont2phys(handle->log2_chunk_sz, i, type); 506 ioctl_info.af_addr = phys_addr; 507 508 ret = cnx_read_ioctl(handle, &ioctl_info); 509 if (ret != 0) { 510 logmsg(MSG_ERROR, gettext("cnx_read_image: Failed to " 511 "read sector %d\n"), i); 512 free(handle->fw); 513 return (FWFLASH_FAILURE); 514 } 515 handle->fw[i / 4] = htonl(ioctl_info.af_quadlet); 516 } 517 518 for (i = 0; i < image_size; i += 4) { 519 logmsg(MSG_INFO, "cnx_read_image: addr[0x%x] = 0x%08x\n", i, 520 ntohl(handle->fw[i / 4])); 521 } 522 523 return (FWFLASH_SUCCESS); 524 } 525 526 static int 527 cnx_write_file(ib_cnx_encap_ident_t *handle, const char *filename) 528 { 529 FILE *fp; 530 int fd; 531 mode_t mode = S_IRUSR | S_IWUSR; 532 int len; 533 534 logmsg(MSG_INFO, "cnx_write_file\n"); 535 536 errno = 0; 537 if ((fd = open(filename, O_RDWR|O_CREAT|O_DSYNC, mode)) < 0) { 538 logmsg(MSG_ERROR, gettext("hermon: Unable to open specified " 539 "file (%s) for writing: %s\n"), filename, strerror(errno)); 540 return (FWFLASH_FAILURE); 541 } 542 543 errno = 0; 544 fp = fdopen(fd, "w"); 545 if (fp == NULL) { 546 (void) fprintf(stderr, gettext("hermon: Unknown filename %s : " 547 "%s\n"), filename, strerror(errno)); 548 return (FWFLASH_FAILURE); 549 } 550 551 len = ntohl(handle->fw[CNX_IMG_SIZE_OFFSET / 4]); 552 logmsg(MSG_INFO, "cnx_write_file: Writing to file. Length 0x%x\n", len); 553 554 if (fwrite(&handle->fw[0], len, 1, fp) == 0) { 555 (void) fprintf(stderr, gettext("hermon: fwrite failed")); 556 perror("fwrite"); 557 (void) fclose(fp); 558 return (FWFLASH_FAILURE); 559 } 560 (void) fclose(fp); 561 return (FWFLASH_SUCCESS); 562 } 563 564 static int 565 cnx_verify_image(ib_cnx_encap_ident_t *handle, int type) 566 { 567 uint32_t new_start_addr; 568 569 logmsg(MSG_INFO, "hermon: cnx_verify_image\n"); 570 571 new_start_addr = cnx_cont2phys(handle->log2_chunk_sz, 0, type); 572 573 return (cnx_check_for_magic_pattern(handle, new_start_addr)); 574 } 575 576 static int 577 cnx_set_guids(ib_cnx_encap_ident_t *handle, void *arg) 578 { 579 uint32_t addr; 580 uint32_t *guids; 581 582 logmsg(MSG_INFO, "hermon: cnx_set_guids\n"); 583 584 guids = (uint32_t *)arg; 585 addr = ntohl(verifier->fwimage[CNX_NGUIDPTR_OFFSET / 4]) / 4; 586 logmsg(MSG_INFO, "cnx_set_guids: guid_start_addr: 0x%x\n", addr * 4); 587 588 /* 589 * guids are supplied by callers as 64 bit values in host byteorder. 590 * Storage is in network byteorder. 591 */ 592 #ifdef _BIG_ENDIAN 593 if (handle->state & FWFLASH_IB_STATE_GUIDN) { 594 verifier->fwimage[addr] = guids[0]; 595 verifier->fwimage[addr + 1] = guids[1]; 596 } 597 598 if (handle->state & FWFLASH_IB_STATE_GUID1) { 599 verifier->fwimage[addr + 2] = guids[2]; 600 verifier->fwimage[addr + 3] = guids[3]; 601 } 602 603 if (handle->state & FWFLASH_IB_STATE_GUID2) { 604 verifier->fwimage[addr + 4] = guids[4]; 605 verifier->fwimage[addr + 5] = guids[5]; 606 } 607 608 if (handle->state & FWFLASH_IB_STATE_GUIDS) { 609 verifier->fwimage[addr + 6] = guids[6]; 610 verifier->fwimage[addr + 7] = guids[7]; 611 } 612 #else 613 if (handle->state & FWFLASH_IB_STATE_GUIDN) { 614 verifier->fwimage[addr] = htonl(guids[1]); 615 verifier->fwimage[addr + 1] = htonl(guids[0]); 616 } 617 618 if (handle->state & FWFLASH_IB_STATE_GUID1) { 619 verifier->fwimage[addr + 2] = htonl(guids[3]); 620 verifier->fwimage[addr + 3] = htonl(guids[2]); 621 } 622 623 if (handle->state & FWFLASH_IB_STATE_GUID2) { 624 verifier->fwimage[addr + 4] = htonl(guids[5]); 625 verifier->fwimage[addr + 5] = htonl(guids[4]); 626 } 627 628 if (handle->state & FWFLASH_IB_STATE_GUIDS) { 629 verifier->fwimage[addr + 6] = htonl(guids[7]); 630 verifier->fwimage[addr + 7] = htonl(guids[6]); 631 } 632 #endif 633 634 cnx_local_set_guid_crc_img((addr * 4) - 0x10, CNX_GUID_CRC16_SIZE, 635 CNX_GUID_CRC16_OFFSET); 636 637 return (FWFLASH_SUCCESS); 638 } 639 640 /* 641 * Notes: Burn the image 642 * 643 * 1. Erase the entire sector where the new image is to be burned. 644 * 2. Burn the image WITHOUT the magic pattern. This marks the new image 645 * as invalid during the burn process. If the current image (i.e 646 * containing a magic pattern) on the Flash is stored on the even 647 * chunks (PRIMARY), burn the new image to the odd chunks (SECONDARY), 648 * or vice versa. 649 * 3. Burn the magic pattern at the beginning of the new image on the Flash. 650 * This will validate the new image. 651 * 4. Set the BootAddress register to its new location. 652 */ 653 static int 654 cnx_write_image(ib_cnx_encap_ident_t *handle, int type) 655 { 656 hermon_flash_ioctl_t ioctl_info; 657 int sector_size; 658 int size; 659 int i; 660 uint32_t new_start_addr; 661 uint32_t log2_chunk_sz; 662 uint8_t *fw; 663 664 logmsg(MSG_INFO, "hermon: cnx_write_image\n"); 665 666 if (type == 0) { 667 logmsg(MSG_ERROR, gettext("cnx_write_image: Must inform us " 668 " where to write.\n")); 669 return (FWFLASH_FAILURE); 670 } 671 672 log2_chunk_sz = cnx_get_log2_chunk_size( 673 ntohl(verifier->fwimage[CNX_CHUNK_SIZE_OFFSET / 4])); 674 675 sector_size = handle->sector_sz; 676 new_start_addr = ((type - 1) << handle->log2_chunk_sz); 677 678 /* Read Image Size */ 679 size = ntohl(verifier->fwimage[CNX_IMG_SIZE_OFFSET / 4]); 680 logmsg(MSG_INFO, "cnx_write_image: fw image size: 0x%x\n", size); 681 682 /* Sectors must be erased before they can be written to. */ 683 ioctl_info.af_type = HERMON_FLASH_ERASE_SECTOR; 684 for (i = 0; i < size; i += sector_size) { 685 ioctl_info.af_sector_num = 686 cnx_cont2phys(log2_chunk_sz, i, type) / sector_size; 687 if (cnx_erase_sector_ioctl(handle, &ioctl_info) != 0) { 688 logmsg(MSG_ERROR, gettext("cnx_write_image: Failed to " 689 "erase sector 0x%x\n"), ioctl_info.af_sector_num); 690 return (FWFLASH_FAILURE); 691 } 692 } 693 694 fw = (uint8_t *)verifier->fwimage; 695 ioctl_info.af_type = HERMON_FLASH_WRITE_BYTE; 696 697 /* Write the new image without the magic pattern */ 698 for (i = 16; i < size; i++) { 699 ioctl_info.af_byte = fw[i]; 700 ioctl_info.af_addr = cnx_cont2phys(log2_chunk_sz, i, type); 701 if (cnx_write_ioctl(handle, &ioctl_info) != 0) { 702 logmsg(MSG_ERROR, gettext("cnx_write_image: Failed to " 703 "write byte 0x%x\n"), ioctl_info.af_byte); 704 return (FWFLASH_FAILURE); 705 } 706 707 if (i && !(i % handle->sector_sz)) { 708 (void) printf(" ."); 709 (void) fflush((void *)NULL); 710 } 711 } 712 713 /* Validate the new image -- Write the magic pattern. */ 714 for (i = 0; i < 16; i++) { 715 ioctl_info.af_byte = fw[i]; 716 ioctl_info.af_addr = cnx_cont2phys(log2_chunk_sz, i, type); 717 if (cnx_write_ioctl(handle, &ioctl_info) != 0) { 718 logmsg(MSG_ERROR, gettext("cnx_write_image: Failed to " 719 "write magic pattern byte 0x%x\n"), 720 ioctl_info.af_byte); 721 return (FWFLASH_FAILURE); 722 } 723 } 724 725 /* Write new image start address to CR space */ 726 errno = 0; 727 ioctl_info.af_addr = new_start_addr; 728 if (ioctl(handle->fd, HERMON_IOCTL_WRITE_BOOT_ADDR, &ioctl_info) != 0) { 729 logmsg(MSG_WARN, gettext("cnx_write_image: Failed to " 730 "update boot address register: %s\n"), strerror(errno)); 731 } 732 733 return (FWFLASH_SUCCESS); 734 } 735 736 737 /* 738 * cnx_identify performs the following actions: 739 * 740 * allocates and assigns thisdev->vpr 741 * 742 * allocates space for the 4 GUIDs which each IB device must have 743 * queries the hermon driver for this device's GUIDs 744 * 745 * determines the hardware vendor, so that thisdev->vpr->vid 746 * can be set correctly 747 */ 748 static int 749 cnx_identify(struct devicelist *thisdev) 750 { 751 int fd, ret, i; 752 hermon_flash_init_ioctl_t init_ioctl; 753 ib_cnx_encap_ident_t *manuf; 754 cfi_t cfi; 755 int hw_psid_found = 0; 756 757 logmsg(MSG_INFO, "hermon: cnx_identify\n"); 758 /* open the device */ 759 /* hook thisdev->ident->encap_ident to ib_cnx_encap_ident_t */ 760 /* check that all the bits are sane */ 761 /* return success, if warranted */ 762 763 errno = 0; 764 if ((fd = open(thisdev->access_devname, O_RDONLY)) < 0) { 765 logmsg(MSG_ERROR, gettext("hermon: Unable to open a %s-" 766 "attached device node: %s: %s\n"), drivername, 767 thisdev->access_devname, strerror(errno)); 768 return (FWFLASH_FAILURE); 769 } 770 771 if ((manuf = calloc(1, sizeof (ib_cnx_encap_ident_t))) == NULL) { 772 logmsg(MSG_ERROR, gettext("hermon: Unable to allocate space " 773 "for a %s-attached handle structure\n"), drivername); 774 close(fd); 775 return (FWFLASH_FAILURE); 776 } 777 manuf->magic = FWFLASH_IB_MAGIC_NUMBER; 778 manuf->state = FWFLASH_IB_STATE_NONE; 779 manuf->fd = fd; 780 manuf->log2_chunk_sz = 0; 781 782 thisdev->ident->encap_ident = manuf; 783 784 /* 785 * Inform driver that this command supports the Intel Extended 786 * CFI command set. 787 */ 788 cfi.cfi_char[0x10] = 'M'; 789 cfi.cfi_char[0x11] = 'X'; 790 cfi.cfi_char[0x12] = '2'; 791 init_ioctl.af_cfi_info[0x4] = ntohl(cfi.cfi_int[0x4]); 792 793 errno = 0; 794 ret = ioctl(fd, HERMON_IOCTL_FLASH_INIT, &init_ioctl); 795 if (ret < 0) { 796 logmsg(MSG_ERROR, gettext("hermon: HERMON_IOCTL_FLASH_INIT " 797 "failed: %s\n"), strerror(errno)); 798 close(fd); 799 free(manuf); 800 return (FWFLASH_FAILURE); 801 } 802 803 manuf->hwrev = init_ioctl.af_hwrev; 804 logmsg(MSG_INFO, "hermon: init_ioctl: hwrev: %x, fwver: %d.%d.%04d, " 805 "PN# Len %d\n", init_ioctl.af_hwrev, init_ioctl.af_fwrev.afi_maj, 806 init_ioctl.af_fwrev.afi_min, init_ioctl.af_fwrev.afi_sub, 807 init_ioctl.af_pn_len); 808 809 /* 810 * Determine whether the attached driver supports the Intel or 811 * AMD Extended CFI command sets. If it doesn't support either, 812 * then we're hosed, so error out. 813 */ 814 for (i = 0; i < HERMON_FLASH_CFI_SIZE_QUADLET; i++) { 815 cfi.cfi_int[i] = ntohl(init_ioctl.af_cfi_info[i]); 816 } 817 manuf->cmd_set = cfi.cfi_char[0x13]; 818 819 if (cfi.cfi_char[0x10] == 'Q' && 820 cfi.cfi_char[0x11] == 'R' && 821 cfi.cfi_char[0x12] == 'Y') { 822 /* make sure the cmd set is SPI */ 823 if (manuf->cmd_set != HERMON_FLASH_SPI_CMDSET) { 824 logmsg(MSG_ERROR, gettext("hermon: Unsupported flash " 825 "device command set\n")); 826 goto identify_end; 827 } 828 /* set some defaults */ 829 manuf->sector_sz = HERMON_FLASH_SECTOR_SZ_DEFAULT; 830 manuf->device_sz = HERMON_FLASH_DEVICE_SZ_DEFAULT; 831 } else if (manuf->cmd_set == HERMON_FLASH_SPI_CMDSET) { 832 manuf->sector_sz = HERMON_FLASH_SPI_SECTOR_SIZE; 833 manuf->device_sz = HERMON_FLASH_SPI_DEVICE_SIZE; 834 } else { 835 if (manuf->cmd_set != HERMON_FLASH_AMD_CMDSET && 836 manuf->cmd_set != HERMON_FLASH_INTEL_CMDSET) { 837 logmsg(MSG_ERROR, gettext("hermon: Unknown flash " 838 "device command set %lx\n"), manuf->cmd_set); 839 goto identify_end; 840 } 841 /* read from the CFI data */ 842 manuf->sector_sz = ((cfi.cfi_char[0x30] << 8) | 843 cfi.cfi_char[0x2F]) << 8; 844 manuf->device_sz = 0x1 << cfi.cfi_char[0x27]; 845 } 846 847 logmsg(MSG_INFO, "hermon: sector_sz: 0x%08x device_sz: 0x%08x\n", 848 manuf->sector_sz, manuf->device_sz); 849 850 /* set firmware revision */ 851 manuf->hwfw_img_info.fw_rev.major = init_ioctl.af_fwrev.afi_maj; 852 manuf->hwfw_img_info.fw_rev.minor = init_ioctl.af_fwrev.afi_min; 853 manuf->hwfw_img_info.fw_rev.subminor = init_ioctl.af_fwrev.afi_sub; 854 855 if (((thisdev->ident->vid = calloc(1, MLX_VPR_VIDLEN + 1)) == NULL) || 856 ((thisdev->ident->revid = calloc(1, MLX_VPR_REVLEN + 1)) == NULL)) { 857 logmsg(MSG_ERROR, gettext("hermon: Unable to allocate space " 858 "for a VPR record.\n")); 859 goto identify_end; 860 } 861 (void) strlcpy(thisdev->ident->vid, "MELLANOX", MLX_VPR_VIDLEN); 862 863 /* 864 * We actually want the hwrev field from the ioctl above. 865 * Until we find out otherwise, add it onto the end of the 866 * firmware version details. 867 */ 868 snprintf(thisdev->ident->revid, MLX_VPR_REVLEN, "%d.%d.%03d", 869 manuf->hwfw_img_info.fw_rev.major, 870 manuf->hwfw_img_info.fw_rev.minor, 871 manuf->hwfw_img_info.fw_rev.subminor); 872 873 if ((ret = cnx_get_guids(manuf)) != FWFLASH_SUCCESS) { 874 logmsg(MSG_WARN, gettext("hermon: No GUIDs found for " 875 "device %s!\n"), thisdev->access_devname); 876 } 877 878 /* set hw part number, psid, and name in handle */ 879 /* now walk the magic decoder ring table */ 880 manuf->info.mlx_pn = NULL; 881 manuf->info.mlx_psid = NULL; 882 manuf->info.mlx_id = NULL; 883 884 if (cnx_get_image_info(manuf) != FWFLASH_SUCCESS) { 885 logmsg(MSG_WARN, gettext("hermon: Failed to read Image Info " 886 "for PSID\n")); 887 hw_psid_found = 0; 888 } else { 889 hw_psid_found = 1; 890 } 891 892 if (init_ioctl.af_pn_len != 0) { 893 /* part number length */ 894 for (i = 0; i < init_ioctl.af_pn_len; i++) { 895 if (init_ioctl.af_hwpn[i] == ' ') { 896 manuf->pn_len = i; 897 break; 898 } 899 } 900 if (i == init_ioctl.af_pn_len) { 901 manuf->pn_len = init_ioctl.af_pn_len; 902 } 903 } else { 904 logmsg(MSG_INFO, "hermon: Failed to get Part# from hermon " 905 "driver \n"); 906 manuf->pn_len = 0; 907 } 908 909 if (manuf->pn_len != 0) { 910 errno = 0; 911 manuf->info.mlx_pn = calloc(1, manuf->pn_len); 912 if (manuf->info.mlx_pn == NULL) { 913 logmsg(MSG_ERROR, gettext("hermon: no space available " 914 "for the HCA PN record (%s)\n"), strerror(errno)); 915 goto identify_end; 916 } 917 (void) memcpy(manuf->info.mlx_pn, init_ioctl.af_hwpn, 918 manuf->pn_len); 919 manuf->info.mlx_pn[manuf->pn_len] = 0; 920 921 logmsg(MSG_INFO, "hermon: HCA PN (%s) PN-Len %d\n", 922 manuf->info.mlx_pn, manuf->pn_len); 923 924 errno = 0; 925 manuf->info.mlx_psid = calloc(1, MLX_PSID_SZ); 926 if (manuf->info.mlx_psid == NULL) { 927 logmsg(MSG_ERROR, gettext("hermon: PSID calloc " 928 "failed :%s\n"), strerror(errno)); 929 goto identify_end; 930 } 931 932 errno = 0; 933 if ((manuf->info.mlx_id = calloc(1, MLX_STR_ID_SZ)) == NULL) { 934 logmsg(MSG_ERROR, gettext("hermon: " 935 "ID calloc failed (%s)\n"), 936 strerror(errno)); 937 goto identify_end; 938 } 939 940 /* Find part number, set the rest */ 941 for (i = 0; i < MLX_MAX_ID; i++) { 942 if (strncmp((const char *)init_ioctl.af_hwpn, 943 mlx_mdr[i].mlx_pn, manuf->pn_len) == 0) { 944 945 if (hw_psid_found) { 946 logmsg(MSG_INFO, "HW-PSID: %s " 947 "MLX_MDR[%d]: %s\n", 948 manuf->hwfw_img_info.psid, i, 949 mlx_mdr[i].mlx_psid); 950 if (strncmp((const char *) 951 manuf->hwfw_img_info.psid, 952 mlx_mdr[i].mlx_psid, 953 MLX_PSID_SZ) != 0) 954 continue; 955 } 956 /* Set PSID */ 957 (void) memcpy(manuf->info.mlx_psid, 958 mlx_mdr[i].mlx_psid, MLX_PSID_SZ); 959 manuf->info.mlx_psid[MLX_PSID_SZ - 1] = 0; 960 961 logmsg(MSG_INFO, "hermon: HCA PSID (%s)\n", 962 manuf->info.mlx_psid); 963 964 (void) strlcpy(manuf->info.mlx_id, 965 mlx_mdr[i].mlx_id, 966 strlen(mlx_mdr[i].mlx_id) + 1); 967 968 logmsg(MSG_INFO, "hermon: HCA Name (%s)\n", 969 manuf->info.mlx_id); 970 971 break; 972 } 973 } 974 } 975 976 if ((manuf->pn_len == 0) || (i == MLX_MAX_ID)) { 977 logmsg(MSG_INFO, "hermon: No hardware part number " 978 "information available for this HCA\n"); 979 980 i = strlen("No hardware information available for this device"); 981 982 thisdev->ident->pid = calloc(1, i + 2); 983 sprintf(thisdev->ident->pid, "No additional hardware info " 984 "available for this device"); 985 } else { 986 errno = 0; 987 if ((thisdev->ident->pid = calloc(1, 988 strlen(manuf->info.mlx_psid) + 1)) != NULL) { 989 (void) strlcpy(thisdev->ident->pid, 990 manuf->info.mlx_psid, 991 strlen(manuf->info.mlx_psid) + 1); 992 } else { 993 logmsg(MSG_ERROR, 994 gettext("hermon: Unable to allocate space for a " 995 "hardware identifier: %s\n"), strerror(errno)); 996 goto identify_end; 997 } 998 } 999 1000 for (i = 0; i < 4; i++) { 1001 errno = 0; 1002 if ((thisdev->addresses[i] = calloc(1, 1003 (2 * sizeof (uint64_t)) + 1)) == NULL) { 1004 logmsg(MSG_ERROR, 1005 gettext("hermon: Unable to allocate space for a " 1006 "human-readable HCA guid: %s\n"), strerror(errno)); 1007 goto identify_end; 1008 } 1009 (void) sprintf(thisdev->addresses[i], "%016llx", 1010 manuf->ibguids[i]); 1011 } 1012 1013 /* 1014 * We do NOT close the fd here, since we can close it 1015 * at the end of the fw_readfw() or fw_writefw() functions 1016 * instead and not get the poor dear confused about whether 1017 * it's been inited already. 1018 */ 1019 1020 return (FWFLASH_SUCCESS); 1021 1022 /* cleanup */ 1023 identify_end: 1024 cnx_close(thisdev); 1025 return (FWFLASH_FAILURE); 1026 } 1027 1028 static int 1029 cnx_get_guids(ib_cnx_encap_ident_t *handle) 1030 { 1031 int i, rv; 1032 1033 logmsg(MSG_INFO, "cnx_get_guids\n"); 1034 1035 /* make sure we've got our fallback position organised */ 1036 for (i = 0; i < 4; i++) { 1037 handle->ibguids[i] = 0x00000000; 1038 } 1039 1040 rv = cnx_find_magic_n_chnk_sz(handle, FWFLASH_IB_STATE_IMAGE_PRI); 1041 if (rv != FWFLASH_SUCCESS) { 1042 logmsg(MSG_INFO, "hermon: Failed to get Primary magic number. " 1043 "Trying Secondary... \n"); 1044 rv = cnx_find_magic_n_chnk_sz(handle, 1045 FWFLASH_IB_STATE_IMAGE_SEC); 1046 if (rv != FWFLASH_SUCCESS) { 1047 logmsg(MSG_ERROR, gettext("hermon: Failed to get " 1048 "Secondary magic number.\n")); 1049 logmsg(MSG_ERROR, 1050 gettext("Warning: HCA Firmware corrupt.\n")); 1051 return (FWFLASH_FAILURE); 1052 } 1053 rv = cnx_read_guids(handle, FWFLASH_IB_STATE_IMAGE_SEC); 1054 if (rv != FWFLASH_SUCCESS) { 1055 logmsg(MSG_ERROR, gettext("hermon: Failed to read " 1056 "secondary guids.\n")); 1057 return (FWFLASH_FAILURE); 1058 } 1059 } else { 1060 rv = cnx_read_guids(handle, FWFLASH_IB_STATE_IMAGE_PRI); 1061 if (rv != FWFLASH_SUCCESS) { 1062 logmsg(MSG_ERROR, gettext("hermon: Failed to read " 1063 "primary guids.\n")); 1064 return (FWFLASH_FAILURE); 1065 } 1066 } 1067 for (i = 0; i < 4; i++) { 1068 logmsg(MSG_INFO, "hermon: ibguids[%d] 0x%016llx\n", i, 1069 handle->ibguids[i]); 1070 } 1071 for (i = 0; i < 2; i++) { 1072 logmsg(MSG_INFO, "hermon: ib_portmac[%d] 0x%016llx\n", i, 1073 handle->ib_mac[i]); 1074 } 1075 1076 return (FWFLASH_SUCCESS); 1077 } 1078 1079 static int 1080 cnx_close(struct devicelist *flashdev) 1081 { 1082 ib_cnx_encap_ident_t *handle; 1083 1084 logmsg(MSG_INFO, "cnx_close\n"); 1085 1086 handle = (ib_cnx_encap_ident_t *)flashdev->ident->encap_ident; 1087 1088 if (CNX_I_CHECK_HANDLE(handle)) { 1089 logmsg(MSG_ERROR, gettext("hermon: Invalid Handle to close " 1090 "device %s! \n"), flashdev->access_devname); 1091 return (FWFLASH_FAILURE); 1092 } 1093 1094 if (handle->fd > 0) { 1095 errno = 0; 1096 (void) ioctl(handle->fd, HERMON_IOCTL_FLASH_FINI); 1097 if (close(handle->fd) != 0) { 1098 logmsg(MSG_ERROR, gettext("hermon: Unable to properly " 1099 "close device %s! (%s)\n"), 1100 flashdev->access_devname, strerror(errno)); 1101 return (FWFLASH_FAILURE); 1102 } 1103 } 1104 1105 if (handle != NULL) { 1106 if (handle->info.mlx_id != NULL) 1107 free(handle->info.mlx_id); 1108 1109 if (handle->info.mlx_psid != NULL) 1110 free(handle->info.mlx_psid); 1111 1112 if (handle->fw != NULL) 1113 free(handle->fw); 1114 free(handle); 1115 } 1116 1117 if (flashdev->ident->vid != NULL) 1118 free(flashdev->ident->vid); 1119 1120 if (flashdev->ident->revid != NULL) 1121 free(flashdev->ident->revid); 1122 1123 return (FWFLASH_SUCCESS); 1124 } 1125 1126 1127 /* 1128 * Driver read/write ioctl calls. 1129 */ 1130 static int 1131 cnx_read_ioctl(ib_cnx_encap_ident_t *hdl, hermon_flash_ioctl_t *info) 1132 { 1133 int ret; 1134 1135 #ifdef CNX_DEBUG 1136 logmsg(MSG_INFO, "cnx_read_ioctl: fd %d af_type 0x%x af_addr 0x%x " 1137 "af_sector_num(0x%x)\n", hdl->fd, info->af_type, 1138 info->af_addr, info->af_sector_num); 1139 #endif 1140 1141 errno = 0; 1142 ret = ioctl(hdl->fd, HERMON_IOCTL_FLASH_READ, info); 1143 if (ret != 0) { 1144 logmsg(MSG_ERROR, gettext("HERMON_IOCTL_FLASH_READ failed " 1145 "(%s)\n"), strerror(errno)); 1146 } 1147 return (ret); 1148 } 1149 1150 static int 1151 cnx_write_ioctl(ib_cnx_encap_ident_t *hdl, hermon_flash_ioctl_t *info) 1152 { 1153 int ret; 1154 1155 #ifdef CNX_DEBUG 1156 logmsg(MSG_INFO, "cnx_write_ioctl: fd(%d) af_type(0x%x) " 1157 "af_addr(0x%x) af_sector_num(0x%x) af_byte(0x%x)\n", 1158 hdl->fd, info->af_type, info->af_addr, info->af_sector_num, 1159 info->af_byte); 1160 #endif 1161 errno = 0; 1162 ret = ioctl(hdl->fd, HERMON_IOCTL_FLASH_WRITE, info); 1163 if (ret != 0) { 1164 logmsg(MSG_ERROR, gettext("HERMON_IOCTL_FLASH_WRITE " 1165 "failed (%s)\n"), strerror(errno)); 1166 } 1167 return (ret); 1168 } 1169 1170 static int 1171 cnx_erase_sector_ioctl(ib_cnx_encap_ident_t *hdl, hermon_flash_ioctl_t *info) 1172 { 1173 int ret; 1174 1175 #ifdef CNX_DEBUG 1176 logmsg(MSG_INFO, "cnx_erase_sector_ioctl: fd(%d) af_type(0x%x) " 1177 "af_sector_num(0x%x)\n", hdl->fd, info->af_type, 1178 info->af_sector_num); 1179 #endif 1180 errno = 0; 1181 ret = ioctl(hdl->fd, HERMON_IOCTL_FLASH_ERASE, info); 1182 if (ret != 0) { 1183 logmsg(MSG_ERROR, gettext("HERMON_IOCTL_FLASH_ERASE " 1184 "failed (%s)\n"), strerror(errno)); 1185 } 1186 return (ret); 1187 } 1188 1189 /* 1190 * cnx_crc16 - computes 16 bit crc of supplied buffer. 1191 * image should be in network byteorder 1192 * result is returned in host byteorder form 1193 */ 1194 uint16_t 1195 cnx_crc16(uint8_t *image, uint32_t size, int is_image) 1196 { 1197 const uint16_t poly = 0x100b; 1198 uint32_t crc = 0xFFFF; 1199 uint32_t word; 1200 uint32_t i, j; 1201 1202 logmsg(MSG_INFO, "hermon: cnx_crc16\n"); 1203 1204 for (i = 0; i < size / 4; i++) { 1205 word = (image[4 * i] << 24) | 1206 (image[4 * i + 1] << 16) | 1207 (image[4 * i + 2] << 8) | 1208 (image[4 * i + 3]); 1209 1210 if (is_image == CNX_HW_IMG) 1211 word = MLXSWAPBITS32(word); 1212 1213 for (j = 0; j < 32; j++) { 1214 if (crc & 0x8000) { 1215 crc = (((crc << 1) | 1216 (word >> 31)) ^ poly) & 0xFFFF; 1217 } else { 1218 crc = ((crc << 1) | (word >> 31)) & 0xFFFF; 1219 } 1220 word = (word << 1) & 0xFFFFFFFF; 1221 } 1222 } 1223 1224 for (i = 0; i < 16; i++) { 1225 if (crc & 0x8000) { 1226 crc = ((crc << 1) ^ poly) & 0xFFFF; 1227 } else { 1228 crc = (crc << 1) & 0xFFFF; 1229 } 1230 } 1231 1232 crc = crc ^ 0xFFFF; 1233 return (crc & 0xFFFF); 1234 } 1235 1236 static void 1237 cnx_local_set_guid_crc_img(uint32_t offset, uint32_t guid_crc_size, 1238 uint32_t guid_crc_offset) 1239 { 1240 uint16_t crc; 1241 uint8_t *fw_p = (uint8_t *)&verifier->fwimage[0]; 1242 1243 crc = htons(cnx_crc16((uint8_t *)&verifier->fwimage[offset / 4], 1244 guid_crc_size, CNX_FILE_IMG)); 1245 1246 logmsg(MSG_INFO, "cnx_local_set_guid_crc_img: new guid_sect crc: %x\n", 1247 ntohs(crc)); 1248 (void) memcpy(&fw_p[offset + guid_crc_offset], &crc, 2); 1249 } 1250 1251 /* 1252 * Address translation functions for ConnectX 1253 * Variable definitions: 1254 * - log2_chunk_size: log2 of a Flash chunk size 1255 * - cont_addr: a contiguous image address to be translated 1256 * - is_image_in_odd_chunk: When this bit is 1, it indicates the new image is 1257 * stored in odd chunks of the Flash. 1258 */ 1259 static uint32_t 1260 cnx_cont2phys(uint32_t log2_chunk_size, uint32_t cont_addr, int type) 1261 { 1262 uint32_t result; 1263 int is_image_in_odd_chunks; 1264 1265 is_image_in_odd_chunks = type - 1; 1266 1267 if (log2_chunk_size) { 1268 result = cont_addr & (0xffffffff >> (32 - log2_chunk_size)) | 1269 (is_image_in_odd_chunks << log2_chunk_size) | 1270 (cont_addr << 1) & (0xffffffff << (log2_chunk_size + 1)); 1271 } else { 1272 result = cont_addr; 1273 } 1274 1275 return (result); 1276 } 1277 1278 static int 1279 cnx_read_guids(ib_cnx_encap_ident_t *handle, int type) 1280 { 1281 #ifdef _LITTLE_ENDIAN 1282 uint32_t *ptr, tmp; 1283 #endif 1284 hermon_flash_ioctl_t ioctl_info; 1285 uint32_t *guids; 1286 uint32_t *ibmac; 1287 int ret, i; 1288 uint32_t nguidptr_addr; 1289 union { 1290 uint8_t bytes[4]; 1291 uint32_t dword; 1292 } crc16_u; 1293 uint32_t *guid_structure; 1294 uint16_t crc; 1295 1296 logmsg(MSG_INFO, "cnx_read_guids\n"); 1297 1298 errno = 0; 1299 guid_structure = (uint32_t *)calloc(1, 1300 CNX_GUID_CRC16_SIZE / 4 * sizeof (uint32_t)); 1301 if (guid_structure == NULL) { 1302 logmsg(MSG_WARN, gettext("hermon: Can't calloc guid_structure " 1303 ": (%s)\n"), strerror(errno)); 1304 return (FWFLASH_FAILURE); 1305 } 1306 1307 ioctl_info.af_type = HERMON_FLASH_READ_QUADLET; 1308 ioctl_info.af_addr = cnx_cont2phys(handle->log2_chunk_sz, 1309 CNX_NGUIDPTR_OFFSET, type); 1310 1311 ret = cnx_read_ioctl(handle, &ioctl_info); 1312 if (ret != 0) { 1313 logmsg(MSG_WARN, gettext("hermon: Failed to read GUID Pointer " 1314 "Address\n")); 1315 goto out; 1316 } 1317 1318 guids = (uint32_t *)&handle->ibguids[0]; 1319 ibmac = (uint32_t *)&handle->ib_mac[0]; 1320 nguidptr_addr = cnx_cont2phys(handle->log2_chunk_sz, 1321 ioctl_info.af_quadlet, type); 1322 1323 logmsg(MSG_INFO, "NGUIDPTR: 0x%08x \n", nguidptr_addr); 1324 /* Read in the entire guid section in order to calculate the CRC */ 1325 ioctl_info.af_addr = nguidptr_addr - 0x10; 1326 ioctl_info.af_type = HERMON_FLASH_READ_QUADLET; 1327 1328 for (i = 0; i < CNX_GUID_CRC16_SIZE / 4; i++) { 1329 ret = cnx_read_ioctl(handle, &ioctl_info); 1330 if (ret != 0) { 1331 logmsg(MSG_INFO, "Failed to read guid_structure " 1332 "(0x%x)\n", i); 1333 goto out; 1334 } 1335 1336 if (i >= 4 && i < 12) { 1337 guids[i - 4] = ioctl_info.af_quadlet; 1338 } 1339 if (i >= 12 && i < 16) { 1340 ibmac[i - 12] = ioctl_info.af_quadlet; 1341 } 1342 1343 guid_structure[i] = ioctl_info.af_quadlet; 1344 ioctl_info.af_addr += 4; 1345 } 1346 1347 for (i = 0; i < CNX_GUID_CRC16_SIZE / 4; i++) { 1348 logmsg(MSG_INFO, "guid_structure[%x] = 0x%08x\n", i, 1349 guid_structure[i]); 1350 } 1351 1352 /* 1353 * Check the CRC--make sure it computes. 1354 */ 1355 1356 /* 0x12 subtracted: 0x2 for alignment, 0x10 to reach structure start */ 1357 ioctl_info.af_addr = nguidptr_addr + CNX_GUID_CRC16_OFFSET - 0x12; 1358 ioctl_info.af_type = HERMON_FLASH_READ_QUADLET; 1359 1360 ret = cnx_read_ioctl(handle, &ioctl_info); 1361 if (ret != 0) { 1362 logmsg(MSG_WARN, gettext("hermon: Failed to read guid crc " 1363 "at 0x%x\n"), ioctl_info.af_addr); 1364 goto out; 1365 } 1366 1367 crc16_u.dword = ioctl_info.af_quadlet; 1368 crc = cnx_crc16((uint8_t *)guid_structure, CNX_GUID_CRC16_SIZE, 1369 CNX_HW_IMG); 1370 1371 if (crc != crc16_u.dword) { 1372 logmsg(MSG_WARN, gettext("hermon: calculated crc16: 0x%x " 1373 "differs from GUID section 0x%x\n"), crc, crc16_u.dword); 1374 } else { 1375 logmsg(MSG_INFO, "hermon: calculated crc16: 0x%x MATCHES with " 1376 "GUID section 0x%x\n", crc, crc16_u.dword); 1377 } 1378 1379 #ifdef _LITTLE_ENDIAN 1380 /* 1381 * guids are read as pairs of 32 bit host byteorder values and treated 1382 * by callers as 64 bit values. So swap each pair of 32 bit values 1383 * to make them correct 1384 */ 1385 ptr = (uint32_t *)guids; 1386 for (ret = 0; ret < 8; ret += 2) { 1387 tmp = ptr[ret]; 1388 ptr[ret] = ptr[ret+1]; 1389 ptr[ret+1] = tmp; 1390 } 1391 ptr = (uint32_t *)&handle->ib_mac[0]; 1392 for (ret = 0; ret < 4; ret += 2) { 1393 tmp = ptr[ret]; 1394 ptr[ret] = ptr[ret+1]; 1395 ptr[ret+1] = tmp; 1396 } 1397 #endif 1398 ret = FWFLASH_SUCCESS; 1399 1400 out: 1401 free(guid_structure); 1402 return (ret); 1403 } 1404 1405 static int 1406 cnx_find_magic_n_chnk_sz(ib_cnx_encap_ident_t *handle, int type) 1407 { 1408 int i, found = 0; 1409 uint32_t addr; 1410 uint32_t boot_addresses[] = 1411 {0, 0x10000, 0x20000, 0x40000, 0x80000, 0x100000}; 1412 1413 logmsg(MSG_INFO, "cnx_find_magic_n_chnk_sz\n"); 1414 1415 switch (type) { 1416 case FWFLASH_IB_STATE_IMAGE_PRI: 1417 addr = 0; 1418 if (cnx_check_for_magic_pattern(handle, addr) != 1419 FWFLASH_SUCCESS) { 1420 goto err; 1421 } 1422 break; 1423 1424 case FWFLASH_IB_STATE_IMAGE_SEC: 1425 for (i = 1; i < 6; i++) { 1426 addr = boot_addresses[i]; 1427 if (cnx_check_for_magic_pattern(handle, addr) == 1428 FWFLASH_SUCCESS) { 1429 found = 1; 1430 break; 1431 } 1432 } 1433 if (!found) { 1434 goto err; 1435 } 1436 break; 1437 1438 default: 1439 logmsg(MSG_INFO, "cnx_find_magic_pattern: unknown type\n"); 1440 goto err; 1441 } 1442 1443 logmsg(MSG_INFO, "magic_pattern found at addr %x\n", addr); 1444 handle->img2_start_addr = addr; 1445 1446 handle->log2_chunk_sz = cnx_get_log2_chunk_size_f_hdl(handle, type); 1447 if (handle->log2_chunk_sz == 0) { 1448 logmsg(MSG_INFO, "no chunk size found for type %x. " 1449 "Assuming non-failsafe burn\n", type); 1450 } 1451 1452 handle->fw_sz = cnx_get_image_size_f_hdl(handle, type); 1453 if (handle->fw_sz == 0) { 1454 logmsg(MSG_INFO, "no fw size found for type %x. \n", type); 1455 } 1456 handle->state |= type; 1457 1458 return (FWFLASH_SUCCESS); 1459 err: 1460 logmsg(MSG_INFO, "no magic_pattern found for type %x\n", type); 1461 return (FWFLASH_FAILURE); 1462 } 1463 1464 static int 1465 cnx_check_for_magic_pattern(ib_cnx_encap_ident_t *handle, uint32_t addr) 1466 { 1467 int i; 1468 hermon_flash_ioctl_t ioctl_info; 1469 int magic_pattern_buf[4]; 1470 1471 logmsg(MSG_INFO, "cnx_check_for_magic_pattern\n"); 1472 1473 ioctl_info.af_type = HERMON_FLASH_READ_QUADLET; 1474 1475 for (i = 0; i < 4; i++) { 1476 ioctl_info.af_addr = addr + (i * sizeof (uint32_t)); 1477 if (cnx_read_ioctl(handle, &ioctl_info) != 0) { 1478 logmsg(MSG_INFO, "\nFailed to read magic pattern\n"); 1479 return (FWFLASH_FAILURE); 1480 } 1481 1482 magic_pattern_buf[i] = ioctl_info.af_quadlet; 1483 } 1484 1485 return (cnx_is_magic_pattern_present(magic_pattern_buf, CNX_HW_IMG)); 1486 1487 } 1488 1489 int 1490 cnx_is_magic_pattern_present(int *data, int is_image) 1491 { 1492 int i; 1493 int dword; 1494 1495 logmsg(MSG_INFO, "cnx_is_magic_pattern_present\n"); 1496 1497 for (i = 0; i < 4; i++) { 1498 if (is_image == CNX_FILE_IMG) 1499 dword = MLXSWAPBITS32(data[i]); 1500 else 1501 dword = data[i]; 1502 logmsg(MSG_INFO, "local_quadlet: %08x, magic pattern: %08x\n", 1503 dword, cnx_magic_pattern[i]); 1504 if (dword != cnx_magic_pattern[i]) { 1505 return (FWFLASH_FAILURE); 1506 } 1507 } 1508 1509 return (FWFLASH_SUCCESS); 1510 } 1511 1512 static uint32_t 1513 cnx_get_log2_chunk_size_f_hdl(ib_cnx_encap_ident_t *handle, int type) 1514 { 1515 hermon_flash_ioctl_t ioctl_info; 1516 int ret; 1517 1518 logmsg(MSG_INFO, "cnx_get_log2_chunk_size_f_hdl\n"); 1519 1520 /* If chunk size is already set, just return it. */ 1521 if (handle->log2_chunk_sz) { 1522 return (handle->log2_chunk_sz); 1523 } 1524 1525 switch (type) { 1526 case FWFLASH_IB_STATE_IMAGE_PRI: 1527 ioctl_info.af_addr = CNX_CHUNK_SIZE_OFFSET; 1528 break; 1529 case FWFLASH_IB_STATE_IMAGE_SEC: 1530 ioctl_info.af_addr = 1531 handle->img2_start_addr + CNX_CHUNK_SIZE_OFFSET; 1532 break; 1533 default: 1534 logmsg(MSG_INFO, 1535 "cnx_get_log2_chunk_size_f_hdl: unknown type\n"); 1536 return (0); 1537 } 1538 1539 ioctl_info.af_type = HERMON_FLASH_READ_QUADLET; 1540 1541 ret = cnx_read_ioctl(handle, &ioctl_info); 1542 if (ret != 0) { 1543 logmsg(MSG_INFO, "\nFailed to read chunk size\n"); 1544 return (0); 1545 } 1546 1547 return (cnx_get_log2_chunk_size(ioctl_info.af_quadlet)); 1548 } 1549 1550 1551 static uint32_t 1552 cnx_get_log2_chunk_size(uint32_t chunk_size_word) 1553 { 1554 uint8_t checksum; 1555 uint32_t log2_chunk_size; 1556 1557 logmsg(MSG_INFO, "cnx_get_log2_chunk_size: chunk_size_word:" 1558 " 0x%x\n", chunk_size_word); 1559 1560 checksum = 1561 (chunk_size_word & 0xff) + 1562 ((chunk_size_word >> 8) & 0xff) + 1563 ((chunk_size_word >> 16) & 0xff) + 1564 ((chunk_size_word >> 24) & 0xff); 1565 1566 if (checksum != 0) { 1567 logmsg(MSG_INFO, "Corrupted chunk size checksum\n"); 1568 return (0); 1569 } 1570 1571 if (chunk_size_word & 0x8) { 1572 log2_chunk_size = (chunk_size_word & 0x7) + 16; 1573 logmsg(MSG_INFO, "log2 chunk size: 0x%x\n", log2_chunk_size); 1574 return (log2_chunk_size); 1575 } else { 1576 return (0); 1577 } 1578 } 1579 1580 static uint32_t 1581 cnx_get_image_size_f_hdl(ib_cnx_encap_ident_t *handle, int type) 1582 { 1583 hermon_flash_ioctl_t ioctl_info; 1584 int ret; 1585 1586 logmsg(MSG_INFO, "cnx_get_image_size_f_hdl\n"); 1587 1588 ioctl_info.af_addr = cnx_cont2phys(handle->log2_chunk_sz, 1589 CNX_IMG_SIZE_OFFSET, type); 1590 ioctl_info.af_type = HERMON_FLASH_READ_QUADLET; 1591 1592 ret = cnx_read_ioctl(handle, &ioctl_info); 1593 if (ret != 0) { 1594 logmsg(MSG_INFO, "Failed to read image size\n"); 1595 return (0); 1596 } 1597 1598 logmsg(MSG_INFO, "Image Size: 0x%x\n", ioctl_info.af_quadlet); 1599 1600 return (ioctl_info.af_quadlet); 1601 } 1602 1603 static int 1604 cnx_get_image_info(ib_cnx_encap_ident_t *handle) 1605 { 1606 uint32_t ii_ptr_addr; 1607 uint32_t ii_size; 1608 int *buf; 1609 int i, type; 1610 hermon_flash_ioctl_t ioctl_info; 1611 1612 logmsg(MSG_INFO, "cnx_get_image_info: state %x\n", handle->state); 1613 1614 type = handle->state & 1615 (FWFLASH_IB_STATE_IMAGE_PRI | FWFLASH_IB_STATE_IMAGE_SEC); 1616 1617 /* Get the image info pointer */ 1618 ioctl_info.af_addr = cnx_cont2phys(handle->log2_chunk_sz, 1619 CNX_IMG_INF_PTR_OFFSET, type); 1620 ioctl_info.af_type = HERMON_FLASH_READ_QUADLET; 1621 1622 if (cnx_read_ioctl(handle, &ioctl_info) != FWFLASH_SUCCESS) { 1623 logmsg(MSG_WARN, gettext("hermon: Failed to read image info " 1624 "Address\n")); 1625 return (FWFLASH_FAILURE); 1626 } 1627 ii_ptr_addr = ioctl_info.af_quadlet & 0xffffff; 1628 1629 /* Get the image info size, a negative offset from the image info ptr */ 1630 ioctl_info.af_addr = cnx_cont2phys(handle->log2_chunk_sz, 1631 ii_ptr_addr + CNX_IMG_INF_SZ_OFFSET, type); 1632 ioctl_info.af_type = HERMON_FLASH_READ_QUADLET; 1633 1634 if (cnx_read_ioctl(handle, &ioctl_info) != FWFLASH_SUCCESS) { 1635 logmsg(MSG_WARN, gettext("hermon: Failed to read image info " 1636 "size\n")); 1637 return (FWFLASH_FAILURE); 1638 } 1639 logmsg(MSG_INFO, "hermon: ImageInfo Sz: 0x%x\n", ioctl_info.af_quadlet); 1640 1641 ii_size = ioctl_info.af_quadlet; 1642 /* size is in dwords--convert it to bytes */ 1643 ii_size *= 4; 1644 1645 logmsg(MSG_INFO, "hermon: ii_ptr_addr: 0x%x ii_size: 0x%x\n", 1646 ii_ptr_addr, ii_size); 1647 1648 buf = (int *)calloc(1, ii_size); 1649 1650 ioctl_info.af_addr = cnx_cont2phys(handle->log2_chunk_sz, 1651 ii_ptr_addr, type); 1652 ioctl_info.af_type = HERMON_FLASH_READ_QUADLET; 1653 1654 for (i = 0; i < ii_size/4; i++) { 1655 if (cnx_read_ioctl(handle, &ioctl_info) != FWFLASH_SUCCESS) { 1656 logmsg(MSG_WARN, gettext("hermon: Failed to read " 1657 "image info (0x%x)\n"), i); 1658 free(buf); 1659 return (FWFLASH_FAILURE); 1660 } 1661 1662 buf[i] = ioctl_info.af_quadlet; 1663 ioctl_info.af_addr += 4; 1664 } 1665 1666 /* Parse the image info section */ 1667 if (cnx_parse_img_info(buf, ii_size, &handle->hwfw_img_info, 1668 CNX_HW_IMG) != FWFLASH_SUCCESS) { 1669 logmsg(MSG_WARN, gettext("hermon: Failed to parse Image Info " 1670 "section\n")); 1671 free(buf); 1672 return (FWFLASH_FAILURE); 1673 } 1674 1675 free(buf); 1676 return (FWFLASH_SUCCESS); 1677 } 1678 1679 int 1680 cnx_parse_img_info(int *buf, uint32_t byte_size, cnx_img_info_t *img_info, 1681 int is_image) 1682 { 1683 uint32_t *p; 1684 uint32_t offs = 0; 1685 uint32_t tag_num = 0; 1686 int end_found = 0; 1687 uint32_t tag_size, tag_id; 1688 uint32_t tmp; 1689 const char *str; 1690 int i; 1691 1692 p = (uint32_t *)buf; 1693 1694 logmsg(MSG_INFO, "hermon: cnx_parse_img_info\n"); 1695 1696 while (!end_found && (offs < byte_size)) { 1697 if (is_image == CNX_FILE_IMG) { 1698 tag_size = ntohl(*p) & 0xffffff; 1699 tag_id = ntohl(*p) >> 24; 1700 tmp = ntohl(*(p + 1)); 1701 } else { 1702 tag_size = ((*p) & 0xffffff); 1703 tag_id = ((*p) >> 24); 1704 tmp = (*(p + 1)); 1705 } 1706 1707 logmsg(MSG_INFO, "tag_id: %d tag_size: %d\n", tag_id, tag_size); 1708 1709 if ((offs + tag_size) > byte_size) { 1710 logmsg(MSG_WARN, gettext("hermon: Image Info section " 1711 "corrupted: Tag# %d - tag_id %d, size %d exceeds " 1712 "info section size (%d bytes)"), tag_num, tag_id, 1713 tag_size, byte_size); 1714 return (FWFLASH_FAILURE); 1715 } 1716 1717 switch (tag_id) { 1718 case CNX_FW_VER: 1719 if (tag_size != CNX_FW_VER_SZ) { 1720 logmsg(MSG_INFO, "ERROR: tag_id: %d tag_size: " 1721 "%d expected sz %d\n", tag_id, tag_size, 1722 CNX_FW_VER_SZ); 1723 } 1724 tmp = (tmp & CNX_MASK_FW_VER_MAJ) >> 16; 1725 img_info->fw_rev.major = tmp; 1726 if (is_image == CNX_FILE_IMG) 1727 tmp = ntohl(*(p + 2)); 1728 else 1729 tmp = (*(p + 2)); 1730 img_info->fw_rev.minor = 1731 (tmp & CNX_MASK_FW_VER_MIN)>> 16; 1732 img_info->fw_rev.subminor = 1733 tmp & CNX_MASK_FW_VER_SUBMIN; 1734 1735 logmsg(MSG_INFO, "FW_VER: %d.%d.%03d\n", 1736 img_info->fw_rev.major, img_info->fw_rev.minor, 1737 img_info->fw_rev.subminor); 1738 break; 1739 1740 case CNX_FW_BUILD_TIME: 1741 if (tag_size != CNX_FW_BUILD_TIME_SZ) { 1742 logmsg(MSG_INFO, "ERROR: tag_id: %d tag_size: " 1743 "%d expected sz %d\n", tag_id, tag_size, 1744 CNX_FW_BUILD_TIME_SZ); 1745 } 1746 img_info->fw_buildtime.hour = 1747 (tmp & CNX_MASK_FW_BUILD_HOUR) >> 16; 1748 img_info->fw_buildtime.minute = 1749 (tmp & CNX_MASK_FW_BUILD_MIN) >> 8; 1750 img_info->fw_buildtime.second = 1751 (tmp & CNX_MASK_FW_BUILD_SEC); 1752 1753 if (is_image == CNX_FILE_IMG) 1754 tmp = ntohl(*(p + 2)); 1755 else 1756 tmp = (*(p + 2)); 1757 1758 img_info->fw_buildtime.year = 1759 (tmp & CNX_MASK_FW_BUILD_YEAR) >> 16; 1760 img_info->fw_buildtime.month = 1761 (tmp & CNX_MASK_FW_BUILD_MON) >> 8; 1762 img_info->fw_buildtime.day = 1763 (tmp & CNX_MASK_FW_BUILD_DAY); 1764 1765 logmsg(MSG_INFO, "Build TIME: %d:%d:%d %d:%d:%d\n", 1766 img_info->fw_buildtime.year, 1767 img_info->fw_buildtime.month, 1768 img_info->fw_buildtime.day, 1769 img_info->fw_buildtime.hour, 1770 img_info->fw_buildtime.minute, 1771 img_info->fw_buildtime.second); 1772 break; 1773 1774 case CNX_DEV_TYPE: 1775 if (tag_size != CNX_DEV_TYPE_SZ) { 1776 logmsg(MSG_INFO, "ERROR: tag_id: %d tag_size: " 1777 "%d expected sz %d\n", tag_id, tag_size, 1778 CNX_DEV_TYPE_SZ); 1779 } 1780 img_info->dev_id = tmp & CNX_MASK_DEV_TYPE_ID; 1781 logmsg(MSG_INFO, "DEV_TYPE: %d\n", img_info->dev_id); 1782 break; 1783 1784 case CNX_VSD_VENDOR_ID: 1785 if (tag_size != CNX_VSD_VENDOR_ID_SZ) { 1786 logmsg(MSG_INFO, "ERROR: tag_id: %d tag_size: " 1787 "%d expected sz %d\n", tag_id, tag_size, 1788 CNX_VSD_VENDOR_ID_SZ); 1789 } 1790 img_info->vsd_vendor_id = tmp & CNX_MASK_VSD_VENDORID; 1791 logmsg(MSG_INFO, "VSD Vendor ID: 0x%lX\n", 1792 img_info->vsd_vendor_id); 1793 break; 1794 1795 case CNX_PSID: 1796 if (tag_size != CNX_PSID_SZ) { 1797 logmsg(MSG_INFO, "ERROR: tag_id: %d tag_size: " 1798 "%d expected sz %d\n", tag_id, tag_size, 1799 CNX_PSID_SZ); 1800 } 1801 str = (const char *)p; 1802 str += 4; 1803 1804 for (i = 0; i < CNX_PSID_SZ; i++) 1805 img_info->psid[i] = str[i]; 1806 1807 #ifdef _LITTLE_ENDIAN 1808 if (is_image == CNX_HW_IMG) { 1809 for (i = 0; i < CNX_PSID_SZ; i += 4) { 1810 img_info->psid[i+3] = str[i]; 1811 img_info->psid[i+2] = str[i+1]; 1812 img_info->psid[i+1] = str[i+2]; 1813 img_info->psid[i] = str[i+3]; 1814 } 1815 } 1816 #endif 1817 1818 logmsg(MSG_INFO, "PSID: %s\n", img_info->psid); 1819 break; 1820 1821 case CNX_VSD: 1822 if (tag_size != CNX_VSD_SZ) { 1823 logmsg(MSG_INFO, "ERROR: tag_id: %d tag_size: " 1824 "%d expected sz %d\n", tag_id, tag_size, 1825 CNX_VSD_SZ); 1826 } 1827 str = (const char *)p; 1828 str += 4; 1829 1830 for (i = 0; i < CNX_VSD_SZ; i++) 1831 img_info->vsd[i] = str[i]; 1832 1833 #ifdef _LITTLE_ENDIAN 1834 if (is_image == CNX_HW_IMG) { 1835 for (i = 0; i < CNX_VSD_SZ; i += 4) { 1836 img_info->vsd[i+3] = str[i]; 1837 img_info->vsd[i+2] = str[i+1]; 1838 img_info->vsd[i+1] = str[i+2]; 1839 img_info->vsd[i] = str[i+3]; 1840 } 1841 } 1842 #endif 1843 logmsg(MSG_INFO, "VSD: %s\n", img_info->vsd); 1844 break; 1845 1846 case CNX_END_TAG: 1847 if (tag_size != CNX_END_TAG_SZ) { 1848 logmsg(MSG_INFO, "ERROR: tag_id: %d tag_size: " 1849 "%d expected sz %d\n", tag_id, tag_size, 1850 CNX_END_TAG_SZ); 1851 } 1852 end_found = 1; 1853 break; 1854 1855 default: 1856 if (tag_id > CNX_END_TAG) { 1857 logmsg(MSG_WARN, gettext("Invalid img_info " 1858 "tag ID %d of size %d\n"), tag_id, 1859 tag_size); 1860 } 1861 break; 1862 } 1863 1864 p += (tag_size / 4) + 1; 1865 offs += tag_size + 4; 1866 tag_num++; 1867 } 1868 1869 if (offs != byte_size) { 1870 logmsg(MSG_WARN, gettext("hermon: Corrupt Image Info section " 1871 "in firmware image\n")); 1872 if (end_found) { 1873 logmsg(MSG_WARN, gettext("Info section corrupted: " 1874 "Section data size is %x bytes, but end tag found " 1875 "after %x bytes.\n"), byte_size, offs); 1876 } else { 1877 logmsg(MSG_WARN, gettext("Info section corrupted: " 1878 "Section data size is %x bytes, but end tag not " 1879 "found at section end.\n"), byte_size); 1880 } 1881 return (FWFLASH_FAILURE); 1882 } 1883 1884 return (FWFLASH_SUCCESS); 1885 } 1886