19e39c5baSBill Taylor /*
29e39c5baSBill Taylor * CDDL HEADER START
39e39c5baSBill Taylor *
49e39c5baSBill Taylor * The contents of this file are subject to the terms of the
59e39c5baSBill Taylor * Common Development and Distribution License (the "License").
69e39c5baSBill Taylor * You may not use this file except in compliance with the License.
79e39c5baSBill Taylor *
89e39c5baSBill Taylor * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
99e39c5baSBill Taylor * or http://www.opensolaris.org/os/licensing.
109e39c5baSBill Taylor * See the License for the specific language governing permissions
119e39c5baSBill Taylor * and limitations under the License.
129e39c5baSBill Taylor *
139e39c5baSBill Taylor * When distributing Covered Code, include this CDDL HEADER in each
149e39c5baSBill Taylor * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
159e39c5baSBill Taylor * If applicable, add the following below this CDDL HEADER, with the
169e39c5baSBill Taylor * fields enclosed by brackets "[]" replaced with your own identifying
179e39c5baSBill Taylor * information: Portions Copyright [yyyy] [name of copyright owner]
189e39c5baSBill Taylor *
199e39c5baSBill Taylor * CDDL HEADER END
209e39c5baSBill Taylor */
219e39c5baSBill Taylor
229e39c5baSBill Taylor /*
23*b67a60d6SShantkumar Hiremath * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
249e39c5baSBill Taylor */
259e39c5baSBill Taylor
269e39c5baSBill Taylor /*
279e39c5baSBill Taylor * The reference for the functions in this file is the
289e39c5baSBill Taylor *
299e39c5baSBill Taylor * Mellanox HCA Flash Programming Application Note
309e39c5baSBill Taylor * (Mellanox document number 2205AN) rev 1.45, 2007.
319e39c5baSBill Taylor * Chapter 4 in particular.
329e39c5baSBill Taylor */
339e39c5baSBill Taylor
349e39c5baSBill Taylor #include <stdio.h>
359e39c5baSBill Taylor #include <stdlib.h>
369e39c5baSBill Taylor #include <unistd.h>
379e39c5baSBill Taylor #include <sys/types.h>
389e39c5baSBill Taylor #include <sys/stat.h>
399e39c5baSBill Taylor #include <sys/sysmacros.h>
409e39c5baSBill Taylor #include <sys/queue.h>
419e39c5baSBill Taylor #include <fcntl.h>
429e39c5baSBill Taylor #include <ctype.h>
439e39c5baSBill Taylor #include <string.h>
449e39c5baSBill Taylor #include <strings.h>
459e39c5baSBill Taylor
469e39c5baSBill Taylor #include <sys/byteorder.h>
479e39c5baSBill Taylor
489e39c5baSBill Taylor #include <libintl.h> /* for gettext(3c) */
499e39c5baSBill Taylor
509e39c5baSBill Taylor #include <fwflash/fwflash.h>
519e39c5baSBill Taylor #include "../../hdrs/hermon_ib.h"
529e39c5baSBill Taylor
539e39c5baSBill Taylor char *devprefix = "/devices";
549e39c5baSBill Taylor char drivername[] = "hermon\0";
559e39c5baSBill Taylor char *devsuffix = ":devctl";
569e39c5baSBill Taylor
579e39c5baSBill Taylor extern di_node_t rootnode;
589e39c5baSBill Taylor extern int errno;
599e39c5baSBill Taylor extern struct fw_plugin *self;
609e39c5baSBill Taylor extern struct vrfyplugin *verifier;
619e39c5baSBill Taylor extern int fwflash_debug;
629e39c5baSBill Taylor
639e39c5baSBill Taylor /* required functions for this plugin */
649e39c5baSBill Taylor int fw_readfw(struct devicelist *device, char *filename);
659e39c5baSBill Taylor int fw_writefw(struct devicelist *device);
669e39c5baSBill Taylor int fw_identify(int start);
679e39c5baSBill Taylor int fw_devinfo();
689e39c5baSBill Taylor
699e39c5baSBill Taylor
709e39c5baSBill Taylor /* helper functions */
719e39c5baSBill Taylor static int cnx_identify(struct devicelist *thisdev);
729e39c5baSBill Taylor static int cnx_get_guids(ib_cnx_encap_ident_t *handle);
739e39c5baSBill Taylor static int cnx_close(struct devicelist *flashdev);
749e39c5baSBill Taylor static int cnx_check_for_magic_pattern(ib_cnx_encap_ident_t *hdl, uint32_t adr);
759e39c5baSBill Taylor static uint32_t cnx_get_log2_chunk_size_f_hdl(ib_cnx_encap_ident_t *handle,
769e39c5baSBill Taylor int type);
779e39c5baSBill Taylor static uint32_t cnx_get_log2_chunk_size(uint32_t chunk_size_word);
789e39c5baSBill Taylor static uint32_t cnx_cont2phys(uint32_t log2_chunk_sz, uint32_t cont_addr,
799e39c5baSBill Taylor int type);
809e39c5baSBill Taylor static uint32_t cnx_get_image_size_f_hdl(ib_cnx_encap_ident_t *hdl, int type);
819e39c5baSBill Taylor static void cnx_local_set_guid_crc_img(uint32_t offset, uint32_t guid_crc_size,
829e39c5baSBill Taylor uint32_t guid_crc_offset);
839e39c5baSBill Taylor static int cnx_read_image(ib_cnx_encap_ident_t *handle);
849e39c5baSBill Taylor static int cnx_write_file(ib_cnx_encap_ident_t *handle, const char *filename);
859e39c5baSBill Taylor static int cnx_verify_image(ib_cnx_encap_ident_t *handle, int type);
869e39c5baSBill Taylor static int cnx_read_guids(ib_cnx_encap_ident_t *handle, int type);
879e39c5baSBill Taylor static int cnx_set_guids(ib_cnx_encap_ident_t *handle, void *arg);
889e39c5baSBill Taylor static int cnx_write_image(ib_cnx_encap_ident_t *handle, int type);
899e39c5baSBill Taylor static int cnx_read_ioctl(ib_cnx_encap_ident_t *hdl,
909e39c5baSBill Taylor hermon_flash_ioctl_t *info);
919e39c5baSBill Taylor static int cnx_write_ioctl(ib_cnx_encap_ident_t *hdl,
929e39c5baSBill Taylor hermon_flash_ioctl_t *info);
939e39c5baSBill Taylor static int cnx_erase_sector_ioctl(ib_cnx_encap_ident_t *hdl,
949e39c5baSBill Taylor hermon_flash_ioctl_t *info);
959e39c5baSBill Taylor static int cnx_find_magic_n_chnk_sz(ib_cnx_encap_ident_t *handle, int type);
969e39c5baSBill Taylor static int cnx_get_image_info(ib_cnx_encap_ident_t *handle);
979e39c5baSBill Taylor
989e39c5baSBill Taylor
999e39c5baSBill Taylor int
fw_readfw(struct devicelist * flashdev,char * filename)1009e39c5baSBill Taylor fw_readfw(struct devicelist *flashdev, char *filename)
1019e39c5baSBill Taylor {
1029e39c5baSBill Taylor ib_cnx_encap_ident_t *manuf;
1039e39c5baSBill Taylor int rv = FWFLASH_SUCCESS;
1049e39c5baSBill Taylor
1059e39c5baSBill Taylor logmsg(MSG_INFO, "hermon: fw_readfw: filename %s\n", filename);
1069e39c5baSBill Taylor
1079e39c5baSBill Taylor manuf = (ib_cnx_encap_ident_t *)flashdev->ident->encap_ident;
1089e39c5baSBill Taylor if (CNX_I_CHECK_HANDLE(manuf)) {
1099e39c5baSBill Taylor logmsg(MSG_ERROR, gettext("hermon: Invalid Handle for "
1109e39c5baSBill Taylor "device %s! \n"), flashdev->access_devname);
1119e39c5baSBill Taylor return (FWFLASH_FAILURE);
1129e39c5baSBill Taylor }
1139e39c5baSBill Taylor
1149e39c5baSBill Taylor logmsg(MSG_INFO, "hermon: fw_identify should have read the image. "
1159e39c5baSBill Taylor "state 0x%x\n", manuf->state);
1169e39c5baSBill Taylor
1179e39c5baSBill Taylor rv = cnx_read_image(manuf);
1189e39c5baSBill Taylor if (rv != FWFLASH_SUCCESS) {
1199e39c5baSBill Taylor logmsg(MSG_ERROR, gettext("hermon: Failed to read any valid "
1209e39c5baSBill Taylor "image on device (%s)\n"), flashdev->access_devname);
1219e39c5baSBill Taylor logmsg(MSG_ERROR, gettext("Aborting read.\n"));
1229e39c5baSBill Taylor } else {
1239e39c5baSBill Taylor rv = cnx_write_file(manuf, filename);
1249e39c5baSBill Taylor }
1259e39c5baSBill Taylor
1269e39c5baSBill Taylor cnx_close(flashdev);
1279e39c5baSBill Taylor return (rv);
1289e39c5baSBill Taylor }
1299e39c5baSBill Taylor
1309e39c5baSBill Taylor
1319e39c5baSBill Taylor /*
1329e39c5baSBill Taylor * If we're invoking fw_writefw, then flashdev is a valid,
1339e39c5baSBill Taylor * flashable device as determined by fw_identify().
1349e39c5baSBill Taylor *
1359e39c5baSBill Taylor * If verifier is null, then we haven't been called following a firmware
1369e39c5baSBill Taylor * image verification load operation.
1379e39c5baSBill Taylor */
1389e39c5baSBill Taylor int
fw_writefw(struct devicelist * flashdev)1399e39c5baSBill Taylor fw_writefw(struct devicelist *flashdev)
1409e39c5baSBill Taylor {
1419e39c5baSBill Taylor ib_cnx_encap_ident_t *manuf;
1429e39c5baSBill Taylor int i, j, k;
1439e39c5baSBill Taylor
1449e39c5baSBill Taylor logmsg(MSG_INFO, "hermon: fw_writefw\n");
1459e39c5baSBill Taylor
1469e39c5baSBill Taylor manuf = (ib_cnx_encap_ident_t *)flashdev->ident->encap_ident;
1479e39c5baSBill Taylor
1489e39c5baSBill Taylor if (CNX_I_CHECK_HANDLE(manuf)) {
1499e39c5baSBill Taylor logmsg(MSG_ERROR, gettext("hermon: Invalid Handle for "
1509e39c5baSBill Taylor "device %s! \n"), flashdev->access_devname);
1519e39c5baSBill Taylor return (FWFLASH_FAILURE);
1529e39c5baSBill Taylor }
1539e39c5baSBill Taylor
1549e39c5baSBill Taylor /*
1559e39c5baSBill Taylor * Try the primary first, then the secondary.
1569e39c5baSBill Taylor * If we get here, then the verifier has _already_ checked that
1579e39c5baSBill Taylor * the part number in the firmware image matches that in the HCA,
1589e39c5baSBill Taylor * so we only need this check if there's no hardware info available
1599e39c5baSBill Taylor * already after running through fw_identify().
1609e39c5baSBill Taylor */
1619e39c5baSBill Taylor if (manuf->pn_len == 0) {
1629e39c5baSBill Taylor int resp;
1639e39c5baSBill Taylor
1649e39c5baSBill Taylor (void) fprintf(stderr, gettext("Unable to completely verify "
1659e39c5baSBill Taylor "that this firmware image (%s) is compatible with your "
1669e39c5baSBill Taylor "HCA %s"), verifier->imgfile, flashdev->access_devname);
1679e39c5baSBill Taylor (void) fprintf(stderr, gettext("Do you really want to "
1689e39c5baSBill Taylor "continue? (Y/N): "));
1699e39c5baSBill Taylor (void) fflush(stdin);
1709e39c5baSBill Taylor resp = getchar();
1719e39c5baSBill Taylor if (resp != 'Y' && resp != 'y') {
1729e39c5baSBill Taylor (void) fprintf(stderr, gettext("Not proceeding with "
1739e39c5baSBill Taylor "flash operation of %s on %s"),
1749e39c5baSBill Taylor verifier->imgfile, flashdev->access_devname);
1759e39c5baSBill Taylor return (FWFLASH_FAILURE);
1769e39c5baSBill Taylor }
1779e39c5baSBill Taylor }
1789e39c5baSBill Taylor
1799e39c5baSBill Taylor logmsg(MSG_INFO, "hermon: fw_writefw: Using Existing GUIDs.\n");
1809e39c5baSBill Taylor manuf->state |=
1819e39c5baSBill Taylor FWFLASH_IB_STATE_GUIDN |
1829e39c5baSBill Taylor FWFLASH_IB_STATE_GUID1 |
1839e39c5baSBill Taylor FWFLASH_IB_STATE_GUID2 |
1849e39c5baSBill Taylor FWFLASH_IB_STATE_GUIDS;
1859e39c5baSBill Taylor if (cnx_set_guids(manuf, manuf->ibguids) != FWFLASH_SUCCESS) {
1869e39c5baSBill Taylor logmsg(MSG_WARN, gettext("hermon: Failed to set GUIDs"));
1879e39c5baSBill Taylor }
1889e39c5baSBill Taylor
1899e39c5baSBill Taylor /*
1909e39c5baSBill Taylor * Update both Primary and Secondary images
1919e39c5baSBill Taylor *
1929e39c5baSBill Taylor * For Failsafe firmware image update, if the current image (i.e.
1939e39c5baSBill Taylor * containing a magic pattern) on the Flash is stored on the Primary
1949e39c5baSBill Taylor * location, burn the new image to the Secondary location first,
1959e39c5baSBill Taylor * or vice versa.
1969e39c5baSBill Taylor */
1979e39c5baSBill Taylor
1989e39c5baSBill Taylor /* Note Current Image location. */
1999e39c5baSBill Taylor j = manuf->state &
2009e39c5baSBill Taylor (FWFLASH_IB_STATE_IMAGE_PRI | FWFLASH_IB_STATE_IMAGE_SEC);
2019e39c5baSBill Taylor
2029e39c5baSBill Taylor /*
2039e39c5baSBill Taylor * If we find that current image location is not found, no worries
2049e39c5baSBill Taylor * we shall default to PRIMARY, and proceed with burning anyway.
2059e39c5baSBill Taylor */
2069e39c5baSBill Taylor if (j == 0)
2079e39c5baSBill Taylor j = FWFLASH_IB_STATE_IMAGE_PRI;
2089e39c5baSBill Taylor
2099e39c5baSBill Taylor for (i = FWFLASH_FLASH_IMAGES; i > 0; i--) {
2109e39c5baSBill Taylor char *type;
2119e39c5baSBill Taylor
2129e39c5baSBill Taylor if (i == 2) {
2139e39c5baSBill Taylor if (j == 2)
2149e39c5baSBill Taylor k = 1; /* Burn PRI First */
2159e39c5baSBill Taylor else
2169e39c5baSBill Taylor k = 2; /* Burn SEC First */
2179e39c5baSBill Taylor } else {
2189e39c5baSBill Taylor if (k == 2)
2199e39c5baSBill Taylor k = 1; /* Burn PRI next */
2209e39c5baSBill Taylor else
2219e39c5baSBill Taylor k = 2; /* Burn SEC next */
2229e39c5baSBill Taylor }
2239e39c5baSBill Taylor type = ((k == 1) ? "Primary" : "Secondary");
2249e39c5baSBill Taylor
2259e39c5baSBill Taylor logmsg(MSG_INFO, "hermon: fw_write: UPDATING %s image\n", type);
2269e39c5baSBill Taylor
2279e39c5baSBill Taylor if (cnx_write_image(manuf, k) != FWFLASH_SUCCESS) {
2289e39c5baSBill Taylor (void) fprintf(stderr,
2299e39c5baSBill Taylor gettext("Failed to update %s image on device %s"),
2309e39c5baSBill Taylor type, flashdev->access_devname);
2319e39c5baSBill Taylor goto out;
2329e39c5baSBill Taylor }
2339e39c5baSBill Taylor
2349e39c5baSBill Taylor logmsg(MSG_INFO, "hermon: fw_write: Verify %s image..\n", type);
2359e39c5baSBill Taylor if (cnx_verify_image(manuf, k) != FWFLASH_SUCCESS) {
2369e39c5baSBill Taylor (void) fprintf(stderr,
2379e39c5baSBill Taylor gettext("Failed to verify %s image for device %s"),
2389e39c5baSBill Taylor type, flashdev->access_devname);
2399e39c5baSBill Taylor goto out;
2409e39c5baSBill Taylor }
2419e39c5baSBill Taylor }
2429e39c5baSBill Taylor out:
2439e39c5baSBill Taylor /* final update marker to the user */
2449e39c5baSBill Taylor (void) printf(" +\n");
2459e39c5baSBill Taylor return (cnx_close(flashdev));
2469e39c5baSBill Taylor }
2479e39c5baSBill Taylor
2489e39c5baSBill Taylor
2499e39c5baSBill Taylor /*
2509e39c5baSBill Taylor * The fw_identify() function walks the device tree trying to find
2519e39c5baSBill Taylor * devices which this plugin can work with.
2529e39c5baSBill Taylor *
2539e39c5baSBill Taylor * The parameter "start" gives us the starting index number
2549e39c5baSBill Taylor * to give the device when we add it to the fw_devices list.
2559e39c5baSBill Taylor *
2569e39c5baSBill Taylor * firstdev is allocated by us and we add space as necessary
2579e39c5baSBill Taylor */
2589e39c5baSBill Taylor int
fw_identify(int start)2599e39c5baSBill Taylor fw_identify(int start)
2609e39c5baSBill Taylor {
2619e39c5baSBill Taylor int rv = FWFLASH_FAILURE;
2629e39c5baSBill Taylor di_node_t thisnode;
2639e39c5baSBill Taylor struct devicelist *newdev;
2649e39c5baSBill Taylor char *devpath;
2659e39c5baSBill Taylor int idx = start;
2669e39c5baSBill Taylor int devlength = 0;
2679e39c5baSBill Taylor
2689e39c5baSBill Taylor logmsg(MSG_INFO, "hermon: fw_identify\n");
2699e39c5baSBill Taylor thisnode = di_drv_first_node(drivername, rootnode);
2709e39c5baSBill Taylor
2719e39c5baSBill Taylor if (thisnode == DI_NODE_NIL) {
2729e39c5baSBill Taylor logmsg(MSG_INFO, gettext("No %s nodes in this system\n"),
2739e39c5baSBill Taylor drivername);
2749e39c5baSBill Taylor return (rv);
2759e39c5baSBill Taylor }
2769e39c5baSBill Taylor
2779e39c5baSBill Taylor /* we've found one, at least */
2789e39c5baSBill Taylor for (; thisnode != DI_NODE_NIL; thisnode = di_drv_next_node(thisnode)) {
2799e39c5baSBill Taylor
2809e39c5baSBill Taylor devpath = di_devfs_path(thisnode);
2819e39c5baSBill Taylor
2829e39c5baSBill Taylor if ((newdev = calloc(1, sizeof (struct devicelist))) == NULL) {
2839e39c5baSBill Taylor logmsg(MSG_ERROR, gettext("hermon: Unable to allocate "
2849e39c5baSBill Taylor "space for device entry\n"));
2859e39c5baSBill Taylor di_devfs_path_free(devpath);
2869e39c5baSBill Taylor return (FWFLASH_FAILURE);
2879e39c5baSBill Taylor }
2889e39c5baSBill Taylor
2899e39c5baSBill Taylor /* calloc enough for /devices + devpath + ":devctl" + '\0' */
2909e39c5baSBill Taylor devlength = strlen(devpath) + strlen(devprefix) +
2919e39c5baSBill Taylor strlen(devsuffix) + 2;
2929e39c5baSBill Taylor
2939e39c5baSBill Taylor if ((newdev->access_devname = calloc(1, devlength)) == NULL) {
2949e39c5baSBill Taylor logmsg(MSG_ERROR, gettext("hermon: Unable to allocate "
2959e39c5baSBill Taylor "space for a devfs name\n"));
2969e39c5baSBill Taylor (void) free(newdev);
2979e39c5baSBill Taylor di_devfs_path_free(devpath);
2989e39c5baSBill Taylor return (FWFLASH_FAILURE);
2999e39c5baSBill Taylor }
3009e39c5baSBill Taylor snprintf(newdev->access_devname, devlength,
3019e39c5baSBill Taylor "%s%s%s", devprefix, devpath, devsuffix);
3029e39c5baSBill Taylor
3039e39c5baSBill Taylor if ((newdev->ident = calloc(1, sizeof (struct vpr))) == NULL) {
3049e39c5baSBill Taylor logmsg(MSG_ERROR, gettext("hermon: Unable to allocate "
3059e39c5baSBill Taylor "space for a device identification record\n"));
3069e39c5baSBill Taylor (void) free(newdev->access_devname);
3079e39c5baSBill Taylor (void) free(newdev);
3089e39c5baSBill Taylor di_devfs_path_free(devpath);
3099e39c5baSBill Taylor return (FWFLASH_FAILURE);
3109e39c5baSBill Taylor }
3119e39c5baSBill Taylor
3129e39c5baSBill Taylor /* CHECK VARIOUS IB THINGS HERE */
3139e39c5baSBill Taylor rv = cnx_identify(newdev);
3149e39c5baSBill Taylor if (rv == FWFLASH_FAILURE) {
3159e39c5baSBill Taylor (void) free(newdev->ident);
3169e39c5baSBill Taylor (void) free(newdev->access_devname);
3179e39c5baSBill Taylor (void) free(newdev);
3189e39c5baSBill Taylor di_devfs_path_free(devpath);
3199e39c5baSBill Taylor continue;
3209e39c5baSBill Taylor }
3219e39c5baSBill Taylor
3229e39c5baSBill Taylor if ((newdev->drvname = calloc(1, strlen(drivername) + 1))
3239e39c5baSBill Taylor == NULL) {
3249e39c5baSBill Taylor logmsg(MSG_ERROR, gettext("hermon: Unable to allocate"
3259e39c5baSBill Taylor " space for a driver name\n"));
3269e39c5baSBill Taylor (void) free(newdev->ident);
3279e39c5baSBill Taylor (void) free(newdev->access_devname);
3289e39c5baSBill Taylor (void) free(newdev);
3299e39c5baSBill Taylor di_devfs_path_free(devpath);
3309e39c5baSBill Taylor return (FWFLASH_FAILURE);
3319e39c5baSBill Taylor }
3329e39c5baSBill Taylor
3339e39c5baSBill Taylor (void) strlcpy(newdev->drvname, drivername,
3349e39c5baSBill Taylor strlen(drivername) + 1);
3359e39c5baSBill Taylor
3369e39c5baSBill Taylor /* this next bit is backwards compatibility - "IB\0" */
3379e39c5baSBill Taylor if ((newdev->classname = calloc(1, 3)) == NULL) {
3389e39c5baSBill Taylor logmsg(MSG_ERROR, gettext("hermon: Unable to allocate "
3399e39c5baSBill Taylor "space for a class name\n"));
3409e39c5baSBill Taylor (void) free(newdev->drvname);
3419e39c5baSBill Taylor (void) free(newdev->ident);
3429e39c5baSBill Taylor (void) free(newdev->access_devname);
3439e39c5baSBill Taylor (void) free(newdev);
3449e39c5baSBill Taylor di_devfs_path_free(devpath);
3459e39c5baSBill Taylor return (FWFLASH_FAILURE);
3469e39c5baSBill Taylor }
3479e39c5baSBill Taylor (void) strlcpy(newdev->classname, "IB", 3);
3489e39c5baSBill Taylor
3499e39c5baSBill Taylor newdev->index = idx;
3509e39c5baSBill Taylor ++idx;
3519e39c5baSBill Taylor newdev->plugin = self;
3529e39c5baSBill Taylor
3539e39c5baSBill Taylor di_devfs_path_free(devpath);
3549e39c5baSBill Taylor
3559e39c5baSBill Taylor TAILQ_INSERT_TAIL(fw_devices, newdev, nextdev);
3569e39c5baSBill Taylor }
3579e39c5baSBill Taylor
3589e39c5baSBill Taylor if (fwflash_debug != 0) {
3599e39c5baSBill Taylor struct devicelist *tempdev;
3609e39c5baSBill Taylor
3619e39c5baSBill Taylor TAILQ_FOREACH(tempdev, fw_devices, nextdev) {
3629e39c5baSBill Taylor logmsg(MSG_INFO, "fw_identify: hermon:\n");
3639e39c5baSBill Taylor logmsg(MSG_INFO, "\ttempdev @ 0x%lx\n"
3649e39c5baSBill Taylor "\t\taccess_devname: %s\n"
3659e39c5baSBill Taylor "\t\tdrvname: %s\tclassname: %s\n"
3669e39c5baSBill Taylor "\t\tident->vid: %s\n"
3679e39c5baSBill Taylor "\t\tident->pid: %s\n"
3689e39c5baSBill Taylor "\t\tident->revid: %s\n"
3699e39c5baSBill Taylor "\t\tindex: %d\n"
3709e39c5baSBill Taylor "\t\tguid0: %s\n"
3719e39c5baSBill Taylor "\t\tguid1: %s\n"
3729e39c5baSBill Taylor "\t\tguid2: %s\n"
3739e39c5baSBill Taylor "\t\tguid3: %s\n"
3749e39c5baSBill Taylor "\t\tplugin @ 0x%lx\n\n",
3759e39c5baSBill Taylor &tempdev,
3769e39c5baSBill Taylor tempdev->access_devname,
3779e39c5baSBill Taylor tempdev->drvname, newdev->classname,
3789e39c5baSBill Taylor tempdev->ident->vid,
3799e39c5baSBill Taylor tempdev->ident->pid,
3809e39c5baSBill Taylor tempdev->ident->revid,
3819e39c5baSBill Taylor tempdev->index,
382*b67a60d6SShantkumar Hiremath (tempdev->addresses[0] ? tempdev->addresses[0] :
383*b67a60d6SShantkumar Hiremath "(not supported)"),
384*b67a60d6SShantkumar Hiremath (tempdev->addresses[1] ? tempdev->addresses[1] :
385*b67a60d6SShantkumar Hiremath "(not supported)"),
386*b67a60d6SShantkumar Hiremath (tempdev->addresses[2] ? tempdev->addresses[2] :
387*b67a60d6SShantkumar Hiremath "(not supported)"),
388*b67a60d6SShantkumar Hiremath (tempdev->addresses[3] ? tempdev->addresses[3] :
389*b67a60d6SShantkumar Hiremath "(not supported)"),
3909e39c5baSBill Taylor tempdev->plugin);
3919e39c5baSBill Taylor }
3929e39c5baSBill Taylor }
3939e39c5baSBill Taylor
3949e39c5baSBill Taylor return (FWFLASH_SUCCESS);
3959e39c5baSBill Taylor }
3969e39c5baSBill Taylor
3979e39c5baSBill Taylor
3989e39c5baSBill Taylor int
fw_devinfo(struct devicelist * thisdev)3999e39c5baSBill Taylor fw_devinfo(struct devicelist *thisdev)
4009e39c5baSBill Taylor {
4019e39c5baSBill Taylor ib_cnx_encap_ident_t *encap;
4029e39c5baSBill Taylor
4039e39c5baSBill Taylor logmsg(MSG_INFO, "hermon: fw_devinfo\n");
4049e39c5baSBill Taylor
4059e39c5baSBill Taylor encap = (ib_cnx_encap_ident_t *)thisdev->ident->encap_ident;
4069e39c5baSBill Taylor if (CNX_I_CHECK_HANDLE(encap)) {
4079e39c5baSBill Taylor logmsg(MSG_ERROR, gettext("hermon: fw_devinfo: Invalid handle "
4089e39c5baSBill Taylor "for device %s! \n"), thisdev->access_devname);
4099e39c5baSBill Taylor return (FWFLASH_FAILURE);
4109e39c5baSBill Taylor }
4119e39c5baSBill Taylor
4129e39c5baSBill Taylor /* Try the primary first, then the secondary */
4139e39c5baSBill Taylor fprintf(stdout, gettext("Device[%d] %s\n"),
4149e39c5baSBill Taylor thisdev->index, thisdev->access_devname);
4159e39c5baSBill Taylor fprintf(stdout, gettext("Class [%s]\n"), thisdev->classname);
4169e39c5baSBill Taylor
4179e39c5baSBill Taylor fprintf(stdout, "\t");
4189e39c5baSBill Taylor
4199e39c5baSBill Taylor /* Mellanox HCA Flash app note, p40, #4.2.3 table 9 */
4209e39c5baSBill Taylor fprintf(stdout, gettext("GUID: System Image - %s\n"),
4219e39c5baSBill Taylor thisdev->addresses[3]);
4229e39c5baSBill Taylor fprintf(stdout, gettext("\t\tNode Image - %s\n"),
4239e39c5baSBill Taylor thisdev->addresses[0]);
4249e39c5baSBill Taylor fprintf(stdout, gettext("\t\tPort 1\t - %s\n"),
4259e39c5baSBill Taylor thisdev->addresses[1]);
4269e39c5baSBill Taylor fprintf(stdout, gettext("\t\tPort 2\t - %s\n"),
4279e39c5baSBill Taylor thisdev->addresses[2]);
4289e39c5baSBill Taylor
4299e39c5baSBill Taylor fprintf(stdout, gettext("\tFirmware revision : %s\n"),
4309e39c5baSBill Taylor thisdev->ident->revid);
4319e39c5baSBill Taylor
4329e39c5baSBill Taylor if (encap->pn_len != 0) {
4339e39c5baSBill Taylor if (strlen(encap->info.mlx_id))
434*b67a60d6SShantkumar Hiremath fprintf(stdout, gettext("\tProduct\t\t : "
435*b67a60d6SShantkumar Hiremath "%s %X (%s)\n"), encap->info.mlx_pn,
436*b67a60d6SShantkumar Hiremath encap->hwrev, encap->info.mlx_id);
4379e39c5baSBill Taylor else
438*b67a60d6SShantkumar Hiremath fprintf(stdout, gettext("\tProduct\t\t : %s %X\n"),
439*b67a60d6SShantkumar Hiremath encap->info.mlx_pn, encap->hwrev);
4409e39c5baSBill Taylor
4419e39c5baSBill Taylor if (strlen(encap->info.mlx_psid))
4429e39c5baSBill Taylor fprintf(stdout, gettext("\tPSID\t\t : %s\n"),
4439e39c5baSBill Taylor encap->info.mlx_psid);
4449e39c5baSBill Taylor else if (strlen(thisdev->ident->pid))
4459e39c5baSBill Taylor fprintf(stdout, gettext("\t%s\n"), thisdev->ident->pid);
4469e39c5baSBill Taylor } else {
4479e39c5baSBill Taylor fprintf(stdout, gettext("\t%s\n"), thisdev->ident->pid);
4489e39c5baSBill Taylor }
4499e39c5baSBill Taylor fprintf(stdout, "\n\n");
4509e39c5baSBill Taylor
4519e39c5baSBill Taylor return (cnx_close(thisdev));
4529e39c5baSBill Taylor }
4539e39c5baSBill Taylor
4549e39c5baSBill Taylor
4559e39c5baSBill Taylor /*
4569e39c5baSBill Taylor * Helper functions lurk beneath this point
4579e39c5baSBill Taylor */
4589e39c5baSBill Taylor
4599e39c5baSBill Taylor
4609e39c5baSBill Taylor /*
4619e39c5baSBill Taylor * Notes:
4629e39c5baSBill Taylor * 1. flash read is done in 32 bit quantities, and the driver returns
4639e39c5baSBill Taylor * data in host byteorder form.
4649e39c5baSBill Taylor * 2. flash write is done in 8 bit quantities by the driver.
4659e39c5baSBill Taylor * 3. data in the flash should be in network byteorder.
4669e39c5baSBill Taylor * 4. data in image files is in network byteorder form.
4679e39c5baSBill Taylor * 5. data in image structures in memory is kept in network byteorder.
4689e39c5baSBill Taylor * 6. the functions in this file deal with data in host byteorder form.
4699e39c5baSBill Taylor */
4709e39c5baSBill Taylor
4719e39c5baSBill Taylor static int
cnx_read_image(ib_cnx_encap_ident_t * handle)4729e39c5baSBill Taylor cnx_read_image(ib_cnx_encap_ident_t *handle)
4739e39c5baSBill Taylor {
4749e39c5baSBill Taylor hermon_flash_ioctl_t ioctl_info;
4759e39c5baSBill Taylor uint32_t phys_addr;
4769e39c5baSBill Taylor int ret, i;
4779e39c5baSBill Taylor int image_size;
4789e39c5baSBill Taylor int type;
4799e39c5baSBill Taylor
4809e39c5baSBill Taylor type = handle->state &
4819e39c5baSBill Taylor (FWFLASH_IB_STATE_IMAGE_PRI | FWFLASH_IB_STATE_IMAGE_SEC);
4829e39c5baSBill Taylor logmsg(MSG_INFO, "cnx_read_image: type %lx\n", type);
4839e39c5baSBill Taylor
4849e39c5baSBill Taylor if (type == 0) {
4859e39c5baSBill Taylor logmsg(MSG_ERROR, gettext("cnx_read_image: Must read in "
4869e39c5baSBill Taylor "image first\n"));
4879e39c5baSBill Taylor return (FWFLASH_FAILURE);
4889e39c5baSBill Taylor }
4899e39c5baSBill Taylor
4909e39c5baSBill Taylor image_size = handle->fw_sz;
4919e39c5baSBill Taylor if (image_size <= 0) {
4929e39c5baSBill Taylor logmsg(MSG_ERROR, gettext("cnx_read_image: Invalid image size "
4939e39c5baSBill Taylor "0x%x for %s image\n"),
4949e39c5baSBill Taylor image_size, (type == 0x1 ? "Primary" : "Secondary"));
4959e39c5baSBill Taylor return (FWFLASH_FAILURE);
4969e39c5baSBill Taylor }
4979e39c5baSBill Taylor
4989e39c5baSBill Taylor logmsg(MSG_INFO, "hermon: fw_size: 0x%x\n", image_size);
4999e39c5baSBill Taylor
5009e39c5baSBill Taylor handle->fw = (uint32_t *)calloc(1, image_size);
5019e39c5baSBill Taylor if (handle->fw == NULL) {
5029e39c5baSBill Taylor logmsg(MSG_ERROR, gettext("cnx_read_image: Unable to allocate "
5039e39c5baSBill Taylor "memory for fw_img : (%s)\n"), strerror(errno));
5049e39c5baSBill Taylor return (FWFLASH_FAILURE);
5059e39c5baSBill Taylor }
5069e39c5baSBill Taylor
5079e39c5baSBill Taylor ioctl_info.af_type = HERMON_FLASH_READ_QUADLET;
5089e39c5baSBill Taylor for (i = 0; i < image_size; i += 4) {
5099e39c5baSBill Taylor phys_addr = cnx_cont2phys(handle->log2_chunk_sz, i, type);
5109e39c5baSBill Taylor ioctl_info.af_addr = phys_addr;
5119e39c5baSBill Taylor
5129e39c5baSBill Taylor ret = cnx_read_ioctl(handle, &ioctl_info);
5139e39c5baSBill Taylor if (ret != 0) {
5149e39c5baSBill Taylor logmsg(MSG_ERROR, gettext("cnx_read_image: Failed to "
5159e39c5baSBill Taylor "read sector %d\n"), i);
5169e39c5baSBill Taylor free(handle->fw);
5179e39c5baSBill Taylor return (FWFLASH_FAILURE);
5189e39c5baSBill Taylor }
5199e39c5baSBill Taylor handle->fw[i / 4] = htonl(ioctl_info.af_quadlet);
5209e39c5baSBill Taylor }
5219e39c5baSBill Taylor
5229e39c5baSBill Taylor for (i = 0; i < image_size; i += 4) {
5239e39c5baSBill Taylor logmsg(MSG_INFO, "cnx_read_image: addr[0x%x] = 0x%08x\n", i,
5249e39c5baSBill Taylor ntohl(handle->fw[i / 4]));
5259e39c5baSBill Taylor }
5269e39c5baSBill Taylor
5279e39c5baSBill Taylor return (FWFLASH_SUCCESS);
5289e39c5baSBill Taylor }
5299e39c5baSBill Taylor
5309e39c5baSBill Taylor static int
cnx_write_file(ib_cnx_encap_ident_t * handle,const char * filename)5319e39c5baSBill Taylor cnx_write_file(ib_cnx_encap_ident_t *handle, const char *filename)
5329e39c5baSBill Taylor {
5339e39c5baSBill Taylor FILE *fp;
5349e39c5baSBill Taylor int fd;
5359e39c5baSBill Taylor mode_t mode = S_IRUSR | S_IWUSR;
5369e39c5baSBill Taylor int len;
5379e39c5baSBill Taylor
5389e39c5baSBill Taylor logmsg(MSG_INFO, "cnx_write_file\n");
5399e39c5baSBill Taylor
5409e39c5baSBill Taylor errno = 0;
5419e39c5baSBill Taylor if ((fd = open(filename, O_RDWR|O_CREAT|O_DSYNC, mode)) < 0) {
5429e39c5baSBill Taylor logmsg(MSG_ERROR, gettext("hermon: Unable to open specified "
5439e39c5baSBill Taylor "file (%s) for writing: %s\n"), filename, strerror(errno));
5449e39c5baSBill Taylor return (FWFLASH_FAILURE);
5459e39c5baSBill Taylor }
5469e39c5baSBill Taylor
5479e39c5baSBill Taylor errno = 0;
5489e39c5baSBill Taylor fp = fdopen(fd, "w");
5499e39c5baSBill Taylor if (fp == NULL) {
5509e39c5baSBill Taylor (void) fprintf(stderr, gettext("hermon: Unknown filename %s : "
5519e39c5baSBill Taylor "%s\n"), filename, strerror(errno));
5529e39c5baSBill Taylor return (FWFLASH_FAILURE);
5539e39c5baSBill Taylor }
5549e39c5baSBill Taylor
5559e39c5baSBill Taylor len = ntohl(handle->fw[CNX_IMG_SIZE_OFFSET / 4]);
5569e39c5baSBill Taylor logmsg(MSG_INFO, "cnx_write_file: Writing to file. Length 0x%x\n", len);
5579e39c5baSBill Taylor
5589e39c5baSBill Taylor if (fwrite(&handle->fw[0], len, 1, fp) == 0) {
5599e39c5baSBill Taylor (void) fprintf(stderr, gettext("hermon: fwrite failed"));
5609e39c5baSBill Taylor perror("fwrite");
5619e39c5baSBill Taylor (void) fclose(fp);
5629e39c5baSBill Taylor return (FWFLASH_FAILURE);
5639e39c5baSBill Taylor }
5649e39c5baSBill Taylor (void) fclose(fp);
5659e39c5baSBill Taylor return (FWFLASH_SUCCESS);
5669e39c5baSBill Taylor }
5679e39c5baSBill Taylor
5689e39c5baSBill Taylor static int
cnx_verify_image(ib_cnx_encap_ident_t * handle,int type)5699e39c5baSBill Taylor cnx_verify_image(ib_cnx_encap_ident_t *handle, int type)
5709e39c5baSBill Taylor {
5719e39c5baSBill Taylor uint32_t new_start_addr;
5729e39c5baSBill Taylor
5739e39c5baSBill Taylor logmsg(MSG_INFO, "hermon: cnx_verify_image\n");
5749e39c5baSBill Taylor
5759e39c5baSBill Taylor new_start_addr = cnx_cont2phys(handle->log2_chunk_sz, 0, type);
5769e39c5baSBill Taylor
5779e39c5baSBill Taylor return (cnx_check_for_magic_pattern(handle, new_start_addr));
5789e39c5baSBill Taylor }
5799e39c5baSBill Taylor
5809e39c5baSBill Taylor static int
cnx_set_guids(ib_cnx_encap_ident_t * handle,void * arg)5819e39c5baSBill Taylor cnx_set_guids(ib_cnx_encap_ident_t *handle, void *arg)
5829e39c5baSBill Taylor {
5839e39c5baSBill Taylor uint32_t addr;
5849e39c5baSBill Taylor uint32_t *guids;
5859e39c5baSBill Taylor
5869e39c5baSBill Taylor logmsg(MSG_INFO, "hermon: cnx_set_guids\n");
5879e39c5baSBill Taylor
5889e39c5baSBill Taylor guids = (uint32_t *)arg;
5899e39c5baSBill Taylor addr = ntohl(verifier->fwimage[CNX_NGUIDPTR_OFFSET / 4]) / 4;
5909e39c5baSBill Taylor logmsg(MSG_INFO, "cnx_set_guids: guid_start_addr: 0x%x\n", addr * 4);
5919e39c5baSBill Taylor
5929e39c5baSBill Taylor /*
5939e39c5baSBill Taylor * guids are supplied by callers as 64 bit values in host byteorder.
5949e39c5baSBill Taylor * Storage is in network byteorder.
5959e39c5baSBill Taylor */
5969e39c5baSBill Taylor #ifdef _BIG_ENDIAN
5979e39c5baSBill Taylor if (handle->state & FWFLASH_IB_STATE_GUIDN) {
5989e39c5baSBill Taylor verifier->fwimage[addr] = guids[0];
5999e39c5baSBill Taylor verifier->fwimage[addr + 1] = guids[1];
6009e39c5baSBill Taylor }
6019e39c5baSBill Taylor
6029e39c5baSBill Taylor if (handle->state & FWFLASH_IB_STATE_GUID1) {
6039e39c5baSBill Taylor verifier->fwimage[addr + 2] = guids[2];
6049e39c5baSBill Taylor verifier->fwimage[addr + 3] = guids[3];
6059e39c5baSBill Taylor }
6069e39c5baSBill Taylor
6079e39c5baSBill Taylor if (handle->state & FWFLASH_IB_STATE_GUID2) {
6089e39c5baSBill Taylor verifier->fwimage[addr + 4] = guids[4];
6099e39c5baSBill Taylor verifier->fwimage[addr + 5] = guids[5];
6109e39c5baSBill Taylor }
6119e39c5baSBill Taylor
6129e39c5baSBill Taylor if (handle->state & FWFLASH_IB_STATE_GUIDS) {
6139e39c5baSBill Taylor verifier->fwimage[addr + 6] = guids[6];
6149e39c5baSBill Taylor verifier->fwimage[addr + 7] = guids[7];
6159e39c5baSBill Taylor }
6169e39c5baSBill Taylor #else
6179e39c5baSBill Taylor if (handle->state & FWFLASH_IB_STATE_GUIDN) {
6189e39c5baSBill Taylor verifier->fwimage[addr] = htonl(guids[1]);
6199e39c5baSBill Taylor verifier->fwimage[addr + 1] = htonl(guids[0]);
6209e39c5baSBill Taylor }
6219e39c5baSBill Taylor
6229e39c5baSBill Taylor if (handle->state & FWFLASH_IB_STATE_GUID1) {
6239e39c5baSBill Taylor verifier->fwimage[addr + 2] = htonl(guids[3]);
6249e39c5baSBill Taylor verifier->fwimage[addr + 3] = htonl(guids[2]);
6259e39c5baSBill Taylor }
6269e39c5baSBill Taylor
6279e39c5baSBill Taylor if (handle->state & FWFLASH_IB_STATE_GUID2) {
6289e39c5baSBill Taylor verifier->fwimage[addr + 4] = htonl(guids[5]);
6299e39c5baSBill Taylor verifier->fwimage[addr + 5] = htonl(guids[4]);
6309e39c5baSBill Taylor }
6319e39c5baSBill Taylor
6329e39c5baSBill Taylor if (handle->state & FWFLASH_IB_STATE_GUIDS) {
6339e39c5baSBill Taylor verifier->fwimage[addr + 6] = htonl(guids[7]);
6349e39c5baSBill Taylor verifier->fwimage[addr + 7] = htonl(guids[6]);
6359e39c5baSBill Taylor }
6369e39c5baSBill Taylor #endif
6379e39c5baSBill Taylor
6389e39c5baSBill Taylor cnx_local_set_guid_crc_img((addr * 4) - 0x10, CNX_GUID_CRC16_SIZE,
6399e39c5baSBill Taylor CNX_GUID_CRC16_OFFSET);
6409e39c5baSBill Taylor
6419e39c5baSBill Taylor return (FWFLASH_SUCCESS);
6429e39c5baSBill Taylor }
6439e39c5baSBill Taylor
6449e39c5baSBill Taylor /*
6459e39c5baSBill Taylor * Notes: Burn the image
6469e39c5baSBill Taylor *
6479e39c5baSBill Taylor * 1. Erase the entire sector where the new image is to be burned.
6489e39c5baSBill Taylor * 2. Burn the image WITHOUT the magic pattern. This marks the new image
6499e39c5baSBill Taylor * as invalid during the burn process. If the current image (i.e
6509e39c5baSBill Taylor * containing a magic pattern) on the Flash is stored on the even
6519e39c5baSBill Taylor * chunks (PRIMARY), burn the new image to the odd chunks (SECONDARY),
6529e39c5baSBill Taylor * or vice versa.
6539e39c5baSBill Taylor * 3. Burn the magic pattern at the beginning of the new image on the Flash.
6549e39c5baSBill Taylor * This will validate the new image.
6559e39c5baSBill Taylor * 4. Set the BootAddress register to its new location.
6569e39c5baSBill Taylor */
6579e39c5baSBill Taylor static int
cnx_write_image(ib_cnx_encap_ident_t * handle,int type)6589e39c5baSBill Taylor cnx_write_image(ib_cnx_encap_ident_t *handle, int type)
6599e39c5baSBill Taylor {
6609e39c5baSBill Taylor hermon_flash_ioctl_t ioctl_info;
6619e39c5baSBill Taylor int sector_size;
6629e39c5baSBill Taylor int size;
6639e39c5baSBill Taylor int i;
6649e39c5baSBill Taylor uint32_t new_start_addr;
6659e39c5baSBill Taylor uint32_t log2_chunk_sz;
6669e39c5baSBill Taylor uint8_t *fw;
6679e39c5baSBill Taylor
6689e39c5baSBill Taylor logmsg(MSG_INFO, "hermon: cnx_write_image\n");
6699e39c5baSBill Taylor
6709e39c5baSBill Taylor if (type == 0) {
6719e39c5baSBill Taylor logmsg(MSG_ERROR, gettext("cnx_write_image: Must inform us "
6729e39c5baSBill Taylor " where to write.\n"));
6739e39c5baSBill Taylor return (FWFLASH_FAILURE);
6749e39c5baSBill Taylor }
6759e39c5baSBill Taylor
6769e39c5baSBill Taylor log2_chunk_sz = cnx_get_log2_chunk_size(
6779e39c5baSBill Taylor ntohl(verifier->fwimage[CNX_CHUNK_SIZE_OFFSET / 4]));
6789e39c5baSBill Taylor
6799e39c5baSBill Taylor sector_size = handle->sector_sz;
6809e39c5baSBill Taylor new_start_addr = ((type - 1) << handle->log2_chunk_sz);
6819e39c5baSBill Taylor
6829e39c5baSBill Taylor /* Read Image Size */
6839e39c5baSBill Taylor size = ntohl(verifier->fwimage[CNX_IMG_SIZE_OFFSET / 4]);
6849e39c5baSBill Taylor logmsg(MSG_INFO, "cnx_write_image: fw image size: 0x%x\n", size);
6859e39c5baSBill Taylor
6869e39c5baSBill Taylor /* Sectors must be erased before they can be written to. */
6879e39c5baSBill Taylor ioctl_info.af_type = HERMON_FLASH_ERASE_SECTOR;
6889e39c5baSBill Taylor for (i = 0; i < size; i += sector_size) {
6899e39c5baSBill Taylor ioctl_info.af_sector_num =
6909e39c5baSBill Taylor cnx_cont2phys(log2_chunk_sz, i, type) / sector_size;
6919e39c5baSBill Taylor if (cnx_erase_sector_ioctl(handle, &ioctl_info) != 0) {
6929e39c5baSBill Taylor logmsg(MSG_ERROR, gettext("cnx_write_image: Failed to "
6939e39c5baSBill Taylor "erase sector 0x%x\n"), ioctl_info.af_sector_num);
6949e39c5baSBill Taylor return (FWFLASH_FAILURE);
6959e39c5baSBill Taylor }
6969e39c5baSBill Taylor }
6979e39c5baSBill Taylor
6989e39c5baSBill Taylor fw = (uint8_t *)verifier->fwimage;
6999e39c5baSBill Taylor ioctl_info.af_type = HERMON_FLASH_WRITE_BYTE;
7009e39c5baSBill Taylor
7019e39c5baSBill Taylor /* Write the new image without the magic pattern */
7029e39c5baSBill Taylor for (i = 16; i < size; i++) {
7039e39c5baSBill Taylor ioctl_info.af_byte = fw[i];
7049e39c5baSBill Taylor ioctl_info.af_addr = cnx_cont2phys(log2_chunk_sz, i, type);
7059e39c5baSBill Taylor if (cnx_write_ioctl(handle, &ioctl_info) != 0) {
7069e39c5baSBill Taylor logmsg(MSG_ERROR, gettext("cnx_write_image: Failed to "
7079e39c5baSBill Taylor "write byte 0x%x\n"), ioctl_info.af_byte);
7089e39c5baSBill Taylor return (FWFLASH_FAILURE);
7099e39c5baSBill Taylor }
7109e39c5baSBill Taylor
7119e39c5baSBill Taylor if (i && !(i % handle->sector_sz)) {
7129e39c5baSBill Taylor (void) printf(" .");
7139e39c5baSBill Taylor (void) fflush((void *)NULL);
7149e39c5baSBill Taylor }
7159e39c5baSBill Taylor }
7169e39c5baSBill Taylor
7179e39c5baSBill Taylor /* Validate the new image -- Write the magic pattern. */
7189e39c5baSBill Taylor for (i = 0; i < 16; i++) {
7199e39c5baSBill Taylor ioctl_info.af_byte = fw[i];
7209e39c5baSBill Taylor ioctl_info.af_addr = cnx_cont2phys(log2_chunk_sz, i, type);
7219e39c5baSBill Taylor if (cnx_write_ioctl(handle, &ioctl_info) != 0) {
7229e39c5baSBill Taylor logmsg(MSG_ERROR, gettext("cnx_write_image: Failed to "
7239e39c5baSBill Taylor "write magic pattern byte 0x%x\n"),
7249e39c5baSBill Taylor ioctl_info.af_byte);
7259e39c5baSBill Taylor return (FWFLASH_FAILURE);
7269e39c5baSBill Taylor }
7279e39c5baSBill Taylor }
7289e39c5baSBill Taylor
7299e39c5baSBill Taylor /* Write new image start address to CR space */
7309e39c5baSBill Taylor errno = 0;
7319e39c5baSBill Taylor ioctl_info.af_addr = new_start_addr;
7329e39c5baSBill Taylor if (ioctl(handle->fd, HERMON_IOCTL_WRITE_BOOT_ADDR, &ioctl_info) != 0) {
7339e39c5baSBill Taylor logmsg(MSG_WARN, gettext("cnx_write_image: Failed to "
7349e39c5baSBill Taylor "update boot address register: %s\n"), strerror(errno));
7359e39c5baSBill Taylor }
7369e39c5baSBill Taylor
7379e39c5baSBill Taylor return (FWFLASH_SUCCESS);
7389e39c5baSBill Taylor }
7399e39c5baSBill Taylor
7409e39c5baSBill Taylor
7419e39c5baSBill Taylor /*
7429e39c5baSBill Taylor * cnx_identify performs the following actions:
7439e39c5baSBill Taylor *
7449e39c5baSBill Taylor * allocates and assigns thisdev->vpr
7459e39c5baSBill Taylor *
7469e39c5baSBill Taylor * allocates space for the 4 GUIDs which each IB device must have
7479e39c5baSBill Taylor * queries the hermon driver for this device's GUIDs
7489e39c5baSBill Taylor *
7499e39c5baSBill Taylor * determines the hardware vendor, so that thisdev->vpr->vid
7509e39c5baSBill Taylor * can be set correctly
7519e39c5baSBill Taylor */
7529e39c5baSBill Taylor static int
cnx_identify(struct devicelist * thisdev)7539e39c5baSBill Taylor cnx_identify(struct devicelist *thisdev)
7549e39c5baSBill Taylor {
7559e39c5baSBill Taylor int fd, ret, i;
7569e39c5baSBill Taylor hermon_flash_init_ioctl_t init_ioctl;
7579e39c5baSBill Taylor ib_cnx_encap_ident_t *manuf;
7589e39c5baSBill Taylor cfi_t cfi;
7599e39c5baSBill Taylor int hw_psid_found = 0;
7609e39c5baSBill Taylor
7619e39c5baSBill Taylor logmsg(MSG_INFO, "hermon: cnx_identify\n");
7629e39c5baSBill Taylor /* open the device */
7639e39c5baSBill Taylor /* hook thisdev->ident->encap_ident to ib_cnx_encap_ident_t */
7649e39c5baSBill Taylor /* check that all the bits are sane */
7659e39c5baSBill Taylor /* return success, if warranted */
7669e39c5baSBill Taylor
7679e39c5baSBill Taylor errno = 0;
7689e39c5baSBill Taylor if ((fd = open(thisdev->access_devname, O_RDONLY)) < 0) {
7699e39c5baSBill Taylor logmsg(MSG_ERROR, gettext("hermon: Unable to open a %s-"
7709e39c5baSBill Taylor "attached device node: %s: %s\n"), drivername,
7719e39c5baSBill Taylor thisdev->access_devname, strerror(errno));
7729e39c5baSBill Taylor return (FWFLASH_FAILURE);
7739e39c5baSBill Taylor }
7749e39c5baSBill Taylor
7759e39c5baSBill Taylor if ((manuf = calloc(1, sizeof (ib_cnx_encap_ident_t))) == NULL) {
7769e39c5baSBill Taylor logmsg(MSG_ERROR, gettext("hermon: Unable to allocate space "
7779e39c5baSBill Taylor "for a %s-attached handle structure\n"), drivername);
7789e39c5baSBill Taylor close(fd);
7799e39c5baSBill Taylor return (FWFLASH_FAILURE);
7809e39c5baSBill Taylor }
7819e39c5baSBill Taylor manuf->magic = FWFLASH_IB_MAGIC_NUMBER;
7829e39c5baSBill Taylor manuf->state = FWFLASH_IB_STATE_NONE;
7839e39c5baSBill Taylor manuf->fd = fd;
7849e39c5baSBill Taylor manuf->log2_chunk_sz = 0;
7859e39c5baSBill Taylor
7869e39c5baSBill Taylor thisdev->ident->encap_ident = manuf;
7879e39c5baSBill Taylor
7889e39c5baSBill Taylor /*
7899e39c5baSBill Taylor * Inform driver that this command supports the Intel Extended
7909e39c5baSBill Taylor * CFI command set.
7919e39c5baSBill Taylor */
7929e39c5baSBill Taylor cfi.cfi_char[0x10] = 'M';
7939e39c5baSBill Taylor cfi.cfi_char[0x11] = 'X';
7949e39c5baSBill Taylor cfi.cfi_char[0x12] = '2';
7959e39c5baSBill Taylor init_ioctl.af_cfi_info[0x4] = ntohl(cfi.cfi_int[0x4]);
7969e39c5baSBill Taylor
7979e39c5baSBill Taylor errno = 0;
7989e39c5baSBill Taylor ret = ioctl(fd, HERMON_IOCTL_FLASH_INIT, &init_ioctl);
7999e39c5baSBill Taylor if (ret < 0) {
8009e39c5baSBill Taylor logmsg(MSG_ERROR, gettext("hermon: HERMON_IOCTL_FLASH_INIT "
8019e39c5baSBill Taylor "failed: %s\n"), strerror(errno));
8029e39c5baSBill Taylor close(fd);
8039e39c5baSBill Taylor free(manuf);
8049e39c5baSBill Taylor return (FWFLASH_FAILURE);
8059e39c5baSBill Taylor }
8069e39c5baSBill Taylor
8079e39c5baSBill Taylor manuf->hwrev = init_ioctl.af_hwrev;
8089e39c5baSBill Taylor logmsg(MSG_INFO, "hermon: init_ioctl: hwrev: %x, fwver: %d.%d.%04d, "
8099e39c5baSBill Taylor "PN# Len %d\n", init_ioctl.af_hwrev, init_ioctl.af_fwrev.afi_maj,
8109e39c5baSBill Taylor init_ioctl.af_fwrev.afi_min, init_ioctl.af_fwrev.afi_sub,
8119e39c5baSBill Taylor init_ioctl.af_pn_len);
8129e39c5baSBill Taylor
8139e39c5baSBill Taylor /*
8149e39c5baSBill Taylor * Determine whether the attached driver supports the Intel or
8159e39c5baSBill Taylor * AMD Extended CFI command sets. If it doesn't support either,
8169e39c5baSBill Taylor * then we're hosed, so error out.
8179e39c5baSBill Taylor */
8189e39c5baSBill Taylor for (i = 0; i < HERMON_FLASH_CFI_SIZE_QUADLET; i++) {
8199e39c5baSBill Taylor cfi.cfi_int[i] = ntohl(init_ioctl.af_cfi_info[i]);
8209e39c5baSBill Taylor }
8219e39c5baSBill Taylor manuf->cmd_set = cfi.cfi_char[0x13];
8229e39c5baSBill Taylor
8239e39c5baSBill Taylor if (cfi.cfi_char[0x10] == 'Q' &&
8249e39c5baSBill Taylor cfi.cfi_char[0x11] == 'R' &&
8259e39c5baSBill Taylor cfi.cfi_char[0x12] == 'Y') {
8269e39c5baSBill Taylor /* make sure the cmd set is SPI */
8279e39c5baSBill Taylor if (manuf->cmd_set != HERMON_FLASH_SPI_CMDSET) {
8289e39c5baSBill Taylor logmsg(MSG_ERROR, gettext("hermon: Unsupported flash "
8299e39c5baSBill Taylor "device command set\n"));
8309e39c5baSBill Taylor goto identify_end;
8319e39c5baSBill Taylor }
8329e39c5baSBill Taylor /* set some defaults */
8339e39c5baSBill Taylor manuf->sector_sz = HERMON_FLASH_SECTOR_SZ_DEFAULT;
8349e39c5baSBill Taylor manuf->device_sz = HERMON_FLASH_DEVICE_SZ_DEFAULT;
8359e39c5baSBill Taylor } else if (manuf->cmd_set == HERMON_FLASH_SPI_CMDSET) {
8369e39c5baSBill Taylor manuf->sector_sz = HERMON_FLASH_SPI_SECTOR_SIZE;
8379e39c5baSBill Taylor manuf->device_sz = HERMON_FLASH_SPI_DEVICE_SIZE;
8389e39c5baSBill Taylor } else {
8399e39c5baSBill Taylor if (manuf->cmd_set != HERMON_FLASH_AMD_CMDSET &&
8409e39c5baSBill Taylor manuf->cmd_set != HERMON_FLASH_INTEL_CMDSET) {
8419e39c5baSBill Taylor logmsg(MSG_ERROR, gettext("hermon: Unknown flash "
8429e39c5baSBill Taylor "device command set %lx\n"), manuf->cmd_set);
8439e39c5baSBill Taylor goto identify_end;
8449e39c5baSBill Taylor }
8459e39c5baSBill Taylor /* read from the CFI data */
8469e39c5baSBill Taylor manuf->sector_sz = ((cfi.cfi_char[0x30] << 8) |
8479e39c5baSBill Taylor cfi.cfi_char[0x2F]) << 8;
8489e39c5baSBill Taylor manuf->device_sz = 0x1 << cfi.cfi_char[0x27];
8499e39c5baSBill Taylor }
8509e39c5baSBill Taylor
8519e39c5baSBill Taylor logmsg(MSG_INFO, "hermon: sector_sz: 0x%08x device_sz: 0x%08x\n",
8529e39c5baSBill Taylor manuf->sector_sz, manuf->device_sz);
8539e39c5baSBill Taylor
8549e39c5baSBill Taylor /* set firmware revision */
8559e39c5baSBill Taylor manuf->hwfw_img_info.fw_rev.major = init_ioctl.af_fwrev.afi_maj;
8569e39c5baSBill Taylor manuf->hwfw_img_info.fw_rev.minor = init_ioctl.af_fwrev.afi_min;
8579e39c5baSBill Taylor manuf->hwfw_img_info.fw_rev.subminor = init_ioctl.af_fwrev.afi_sub;
8589e39c5baSBill Taylor
8599e39c5baSBill Taylor if (((thisdev->ident->vid = calloc(1, MLX_VPR_VIDLEN + 1)) == NULL) ||
8609e39c5baSBill Taylor ((thisdev->ident->revid = calloc(1, MLX_VPR_REVLEN + 1)) == NULL)) {
8619e39c5baSBill Taylor logmsg(MSG_ERROR, gettext("hermon: Unable to allocate space "
8629e39c5baSBill Taylor "for a VPR record.\n"));
8639e39c5baSBill Taylor goto identify_end;
8649e39c5baSBill Taylor }
8659e39c5baSBill Taylor (void) strlcpy(thisdev->ident->vid, "MELLANOX", MLX_VPR_VIDLEN);
8669e39c5baSBill Taylor
8679e39c5baSBill Taylor /*
8689e39c5baSBill Taylor * We actually want the hwrev field from the ioctl above.
8699e39c5baSBill Taylor * Until we find out otherwise, add it onto the end of the
8709e39c5baSBill Taylor * firmware version details.
8719e39c5baSBill Taylor */
872ee5d8455SShantkumar Hiremath snprintf(thisdev->ident->revid, MLX_VPR_REVLEN, "%d.%d.%03d",
8739e39c5baSBill Taylor manuf->hwfw_img_info.fw_rev.major,
8749e39c5baSBill Taylor manuf->hwfw_img_info.fw_rev.minor,
8759e39c5baSBill Taylor manuf->hwfw_img_info.fw_rev.subminor);
8769e39c5baSBill Taylor
8779e39c5baSBill Taylor if ((ret = cnx_get_guids(manuf)) != FWFLASH_SUCCESS) {
8789e39c5baSBill Taylor logmsg(MSG_WARN, gettext("hermon: No GUIDs found for "
8799e39c5baSBill Taylor "device %s!\n"), thisdev->access_devname);
8809e39c5baSBill Taylor }
8819e39c5baSBill Taylor
8829e39c5baSBill Taylor /* set hw part number, psid, and name in handle */
8839e39c5baSBill Taylor /* now walk the magic decoder ring table */
8849e39c5baSBill Taylor manuf->info.mlx_pn = NULL;
8859e39c5baSBill Taylor manuf->info.mlx_psid = NULL;
8869e39c5baSBill Taylor manuf->info.mlx_id = NULL;
8879e39c5baSBill Taylor
8889e39c5baSBill Taylor if (cnx_get_image_info(manuf) != FWFLASH_SUCCESS) {
8899e39c5baSBill Taylor logmsg(MSG_WARN, gettext("hermon: Failed to read Image Info "
8909e39c5baSBill Taylor "for PSID\n"));
8919e39c5baSBill Taylor hw_psid_found = 0;
8929e39c5baSBill Taylor } else {
8939e39c5baSBill Taylor hw_psid_found = 1;
8949e39c5baSBill Taylor }
8959e39c5baSBill Taylor
8969e39c5baSBill Taylor if (init_ioctl.af_pn_len != 0) {
8979e39c5baSBill Taylor /* part number length */
8989e39c5baSBill Taylor for (i = 0; i < init_ioctl.af_pn_len; i++) {
8999e39c5baSBill Taylor if (init_ioctl.af_hwpn[i] == ' ') {
9009e39c5baSBill Taylor manuf->pn_len = i;
9019e39c5baSBill Taylor break;
9029e39c5baSBill Taylor }
9039e39c5baSBill Taylor }
9049e39c5baSBill Taylor if (i == init_ioctl.af_pn_len) {
9059e39c5baSBill Taylor manuf->pn_len = init_ioctl.af_pn_len;
9069e39c5baSBill Taylor }
9079e39c5baSBill Taylor } else {
9089e39c5baSBill Taylor logmsg(MSG_INFO, "hermon: Failed to get Part# from hermon "
9099e39c5baSBill Taylor "driver \n");
9109e39c5baSBill Taylor manuf->pn_len = 0;
9119e39c5baSBill Taylor }
9129e39c5baSBill Taylor
9139e39c5baSBill Taylor if (manuf->pn_len != 0) {
9149e39c5baSBill Taylor errno = 0;
9159e39c5baSBill Taylor manuf->info.mlx_pn = calloc(1, manuf->pn_len);
9169e39c5baSBill Taylor if (manuf->info.mlx_pn == NULL) {
9179e39c5baSBill Taylor logmsg(MSG_ERROR, gettext("hermon: no space available "
9189e39c5baSBill Taylor "for the HCA PN record (%s)\n"), strerror(errno));
9199e39c5baSBill Taylor goto identify_end;
9209e39c5baSBill Taylor }
9219e39c5baSBill Taylor (void) memcpy(manuf->info.mlx_pn, init_ioctl.af_hwpn,
9229e39c5baSBill Taylor manuf->pn_len);
9239e39c5baSBill Taylor manuf->info.mlx_pn[manuf->pn_len] = 0;
9249e39c5baSBill Taylor
9259e39c5baSBill Taylor logmsg(MSG_INFO, "hermon: HCA PN (%s) PN-Len %d\n",
9269e39c5baSBill Taylor manuf->info.mlx_pn, manuf->pn_len);
9279e39c5baSBill Taylor
9289e39c5baSBill Taylor errno = 0;
9299e39c5baSBill Taylor manuf->info.mlx_psid = calloc(1, MLX_PSID_SZ);
9309e39c5baSBill Taylor if (manuf->info.mlx_psid == NULL) {
9319e39c5baSBill Taylor logmsg(MSG_ERROR, gettext("hermon: PSID calloc "
9329e39c5baSBill Taylor "failed :%s\n"), strerror(errno));
9339e39c5baSBill Taylor goto identify_end;
9349e39c5baSBill Taylor }
9359e39c5baSBill Taylor
9369e39c5baSBill Taylor errno = 0;
9379e39c5baSBill Taylor if ((manuf->info.mlx_id = calloc(1, MLX_STR_ID_SZ)) == NULL) {
9389e39c5baSBill Taylor logmsg(MSG_ERROR, gettext("hermon: "
9399e39c5baSBill Taylor "ID calloc failed (%s)\n"),
9409e39c5baSBill Taylor strerror(errno));
9419e39c5baSBill Taylor goto identify_end;
9429e39c5baSBill Taylor }
9439e39c5baSBill Taylor
9449e39c5baSBill Taylor /* Find part number, set the rest */
9459e39c5baSBill Taylor for (i = 0; i < MLX_MAX_ID; i++) {
9469e39c5baSBill Taylor if (strncmp((const char *)init_ioctl.af_hwpn,
9479e39c5baSBill Taylor mlx_mdr[i].mlx_pn, manuf->pn_len) == 0) {
9489e39c5baSBill Taylor
9499e39c5baSBill Taylor if (hw_psid_found) {
9509e39c5baSBill Taylor logmsg(MSG_INFO, "HW-PSID: %s "
9519e39c5baSBill Taylor "MLX_MDR[%d]: %s\n",
9529e39c5baSBill Taylor manuf->hwfw_img_info.psid, i,
9539e39c5baSBill Taylor mlx_mdr[i].mlx_psid);
9549e39c5baSBill Taylor if (strncmp((const char *)
9559e39c5baSBill Taylor manuf->hwfw_img_info.psid,
9569e39c5baSBill Taylor mlx_mdr[i].mlx_psid,
9579e39c5baSBill Taylor MLX_PSID_SZ) != 0)
9589e39c5baSBill Taylor continue;
9599e39c5baSBill Taylor }
9609e39c5baSBill Taylor /* Set PSID */
9619e39c5baSBill Taylor (void) memcpy(manuf->info.mlx_psid,
9629e39c5baSBill Taylor mlx_mdr[i].mlx_psid, MLX_PSID_SZ);
9639e39c5baSBill Taylor manuf->info.mlx_psid[MLX_PSID_SZ - 1] = 0;
9649e39c5baSBill Taylor
9659e39c5baSBill Taylor logmsg(MSG_INFO, "hermon: HCA PSID (%s)\n",
9669e39c5baSBill Taylor manuf->info.mlx_psid);
9679e39c5baSBill Taylor
9689e39c5baSBill Taylor (void) strlcpy(manuf->info.mlx_id,
9699e39c5baSBill Taylor mlx_mdr[i].mlx_id,
9709e39c5baSBill Taylor strlen(mlx_mdr[i].mlx_id) + 1);
9719e39c5baSBill Taylor
9729e39c5baSBill Taylor logmsg(MSG_INFO, "hermon: HCA Name (%s)\n",
9739e39c5baSBill Taylor manuf->info.mlx_id);
9749e39c5baSBill Taylor
9759e39c5baSBill Taylor break;
9769e39c5baSBill Taylor }
9779e39c5baSBill Taylor }
9789e39c5baSBill Taylor }
9799e39c5baSBill Taylor
9809e39c5baSBill Taylor if ((manuf->pn_len == 0) || (i == MLX_MAX_ID)) {
9819e39c5baSBill Taylor logmsg(MSG_INFO, "hermon: No hardware part number "
9829e39c5baSBill Taylor "information available for this HCA\n");
9839e39c5baSBill Taylor
9849e39c5baSBill Taylor i = strlen("No hardware information available for this device");
9859e39c5baSBill Taylor
9869e39c5baSBill Taylor thisdev->ident->pid = calloc(1, i + 2);
9879e39c5baSBill Taylor sprintf(thisdev->ident->pid, "No additional hardware info "
9889e39c5baSBill Taylor "available for this device");
9899e39c5baSBill Taylor } else {
9909e39c5baSBill Taylor errno = 0;
9919e39c5baSBill Taylor if ((thisdev->ident->pid = calloc(1,
9929e39c5baSBill Taylor strlen(manuf->info.mlx_psid) + 1)) != NULL) {
9939e39c5baSBill Taylor (void) strlcpy(thisdev->ident->pid,
9949e39c5baSBill Taylor manuf->info.mlx_psid,
9959e39c5baSBill Taylor strlen(manuf->info.mlx_psid) + 1);
9969e39c5baSBill Taylor } else {
9979e39c5baSBill Taylor logmsg(MSG_ERROR,
9989e39c5baSBill Taylor gettext("hermon: Unable to allocate space for a "
9999e39c5baSBill Taylor "hardware identifier: %s\n"), strerror(errno));
10009e39c5baSBill Taylor goto identify_end;
10019e39c5baSBill Taylor }
10029e39c5baSBill Taylor }
10039e39c5baSBill Taylor
10049e39c5baSBill Taylor for (i = 0; i < 4; i++) {
10059e39c5baSBill Taylor errno = 0;
10069e39c5baSBill Taylor if ((thisdev->addresses[i] = calloc(1,
10079e39c5baSBill Taylor (2 * sizeof (uint64_t)) + 1)) == NULL) {
10089e39c5baSBill Taylor logmsg(MSG_ERROR,
10099e39c5baSBill Taylor gettext("hermon: Unable to allocate space for a "
10109e39c5baSBill Taylor "human-readable HCA guid: %s\n"), strerror(errno));
10119e39c5baSBill Taylor goto identify_end;
10129e39c5baSBill Taylor }
10139e39c5baSBill Taylor (void) sprintf(thisdev->addresses[i], "%016llx",
10149e39c5baSBill Taylor manuf->ibguids[i]);
10159e39c5baSBill Taylor }
10169e39c5baSBill Taylor
10179e39c5baSBill Taylor /*
10189e39c5baSBill Taylor * We do NOT close the fd here, since we can close it
10199e39c5baSBill Taylor * at the end of the fw_readfw() or fw_writefw() functions
10209e39c5baSBill Taylor * instead and not get the poor dear confused about whether
10219e39c5baSBill Taylor * it's been inited already.
10229e39c5baSBill Taylor */
10239e39c5baSBill Taylor
10249e39c5baSBill Taylor return (FWFLASH_SUCCESS);
10259e39c5baSBill Taylor
10269e39c5baSBill Taylor /* cleanup */
10279e39c5baSBill Taylor identify_end:
10289e39c5baSBill Taylor cnx_close(thisdev);
10299e39c5baSBill Taylor return (FWFLASH_FAILURE);
10309e39c5baSBill Taylor }
10319e39c5baSBill Taylor
10329e39c5baSBill Taylor static int
cnx_get_guids(ib_cnx_encap_ident_t * handle)10339e39c5baSBill Taylor cnx_get_guids(ib_cnx_encap_ident_t *handle)
10349e39c5baSBill Taylor {
10359e39c5baSBill Taylor int i, rv;
10369e39c5baSBill Taylor
10379e39c5baSBill Taylor logmsg(MSG_INFO, "cnx_get_guids\n");
10389e39c5baSBill Taylor
10399e39c5baSBill Taylor /* make sure we've got our fallback position organised */
10409e39c5baSBill Taylor for (i = 0; i < 4; i++) {
10419e39c5baSBill Taylor handle->ibguids[i] = 0x00000000;
10429e39c5baSBill Taylor }
10439e39c5baSBill Taylor
10449e39c5baSBill Taylor rv = cnx_find_magic_n_chnk_sz(handle, FWFLASH_IB_STATE_IMAGE_PRI);
10459e39c5baSBill Taylor if (rv != FWFLASH_SUCCESS) {
10469e39c5baSBill Taylor logmsg(MSG_INFO, "hermon: Failed to get Primary magic number. "
10479e39c5baSBill Taylor "Trying Secondary... \n");
10489e39c5baSBill Taylor rv = cnx_find_magic_n_chnk_sz(handle,
10499e39c5baSBill Taylor FWFLASH_IB_STATE_IMAGE_SEC);
10509e39c5baSBill Taylor if (rv != FWFLASH_SUCCESS) {
10519e39c5baSBill Taylor logmsg(MSG_ERROR, gettext("hermon: Failed to get "
10529e39c5baSBill Taylor "Secondary magic number.\n"));
10539e39c5baSBill Taylor logmsg(MSG_ERROR,
10549e39c5baSBill Taylor gettext("Warning: HCA Firmware corrupt.\n"));
10559e39c5baSBill Taylor return (FWFLASH_FAILURE);
10569e39c5baSBill Taylor }
10579e39c5baSBill Taylor rv = cnx_read_guids(handle, FWFLASH_IB_STATE_IMAGE_SEC);
10589e39c5baSBill Taylor if (rv != FWFLASH_SUCCESS) {
10599e39c5baSBill Taylor logmsg(MSG_ERROR, gettext("hermon: Failed to read "
10609e39c5baSBill Taylor "secondary guids.\n"));
10619e39c5baSBill Taylor return (FWFLASH_FAILURE);
10629e39c5baSBill Taylor }
10639e39c5baSBill Taylor } else {
10649e39c5baSBill Taylor rv = cnx_read_guids(handle, FWFLASH_IB_STATE_IMAGE_PRI);
10659e39c5baSBill Taylor if (rv != FWFLASH_SUCCESS) {
10669e39c5baSBill Taylor logmsg(MSG_ERROR, gettext("hermon: Failed to read "
10679e39c5baSBill Taylor "primary guids.\n"));
10689e39c5baSBill Taylor return (FWFLASH_FAILURE);
10699e39c5baSBill Taylor }
10709e39c5baSBill Taylor }
10719e39c5baSBill Taylor for (i = 0; i < 4; i++) {
10729e39c5baSBill Taylor logmsg(MSG_INFO, "hermon: ibguids[%d] 0x%016llx\n", i,
10739e39c5baSBill Taylor handle->ibguids[i]);
10749e39c5baSBill Taylor }
10759e39c5baSBill Taylor for (i = 0; i < 2; i++) {
10769e39c5baSBill Taylor logmsg(MSG_INFO, "hermon: ib_portmac[%d] 0x%016llx\n", i,
10779e39c5baSBill Taylor handle->ib_mac[i]);
10789e39c5baSBill Taylor }
10799e39c5baSBill Taylor
10809e39c5baSBill Taylor return (FWFLASH_SUCCESS);
10819e39c5baSBill Taylor }
10829e39c5baSBill Taylor
10839e39c5baSBill Taylor static int
cnx_close(struct devicelist * flashdev)10849e39c5baSBill Taylor cnx_close(struct devicelist *flashdev)
10859e39c5baSBill Taylor {
10869e39c5baSBill Taylor ib_cnx_encap_ident_t *handle;
10879e39c5baSBill Taylor
10889e39c5baSBill Taylor logmsg(MSG_INFO, "cnx_close\n");
10899e39c5baSBill Taylor
10909e39c5baSBill Taylor handle = (ib_cnx_encap_ident_t *)flashdev->ident->encap_ident;
10919e39c5baSBill Taylor
10929e39c5baSBill Taylor if (CNX_I_CHECK_HANDLE(handle)) {
10939e39c5baSBill Taylor logmsg(MSG_ERROR, gettext("hermon: Invalid Handle to close "
10949e39c5baSBill Taylor "device %s! \n"), flashdev->access_devname);
10959e39c5baSBill Taylor return (FWFLASH_FAILURE);
10969e39c5baSBill Taylor }
10979e39c5baSBill Taylor
10989e39c5baSBill Taylor if (handle->fd > 0) {
10999e39c5baSBill Taylor errno = 0;
11009e39c5baSBill Taylor (void) ioctl(handle->fd, HERMON_IOCTL_FLASH_FINI);
11019e39c5baSBill Taylor if (close(handle->fd) != 0) {
11029e39c5baSBill Taylor logmsg(MSG_ERROR, gettext("hermon: Unable to properly "
11039e39c5baSBill Taylor "close device %s! (%s)\n"),
11049e39c5baSBill Taylor flashdev->access_devname, strerror(errno));
11059e39c5baSBill Taylor return (FWFLASH_FAILURE);
11069e39c5baSBill Taylor }
11079e39c5baSBill Taylor }
11089e39c5baSBill Taylor
11099e39c5baSBill Taylor if (handle != NULL) {
11109e39c5baSBill Taylor if (handle->info.mlx_id != NULL)
11119e39c5baSBill Taylor free(handle->info.mlx_id);
11129e39c5baSBill Taylor
11139e39c5baSBill Taylor if (handle->info.mlx_psid != NULL)
11149e39c5baSBill Taylor free(handle->info.mlx_psid);
11159e39c5baSBill Taylor
11169e39c5baSBill Taylor if (handle->fw != NULL)
11179e39c5baSBill Taylor free(handle->fw);
11189e39c5baSBill Taylor free(handle);
11199e39c5baSBill Taylor }
11209e39c5baSBill Taylor
11219e39c5baSBill Taylor if (flashdev->ident->vid != NULL)
11229e39c5baSBill Taylor free(flashdev->ident->vid);
11239e39c5baSBill Taylor
11249e39c5baSBill Taylor if (flashdev->ident->revid != NULL)
11259e39c5baSBill Taylor free(flashdev->ident->revid);
11269e39c5baSBill Taylor
11279e39c5baSBill Taylor return (FWFLASH_SUCCESS);
11289e39c5baSBill Taylor }
11299e39c5baSBill Taylor
11309e39c5baSBill Taylor
11319e39c5baSBill Taylor /*
11329e39c5baSBill Taylor * Driver read/write ioctl calls.
11339e39c5baSBill Taylor */
11349e39c5baSBill Taylor static int
cnx_read_ioctl(ib_cnx_encap_ident_t * hdl,hermon_flash_ioctl_t * info)11359e39c5baSBill Taylor cnx_read_ioctl(ib_cnx_encap_ident_t *hdl, hermon_flash_ioctl_t *info)
11369e39c5baSBill Taylor {
11379e39c5baSBill Taylor int ret;
11389e39c5baSBill Taylor
11399e39c5baSBill Taylor #ifdef CNX_DEBUG
11409e39c5baSBill Taylor logmsg(MSG_INFO, "cnx_read_ioctl: fd %d af_type 0x%x af_addr 0x%x "
11419e39c5baSBill Taylor "af_sector_num(0x%x)\n", hdl->fd, info->af_type,
11429e39c5baSBill Taylor info->af_addr, info->af_sector_num);
11439e39c5baSBill Taylor #endif
11449e39c5baSBill Taylor
11459e39c5baSBill Taylor errno = 0;
11469e39c5baSBill Taylor ret = ioctl(hdl->fd, HERMON_IOCTL_FLASH_READ, info);
11479e39c5baSBill Taylor if (ret != 0) {
11489e39c5baSBill Taylor logmsg(MSG_ERROR, gettext("HERMON_IOCTL_FLASH_READ failed "
11499e39c5baSBill Taylor "(%s)\n"), strerror(errno));
11509e39c5baSBill Taylor }
11519e39c5baSBill Taylor return (ret);
11529e39c5baSBill Taylor }
11539e39c5baSBill Taylor
11549e39c5baSBill Taylor static int
cnx_write_ioctl(ib_cnx_encap_ident_t * hdl,hermon_flash_ioctl_t * info)11559e39c5baSBill Taylor cnx_write_ioctl(ib_cnx_encap_ident_t *hdl, hermon_flash_ioctl_t *info)
11569e39c5baSBill Taylor {
11579e39c5baSBill Taylor int ret;
11589e39c5baSBill Taylor
11599e39c5baSBill Taylor #ifdef CNX_DEBUG
11609e39c5baSBill Taylor logmsg(MSG_INFO, "cnx_write_ioctl: fd(%d) af_type(0x%x) "
11619e39c5baSBill Taylor "af_addr(0x%x) af_sector_num(0x%x) af_byte(0x%x)\n",
11629e39c5baSBill Taylor hdl->fd, info->af_type, info->af_addr, info->af_sector_num,
11639e39c5baSBill Taylor info->af_byte);
11649e39c5baSBill Taylor #endif
11659e39c5baSBill Taylor errno = 0;
11669e39c5baSBill Taylor ret = ioctl(hdl->fd, HERMON_IOCTL_FLASH_WRITE, info);
11679e39c5baSBill Taylor if (ret != 0) {
11689e39c5baSBill Taylor logmsg(MSG_ERROR, gettext("HERMON_IOCTL_FLASH_WRITE "
11699e39c5baSBill Taylor "failed (%s)\n"), strerror(errno));
11709e39c5baSBill Taylor }
11719e39c5baSBill Taylor return (ret);
11729e39c5baSBill Taylor }
11739e39c5baSBill Taylor
11749e39c5baSBill Taylor static int
cnx_erase_sector_ioctl(ib_cnx_encap_ident_t * hdl,hermon_flash_ioctl_t * info)11759e39c5baSBill Taylor cnx_erase_sector_ioctl(ib_cnx_encap_ident_t *hdl, hermon_flash_ioctl_t *info)
11769e39c5baSBill Taylor {
11779e39c5baSBill Taylor int ret;
11789e39c5baSBill Taylor
11799e39c5baSBill Taylor #ifdef CNX_DEBUG
11809e39c5baSBill Taylor logmsg(MSG_INFO, "cnx_erase_sector_ioctl: fd(%d) af_type(0x%x) "
11819e39c5baSBill Taylor "af_sector_num(0x%x)\n", hdl->fd, info->af_type,
11829e39c5baSBill Taylor info->af_sector_num);
11839e39c5baSBill Taylor #endif
11849e39c5baSBill Taylor errno = 0;
11859e39c5baSBill Taylor ret = ioctl(hdl->fd, HERMON_IOCTL_FLASH_ERASE, info);
11869e39c5baSBill Taylor if (ret != 0) {
11879e39c5baSBill Taylor logmsg(MSG_ERROR, gettext("HERMON_IOCTL_FLASH_ERASE "
11889e39c5baSBill Taylor "failed (%s)\n"), strerror(errno));
11899e39c5baSBill Taylor }
11909e39c5baSBill Taylor return (ret);
11919e39c5baSBill Taylor }
11929e39c5baSBill Taylor
11939e39c5baSBill Taylor /*
11949e39c5baSBill Taylor * cnx_crc16 - computes 16 bit crc of supplied buffer.
11959e39c5baSBill Taylor * image should be in network byteorder
11969e39c5baSBill Taylor * result is returned in host byteorder form
11979e39c5baSBill Taylor */
11989e39c5baSBill Taylor uint16_t
cnx_crc16(uint8_t * image,uint32_t size,int is_image)11999e39c5baSBill Taylor cnx_crc16(uint8_t *image, uint32_t size, int is_image)
12009e39c5baSBill Taylor {
12019e39c5baSBill Taylor const uint16_t poly = 0x100b;
12029e39c5baSBill Taylor uint32_t crc = 0xFFFF;
12039e39c5baSBill Taylor uint32_t word;
12049e39c5baSBill Taylor uint32_t i, j;
12059e39c5baSBill Taylor
12069e39c5baSBill Taylor logmsg(MSG_INFO, "hermon: cnx_crc16\n");
12079e39c5baSBill Taylor
12089e39c5baSBill Taylor for (i = 0; i < size / 4; i++) {
12099e39c5baSBill Taylor word = (image[4 * i] << 24) |
12109e39c5baSBill Taylor (image[4 * i + 1] << 16) |
12119e39c5baSBill Taylor (image[4 * i + 2] << 8) |
12129e39c5baSBill Taylor (image[4 * i + 3]);
12139e39c5baSBill Taylor
12149e39c5baSBill Taylor if (is_image == CNX_HW_IMG)
12159e39c5baSBill Taylor word = MLXSWAPBITS32(word);
12169e39c5baSBill Taylor
12179e39c5baSBill Taylor for (j = 0; j < 32; j++) {
12189e39c5baSBill Taylor if (crc & 0x8000) {
12199e39c5baSBill Taylor crc = (((crc << 1) |
12209e39c5baSBill Taylor (word >> 31)) ^ poly) & 0xFFFF;
12219e39c5baSBill Taylor } else {
12229e39c5baSBill Taylor crc = ((crc << 1) | (word >> 31)) & 0xFFFF;
12239e39c5baSBill Taylor }
12249e39c5baSBill Taylor word = (word << 1) & 0xFFFFFFFF;
12259e39c5baSBill Taylor }
12269e39c5baSBill Taylor }
12279e39c5baSBill Taylor
12289e39c5baSBill Taylor for (i = 0; i < 16; i++) {
12299e39c5baSBill Taylor if (crc & 0x8000) {
12309e39c5baSBill Taylor crc = ((crc << 1) ^ poly) & 0xFFFF;
12319e39c5baSBill Taylor } else {
12329e39c5baSBill Taylor crc = (crc << 1) & 0xFFFF;
12339e39c5baSBill Taylor }
12349e39c5baSBill Taylor }
12359e39c5baSBill Taylor
12369e39c5baSBill Taylor crc = crc ^ 0xFFFF;
12379e39c5baSBill Taylor return (crc & 0xFFFF);
12389e39c5baSBill Taylor }
12399e39c5baSBill Taylor
12409e39c5baSBill Taylor static void
cnx_local_set_guid_crc_img(uint32_t offset,uint32_t guid_crc_size,uint32_t guid_crc_offset)12419e39c5baSBill Taylor cnx_local_set_guid_crc_img(uint32_t offset, uint32_t guid_crc_size,
12429e39c5baSBill Taylor uint32_t guid_crc_offset)
12439e39c5baSBill Taylor {
12449e39c5baSBill Taylor uint16_t crc;
12459e39c5baSBill Taylor uint8_t *fw_p = (uint8_t *)&verifier->fwimage[0];
12469e39c5baSBill Taylor
12479e39c5baSBill Taylor crc = htons(cnx_crc16((uint8_t *)&verifier->fwimage[offset / 4],
12489e39c5baSBill Taylor guid_crc_size, CNX_FILE_IMG));
12499e39c5baSBill Taylor
12509e39c5baSBill Taylor logmsg(MSG_INFO, "cnx_local_set_guid_crc_img: new guid_sect crc: %x\n",
12519e39c5baSBill Taylor ntohs(crc));
12529e39c5baSBill Taylor (void) memcpy(&fw_p[offset + guid_crc_offset], &crc, 2);
12539e39c5baSBill Taylor }
12549e39c5baSBill Taylor
12559e39c5baSBill Taylor /*
12569e39c5baSBill Taylor * Address translation functions for ConnectX
12579e39c5baSBill Taylor * Variable definitions:
12589e39c5baSBill Taylor * - log2_chunk_size: log2 of a Flash chunk size
12599e39c5baSBill Taylor * - cont_addr: a contiguous image address to be translated
12609e39c5baSBill Taylor * - is_image_in_odd_chunk: When this bit is 1, it indicates the new image is
12619e39c5baSBill Taylor * stored in odd chunks of the Flash.
12629e39c5baSBill Taylor */
12639e39c5baSBill Taylor static uint32_t
cnx_cont2phys(uint32_t log2_chunk_size,uint32_t cont_addr,int type)12649e39c5baSBill Taylor cnx_cont2phys(uint32_t log2_chunk_size, uint32_t cont_addr, int type)
12659e39c5baSBill Taylor {
12669e39c5baSBill Taylor uint32_t result;
12679e39c5baSBill Taylor int is_image_in_odd_chunks;
12689e39c5baSBill Taylor
12699e39c5baSBill Taylor is_image_in_odd_chunks = type - 1;
12709e39c5baSBill Taylor
12719e39c5baSBill Taylor if (log2_chunk_size) {
12729e39c5baSBill Taylor result = cont_addr & (0xffffffff >> (32 - log2_chunk_size)) |
12739e39c5baSBill Taylor (is_image_in_odd_chunks << log2_chunk_size) |
12749e39c5baSBill Taylor (cont_addr << 1) & (0xffffffff << (log2_chunk_size + 1));
12759e39c5baSBill Taylor } else {
12769e39c5baSBill Taylor result = cont_addr;
12779e39c5baSBill Taylor }
12789e39c5baSBill Taylor
12799e39c5baSBill Taylor return (result);
12809e39c5baSBill Taylor }
12819e39c5baSBill Taylor
12829e39c5baSBill Taylor static int
cnx_read_guids(ib_cnx_encap_ident_t * handle,int type)12839e39c5baSBill Taylor cnx_read_guids(ib_cnx_encap_ident_t *handle, int type)
12849e39c5baSBill Taylor {
12859e39c5baSBill Taylor #ifdef _LITTLE_ENDIAN
12869e39c5baSBill Taylor uint32_t *ptr, tmp;
12879e39c5baSBill Taylor #endif
12889e39c5baSBill Taylor hermon_flash_ioctl_t ioctl_info;
12899e39c5baSBill Taylor uint32_t *guids;
12909e39c5baSBill Taylor uint32_t *ibmac;
12919e39c5baSBill Taylor int ret, i;
12929e39c5baSBill Taylor uint32_t nguidptr_addr;
12939e39c5baSBill Taylor union {
12949e39c5baSBill Taylor uint8_t bytes[4];
12959e39c5baSBill Taylor uint32_t dword;
12969e39c5baSBill Taylor } crc16_u;
12979e39c5baSBill Taylor uint32_t *guid_structure;
12989e39c5baSBill Taylor uint16_t crc;
12999e39c5baSBill Taylor
13009e39c5baSBill Taylor logmsg(MSG_INFO, "cnx_read_guids\n");
13019e39c5baSBill Taylor
13029e39c5baSBill Taylor errno = 0;
13039e39c5baSBill Taylor guid_structure = (uint32_t *)calloc(1,
13049e39c5baSBill Taylor CNX_GUID_CRC16_SIZE / 4 * sizeof (uint32_t));
13059e39c5baSBill Taylor if (guid_structure == NULL) {
13069e39c5baSBill Taylor logmsg(MSG_WARN, gettext("hermon: Can't calloc guid_structure "
13079e39c5baSBill Taylor ": (%s)\n"), strerror(errno));
13089e39c5baSBill Taylor return (FWFLASH_FAILURE);
13099e39c5baSBill Taylor }
13109e39c5baSBill Taylor
13119e39c5baSBill Taylor ioctl_info.af_type = HERMON_FLASH_READ_QUADLET;
13129e39c5baSBill Taylor ioctl_info.af_addr = cnx_cont2phys(handle->log2_chunk_sz,
13139e39c5baSBill Taylor CNX_NGUIDPTR_OFFSET, type);
13149e39c5baSBill Taylor
13159e39c5baSBill Taylor ret = cnx_read_ioctl(handle, &ioctl_info);
13169e39c5baSBill Taylor if (ret != 0) {
13179e39c5baSBill Taylor logmsg(MSG_WARN, gettext("hermon: Failed to read GUID Pointer "
13189e39c5baSBill Taylor "Address\n"));
13199e39c5baSBill Taylor goto out;
13209e39c5baSBill Taylor }
13219e39c5baSBill Taylor
13229e39c5baSBill Taylor guids = (uint32_t *)&handle->ibguids[0];
13239e39c5baSBill Taylor ibmac = (uint32_t *)&handle->ib_mac[0];
13249e39c5baSBill Taylor nguidptr_addr = cnx_cont2phys(handle->log2_chunk_sz,
13259e39c5baSBill Taylor ioctl_info.af_quadlet, type);
13269e39c5baSBill Taylor
13279e39c5baSBill Taylor logmsg(MSG_INFO, "NGUIDPTR: 0x%08x \n", nguidptr_addr);
13289e39c5baSBill Taylor /* Read in the entire guid section in order to calculate the CRC */
13299e39c5baSBill Taylor ioctl_info.af_addr = nguidptr_addr - 0x10;
13309e39c5baSBill Taylor ioctl_info.af_type = HERMON_FLASH_READ_QUADLET;
13319e39c5baSBill Taylor
13329e39c5baSBill Taylor for (i = 0; i < CNX_GUID_CRC16_SIZE / 4; i++) {
13339e39c5baSBill Taylor ret = cnx_read_ioctl(handle, &ioctl_info);
13349e39c5baSBill Taylor if (ret != 0) {
13359e39c5baSBill Taylor logmsg(MSG_INFO, "Failed to read guid_structure "
13369e39c5baSBill Taylor "(0x%x)\n", i);
13379e39c5baSBill Taylor goto out;
13389e39c5baSBill Taylor }
13399e39c5baSBill Taylor
13409e39c5baSBill Taylor if (i >= 4 && i < 12) {
13419e39c5baSBill Taylor guids[i - 4] = ioctl_info.af_quadlet;
13429e39c5baSBill Taylor }
13439e39c5baSBill Taylor if (i >= 12 && i < 16) {
13449e39c5baSBill Taylor ibmac[i - 12] = ioctl_info.af_quadlet;
13459e39c5baSBill Taylor }
13469e39c5baSBill Taylor
13479e39c5baSBill Taylor guid_structure[i] = ioctl_info.af_quadlet;
13489e39c5baSBill Taylor ioctl_info.af_addr += 4;
13499e39c5baSBill Taylor }
13509e39c5baSBill Taylor
13519e39c5baSBill Taylor for (i = 0; i < CNX_GUID_CRC16_SIZE / 4; i++) {
13529e39c5baSBill Taylor logmsg(MSG_INFO, "guid_structure[%x] = 0x%08x\n", i,
13539e39c5baSBill Taylor guid_structure[i]);
13549e39c5baSBill Taylor }
13559e39c5baSBill Taylor
13569e39c5baSBill Taylor /*
13579e39c5baSBill Taylor * Check the CRC--make sure it computes.
13589e39c5baSBill Taylor */
13599e39c5baSBill Taylor
13609e39c5baSBill Taylor /* 0x12 subtracted: 0x2 for alignment, 0x10 to reach structure start */
13619e39c5baSBill Taylor ioctl_info.af_addr = nguidptr_addr + CNX_GUID_CRC16_OFFSET - 0x12;
13629e39c5baSBill Taylor ioctl_info.af_type = HERMON_FLASH_READ_QUADLET;
13639e39c5baSBill Taylor
13649e39c5baSBill Taylor ret = cnx_read_ioctl(handle, &ioctl_info);
13659e39c5baSBill Taylor if (ret != 0) {
13669e39c5baSBill Taylor logmsg(MSG_WARN, gettext("hermon: Failed to read guid crc "
13679e39c5baSBill Taylor "at 0x%x\n"), ioctl_info.af_addr);
13689e39c5baSBill Taylor goto out;
13699e39c5baSBill Taylor }
13709e39c5baSBill Taylor
13719e39c5baSBill Taylor crc16_u.dword = ioctl_info.af_quadlet;
13729e39c5baSBill Taylor crc = cnx_crc16((uint8_t *)guid_structure, CNX_GUID_CRC16_SIZE,
13739e39c5baSBill Taylor CNX_HW_IMG);
13749e39c5baSBill Taylor
13759e39c5baSBill Taylor if (crc != crc16_u.dword) {
13769e39c5baSBill Taylor logmsg(MSG_WARN, gettext("hermon: calculated crc16: 0x%x "
13779e39c5baSBill Taylor "differs from GUID section 0x%x\n"), crc, crc16_u.dword);
13789e39c5baSBill Taylor } else {
13799e39c5baSBill Taylor logmsg(MSG_INFO, "hermon: calculated crc16: 0x%x MATCHES with "
13809e39c5baSBill Taylor "GUID section 0x%x\n", crc, crc16_u.dword);
13819e39c5baSBill Taylor }
13829e39c5baSBill Taylor
13839e39c5baSBill Taylor #ifdef _LITTLE_ENDIAN
13849e39c5baSBill Taylor /*
13859e39c5baSBill Taylor * guids are read as pairs of 32 bit host byteorder values and treated
13869e39c5baSBill Taylor * by callers as 64 bit values. So swap each pair of 32 bit values
13879e39c5baSBill Taylor * to make them correct
13889e39c5baSBill Taylor */
13899e39c5baSBill Taylor ptr = (uint32_t *)guids;
13909e39c5baSBill Taylor for (ret = 0; ret < 8; ret += 2) {
13919e39c5baSBill Taylor tmp = ptr[ret];
13929e39c5baSBill Taylor ptr[ret] = ptr[ret+1];
13939e39c5baSBill Taylor ptr[ret+1] = tmp;
13949e39c5baSBill Taylor }
13959e39c5baSBill Taylor ptr = (uint32_t *)&handle->ib_mac[0];
13969e39c5baSBill Taylor for (ret = 0; ret < 4; ret += 2) {
13979e39c5baSBill Taylor tmp = ptr[ret];
13989e39c5baSBill Taylor ptr[ret] = ptr[ret+1];
13999e39c5baSBill Taylor ptr[ret+1] = tmp;
14009e39c5baSBill Taylor }
14019e39c5baSBill Taylor #endif
14029e39c5baSBill Taylor ret = FWFLASH_SUCCESS;
14039e39c5baSBill Taylor
14049e39c5baSBill Taylor out:
14059e39c5baSBill Taylor free(guid_structure);
14069e39c5baSBill Taylor return (ret);
14079e39c5baSBill Taylor }
14089e39c5baSBill Taylor
14099e39c5baSBill Taylor static int
cnx_find_magic_n_chnk_sz(ib_cnx_encap_ident_t * handle,int type)14109e39c5baSBill Taylor cnx_find_magic_n_chnk_sz(ib_cnx_encap_ident_t *handle, int type)
14119e39c5baSBill Taylor {
14129e39c5baSBill Taylor int i, found = 0;
14139e39c5baSBill Taylor uint32_t addr;
14149e39c5baSBill Taylor uint32_t boot_addresses[] =
14159e39c5baSBill Taylor {0, 0x10000, 0x20000, 0x40000, 0x80000, 0x100000};
14169e39c5baSBill Taylor
14179e39c5baSBill Taylor logmsg(MSG_INFO, "cnx_find_magic_n_chnk_sz\n");
14189e39c5baSBill Taylor
14199e39c5baSBill Taylor switch (type) {
14209e39c5baSBill Taylor case FWFLASH_IB_STATE_IMAGE_PRI:
14219e39c5baSBill Taylor addr = 0;
14229e39c5baSBill Taylor if (cnx_check_for_magic_pattern(handle, addr) !=
14239e39c5baSBill Taylor FWFLASH_SUCCESS) {
14249e39c5baSBill Taylor goto err;
14259e39c5baSBill Taylor }
14269e39c5baSBill Taylor break;
14279e39c5baSBill Taylor
14289e39c5baSBill Taylor case FWFLASH_IB_STATE_IMAGE_SEC:
14299e39c5baSBill Taylor for (i = 1; i < 6; i++) {
14309e39c5baSBill Taylor addr = boot_addresses[i];
14319e39c5baSBill Taylor if (cnx_check_for_magic_pattern(handle, addr) ==
14329e39c5baSBill Taylor FWFLASH_SUCCESS) {
14339e39c5baSBill Taylor found = 1;
14349e39c5baSBill Taylor break;
14359e39c5baSBill Taylor }
14369e39c5baSBill Taylor }
14379e39c5baSBill Taylor if (!found) {
14389e39c5baSBill Taylor goto err;
14399e39c5baSBill Taylor }
14409e39c5baSBill Taylor break;
14419e39c5baSBill Taylor
14429e39c5baSBill Taylor default:
14439e39c5baSBill Taylor logmsg(MSG_INFO, "cnx_find_magic_pattern: unknown type\n");
14449e39c5baSBill Taylor goto err;
14459e39c5baSBill Taylor }
14469e39c5baSBill Taylor
14479e39c5baSBill Taylor logmsg(MSG_INFO, "magic_pattern found at addr %x\n", addr);
14489e39c5baSBill Taylor handle->img2_start_addr = addr;
14499e39c5baSBill Taylor
14509e39c5baSBill Taylor handle->log2_chunk_sz = cnx_get_log2_chunk_size_f_hdl(handle, type);
14519e39c5baSBill Taylor if (handle->log2_chunk_sz == 0) {
14529e39c5baSBill Taylor logmsg(MSG_INFO, "no chunk size found for type %x. "
14539e39c5baSBill Taylor "Assuming non-failsafe burn\n", type);
14549e39c5baSBill Taylor }
14559e39c5baSBill Taylor
14569e39c5baSBill Taylor handle->fw_sz = cnx_get_image_size_f_hdl(handle, type);
14579e39c5baSBill Taylor if (handle->fw_sz == 0) {
14589e39c5baSBill Taylor logmsg(MSG_INFO, "no fw size found for type %x. \n", type);
14599e39c5baSBill Taylor }
14609e39c5baSBill Taylor handle->state |= type;
14619e39c5baSBill Taylor
14629e39c5baSBill Taylor return (FWFLASH_SUCCESS);
14639e39c5baSBill Taylor err:
14649e39c5baSBill Taylor logmsg(MSG_INFO, "no magic_pattern found for type %x\n", type);
14659e39c5baSBill Taylor return (FWFLASH_FAILURE);
14669e39c5baSBill Taylor }
14679e39c5baSBill Taylor
14689e39c5baSBill Taylor static int
cnx_check_for_magic_pattern(ib_cnx_encap_ident_t * handle,uint32_t addr)14699e39c5baSBill Taylor cnx_check_for_magic_pattern(ib_cnx_encap_ident_t *handle, uint32_t addr)
14709e39c5baSBill Taylor {
14719e39c5baSBill Taylor int i;
14729e39c5baSBill Taylor hermon_flash_ioctl_t ioctl_info;
14739e39c5baSBill Taylor int magic_pattern_buf[4];
14749e39c5baSBill Taylor
14759e39c5baSBill Taylor logmsg(MSG_INFO, "cnx_check_for_magic_pattern\n");
14769e39c5baSBill Taylor
14779e39c5baSBill Taylor ioctl_info.af_type = HERMON_FLASH_READ_QUADLET;
14789e39c5baSBill Taylor
14799e39c5baSBill Taylor for (i = 0; i < 4; i++) {
14809e39c5baSBill Taylor ioctl_info.af_addr = addr + (i * sizeof (uint32_t));
14819e39c5baSBill Taylor if (cnx_read_ioctl(handle, &ioctl_info) != 0) {
14829e39c5baSBill Taylor logmsg(MSG_INFO, "\nFailed to read magic pattern\n");
14839e39c5baSBill Taylor return (FWFLASH_FAILURE);
14849e39c5baSBill Taylor }
14859e39c5baSBill Taylor
14869e39c5baSBill Taylor magic_pattern_buf[i] = ioctl_info.af_quadlet;
14879e39c5baSBill Taylor }
14889e39c5baSBill Taylor
14899e39c5baSBill Taylor return (cnx_is_magic_pattern_present(magic_pattern_buf, CNX_HW_IMG));
14909e39c5baSBill Taylor
14919e39c5baSBill Taylor }
14929e39c5baSBill Taylor
14939e39c5baSBill Taylor int
cnx_is_magic_pattern_present(int * data,int is_image)14949e39c5baSBill Taylor cnx_is_magic_pattern_present(int *data, int is_image)
14959e39c5baSBill Taylor {
14969e39c5baSBill Taylor int i;
14979e39c5baSBill Taylor int dword;
14989e39c5baSBill Taylor
14999e39c5baSBill Taylor logmsg(MSG_INFO, "cnx_is_magic_pattern_present\n");
15009e39c5baSBill Taylor
15019e39c5baSBill Taylor for (i = 0; i < 4; i++) {
15029e39c5baSBill Taylor if (is_image == CNX_FILE_IMG)
15039e39c5baSBill Taylor dword = MLXSWAPBITS32(data[i]);
15049e39c5baSBill Taylor else
15059e39c5baSBill Taylor dword = data[i];
15069e39c5baSBill Taylor logmsg(MSG_INFO, "local_quadlet: %08x, magic pattern: %08x\n",
15079e39c5baSBill Taylor dword, cnx_magic_pattern[i]);
15089e39c5baSBill Taylor if (dword != cnx_magic_pattern[i]) {
15099e39c5baSBill Taylor return (FWFLASH_FAILURE);
15109e39c5baSBill Taylor }
15119e39c5baSBill Taylor }
15129e39c5baSBill Taylor
15139e39c5baSBill Taylor return (FWFLASH_SUCCESS);
15149e39c5baSBill Taylor }
15159e39c5baSBill Taylor
15169e39c5baSBill Taylor static uint32_t
cnx_get_log2_chunk_size_f_hdl(ib_cnx_encap_ident_t * handle,int type)15179e39c5baSBill Taylor cnx_get_log2_chunk_size_f_hdl(ib_cnx_encap_ident_t *handle, int type)
15189e39c5baSBill Taylor {
15199e39c5baSBill Taylor hermon_flash_ioctl_t ioctl_info;
15209e39c5baSBill Taylor int ret;
15219e39c5baSBill Taylor
15229e39c5baSBill Taylor logmsg(MSG_INFO, "cnx_get_log2_chunk_size_f_hdl\n");
15239e39c5baSBill Taylor
15249e39c5baSBill Taylor /* If chunk size is already set, just return it. */
15259e39c5baSBill Taylor if (handle->log2_chunk_sz) {
15269e39c5baSBill Taylor return (handle->log2_chunk_sz);
15279e39c5baSBill Taylor }
15289e39c5baSBill Taylor
15299e39c5baSBill Taylor switch (type) {
15309e39c5baSBill Taylor case FWFLASH_IB_STATE_IMAGE_PRI:
15319e39c5baSBill Taylor ioctl_info.af_addr = CNX_CHUNK_SIZE_OFFSET;
15329e39c5baSBill Taylor break;
15339e39c5baSBill Taylor case FWFLASH_IB_STATE_IMAGE_SEC:
15349e39c5baSBill Taylor ioctl_info.af_addr =
15359e39c5baSBill Taylor handle->img2_start_addr + CNX_CHUNK_SIZE_OFFSET;
15369e39c5baSBill Taylor break;
15379e39c5baSBill Taylor default:
15389e39c5baSBill Taylor logmsg(MSG_INFO,
15399e39c5baSBill Taylor "cnx_get_log2_chunk_size_f_hdl: unknown type\n");
15409e39c5baSBill Taylor return (0);
15419e39c5baSBill Taylor }
15429e39c5baSBill Taylor
15439e39c5baSBill Taylor ioctl_info.af_type = HERMON_FLASH_READ_QUADLET;
15449e39c5baSBill Taylor
15459e39c5baSBill Taylor ret = cnx_read_ioctl(handle, &ioctl_info);
15469e39c5baSBill Taylor if (ret != 0) {
15479e39c5baSBill Taylor logmsg(MSG_INFO, "\nFailed to read chunk size\n");
15489e39c5baSBill Taylor return (0);
15499e39c5baSBill Taylor }
15509e39c5baSBill Taylor
15519e39c5baSBill Taylor return (cnx_get_log2_chunk_size(ioctl_info.af_quadlet));
15529e39c5baSBill Taylor }
15539e39c5baSBill Taylor
15549e39c5baSBill Taylor
15559e39c5baSBill Taylor static uint32_t
cnx_get_log2_chunk_size(uint32_t chunk_size_word)15569e39c5baSBill Taylor cnx_get_log2_chunk_size(uint32_t chunk_size_word)
15579e39c5baSBill Taylor {
15589e39c5baSBill Taylor uint8_t checksum;
15599e39c5baSBill Taylor uint32_t log2_chunk_size;
15609e39c5baSBill Taylor
15619e39c5baSBill Taylor logmsg(MSG_INFO, "cnx_get_log2_chunk_size: chunk_size_word:"
15629e39c5baSBill Taylor " 0x%x\n", chunk_size_word);
15639e39c5baSBill Taylor
15649e39c5baSBill Taylor checksum =
15659e39c5baSBill Taylor (chunk_size_word & 0xff) +
15669e39c5baSBill Taylor ((chunk_size_word >> 8) & 0xff) +
15679e39c5baSBill Taylor ((chunk_size_word >> 16) & 0xff) +
15689e39c5baSBill Taylor ((chunk_size_word >> 24) & 0xff);
15699e39c5baSBill Taylor
15709e39c5baSBill Taylor if (checksum != 0) {
15719e39c5baSBill Taylor logmsg(MSG_INFO, "Corrupted chunk size checksum\n");
15729e39c5baSBill Taylor return (0);
15739e39c5baSBill Taylor }
15749e39c5baSBill Taylor
15759e39c5baSBill Taylor if (chunk_size_word & 0x8) {
15769e39c5baSBill Taylor log2_chunk_size = (chunk_size_word & 0x7) + 16;
15779e39c5baSBill Taylor logmsg(MSG_INFO, "log2 chunk size: 0x%x\n", log2_chunk_size);
15789e39c5baSBill Taylor return (log2_chunk_size);
15799e39c5baSBill Taylor } else {
15809e39c5baSBill Taylor return (0);
15819e39c5baSBill Taylor }
15829e39c5baSBill Taylor }
15839e39c5baSBill Taylor
15849e39c5baSBill Taylor static uint32_t
cnx_get_image_size_f_hdl(ib_cnx_encap_ident_t * handle,int type)15859e39c5baSBill Taylor cnx_get_image_size_f_hdl(ib_cnx_encap_ident_t *handle, int type)
15869e39c5baSBill Taylor {
15879e39c5baSBill Taylor hermon_flash_ioctl_t ioctl_info;
15889e39c5baSBill Taylor int ret;
15899e39c5baSBill Taylor
15909e39c5baSBill Taylor logmsg(MSG_INFO, "cnx_get_image_size_f_hdl\n");
15919e39c5baSBill Taylor
15929e39c5baSBill Taylor ioctl_info.af_addr = cnx_cont2phys(handle->log2_chunk_sz,
15939e39c5baSBill Taylor CNX_IMG_SIZE_OFFSET, type);
15949e39c5baSBill Taylor ioctl_info.af_type = HERMON_FLASH_READ_QUADLET;
15959e39c5baSBill Taylor
15969e39c5baSBill Taylor ret = cnx_read_ioctl(handle, &ioctl_info);
15979e39c5baSBill Taylor if (ret != 0) {
15989e39c5baSBill Taylor logmsg(MSG_INFO, "Failed to read image size\n");
15999e39c5baSBill Taylor return (0);
16009e39c5baSBill Taylor }
16019e39c5baSBill Taylor
16029e39c5baSBill Taylor logmsg(MSG_INFO, "Image Size: 0x%x\n", ioctl_info.af_quadlet);
16039e39c5baSBill Taylor
16049e39c5baSBill Taylor return (ioctl_info.af_quadlet);
16059e39c5baSBill Taylor }
16069e39c5baSBill Taylor
16079e39c5baSBill Taylor static int
cnx_get_image_info(ib_cnx_encap_ident_t * handle)16089e39c5baSBill Taylor cnx_get_image_info(ib_cnx_encap_ident_t *handle)
16099e39c5baSBill Taylor {
16109e39c5baSBill Taylor uint32_t ii_ptr_addr;
16119e39c5baSBill Taylor uint32_t ii_size;
16129e39c5baSBill Taylor int *buf;
16139e39c5baSBill Taylor int i, type;
16149e39c5baSBill Taylor hermon_flash_ioctl_t ioctl_info;
16159e39c5baSBill Taylor
16169e39c5baSBill Taylor logmsg(MSG_INFO, "cnx_get_image_info: state %x\n", handle->state);
16179e39c5baSBill Taylor
16189e39c5baSBill Taylor type = handle->state &
16199e39c5baSBill Taylor (FWFLASH_IB_STATE_IMAGE_PRI | FWFLASH_IB_STATE_IMAGE_SEC);
16209e39c5baSBill Taylor
16219e39c5baSBill Taylor /* Get the image info pointer */
16229e39c5baSBill Taylor ioctl_info.af_addr = cnx_cont2phys(handle->log2_chunk_sz,
16239e39c5baSBill Taylor CNX_IMG_INF_PTR_OFFSET, type);
16249e39c5baSBill Taylor ioctl_info.af_type = HERMON_FLASH_READ_QUADLET;
16259e39c5baSBill Taylor
16269e39c5baSBill Taylor if (cnx_read_ioctl(handle, &ioctl_info) != FWFLASH_SUCCESS) {
16279e39c5baSBill Taylor logmsg(MSG_WARN, gettext("hermon: Failed to read image info "
16289e39c5baSBill Taylor "Address\n"));
16299e39c5baSBill Taylor return (FWFLASH_FAILURE);
16309e39c5baSBill Taylor }
16319e39c5baSBill Taylor ii_ptr_addr = ioctl_info.af_quadlet & 0xffffff;
16329e39c5baSBill Taylor
16339e39c5baSBill Taylor /* Get the image info size, a negative offset from the image info ptr */
16349e39c5baSBill Taylor ioctl_info.af_addr = cnx_cont2phys(handle->log2_chunk_sz,
16359e39c5baSBill Taylor ii_ptr_addr + CNX_IMG_INF_SZ_OFFSET, type);
16369e39c5baSBill Taylor ioctl_info.af_type = HERMON_FLASH_READ_QUADLET;
16379e39c5baSBill Taylor
16389e39c5baSBill Taylor if (cnx_read_ioctl(handle, &ioctl_info) != FWFLASH_SUCCESS) {
16399e39c5baSBill Taylor logmsg(MSG_WARN, gettext("hermon: Failed to read image info "
16409e39c5baSBill Taylor "size\n"));
16419e39c5baSBill Taylor return (FWFLASH_FAILURE);
16429e39c5baSBill Taylor }
16439e39c5baSBill Taylor logmsg(MSG_INFO, "hermon: ImageInfo Sz: 0x%x\n", ioctl_info.af_quadlet);
16449e39c5baSBill Taylor
16459e39c5baSBill Taylor ii_size = ioctl_info.af_quadlet;
16469e39c5baSBill Taylor /* size is in dwords--convert it to bytes */
16479e39c5baSBill Taylor ii_size *= 4;
16489e39c5baSBill Taylor
16499e39c5baSBill Taylor logmsg(MSG_INFO, "hermon: ii_ptr_addr: 0x%x ii_size: 0x%x\n",
16509e39c5baSBill Taylor ii_ptr_addr, ii_size);
16519e39c5baSBill Taylor
16529e39c5baSBill Taylor buf = (int *)calloc(1, ii_size);
16539e39c5baSBill Taylor
16549e39c5baSBill Taylor ioctl_info.af_addr = cnx_cont2phys(handle->log2_chunk_sz,
16559e39c5baSBill Taylor ii_ptr_addr, type);
16569e39c5baSBill Taylor ioctl_info.af_type = HERMON_FLASH_READ_QUADLET;
16579e39c5baSBill Taylor
16589e39c5baSBill Taylor for (i = 0; i < ii_size/4; i++) {
16599e39c5baSBill Taylor if (cnx_read_ioctl(handle, &ioctl_info) != FWFLASH_SUCCESS) {
16609e39c5baSBill Taylor logmsg(MSG_WARN, gettext("hermon: Failed to read "
16619e39c5baSBill Taylor "image info (0x%x)\n"), i);
16629e39c5baSBill Taylor free(buf);
16639e39c5baSBill Taylor return (FWFLASH_FAILURE);
16649e39c5baSBill Taylor }
16659e39c5baSBill Taylor
16669e39c5baSBill Taylor buf[i] = ioctl_info.af_quadlet;
16679e39c5baSBill Taylor ioctl_info.af_addr += 4;
16689e39c5baSBill Taylor }
16699e39c5baSBill Taylor
16709e39c5baSBill Taylor /* Parse the image info section */
16719e39c5baSBill Taylor if (cnx_parse_img_info(buf, ii_size, &handle->hwfw_img_info,
16729e39c5baSBill Taylor CNX_HW_IMG) != FWFLASH_SUCCESS) {
16739e39c5baSBill Taylor logmsg(MSG_WARN, gettext("hermon: Failed to parse Image Info "
16749e39c5baSBill Taylor "section\n"));
16759e39c5baSBill Taylor free(buf);
16769e39c5baSBill Taylor return (FWFLASH_FAILURE);
16779e39c5baSBill Taylor }
16789e39c5baSBill Taylor
16799e39c5baSBill Taylor free(buf);
16809e39c5baSBill Taylor return (FWFLASH_SUCCESS);
16819e39c5baSBill Taylor }
16829e39c5baSBill Taylor
16839e39c5baSBill Taylor int
cnx_parse_img_info(int * buf,uint32_t byte_size,cnx_img_info_t * img_info,int is_image)16849e39c5baSBill Taylor cnx_parse_img_info(int *buf, uint32_t byte_size, cnx_img_info_t *img_info,
16859e39c5baSBill Taylor int is_image)
16869e39c5baSBill Taylor {
16879e39c5baSBill Taylor uint32_t *p;
16889e39c5baSBill Taylor uint32_t offs = 0;
16899e39c5baSBill Taylor uint32_t tag_num = 0;
16909e39c5baSBill Taylor int end_found = 0;
16919e39c5baSBill Taylor uint32_t tag_size, tag_id;
16929e39c5baSBill Taylor uint32_t tmp;
16939e39c5baSBill Taylor const char *str;
16949e39c5baSBill Taylor int i;
16959e39c5baSBill Taylor
16969e39c5baSBill Taylor p = (uint32_t *)buf;
16979e39c5baSBill Taylor
16989e39c5baSBill Taylor logmsg(MSG_INFO, "hermon: cnx_parse_img_info\n");
16999e39c5baSBill Taylor
17009e39c5baSBill Taylor while (!end_found && (offs < byte_size)) {
17019e39c5baSBill Taylor if (is_image == CNX_FILE_IMG) {
17029e39c5baSBill Taylor tag_size = ntohl(*p) & 0xffffff;
17039e39c5baSBill Taylor tag_id = ntohl(*p) >> 24;
17049e39c5baSBill Taylor tmp = ntohl(*(p + 1));
17059e39c5baSBill Taylor } else {
17069e39c5baSBill Taylor tag_size = ((*p) & 0xffffff);
17079e39c5baSBill Taylor tag_id = ((*p) >> 24);
17089e39c5baSBill Taylor tmp = (*(p + 1));
17099e39c5baSBill Taylor }
17109e39c5baSBill Taylor
17119e39c5baSBill Taylor logmsg(MSG_INFO, "tag_id: %d tag_size: %d\n", tag_id, tag_size);
17129e39c5baSBill Taylor
17139e39c5baSBill Taylor if ((offs + tag_size) > byte_size) {
17149e39c5baSBill Taylor logmsg(MSG_WARN, gettext("hermon: Image Info section "
17159e39c5baSBill Taylor "corrupted: Tag# %d - tag_id %d, size %d exceeds "
17169e39c5baSBill Taylor "info section size (%d bytes)"), tag_num, tag_id,
17179e39c5baSBill Taylor tag_size, byte_size);
17189e39c5baSBill Taylor return (FWFLASH_FAILURE);
17199e39c5baSBill Taylor }
17209e39c5baSBill Taylor
17219e39c5baSBill Taylor switch (tag_id) {
17229e39c5baSBill Taylor case CNX_FW_VER:
17239e39c5baSBill Taylor if (tag_size != CNX_FW_VER_SZ) {
17249e39c5baSBill Taylor logmsg(MSG_INFO, "ERROR: tag_id: %d tag_size: "
17259e39c5baSBill Taylor "%d expected sz %d\n", tag_id, tag_size,
17269e39c5baSBill Taylor CNX_FW_VER_SZ);
17279e39c5baSBill Taylor }
17289e39c5baSBill Taylor tmp = (tmp & CNX_MASK_FW_VER_MAJ) >> 16;
17299e39c5baSBill Taylor img_info->fw_rev.major = tmp;
17309e39c5baSBill Taylor if (is_image == CNX_FILE_IMG)
17319e39c5baSBill Taylor tmp = ntohl(*(p + 2));
17329e39c5baSBill Taylor else
17339e39c5baSBill Taylor tmp = (*(p + 2));
17349e39c5baSBill Taylor img_info->fw_rev.minor =
17359e39c5baSBill Taylor (tmp & CNX_MASK_FW_VER_MIN)>> 16;
17369e39c5baSBill Taylor img_info->fw_rev.subminor =
17379e39c5baSBill Taylor tmp & CNX_MASK_FW_VER_SUBMIN;
17389e39c5baSBill Taylor
1739ee5d8455SShantkumar Hiremath logmsg(MSG_INFO, "FW_VER: %d.%d.%03d\n",
17409e39c5baSBill Taylor img_info->fw_rev.major, img_info->fw_rev.minor,
17419e39c5baSBill Taylor img_info->fw_rev.subminor);
17429e39c5baSBill Taylor break;
17439e39c5baSBill Taylor
17449e39c5baSBill Taylor case CNX_FW_BUILD_TIME:
17459e39c5baSBill Taylor if (tag_size != CNX_FW_BUILD_TIME_SZ) {
17469e39c5baSBill Taylor logmsg(MSG_INFO, "ERROR: tag_id: %d tag_size: "
17479e39c5baSBill Taylor "%d expected sz %d\n", tag_id, tag_size,
17489e39c5baSBill Taylor CNX_FW_BUILD_TIME_SZ);
17499e39c5baSBill Taylor }
17509e39c5baSBill Taylor img_info->fw_buildtime.hour =
17519e39c5baSBill Taylor (tmp & CNX_MASK_FW_BUILD_HOUR) >> 16;
17529e39c5baSBill Taylor img_info->fw_buildtime.minute =
17539e39c5baSBill Taylor (tmp & CNX_MASK_FW_BUILD_MIN) >> 8;
17549e39c5baSBill Taylor img_info->fw_buildtime.second =
17559e39c5baSBill Taylor (tmp & CNX_MASK_FW_BUILD_SEC);
17569e39c5baSBill Taylor
17579e39c5baSBill Taylor if (is_image == CNX_FILE_IMG)
17589e39c5baSBill Taylor tmp = ntohl(*(p + 2));
17599e39c5baSBill Taylor else
17609e39c5baSBill Taylor tmp = (*(p + 2));
17619e39c5baSBill Taylor
17629e39c5baSBill Taylor img_info->fw_buildtime.year =
17639e39c5baSBill Taylor (tmp & CNX_MASK_FW_BUILD_YEAR) >> 16;
17649e39c5baSBill Taylor img_info->fw_buildtime.month =
17659e39c5baSBill Taylor (tmp & CNX_MASK_FW_BUILD_MON) >> 8;
17669e39c5baSBill Taylor img_info->fw_buildtime.day =
17679e39c5baSBill Taylor (tmp & CNX_MASK_FW_BUILD_DAY);
17689e39c5baSBill Taylor
17699e39c5baSBill Taylor logmsg(MSG_INFO, "Build TIME: %d:%d:%d %d:%d:%d\n",
17709e39c5baSBill Taylor img_info->fw_buildtime.year,
17719e39c5baSBill Taylor img_info->fw_buildtime.month,
17729e39c5baSBill Taylor img_info->fw_buildtime.day,
17739e39c5baSBill Taylor img_info->fw_buildtime.hour,
17749e39c5baSBill Taylor img_info->fw_buildtime.minute,
17759e39c5baSBill Taylor img_info->fw_buildtime.second);
17769e39c5baSBill Taylor break;
17779e39c5baSBill Taylor
17789e39c5baSBill Taylor case CNX_DEV_TYPE:
17799e39c5baSBill Taylor if (tag_size != CNX_DEV_TYPE_SZ) {
17809e39c5baSBill Taylor logmsg(MSG_INFO, "ERROR: tag_id: %d tag_size: "
17819e39c5baSBill Taylor "%d expected sz %d\n", tag_id, tag_size,
17829e39c5baSBill Taylor CNX_DEV_TYPE_SZ);
17839e39c5baSBill Taylor }
17849e39c5baSBill Taylor img_info->dev_id = tmp & CNX_MASK_DEV_TYPE_ID;
17859e39c5baSBill Taylor logmsg(MSG_INFO, "DEV_TYPE: %d\n", img_info->dev_id);
17869e39c5baSBill Taylor break;
17879e39c5baSBill Taylor
17889e39c5baSBill Taylor case CNX_VSD_VENDOR_ID:
17899e39c5baSBill Taylor if (tag_size != CNX_VSD_VENDOR_ID_SZ) {
17909e39c5baSBill Taylor logmsg(MSG_INFO, "ERROR: tag_id: %d tag_size: "
17919e39c5baSBill Taylor "%d expected sz %d\n", tag_id, tag_size,
17929e39c5baSBill Taylor CNX_VSD_VENDOR_ID_SZ);
17939e39c5baSBill Taylor }
17949e39c5baSBill Taylor img_info->vsd_vendor_id = tmp & CNX_MASK_VSD_VENDORID;
17959e39c5baSBill Taylor logmsg(MSG_INFO, "VSD Vendor ID: 0x%lX\n",
17969e39c5baSBill Taylor img_info->vsd_vendor_id);
17979e39c5baSBill Taylor break;
17989e39c5baSBill Taylor
17999e39c5baSBill Taylor case CNX_PSID:
18009e39c5baSBill Taylor if (tag_size != CNX_PSID_SZ) {
18019e39c5baSBill Taylor logmsg(MSG_INFO, "ERROR: tag_id: %d tag_size: "
18029e39c5baSBill Taylor "%d expected sz %d\n", tag_id, tag_size,
18039e39c5baSBill Taylor CNX_PSID_SZ);
18049e39c5baSBill Taylor }
18059e39c5baSBill Taylor str = (const char *)p;
18069e39c5baSBill Taylor str += 4;
18079e39c5baSBill Taylor
18089e39c5baSBill Taylor for (i = 0; i < CNX_PSID_SZ; i++)
18099e39c5baSBill Taylor img_info->psid[i] = str[i];
18109e39c5baSBill Taylor
18119e39c5baSBill Taylor #ifdef _LITTLE_ENDIAN
18129e39c5baSBill Taylor if (is_image == CNX_HW_IMG) {
18139e39c5baSBill Taylor for (i = 0; i < CNX_PSID_SZ; i += 4) {
18149e39c5baSBill Taylor img_info->psid[i+3] = str[i];
18159e39c5baSBill Taylor img_info->psid[i+2] = str[i+1];
18169e39c5baSBill Taylor img_info->psid[i+1] = str[i+2];
18179e39c5baSBill Taylor img_info->psid[i] = str[i+3];
18189e39c5baSBill Taylor }
18199e39c5baSBill Taylor }
18209e39c5baSBill Taylor #endif
18219e39c5baSBill Taylor
18229e39c5baSBill Taylor logmsg(MSG_INFO, "PSID: %s\n", img_info->psid);
18239e39c5baSBill Taylor break;
18249e39c5baSBill Taylor
18259e39c5baSBill Taylor case CNX_VSD:
18269e39c5baSBill Taylor if (tag_size != CNX_VSD_SZ) {
18279e39c5baSBill Taylor logmsg(MSG_INFO, "ERROR: tag_id: %d tag_size: "
18289e39c5baSBill Taylor "%d expected sz %d\n", tag_id, tag_size,
18299e39c5baSBill Taylor CNX_VSD_SZ);
18309e39c5baSBill Taylor }
18319e39c5baSBill Taylor str = (const char *)p;
18329e39c5baSBill Taylor str += 4;
18339e39c5baSBill Taylor
18349e39c5baSBill Taylor for (i = 0; i < CNX_VSD_SZ; i++)
18359e39c5baSBill Taylor img_info->vsd[i] = str[i];
18369e39c5baSBill Taylor
18379e39c5baSBill Taylor #ifdef _LITTLE_ENDIAN
18389e39c5baSBill Taylor if (is_image == CNX_HW_IMG) {
18399e39c5baSBill Taylor for (i = 0; i < CNX_VSD_SZ; i += 4) {
18409e39c5baSBill Taylor img_info->vsd[i+3] = str[i];
18419e39c5baSBill Taylor img_info->vsd[i+2] = str[i+1];
18429e39c5baSBill Taylor img_info->vsd[i+1] = str[i+2];
18439e39c5baSBill Taylor img_info->vsd[i] = str[i+3];
18449e39c5baSBill Taylor }
18459e39c5baSBill Taylor }
18469e39c5baSBill Taylor #endif
18479e39c5baSBill Taylor logmsg(MSG_INFO, "VSD: %s\n", img_info->vsd);
18489e39c5baSBill Taylor break;
18499e39c5baSBill Taylor
18509e39c5baSBill Taylor case CNX_END_TAG:
18519e39c5baSBill Taylor if (tag_size != CNX_END_TAG_SZ) {
18529e39c5baSBill Taylor logmsg(MSG_INFO, "ERROR: tag_id: %d tag_size: "
18539e39c5baSBill Taylor "%d expected sz %d\n", tag_id, tag_size,
18549e39c5baSBill Taylor CNX_END_TAG_SZ);
18559e39c5baSBill Taylor }
18569e39c5baSBill Taylor end_found = 1;
18579e39c5baSBill Taylor break;
18589e39c5baSBill Taylor
18599e39c5baSBill Taylor default:
18609e39c5baSBill Taylor if (tag_id > CNX_END_TAG) {
18619e39c5baSBill Taylor logmsg(MSG_WARN, gettext("Invalid img_info "
18629e39c5baSBill Taylor "tag ID %d of size %d\n"), tag_id,
18639e39c5baSBill Taylor tag_size);
18649e39c5baSBill Taylor }
18659e39c5baSBill Taylor break;
18669e39c5baSBill Taylor }
18679e39c5baSBill Taylor
18689e39c5baSBill Taylor p += (tag_size / 4) + 1;
18699e39c5baSBill Taylor offs += tag_size + 4;
18709e39c5baSBill Taylor tag_num++;
18719e39c5baSBill Taylor }
18729e39c5baSBill Taylor
18739e39c5baSBill Taylor if (offs != byte_size) {
18749e39c5baSBill Taylor logmsg(MSG_WARN, gettext("hermon: Corrupt Image Info section "
18759e39c5baSBill Taylor "in firmware image\n"));
18769e39c5baSBill Taylor if (end_found) {
18779e39c5baSBill Taylor logmsg(MSG_WARN, gettext("Info section corrupted: "
18789e39c5baSBill Taylor "Section data size is %x bytes, but end tag found "
18799e39c5baSBill Taylor "after %x bytes.\n"), byte_size, offs);
18809e39c5baSBill Taylor } else {
18819e39c5baSBill Taylor logmsg(MSG_WARN, gettext("Info section corrupted: "
18829e39c5baSBill Taylor "Section data size is %x bytes, but end tag not "
18839e39c5baSBill Taylor "found at section end.\n"), byte_size);
18849e39c5baSBill Taylor }
18859e39c5baSBill Taylor return (FWFLASH_FAILURE);
18869e39c5baSBill Taylor }
18879e39c5baSBill Taylor
18889e39c5baSBill Taylor return (FWFLASH_SUCCESS);
18899e39c5baSBill Taylor }
1890