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.
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.
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]
23 * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
27 * The reference for the functions in this file is the
29 * Mellanox HCA Flash Programming Application Note
30 * (Mellanox document number 2205AN) rev 1.45, 2007.
31 * Chapter 4 in particular.
37 #include <sys/types.h>
39 #include <sys/sysmacros.h>
40 #include <sys/queue.h>
46 #include <sys/byteorder.h>
48 #include <libintl.h> /* for gettext(3c) */
50 #include <fwflash/fwflash.h>
51 #include "../../hdrs/hermon_ib.h"
53 char *devprefix
= "/devices";
54 char drivername
[] = "hermon\0";
55 char *devsuffix
= ":devctl";
57 extern di_node_t rootnode
;
59 extern struct fw_plugin
*self
;
60 extern struct vrfyplugin
*verifier
;
61 extern int fwflash_debug
;
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
);
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
,
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
,
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
);
100 fw_readfw(struct devicelist
*flashdev
, char *filename
)
102 ib_cnx_encap_ident_t
*manuf
;
103 int rv
= FWFLASH_SUCCESS
;
105 logmsg(MSG_INFO
, "hermon: fw_readfw: filename %s\n", filename
);
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
);
114 logmsg(MSG_INFO
, "hermon: fw_identify should have read the image. "
115 "state 0x%x\n", manuf
->state
);
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"));
123 rv
= cnx_write_file(manuf
, filename
);
132 * If we're invoking fw_writefw, then flashdev is a valid,
133 * flashable device as determined by fw_identify().
135 * If verifier is null, then we haven't been called following a firmware
136 * image verification load operation.
139 fw_writefw(struct devicelist
*flashdev
)
141 ib_cnx_encap_ident_t
*manuf
;
144 logmsg(MSG_INFO
, "hermon: fw_writefw\n");
146 manuf
= (ib_cnx_encap_ident_t
*)flashdev
->ident
->encap_ident
;
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
);
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().
161 if (manuf
->pn_len
== 0) {
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
);
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
);
179 logmsg(MSG_INFO
, "hermon: fw_writefw: Using Existing GUIDs.\n");
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"));
190 * Update both Primary and Secondary images
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,
198 /* Note Current Image location. */
200 (FWFLASH_IB_STATE_IMAGE_PRI
| FWFLASH_IB_STATE_IMAGE_SEC
);
203 * If we find that current image location is not found, no worries
204 * we shall default to PRIMARY, and proceed with burning anyway.
207 j
= FWFLASH_IB_STATE_IMAGE_PRI
;
209 for (i
= FWFLASH_FLASH_IMAGES
; i
> 0; i
--) {
214 k
= 1; /* Burn PRI First */
216 k
= 2; /* Burn SEC First */
219 k
= 1; /* Burn PRI next */
221 k
= 2; /* Burn SEC next */
223 type
= ((k
== 1) ? "Primary" : "Secondary");
225 logmsg(MSG_INFO
, "hermon: fw_write: UPDATING %s image\n", type
);
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
);
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
);
243 /* final update marker to the user */
244 (void) printf(" +\n");
245 return (cnx_close(flashdev
));
250 * The fw_identify() function walks the device tree trying to find
251 * devices which this plugin can work with.
253 * The parameter "start" gives us the starting index number
254 * to give the device when we add it to the fw_devices list.
256 * firstdev is allocated by us and we add space as necessary
259 fw_identify(int start
)
261 int rv
= FWFLASH_FAILURE
;
263 struct devicelist
*newdev
;
268 logmsg(MSG_INFO
, "hermon: fw_identify\n");
269 thisnode
= di_drv_first_node(drivername
, rootnode
);
271 if (thisnode
== DI_NODE_NIL
) {
272 logmsg(MSG_INFO
, gettext("No %s nodes in this system\n"),
277 /* we've found one, at least */
278 for (; thisnode
!= DI_NODE_NIL
; thisnode
= di_drv_next_node(thisnode
)) {
280 devpath
= di_devfs_path(thisnode
);
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
);
289 /* calloc enough for /devices + devpath + ":devctl" + '\0' */
290 devlength
= strlen(devpath
) + strlen(devprefix
) +
291 strlen(devsuffix
) + 2;
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"));
297 di_devfs_path_free(devpath
);
298 return (FWFLASH_FAILURE
);
300 snprintf(newdev
->access_devname
, devlength
,
301 "%s%s%s", devprefix
, devpath
, devsuffix
);
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
);
308 di_devfs_path_free(devpath
);
309 return (FWFLASH_FAILURE
);
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
);
318 di_devfs_path_free(devpath
);
322 if ((newdev
->drvname
= calloc(1, strlen(drivername
) + 1))
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
);
329 di_devfs_path_free(devpath
);
330 return (FWFLASH_FAILURE
);
333 (void) strlcpy(newdev
->drvname
, drivername
,
334 strlen(drivername
) + 1);
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
);
344 di_devfs_path_free(devpath
);
345 return (FWFLASH_FAILURE
);
347 (void) strlcpy(newdev
->classname
, "IB", 3);
351 newdev
->plugin
= self
;
353 di_devfs_path_free(devpath
);
355 TAILQ_INSERT_TAIL(fw_devices
, newdev
, nextdev
);
358 if (fwflash_debug
!= 0) {
359 struct devicelist
*tempdev
;
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"
374 "\t\tplugin @ 0x%lx\n\n",
376 tempdev
->access_devname
,
377 tempdev
->drvname
, newdev
->classname
,
380 tempdev
->ident
->revid
,
382 (tempdev
->addresses
[0] ? tempdev
->addresses
[0] :
384 (tempdev
->addresses
[1] ? tempdev
->addresses
[1] :
386 (tempdev
->addresses
[2] ? tempdev
->addresses
[2] :
388 (tempdev
->addresses
[3] ? tempdev
->addresses
[3] :
394 return (FWFLASH_SUCCESS
);
399 fw_devinfo(struct devicelist
*thisdev
)
401 ib_cnx_encap_ident_t
*encap
;
403 logmsg(MSG_INFO
, "hermon: fw_devinfo\n");
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
);
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
);
417 fprintf(stdout
, "\t");
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]);
429 fprintf(stdout
, gettext("\tFirmware revision : %s\n"),
430 thisdev
->ident
->revid
);
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
);
438 fprintf(stdout
, gettext("\tProduct\t\t : %s %X\n"),
439 encap
->info
.mlx_pn
, encap
->hwrev
);
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
);
447 fprintf(stdout
, gettext("\t%s\n"), thisdev
->ident
->pid
);
449 fprintf(stdout
, "\n\n");
451 return (cnx_close(thisdev
));
456 * Helper functions lurk beneath this point
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.
472 cnx_read_image(ib_cnx_encap_ident_t
*handle
)
474 hermon_flash_ioctl_t ioctl_info
;
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
);
485 logmsg(MSG_ERROR
, gettext("cnx_read_image: Must read in "
487 return (FWFLASH_FAILURE
);
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
);
498 logmsg(MSG_INFO
, "hermon: fw_size: 0x%x\n", image_size
);
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
);
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
;
512 ret
= cnx_read_ioctl(handle
, &ioctl_info
);
514 logmsg(MSG_ERROR
, gettext("cnx_read_image: Failed to "
515 "read sector %d\n"), i
);
517 return (FWFLASH_FAILURE
);
519 handle
->fw
[i
/ 4] = htonl(ioctl_info
.af_quadlet
);
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]));
527 return (FWFLASH_SUCCESS
);
531 cnx_write_file(ib_cnx_encap_ident_t
*handle
, const char *filename
)
535 mode_t mode
= S_IRUSR
| S_IWUSR
;
538 logmsg(MSG_INFO
, "cnx_write_file\n");
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
);
548 fp
= fdopen(fd
, "w");
550 (void) fprintf(stderr
, gettext("hermon: Unknown filename %s : "
551 "%s\n"), filename
, strerror(errno
));
552 return (FWFLASH_FAILURE
);
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
);
558 if (fwrite(&handle
->fw
[0], len
, 1, fp
) == 0) {
559 (void) fprintf(stderr
, gettext("hermon: fwrite failed"));
562 return (FWFLASH_FAILURE
);
565 return (FWFLASH_SUCCESS
);
569 cnx_verify_image(ib_cnx_encap_ident_t
*handle
, int type
)
571 uint32_t new_start_addr
;
573 logmsg(MSG_INFO
, "hermon: cnx_verify_image\n");
575 new_start_addr
= cnx_cont2phys(handle
->log2_chunk_sz
, 0, type
);
577 return (cnx_check_for_magic_pattern(handle
, new_start_addr
));
581 cnx_set_guids(ib_cnx_encap_ident_t
*handle
, void *arg
)
586 logmsg(MSG_INFO
, "hermon: cnx_set_guids\n");
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);
593 * guids are supplied by callers as 64 bit values in host byteorder.
594 * Storage is in network byteorder.
597 if (handle
->state
& FWFLASH_IB_STATE_GUIDN
) {
598 verifier
->fwimage
[addr
] = guids
[0];
599 verifier
->fwimage
[addr
+ 1] = guids
[1];
602 if (handle
->state
& FWFLASH_IB_STATE_GUID1
) {
603 verifier
->fwimage
[addr
+ 2] = guids
[2];
604 verifier
->fwimage
[addr
+ 3] = guids
[3];
607 if (handle
->state
& FWFLASH_IB_STATE_GUID2
) {
608 verifier
->fwimage
[addr
+ 4] = guids
[4];
609 verifier
->fwimage
[addr
+ 5] = guids
[5];
612 if (handle
->state
& FWFLASH_IB_STATE_GUIDS
) {
613 verifier
->fwimage
[addr
+ 6] = guids
[6];
614 verifier
->fwimage
[addr
+ 7] = guids
[7];
617 if (handle
->state
& FWFLASH_IB_STATE_GUIDN
) {
618 verifier
->fwimage
[addr
] = htonl(guids
[1]);
619 verifier
->fwimage
[addr
+ 1] = htonl(guids
[0]);
622 if (handle
->state
& FWFLASH_IB_STATE_GUID1
) {
623 verifier
->fwimage
[addr
+ 2] = htonl(guids
[3]);
624 verifier
->fwimage
[addr
+ 3] = htonl(guids
[2]);
627 if (handle
->state
& FWFLASH_IB_STATE_GUID2
) {
628 verifier
->fwimage
[addr
+ 4] = htonl(guids
[5]);
629 verifier
->fwimage
[addr
+ 5] = htonl(guids
[4]);
632 if (handle
->state
& FWFLASH_IB_STATE_GUIDS
) {
633 verifier
->fwimage
[addr
+ 6] = htonl(guids
[7]);
634 verifier
->fwimage
[addr
+ 7] = htonl(guids
[6]);
638 cnx_local_set_guid_crc_img((addr
* 4) - 0x10, CNX_GUID_CRC16_SIZE
,
639 CNX_GUID_CRC16_OFFSET
);
641 return (FWFLASH_SUCCESS
);
645 * Notes: Burn the image
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),
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.
658 cnx_write_image(ib_cnx_encap_ident_t
*handle
, int type
)
660 hermon_flash_ioctl_t ioctl_info
;
664 uint32_t new_start_addr
;
665 uint32_t log2_chunk_sz
;
668 logmsg(MSG_INFO
, "hermon: cnx_write_image\n");
671 logmsg(MSG_ERROR
, gettext("cnx_write_image: Must inform us "
672 " where to write.\n"));
673 return (FWFLASH_FAILURE
);
676 log2_chunk_sz
= cnx_get_log2_chunk_size(
677 ntohl(verifier
->fwimage
[CNX_CHUNK_SIZE_OFFSET
/ 4]));
679 sector_size
= handle
->sector_sz
;
680 new_start_addr
= ((type
- 1) << handle
->log2_chunk_sz
);
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
);
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
);
698 fw
= (uint8_t *)verifier
->fwimage
;
699 ioctl_info
.af_type
= HERMON_FLASH_WRITE_BYTE
;
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
);
711 if (i
&& !(i
% handle
->sector_sz
)) {
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"),
725 return (FWFLASH_FAILURE
);
729 /* Write new image start address to CR space */
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
));
737 return (FWFLASH_SUCCESS
);
742 * cnx_identify performs the following actions:
744 * allocates and assigns thisdev->vpr
746 * allocates space for the 4 GUIDs which each IB device must have
747 * queries the hermon driver for this device's GUIDs
749 * determines the hardware vendor, so that thisdev->vpr->vid
750 * can be set correctly
753 cnx_identify(struct devicelist
*thisdev
)
756 hermon_flash_init_ioctl_t init_ioctl
;
757 ib_cnx_encap_ident_t
*manuf
;
759 int hw_psid_found
= 0;
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 */
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
);
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
);
779 return (FWFLASH_FAILURE
);
781 manuf
->magic
= FWFLASH_IB_MAGIC_NUMBER
;
782 manuf
->state
= FWFLASH_IB_STATE_NONE
;
784 manuf
->log2_chunk_sz
= 0;
786 thisdev
->ident
->encap_ident
= manuf
;
789 * Inform driver that this command supports the Intel Extended
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]);
798 ret
= ioctl(fd
, HERMON_IOCTL_FLASH_INIT
, &init_ioctl
);
800 logmsg(MSG_ERROR
, gettext("hermon: HERMON_IOCTL_FLASH_INIT "
801 "failed: %s\n"), strerror(errno
));
804 return (FWFLASH_FAILURE
);
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
);
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.
818 for (i
= 0; i
< HERMON_FLASH_CFI_SIZE_QUADLET
; i
++) {
819 cfi
.cfi_int
[i
] = ntohl(init_ioctl
.af_cfi_info
[i
]);
821 manuf
->cmd_set
= cfi
.cfi_char
[0x13];
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"));
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
;
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
);
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];
851 logmsg(MSG_INFO
, "hermon: sector_sz: 0x%08x device_sz: 0x%08x\n",
852 manuf
->sector_sz
, manuf
->device_sz
);
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
;
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"));
865 (void) strlcpy(thisdev
->ident
->vid
, "MELLANOX", MLX_VPR_VIDLEN
);
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.
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
);
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
);
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
;
888 if (cnx_get_image_info(manuf
) != FWFLASH_SUCCESS
) {
889 logmsg(MSG_WARN
, gettext("hermon: Failed to read Image Info "
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
] == ' ') {
904 if (i
== init_ioctl
.af_pn_len
) {
905 manuf
->pn_len
= init_ioctl
.af_pn_len
;
908 logmsg(MSG_INFO
, "hermon: Failed to get Part# from hermon "
913 if (manuf
->pn_len
!= 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
));
921 (void) memcpy(manuf
->info
.mlx_pn
, init_ioctl
.af_hwpn
,
923 manuf
->info
.mlx_pn
[manuf
->pn_len
] = 0;
925 logmsg(MSG_INFO
, "hermon: HCA PN (%s) PN-Len %d\n",
926 manuf
->info
.mlx_pn
, manuf
->pn_len
);
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
));
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"),
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) {
950 logmsg(MSG_INFO
, "HW-PSID: %s "
952 manuf
->hwfw_img_info
.psid
, i
,
953 mlx_mdr
[i
].mlx_psid
);
954 if (strncmp((const char *)
955 manuf
->hwfw_img_info
.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;
965 logmsg(MSG_INFO
, "hermon: HCA PSID (%s)\n",
966 manuf
->info
.mlx_psid
);
968 (void) strlcpy(manuf
->info
.mlx_id
,
970 strlen(mlx_mdr
[i
].mlx_id
) + 1);
972 logmsg(MSG_INFO
, "hermon: HCA Name (%s)\n",
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");
984 i
= strlen("No hardware information available for this device");
986 thisdev
->ident
->pid
= calloc(1, i
+ 2);
987 sprintf(thisdev
->ident
->pid
, "No additional hardware info "
988 "available for this device");
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);
998 gettext("hermon: Unable to allocate space for a "
999 "hardware identifier: %s\n"), strerror(errno
));
1004 for (i
= 0; i
< 4; i
++) {
1006 if ((thisdev
->addresses
[i
] = calloc(1,
1007 (2 * sizeof (uint64_t)) + 1)) == NULL
) {
1009 gettext("hermon: Unable to allocate space for a "
1010 "human-readable HCA guid: %s\n"), strerror(errno
));
1013 (void) sprintf(thisdev
->addresses
[i
], "%016llx",
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.
1024 return (FWFLASH_SUCCESS
);
1029 return (FWFLASH_FAILURE
);
1033 cnx_get_guids(ib_cnx_encap_ident_t
*handle
)
1037 logmsg(MSG_INFO
, "cnx_get_guids\n");
1039 /* make sure we've got our fallback position organised */
1040 for (i
= 0; i
< 4; i
++) {
1041 handle
->ibguids
[i
] = 0x00000000;
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"));
1054 gettext("Warning: HCA Firmware corrupt.\n"));
1055 return (FWFLASH_FAILURE
);
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
);
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
);
1071 for (i
= 0; i
< 4; i
++) {
1072 logmsg(MSG_INFO
, "hermon: ibguids[%d] 0x%016llx\n", i
,
1073 handle
->ibguids
[i
]);
1075 for (i
= 0; i
< 2; i
++) {
1076 logmsg(MSG_INFO
, "hermon: ib_portmac[%d] 0x%016llx\n", i
,
1080 return (FWFLASH_SUCCESS
);
1084 cnx_close(struct devicelist
*flashdev
)
1086 ib_cnx_encap_ident_t
*handle
;
1088 logmsg(MSG_INFO
, "cnx_close\n");
1090 handle
= (ib_cnx_encap_ident_t
*)flashdev
->ident
->encap_ident
;
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
);
1098 if (handle
->fd
> 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
);
1109 if (handle
!= NULL
) {
1110 free(handle
->info
.mlx_id
);
1112 free(handle
->info
.mlx_psid
);
1118 free(flashdev
->ident
->vid
);
1120 free(flashdev
->ident
->revid
);
1122 return (FWFLASH_SUCCESS
);
1127 * Driver read/write ioctl calls.
1130 cnx_read_ioctl(ib_cnx_encap_ident_t
*hdl
, hermon_flash_ioctl_t
*info
)
1135 logmsg(MSG_INFO
, "cnx_read_ioctl: fd %d af_type 0x%x af_addr 0x%x "
1136 "af_sector_num(0x%x)\n", hdl
->fd
, info
->af_type
,
1137 info
->af_addr
, info
->af_sector_num
);
1141 ret
= ioctl(hdl
->fd
, HERMON_IOCTL_FLASH_READ
, info
);
1143 logmsg(MSG_ERROR
, gettext("HERMON_IOCTL_FLASH_READ failed "
1144 "(%s)\n"), strerror(errno
));
1150 cnx_write_ioctl(ib_cnx_encap_ident_t
*hdl
, hermon_flash_ioctl_t
*info
)
1155 logmsg(MSG_INFO
, "cnx_write_ioctl: fd(%d) af_type(0x%x) "
1156 "af_addr(0x%x) af_sector_num(0x%x) af_byte(0x%x)\n",
1157 hdl
->fd
, info
->af_type
, info
->af_addr
, info
->af_sector_num
,
1161 ret
= ioctl(hdl
->fd
, HERMON_IOCTL_FLASH_WRITE
, info
);
1163 logmsg(MSG_ERROR
, gettext("HERMON_IOCTL_FLASH_WRITE "
1164 "failed (%s)\n"), strerror(errno
));
1170 cnx_erase_sector_ioctl(ib_cnx_encap_ident_t
*hdl
, hermon_flash_ioctl_t
*info
)
1175 logmsg(MSG_INFO
, "cnx_erase_sector_ioctl: fd(%d) af_type(0x%x) "
1176 "af_sector_num(0x%x)\n", hdl
->fd
, info
->af_type
,
1177 info
->af_sector_num
);
1180 ret
= ioctl(hdl
->fd
, HERMON_IOCTL_FLASH_ERASE
, info
);
1182 logmsg(MSG_ERROR
, gettext("HERMON_IOCTL_FLASH_ERASE "
1183 "failed (%s)\n"), strerror(errno
));
1189 * cnx_crc16 - computes 16 bit crc of supplied buffer.
1190 * image should be in network byteorder
1191 * result is returned in host byteorder form
1194 cnx_crc16(uint8_t *image
, uint32_t size
, int is_image
)
1196 const uint16_t poly
= 0x100b;
1197 uint32_t crc
= 0xFFFF;
1201 logmsg(MSG_INFO
, "hermon: cnx_crc16\n");
1203 for (i
= 0; i
< size
/ 4; i
++) {
1204 word
= (image
[4 * i
] << 24) |
1205 (image
[4 * i
+ 1] << 16) |
1206 (image
[4 * i
+ 2] << 8) |
1209 if (is_image
== CNX_HW_IMG
)
1210 word
= MLXSWAPBITS32(word
);
1212 for (j
= 0; j
< 32; j
++) {
1214 crc
= (((crc
<< 1) |
1215 (word
>> 31)) ^ poly
) & 0xFFFF;
1217 crc
= ((crc
<< 1) | (word
>> 31)) & 0xFFFF;
1219 word
= (word
<< 1) & 0xFFFFFFFF;
1223 for (i
= 0; i
< 16; i
++) {
1225 crc
= ((crc
<< 1) ^ poly
) & 0xFFFF;
1227 crc
= (crc
<< 1) & 0xFFFF;
1232 return (crc
& 0xFFFF);
1236 cnx_local_set_guid_crc_img(uint32_t offset
, uint32_t guid_crc_size
,
1237 uint32_t guid_crc_offset
)
1240 uint8_t *fw_p
= (uint8_t *)&verifier
->fwimage
[0];
1242 crc
= htons(cnx_crc16((uint8_t *)&verifier
->fwimage
[offset
/ 4],
1243 guid_crc_size
, CNX_FILE_IMG
));
1245 logmsg(MSG_INFO
, "cnx_local_set_guid_crc_img: new guid_sect crc: %x\n",
1247 (void) memcpy(&fw_p
[offset
+ guid_crc_offset
], &crc
, 2);
1251 * Address translation functions for ConnectX
1252 * Variable definitions:
1253 * - log2_chunk_size: log2 of a Flash chunk size
1254 * - cont_addr: a contiguous image address to be translated
1255 * - is_image_in_odd_chunk: When this bit is 1, it indicates the new image is
1256 * stored in odd chunks of the Flash.
1259 cnx_cont2phys(uint32_t log2_chunk_size
, uint32_t cont_addr
, int type
)
1262 int is_image_in_odd_chunks
;
1264 is_image_in_odd_chunks
= type
- 1;
1266 if (log2_chunk_size
) {
1267 result
= cont_addr
& (0xffffffff >> (32 - log2_chunk_size
)) |
1268 (is_image_in_odd_chunks
<< log2_chunk_size
) |
1269 (cont_addr
<< 1) & (0xffffffff << (log2_chunk_size
+ 1));
1278 cnx_read_guids(ib_cnx_encap_ident_t
*handle
, int type
)
1280 #ifdef _LITTLE_ENDIAN
1283 hermon_flash_ioctl_t ioctl_info
;
1287 uint32_t nguidptr_addr
;
1292 uint32_t *guid_structure
;
1295 logmsg(MSG_INFO
, "cnx_read_guids\n");
1298 guid_structure
= (uint32_t *)calloc(1,
1299 CNX_GUID_CRC16_SIZE
/ 4 * sizeof (uint32_t));
1300 if (guid_structure
== NULL
) {
1301 logmsg(MSG_WARN
, gettext("hermon: Can't calloc guid_structure "
1302 ": (%s)\n"), strerror(errno
));
1303 return (FWFLASH_FAILURE
);
1306 ioctl_info
.af_type
= HERMON_FLASH_READ_QUADLET
;
1307 ioctl_info
.af_addr
= cnx_cont2phys(handle
->log2_chunk_sz
,
1308 CNX_NGUIDPTR_OFFSET
, type
);
1310 ret
= cnx_read_ioctl(handle
, &ioctl_info
);
1312 logmsg(MSG_WARN
, gettext("hermon: Failed to read GUID Pointer "
1317 guids
= (uint32_t *)&handle
->ibguids
[0];
1318 ibmac
= (uint32_t *)&handle
->ib_mac
[0];
1319 nguidptr_addr
= cnx_cont2phys(handle
->log2_chunk_sz
,
1320 ioctl_info
.af_quadlet
, type
);
1322 logmsg(MSG_INFO
, "NGUIDPTR: 0x%08x \n", nguidptr_addr
);
1323 /* Read in the entire guid section in order to calculate the CRC */
1324 ioctl_info
.af_addr
= nguidptr_addr
- 0x10;
1325 ioctl_info
.af_type
= HERMON_FLASH_READ_QUADLET
;
1327 for (i
= 0; i
< CNX_GUID_CRC16_SIZE
/ 4; i
++) {
1328 ret
= cnx_read_ioctl(handle
, &ioctl_info
);
1330 logmsg(MSG_INFO
, "Failed to read guid_structure "
1335 if (i
>= 4 && i
< 12) {
1336 guids
[i
- 4] = ioctl_info
.af_quadlet
;
1338 if (i
>= 12 && i
< 16) {
1339 ibmac
[i
- 12] = ioctl_info
.af_quadlet
;
1342 guid_structure
[i
] = ioctl_info
.af_quadlet
;
1343 ioctl_info
.af_addr
+= 4;
1346 for (i
= 0; i
< CNX_GUID_CRC16_SIZE
/ 4; i
++) {
1347 logmsg(MSG_INFO
, "guid_structure[%x] = 0x%08x\n", i
,
1352 * Check the CRC--make sure it computes.
1355 /* 0x12 subtracted: 0x2 for alignment, 0x10 to reach structure start */
1356 ioctl_info
.af_addr
= nguidptr_addr
+ CNX_GUID_CRC16_OFFSET
- 0x12;
1357 ioctl_info
.af_type
= HERMON_FLASH_READ_QUADLET
;
1359 ret
= cnx_read_ioctl(handle
, &ioctl_info
);
1361 logmsg(MSG_WARN
, gettext("hermon: Failed to read guid crc "
1362 "at 0x%x\n"), ioctl_info
.af_addr
);
1366 crc16_u
.dword
= ioctl_info
.af_quadlet
;
1367 crc
= cnx_crc16((uint8_t *)guid_structure
, CNX_GUID_CRC16_SIZE
,
1370 if (crc
!= crc16_u
.dword
) {
1371 logmsg(MSG_WARN
, gettext("hermon: calculated crc16: 0x%x "
1372 "differs from GUID section 0x%x\n"), crc
, crc16_u
.dword
);
1374 logmsg(MSG_INFO
, "hermon: calculated crc16: 0x%x MATCHES with "
1375 "GUID section 0x%x\n", crc
, crc16_u
.dword
);
1378 #ifdef _LITTLE_ENDIAN
1380 * guids are read as pairs of 32 bit host byteorder values and treated
1381 * by callers as 64 bit values. So swap each pair of 32 bit values
1382 * to make them correct
1384 ptr
= (uint32_t *)guids
;
1385 for (ret
= 0; ret
< 8; ret
+= 2) {
1387 ptr
[ret
] = ptr
[ret
+1];
1390 ptr
= (uint32_t *)&handle
->ib_mac
[0];
1391 for (ret
= 0; ret
< 4; ret
+= 2) {
1393 ptr
[ret
] = ptr
[ret
+1];
1397 ret
= FWFLASH_SUCCESS
;
1400 free(guid_structure
);
1405 cnx_find_magic_n_chnk_sz(ib_cnx_encap_ident_t
*handle
, int type
)
1409 uint32_t boot_addresses
[] =
1410 {0, 0x10000, 0x20000, 0x40000, 0x80000, 0x100000};
1412 logmsg(MSG_INFO
, "cnx_find_magic_n_chnk_sz\n");
1415 case FWFLASH_IB_STATE_IMAGE_PRI
:
1417 if (cnx_check_for_magic_pattern(handle
, addr
) !=
1423 case FWFLASH_IB_STATE_IMAGE_SEC
:
1424 for (i
= 1; i
< 6; i
++) {
1425 addr
= boot_addresses
[i
];
1426 if (cnx_check_for_magic_pattern(handle
, addr
) ==
1438 logmsg(MSG_INFO
, "cnx_find_magic_pattern: unknown type\n");
1442 logmsg(MSG_INFO
, "magic_pattern found at addr %x\n", addr
);
1443 handle
->img2_start_addr
= addr
;
1445 handle
->log2_chunk_sz
= cnx_get_log2_chunk_size_f_hdl(handle
, type
);
1446 if (handle
->log2_chunk_sz
== 0) {
1447 logmsg(MSG_INFO
, "no chunk size found for type %x. "
1448 "Assuming non-failsafe burn\n", type
);
1451 handle
->fw_sz
= cnx_get_image_size_f_hdl(handle
, type
);
1452 if (handle
->fw_sz
== 0) {
1453 logmsg(MSG_INFO
, "no fw size found for type %x. \n", type
);
1455 handle
->state
|= type
;
1457 return (FWFLASH_SUCCESS
);
1459 logmsg(MSG_INFO
, "no magic_pattern found for type %x\n", type
);
1460 return (FWFLASH_FAILURE
);
1464 cnx_check_for_magic_pattern(ib_cnx_encap_ident_t
*handle
, uint32_t addr
)
1467 hermon_flash_ioctl_t ioctl_info
;
1468 int magic_pattern_buf
[4];
1470 logmsg(MSG_INFO
, "cnx_check_for_magic_pattern\n");
1472 ioctl_info
.af_type
= HERMON_FLASH_READ_QUADLET
;
1474 for (i
= 0; i
< 4; i
++) {
1475 ioctl_info
.af_addr
= addr
+ (i
* sizeof (uint32_t));
1476 if (cnx_read_ioctl(handle
, &ioctl_info
) != 0) {
1477 logmsg(MSG_INFO
, "\nFailed to read magic pattern\n");
1478 return (FWFLASH_FAILURE
);
1481 magic_pattern_buf
[i
] = ioctl_info
.af_quadlet
;
1484 return (cnx_is_magic_pattern_present(magic_pattern_buf
, CNX_HW_IMG
));
1489 cnx_is_magic_pattern_present(int *data
, int is_image
)
1494 logmsg(MSG_INFO
, "cnx_is_magic_pattern_present\n");
1496 for (i
= 0; i
< 4; i
++) {
1497 if (is_image
== CNX_FILE_IMG
)
1498 dword
= MLXSWAPBITS32(data
[i
]);
1501 logmsg(MSG_INFO
, "local_quadlet: %08x, magic pattern: %08x\n",
1502 dword
, cnx_magic_pattern
[i
]);
1503 if (dword
!= cnx_magic_pattern
[i
]) {
1504 return (FWFLASH_FAILURE
);
1508 return (FWFLASH_SUCCESS
);
1512 cnx_get_log2_chunk_size_f_hdl(ib_cnx_encap_ident_t
*handle
, int type
)
1514 hermon_flash_ioctl_t ioctl_info
;
1517 logmsg(MSG_INFO
, "cnx_get_log2_chunk_size_f_hdl\n");
1519 /* If chunk size is already set, just return it. */
1520 if (handle
->log2_chunk_sz
) {
1521 return (handle
->log2_chunk_sz
);
1525 case FWFLASH_IB_STATE_IMAGE_PRI
:
1526 ioctl_info
.af_addr
= CNX_CHUNK_SIZE_OFFSET
;
1528 case FWFLASH_IB_STATE_IMAGE_SEC
:
1529 ioctl_info
.af_addr
=
1530 handle
->img2_start_addr
+ CNX_CHUNK_SIZE_OFFSET
;
1534 "cnx_get_log2_chunk_size_f_hdl: unknown type\n");
1538 ioctl_info
.af_type
= HERMON_FLASH_READ_QUADLET
;
1540 ret
= cnx_read_ioctl(handle
, &ioctl_info
);
1542 logmsg(MSG_INFO
, "\nFailed to read chunk size\n");
1546 return (cnx_get_log2_chunk_size(ioctl_info
.af_quadlet
));
1551 cnx_get_log2_chunk_size(uint32_t chunk_size_word
)
1554 uint32_t log2_chunk_size
;
1556 logmsg(MSG_INFO
, "cnx_get_log2_chunk_size: chunk_size_word:"
1557 " 0x%x\n", chunk_size_word
);
1560 (chunk_size_word
& 0xff) +
1561 ((chunk_size_word
>> 8) & 0xff) +
1562 ((chunk_size_word
>> 16) & 0xff) +
1563 ((chunk_size_word
>> 24) & 0xff);
1565 if (checksum
!= 0) {
1566 logmsg(MSG_INFO
, "Corrupted chunk size checksum\n");
1570 if (chunk_size_word
& 0x8) {
1571 log2_chunk_size
= (chunk_size_word
& 0x7) + 16;
1572 logmsg(MSG_INFO
, "log2 chunk size: 0x%x\n", log2_chunk_size
);
1573 return (log2_chunk_size
);
1580 cnx_get_image_size_f_hdl(ib_cnx_encap_ident_t
*handle
, int type
)
1582 hermon_flash_ioctl_t ioctl_info
;
1585 logmsg(MSG_INFO
, "cnx_get_image_size_f_hdl\n");
1587 ioctl_info
.af_addr
= cnx_cont2phys(handle
->log2_chunk_sz
,
1588 CNX_IMG_SIZE_OFFSET
, type
);
1589 ioctl_info
.af_type
= HERMON_FLASH_READ_QUADLET
;
1591 ret
= cnx_read_ioctl(handle
, &ioctl_info
);
1593 logmsg(MSG_INFO
, "Failed to read image size\n");
1597 logmsg(MSG_INFO
, "Image Size: 0x%x\n", ioctl_info
.af_quadlet
);
1599 return (ioctl_info
.af_quadlet
);
1603 cnx_get_image_info(ib_cnx_encap_ident_t
*handle
)
1605 uint32_t ii_ptr_addr
;
1609 hermon_flash_ioctl_t ioctl_info
;
1611 logmsg(MSG_INFO
, "cnx_get_image_info: state %x\n", handle
->state
);
1613 type
= handle
->state
&
1614 (FWFLASH_IB_STATE_IMAGE_PRI
| FWFLASH_IB_STATE_IMAGE_SEC
);
1616 /* Get the image info pointer */
1617 ioctl_info
.af_addr
= cnx_cont2phys(handle
->log2_chunk_sz
,
1618 CNX_IMG_INF_PTR_OFFSET
, type
);
1619 ioctl_info
.af_type
= HERMON_FLASH_READ_QUADLET
;
1621 if (cnx_read_ioctl(handle
, &ioctl_info
) != FWFLASH_SUCCESS
) {
1622 logmsg(MSG_WARN
, gettext("hermon: Failed to read image info "
1624 return (FWFLASH_FAILURE
);
1626 ii_ptr_addr
= ioctl_info
.af_quadlet
& 0xffffff;
1628 /* Get the image info size, a negative offset from the image info ptr */
1629 ioctl_info
.af_addr
= cnx_cont2phys(handle
->log2_chunk_sz
,
1630 ii_ptr_addr
+ CNX_IMG_INF_SZ_OFFSET
, type
);
1631 ioctl_info
.af_type
= HERMON_FLASH_READ_QUADLET
;
1633 if (cnx_read_ioctl(handle
, &ioctl_info
) != FWFLASH_SUCCESS
) {
1634 logmsg(MSG_WARN
, gettext("hermon: Failed to read image info "
1636 return (FWFLASH_FAILURE
);
1638 logmsg(MSG_INFO
, "hermon: ImageInfo Sz: 0x%x\n", ioctl_info
.af_quadlet
);
1640 ii_size
= ioctl_info
.af_quadlet
;
1641 /* size is in dwords--convert it to bytes */
1644 logmsg(MSG_INFO
, "hermon: ii_ptr_addr: 0x%x ii_size: 0x%x\n",
1645 ii_ptr_addr
, ii_size
);
1647 buf
= (int *)calloc(1, ii_size
);
1649 ioctl_info
.af_addr
= cnx_cont2phys(handle
->log2_chunk_sz
,
1651 ioctl_info
.af_type
= HERMON_FLASH_READ_QUADLET
;
1653 for (i
= 0; i
< ii_size
/4; i
++) {
1654 if (cnx_read_ioctl(handle
, &ioctl_info
) != FWFLASH_SUCCESS
) {
1655 logmsg(MSG_WARN
, gettext("hermon: Failed to read "
1656 "image info (0x%x)\n"), i
);
1658 return (FWFLASH_FAILURE
);
1661 buf
[i
] = ioctl_info
.af_quadlet
;
1662 ioctl_info
.af_addr
+= 4;
1665 /* Parse the image info section */
1666 if (cnx_parse_img_info(buf
, ii_size
, &handle
->hwfw_img_info
,
1667 CNX_HW_IMG
) != FWFLASH_SUCCESS
) {
1668 logmsg(MSG_WARN
, gettext("hermon: Failed to parse Image Info "
1671 return (FWFLASH_FAILURE
);
1675 return (FWFLASH_SUCCESS
);
1679 cnx_parse_img_info(int *buf
, uint32_t byte_size
, cnx_img_info_t
*img_info
,
1684 uint32_t tag_num
= 0;
1686 uint32_t tag_size
, tag_id
;
1691 p
= (uint32_t *)buf
;
1693 logmsg(MSG_INFO
, "hermon: cnx_parse_img_info\n");
1695 while (!end_found
&& (offs
< byte_size
)) {
1696 if (is_image
== CNX_FILE_IMG
) {
1697 tag_size
= ntohl(*p
) & 0xffffff;
1698 tag_id
= ntohl(*p
) >> 24;
1699 tmp
= ntohl(*(p
+ 1));
1701 tag_size
= ((*p
) & 0xffffff);
1702 tag_id
= ((*p
) >> 24);
1706 logmsg(MSG_INFO
, "tag_id: %d tag_size: %d\n", tag_id
, tag_size
);
1708 if ((offs
+ tag_size
) > byte_size
) {
1709 logmsg(MSG_WARN
, gettext("hermon: Image Info section "
1710 "corrupted: Tag# %d - tag_id %d, size %d exceeds "
1711 "info section size (%d bytes)"), tag_num
, tag_id
,
1712 tag_size
, byte_size
);
1713 return (FWFLASH_FAILURE
);
1718 if (tag_size
!= CNX_FW_VER_SZ
) {
1719 logmsg(MSG_INFO
, "ERROR: tag_id: %d tag_size: "
1720 "%d expected sz %d\n", tag_id
, tag_size
,
1723 tmp
= (tmp
& CNX_MASK_FW_VER_MAJ
) >> 16;
1724 img_info
->fw_rev
.major
= tmp
;
1725 if (is_image
== CNX_FILE_IMG
)
1726 tmp
= ntohl(*(p
+ 2));
1729 img_info
->fw_rev
.minor
=
1730 (tmp
& CNX_MASK_FW_VER_MIN
)>> 16;
1731 img_info
->fw_rev
.subminor
=
1732 tmp
& CNX_MASK_FW_VER_SUBMIN
;
1734 logmsg(MSG_INFO
, "FW_VER: %d.%d.%03d\n",
1735 img_info
->fw_rev
.major
, img_info
->fw_rev
.minor
,
1736 img_info
->fw_rev
.subminor
);
1739 case CNX_FW_BUILD_TIME
:
1740 if (tag_size
!= CNX_FW_BUILD_TIME_SZ
) {
1741 logmsg(MSG_INFO
, "ERROR: tag_id: %d tag_size: "
1742 "%d expected sz %d\n", tag_id
, tag_size
,
1743 CNX_FW_BUILD_TIME_SZ
);
1745 img_info
->fw_buildtime
.hour
=
1746 (tmp
& CNX_MASK_FW_BUILD_HOUR
) >> 16;
1747 img_info
->fw_buildtime
.minute
=
1748 (tmp
& CNX_MASK_FW_BUILD_MIN
) >> 8;
1749 img_info
->fw_buildtime
.second
=
1750 (tmp
& CNX_MASK_FW_BUILD_SEC
);
1752 if (is_image
== CNX_FILE_IMG
)
1753 tmp
= ntohl(*(p
+ 2));
1757 img_info
->fw_buildtime
.year
=
1758 (tmp
& CNX_MASK_FW_BUILD_YEAR
) >> 16;
1759 img_info
->fw_buildtime
.month
=
1760 (tmp
& CNX_MASK_FW_BUILD_MON
) >> 8;
1761 img_info
->fw_buildtime
.day
=
1762 (tmp
& CNX_MASK_FW_BUILD_DAY
);
1764 logmsg(MSG_INFO
, "Build TIME: %d:%d:%d %d:%d:%d\n",
1765 img_info
->fw_buildtime
.year
,
1766 img_info
->fw_buildtime
.month
,
1767 img_info
->fw_buildtime
.day
,
1768 img_info
->fw_buildtime
.hour
,
1769 img_info
->fw_buildtime
.minute
,
1770 img_info
->fw_buildtime
.second
);
1774 if (tag_size
!= CNX_DEV_TYPE_SZ
) {
1775 logmsg(MSG_INFO
, "ERROR: tag_id: %d tag_size: "
1776 "%d expected sz %d\n", tag_id
, tag_size
,
1779 img_info
->dev_id
= tmp
& CNX_MASK_DEV_TYPE_ID
;
1780 logmsg(MSG_INFO
, "DEV_TYPE: %d\n", img_info
->dev_id
);
1783 case CNX_VSD_VENDOR_ID
:
1784 if (tag_size
!= CNX_VSD_VENDOR_ID_SZ
) {
1785 logmsg(MSG_INFO
, "ERROR: tag_id: %d tag_size: "
1786 "%d expected sz %d\n", tag_id
, tag_size
,
1787 CNX_VSD_VENDOR_ID_SZ
);
1789 img_info
->vsd_vendor_id
= tmp
& CNX_MASK_VSD_VENDORID
;
1790 logmsg(MSG_INFO
, "VSD Vendor ID: 0x%lX\n",
1791 img_info
->vsd_vendor_id
);
1795 if (tag_size
!= CNX_PSID_SZ
) {
1796 logmsg(MSG_INFO
, "ERROR: tag_id: %d tag_size: "
1797 "%d expected sz %d\n", tag_id
, tag_size
,
1800 str
= (const char *)p
;
1803 for (i
= 0; i
< CNX_PSID_SZ
; i
++)
1804 img_info
->psid
[i
] = str
[i
];
1806 #ifdef _LITTLE_ENDIAN
1807 if (is_image
== CNX_HW_IMG
) {
1808 for (i
= 0; i
< CNX_PSID_SZ
; i
+= 4) {
1809 img_info
->psid
[i
+3] = str
[i
];
1810 img_info
->psid
[i
+2] = str
[i
+1];
1811 img_info
->psid
[i
+1] = str
[i
+2];
1812 img_info
->psid
[i
] = str
[i
+3];
1817 logmsg(MSG_INFO
, "PSID: %s\n", img_info
->psid
);
1821 if (tag_size
!= CNX_VSD_SZ
) {
1822 logmsg(MSG_INFO
, "ERROR: tag_id: %d tag_size: "
1823 "%d expected sz %d\n", tag_id
, tag_size
,
1826 str
= (const char *)p
;
1829 for (i
= 0; i
< CNX_VSD_SZ
; i
++)
1830 img_info
->vsd
[i
] = str
[i
];
1832 #ifdef _LITTLE_ENDIAN
1833 if (is_image
== CNX_HW_IMG
) {
1834 for (i
= 0; i
< CNX_VSD_SZ
; i
+= 4) {
1835 img_info
->vsd
[i
+3] = str
[i
];
1836 img_info
->vsd
[i
+2] = str
[i
+1];
1837 img_info
->vsd
[i
+1] = str
[i
+2];
1838 img_info
->vsd
[i
] = str
[i
+3];
1842 logmsg(MSG_INFO
, "VSD: %s\n", img_info
->vsd
);
1846 if (tag_size
!= CNX_END_TAG_SZ
) {
1847 logmsg(MSG_INFO
, "ERROR: tag_id: %d tag_size: "
1848 "%d expected sz %d\n", tag_id
, tag_size
,
1855 if (tag_id
> CNX_END_TAG
) {
1856 logmsg(MSG_WARN
, gettext("Invalid img_info "
1857 "tag ID %d of size %d\n"), tag_id
,
1863 p
+= (tag_size
/ 4) + 1;
1864 offs
+= tag_size
+ 4;
1868 if (offs
!= byte_size
) {
1869 logmsg(MSG_WARN
, gettext("hermon: Corrupt Image Info section "
1870 "in firmware image\n"));
1872 logmsg(MSG_WARN
, gettext("Info section corrupted: "
1873 "Section data size is %x bytes, but end tag found "
1874 "after %x bytes.\n"), byte_size
, offs
);
1876 logmsg(MSG_WARN
, gettext("Info section corrupted: "
1877 "Section data size is %x bytes, but end tag not "
1878 "found at section end.\n"), byte_size
);
1880 return (FWFLASH_FAILURE
);
1883 return (FWFLASH_SUCCESS
);