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
fw_readfw(struct devicelist * flashdev,char * filename)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
fw_writefw(struct devicelist * flashdev)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
fw_identify(int start)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
fw_devinfo(struct devicelist * thisdev)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
cnx_read_image(ib_cnx_encap_ident_t * handle)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
cnx_write_file(ib_cnx_encap_ident_t * handle,const char * filename)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
cnx_verify_image(ib_cnx_encap_ident_t * handle,int type)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
cnx_set_guids(ib_cnx_encap_ident_t * handle,void * arg)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
cnx_write_image(ib_cnx_encap_ident_t * handle,int type)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
cnx_identify(struct devicelist * thisdev)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
cnx_get_guids(ib_cnx_encap_ident_t * handle)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
cnx_close(struct devicelist * flashdev)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
cnx_read_ioctl(ib_cnx_encap_ident_t * hdl,hermon_flash_ioctl_t * info)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
cnx_write_ioctl(ib_cnx_encap_ident_t * hdl,hermon_flash_ioctl_t * info)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
cnx_erase_sector_ioctl(ib_cnx_encap_ident_t * hdl,hermon_flash_ioctl_t * info)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
cnx_crc16(uint8_t * image,uint32_t size,int is_image)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
cnx_local_set_guid_crc_img(uint32_t offset,uint32_t guid_crc_size,uint32_t guid_crc_offset)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
cnx_cont2phys(uint32_t log2_chunk_size,uint32_t cont_addr,int type)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
cnx_read_guids(ib_cnx_encap_ident_t * handle,int type)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
cnx_find_magic_n_chnk_sz(ib_cnx_encap_ident_t * handle,int type)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
cnx_check_for_magic_pattern(ib_cnx_encap_ident_t * handle,uint32_t addr)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
cnx_is_magic_pattern_present(int * data,int is_image)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
cnx_get_log2_chunk_size_f_hdl(ib_cnx_encap_ident_t * handle,int type)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
cnx_get_log2_chunk_size(uint32_t chunk_size_word)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
cnx_get_image_size_f_hdl(ib_cnx_encap_ident_t * handle,int type)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
cnx_get_image_info(ib_cnx_encap_ident_t * handle)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
cnx_parse_img_info(int * buf,uint32_t byte_size,cnx_img_info_t * img_info,int is_image)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