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