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 * IB (InfiniBand) specific functions.
289e39c5baSBill Taylor */
299e39c5baSBill Taylor
309e39c5baSBill Taylor /*
319e39c5baSBill Taylor * The reference for the functions in this file is the
329e39c5baSBill Taylor *
339e39c5baSBill Taylor * Mellanox HCA Flash Programming Application Note
349e39c5baSBill Taylor * (Mellanox document number 2205AN)
359e39c5baSBill Taylor * rev 1.44, 2007. Chapter 4 in particular.
369e39c5baSBill Taylor *
379e39c5baSBill Taylor * NOTE: this Mellanox document is labelled Confidential
389e39c5baSBill Taylor * so DO NOT move this file out of usr/closed without
399e39c5baSBill Taylor * explicit approval from Sun Legal.
409e39c5baSBill Taylor */
419e39c5baSBill Taylor
429e39c5baSBill Taylor /*
439e39c5baSBill Taylor * IMPORTANT NOTE:
449e39c5baSBill Taylor * 1. flash read is done in 32 bit quantities, and the driver returns
459e39c5baSBill Taylor * data in host byteorder form.
469e39c5baSBill Taylor * 2. flash write is done in 8 bit quantities by the driver.
479e39c5baSBill Taylor * 3. data in the flash should be in network byteorder (bigendian).
489e39c5baSBill Taylor * 4. data in image files is in network byteorder form.
499e39c5baSBill Taylor * 5. data in image structures in memory is kept in network byteorder.
509e39c5baSBill Taylor * 6. the functions in this file deal with data in host byteorder form.
519e39c5baSBill Taylor */
529e39c5baSBill Taylor
539e39c5baSBill Taylor
549e39c5baSBill Taylor #include <stdio.h>
559e39c5baSBill Taylor #include <stdlib.h>
569e39c5baSBill Taylor #include <unistd.h>
579e39c5baSBill Taylor #include <sys/types.h>
589e39c5baSBill Taylor #include <sys/stat.h>
599e39c5baSBill Taylor #include <sys/sysmacros.h>
609e39c5baSBill Taylor #include <sys/queue.h>
619e39c5baSBill Taylor #include <fcntl.h>
629e39c5baSBill Taylor #include <ctype.h>
639e39c5baSBill Taylor #include <string.h>
649e39c5baSBill Taylor #include <strings.h>
659e39c5baSBill Taylor
669e39c5baSBill Taylor #include <sys/byteorder.h>
679e39c5baSBill Taylor
689e39c5baSBill Taylor #include <libintl.h> /* for gettext(3c) */
699e39c5baSBill Taylor
709e39c5baSBill Taylor #include <fwflash/fwflash.h>
719e39c5baSBill Taylor #include "../../hdrs/MELLANOX.h"
729e39c5baSBill Taylor #include "../../hdrs/tavor_ib.h"
739e39c5baSBill Taylor
749e39c5baSBill Taylor
759e39c5baSBill Taylor
769e39c5baSBill Taylor char *devprefix = "/devices";
779e39c5baSBill Taylor char drivername[] = "tavor\0";
789e39c5baSBill Taylor char *devsuffix = ":devctl";
799e39c5baSBill Taylor
809e39c5baSBill Taylor
819e39c5baSBill Taylor extern di_node_t rootnode;
829e39c5baSBill Taylor extern int errno;
839e39c5baSBill Taylor extern struct fw_plugin *self;
849e39c5baSBill Taylor extern struct vrfyplugin *verifier;
859e39c5baSBill Taylor extern int fwflash_debug;
869e39c5baSBill Taylor
879e39c5baSBill Taylor
889e39c5baSBill Taylor /* required functions for this plugin */
899e39c5baSBill Taylor int fw_readfw(struct devicelist *device, char *filename);
909e39c5baSBill Taylor int fw_writefw(struct devicelist *device);
919e39c5baSBill Taylor int fw_identify(int start);
929e39c5baSBill Taylor int fw_devinfo();
939e39c5baSBill Taylor
949e39c5baSBill Taylor
959e39c5baSBill Taylor /* helper functions */
969e39c5baSBill Taylor
979e39c5baSBill Taylor static int tavor_identify(struct devicelist *thisdev);
989e39c5baSBill Taylor static int tavor_get_guids(struct ib_encap_ident *handle);
999e39c5baSBill Taylor static int tavor_close(struct devicelist *flashdev);
1009e39c5baSBill Taylor static void tavor_cisco_extensions(mlx_xps_t *hcaxps, mlx_xps_t *diskxps);
1019e39c5baSBill Taylor static uint16_t crc16(uint8_t *image, uint32_t size);
1029e39c5baSBill Taylor static int tavor_write_sector(int fd, int sectnum, int32_t *data);
1039e39c5baSBill Taylor static int tavor_zero_sig_crc(int fd, uint32_t start);
1049e39c5baSBill Taylor static int tavor_write_xps_fia(int fd, uint32_t offset, uint32_t start);
1059e39c5baSBill Taylor static int tavor_write_xps_crc_sig(int fd, uint32_t offset, uint16_t newcrc);
1069e39c5baSBill Taylor static int tavor_blast_image(int fd, int prisec, uint32_t hcafia,
1079e39c5baSBill Taylor uint32_t sectsz, struct mlx_xps *newxps);
1089e39c5baSBill Taylor static int tavor_readback(int infd, int whichsect, int sectsz);
1099e39c5baSBill Taylor
1109e39c5baSBill Taylor
1119e39c5baSBill Taylor
1129e39c5baSBill Taylor int
fw_readfw(struct devicelist * flashdev,char * filename)1139e39c5baSBill Taylor fw_readfw(struct devicelist *flashdev, char *filename)
1149e39c5baSBill Taylor {
1159e39c5baSBill Taylor
1169e39c5baSBill Taylor int rv = FWFLASH_SUCCESS;
1179e39c5baSBill Taylor int fd;
1189e39c5baSBill Taylor mode_t mode = S_IRUSR | S_IWUSR;
1199e39c5baSBill Taylor uint8_t pchunks;
1209e39c5baSBill Taylor uint8_t *raw_pfi;
1219e39c5baSBill Taylor uint8_t *raw_sfi;
1229e39c5baSBill Taylor uint32_t j, offset;
1239e39c5baSBill Taylor uint32_t pfia, sfia, psz, ssz;
1249e39c5baSBill Taylor tavor_flash_ioctl_t tfi_data;
1259e39c5baSBill Taylor struct ib_encap_ident *manuf;
1269e39c5baSBill Taylor struct mlx_xps *lpps;
1279e39c5baSBill Taylor struct mlx_xps *lsps;
1289e39c5baSBill Taylor #if defined(_LITTLE_ENDIAN)
1299e39c5baSBill Taylor uint32_t *ptr;
1309e39c5baSBill Taylor #endif
1319e39c5baSBill Taylor
1329e39c5baSBill Taylor errno = 0;
1339e39c5baSBill Taylor if ((fd = open(filename, O_RDWR|O_CREAT|O_DSYNC, mode)) < 0) {
1349e39c5baSBill Taylor logmsg(MSG_ERROR,
1359e39c5baSBill Taylor gettext("tavor: Unable to open specified file "
1369e39c5baSBill Taylor "(%s) for writing: %s\n"), filename, strerror(errno));
1379e39c5baSBill Taylor return (FWFLASH_FAILURE);
1389e39c5baSBill Taylor }
1399e39c5baSBill Taylor
1409e39c5baSBill Taylor manuf =
1419e39c5baSBill Taylor (struct ib_encap_ident *)(uintptr_t)flashdev->ident->encap_ident;
1429e39c5baSBill Taylor lpps = (struct mlx_xps *)(uintptr_t)manuf->pps;
1439e39c5baSBill Taylor lsps = (struct mlx_xps *)(uintptr_t)manuf->sps;
1449e39c5baSBill Taylor
1459e39c5baSBill Taylor /*
1469e39c5baSBill Taylor * Now that we've got an open, init'd fd, we can read the
1479e39c5baSBill Taylor * xFI from the device itself. We've already got the IS
1489e39c5baSBill Taylor * and xPS stored in manuf.
1499e39c5baSBill Taylor */
1509e39c5baSBill Taylor
1519e39c5baSBill Taylor /* stash some values for later */
1529e39c5baSBill Taylor pfia = MLXSWAPBITS32(lpps->fia);
1539e39c5baSBill Taylor sfia = MLXSWAPBITS32(lsps->fia);
1549e39c5baSBill Taylor psz = MLXSWAPBITS32(lpps->fis);
1559e39c5baSBill Taylor ssz = MLXSWAPBITS32(lsps->fis);
1569e39c5baSBill Taylor
1579e39c5baSBill Taylor /* Invariant Sector comes first */
1589e39c5baSBill Taylor if ((j = write(fd, manuf->inv, manuf->sector_sz)) !=
1599e39c5baSBill Taylor manuf->sector_sz) {
1609e39c5baSBill Taylor logmsg(MSG_ERROR,
1619e39c5baSBill Taylor gettext("tavor: Unable to write HCA Invariant Sector "
1629e39c5baSBill Taylor "(%d of %d bytes)\n"),
1639e39c5baSBill Taylor j, manuf->sector_sz);
1649e39c5baSBill Taylor (void) tavor_close(flashdev);
1659e39c5baSBill Taylor return (FWFLASH_FAILURE);
1669e39c5baSBill Taylor } else {
1679e39c5baSBill Taylor fprintf(stdout, gettext("Writing ."));
1689e39c5baSBill Taylor }
1699e39c5baSBill Taylor
1709e39c5baSBill Taylor /* followed by Primary Pointer Sector */
1719e39c5baSBill Taylor if ((j = write(fd, manuf->pps, manuf->sector_sz)) !=
1729e39c5baSBill Taylor manuf->sector_sz) {
1739e39c5baSBill Taylor logmsg(MSG_ERROR,
1749e39c5baSBill Taylor gettext("tavor: Unable to write HCA Primary Pointer "
1759e39c5baSBill Taylor "Sector (%d of %d bytes)\n)"),
1769e39c5baSBill Taylor j, manuf->sector_sz);
1779e39c5baSBill Taylor (void) tavor_close(flashdev);
1789e39c5baSBill Taylor return (FWFLASH_FAILURE);
1799e39c5baSBill Taylor } else {
1809e39c5baSBill Taylor fprintf(stdout, " .");
1819e39c5baSBill Taylor }
1829e39c5baSBill Taylor
1839e39c5baSBill Taylor /* followed by Secondary Pointer Sector */
1849e39c5baSBill Taylor if ((j = write(fd, manuf->sps, manuf->sector_sz)) !=
1859e39c5baSBill Taylor manuf->sector_sz) {
1869e39c5baSBill Taylor logmsg(MSG_ERROR,
1879e39c5baSBill Taylor gettext("tavor: Unable to write HCA Secondary Pointer "
1889e39c5baSBill Taylor "Sector (%d of %d bytes)\n"),
1899e39c5baSBill Taylor j, manuf->sector_sz);
1909e39c5baSBill Taylor (void) tavor_close(flashdev);
1919e39c5baSBill Taylor return (FWFLASH_FAILURE);
1929e39c5baSBill Taylor } else {
1939e39c5baSBill Taylor fprintf(stdout, " .");
1949e39c5baSBill Taylor }
1959e39c5baSBill Taylor
1969e39c5baSBill Taylor /* Now for the xFI sectors */
1979e39c5baSBill Taylor pchunks = psz / manuf->sector_sz;
1989e39c5baSBill Taylor
1999e39c5baSBill Taylor if ((psz % manuf->sector_sz) != 0)
2009e39c5baSBill Taylor pchunks++;
2019e39c5baSBill Taylor
2029e39c5baSBill Taylor /* Get the PFI, then the SFI */
2039e39c5baSBill Taylor if ((raw_pfi = calloc(1, pchunks * manuf->sector_sz)) == NULL) {
2049e39c5baSBill Taylor logmsg(MSG_ERROR,
2059e39c5baSBill Taylor gettext("tavor: Unable to allocate space for "
2069e39c5baSBill Taylor "device's Primary Firmware Image\n"));
2079e39c5baSBill Taylor return (FWFLASH_FAILURE);
2089e39c5baSBill Taylor }
2099e39c5baSBill Taylor bzero(&tfi_data, sizeof (tavor_flash_ioctl_t));
2109e39c5baSBill Taylor tfi_data.tf_type = TAVOR_FLASH_READ_SECTOR;
2119e39c5baSBill Taylor j = pfia / manuf->sector_sz;
2129e39c5baSBill Taylor
2139e39c5baSBill Taylor for (offset = 0; offset < psz; offset += manuf->sector_sz) {
2149e39c5baSBill Taylor tfi_data.tf_sector_num = j;
2159e39c5baSBill Taylor tfi_data.tf_sector = (caddr_t)&raw_pfi[offset];
2169e39c5baSBill Taylor rv = ioctl(manuf->fd, TAVOR_IOCTL_FLASH_READ, &tfi_data);
2179e39c5baSBill Taylor if (rv < 0) {
2189e39c5baSBill Taylor logmsg(MSG_ERROR,
2199e39c5baSBill Taylor gettext("tavor: Unable to read sector %d of "
2209e39c5baSBill Taylor "HCA Primary Firmware Image\n"), j);
2219e39c5baSBill Taylor free(raw_pfi);
2229e39c5baSBill Taylor (void) tavor_close(flashdev);
2239e39c5baSBill Taylor return (FWFLASH_FAILURE);
2249e39c5baSBill Taylor }
2259e39c5baSBill Taylor ++j;
2269e39c5baSBill Taylor }
2279e39c5baSBill Taylor
2289e39c5baSBill Taylor /*
2299e39c5baSBill Taylor * It appears that the tavor driver is returning a signed
2309e39c5baSBill Taylor * -1 (0xffff) in unassigned quadlets if we read a sector
2319e39c5baSBill Taylor * that isn't full, so for backwards compatibility with
2329e39c5baSBill Taylor * earlier fwflash versions, we need to zero out what
2339e39c5baSBill Taylor * remains in the sector.
2349e39c5baSBill Taylor */
2359e39c5baSBill Taylor bzero(&raw_pfi[psz], (pchunks * manuf->sector_sz) - psz);
2369e39c5baSBill Taylor
2379e39c5baSBill Taylor #if defined(_LITTLE_ENDIAN)
2389e39c5baSBill Taylor ptr = (uint32_t *)(uintptr_t)raw_pfi;
2399e39c5baSBill Taylor for (j = 0; j < (pchunks * manuf->sector_sz / 4); j++) {
2409e39c5baSBill Taylor ptr[j] = htonl(ptr[j]);
2419e39c5baSBill Taylor if (j > psz)
2429e39c5baSBill Taylor break;
2439e39c5baSBill Taylor }
2449e39c5baSBill Taylor #endif
2459e39c5baSBill Taylor
2469e39c5baSBill Taylor if ((j = write(fd, raw_pfi, pchunks * manuf->sector_sz))
2479e39c5baSBill Taylor != pchunks * manuf->sector_sz) {
2489e39c5baSBill Taylor logmsg(MSG_ERROR,
2499e39c5baSBill Taylor gettext("tavor: Unable to write HCA Primary Firmware "
2509e39c5baSBill Taylor "Image data (%d of %d bytes)\n"),
2519e39c5baSBill Taylor j, pchunks * manuf->sector_sz);
2529e39c5baSBill Taylor free(raw_pfi);
2539e39c5baSBill Taylor (void) tavor_close(flashdev);
2549e39c5baSBill Taylor return (FWFLASH_FAILURE);
2559e39c5baSBill Taylor } else {
2569e39c5baSBill Taylor fprintf(stdout, " .");
2579e39c5baSBill Taylor }
2589e39c5baSBill Taylor
2599e39c5baSBill Taylor pchunks = ssz / manuf->sector_sz;
2609e39c5baSBill Taylor
2619e39c5baSBill Taylor if ((ssz % manuf->sector_sz) != 0)
2629e39c5baSBill Taylor pchunks++;
2639e39c5baSBill Taylor
2649e39c5baSBill Taylor /*
2659e39c5baSBill Taylor * We allocate wholenum sectors, but only write out what we
2669e39c5baSBill Taylor * really need (ssz bytes)
2679e39c5baSBill Taylor */
2689e39c5baSBill Taylor if ((raw_sfi = calloc(1, pchunks * manuf->sector_sz)) == NULL) {
2699e39c5baSBill Taylor logmsg(MSG_ERROR,
2709e39c5baSBill Taylor gettext("tavor: Unable to allocate space for "
2719e39c5baSBill Taylor "device's Secondary Firmware Image\n"));
2729e39c5baSBill Taylor free(raw_pfi);
2739e39c5baSBill Taylor return (FWFLASH_FAILURE);
2749e39c5baSBill Taylor }
2759e39c5baSBill Taylor bzero(&tfi_data, sizeof (tavor_flash_ioctl_t));
2769e39c5baSBill Taylor tfi_data.tf_type = TAVOR_FLASH_READ_SECTOR;
2779e39c5baSBill Taylor
2789e39c5baSBill Taylor /* get our starting sector number */
2799e39c5baSBill Taylor j = sfia / manuf->sector_sz;
2809e39c5baSBill Taylor
2819e39c5baSBill Taylor for (offset = 0; offset < ssz; offset += manuf->sector_sz) {
2829e39c5baSBill Taylor tfi_data.tf_sector_num = j;
2839e39c5baSBill Taylor tfi_data.tf_sector = (caddr_t)&raw_sfi[offset];
2849e39c5baSBill Taylor if ((rv = ioctl(manuf->fd, TAVOR_IOCTL_FLASH_READ,
2859e39c5baSBill Taylor &tfi_data)) < 0) {
2869e39c5baSBill Taylor logmsg(MSG_ERROR,
2879e39c5baSBill Taylor gettext("tavor: Unable to read sector %d of "
2889e39c5baSBill Taylor "HCA Secondary Firmware Image\n"), j);
2899e39c5baSBill Taylor (void) tavor_close(flashdev);
2909e39c5baSBill Taylor free(raw_pfi);
2919e39c5baSBill Taylor free(raw_sfi);
2929e39c5baSBill Taylor return (FWFLASH_FAILURE);
2939e39c5baSBill Taylor }
2949e39c5baSBill Taylor ++j;
2959e39c5baSBill Taylor }
2969e39c5baSBill Taylor
2979e39c5baSBill Taylor /*
2989e39c5baSBill Taylor * It appears that the tavor driver is returning a signed
2999e39c5baSBill Taylor * -1 (0xffff) in unassigned quadlets if we read a sector
3009e39c5baSBill Taylor * that isn't full, so for backwards compatibility with
3019e39c5baSBill Taylor * earlier fwflash versions, we need to zero out what
3029e39c5baSBill Taylor * remains in the sector.
3039e39c5baSBill Taylor */
3049e39c5baSBill Taylor bzero(&raw_sfi[ssz], (pchunks * manuf->sector_sz) - ssz);
3059e39c5baSBill Taylor
3069e39c5baSBill Taylor #if defined(_LITTLE_ENDIAN)
3079e39c5baSBill Taylor ptr = (uint32_t *)(uintptr_t)raw_sfi;
3089e39c5baSBill Taylor for (j = 0; j < ssz / 4; j++) {
3099e39c5baSBill Taylor ptr[j] = htonl(ptr[j]);
3109e39c5baSBill Taylor }
3119e39c5baSBill Taylor #endif
3129e39c5baSBill Taylor
3139e39c5baSBill Taylor /* only write out ssz bytes */
3149e39c5baSBill Taylor if ((j = write(fd, raw_sfi, ssz)) != ssz) {
3159e39c5baSBill Taylor logmsg(MSG_ERROR,
3169e39c5baSBill Taylor gettext("tavor: Unable to write HCA Secondary Firmware "
3179e39c5baSBill Taylor "Image data (%d of %d bytes)\n"),
3189e39c5baSBill Taylor j, ssz);
3199e39c5baSBill Taylor (void) tavor_close(flashdev);
3209e39c5baSBill Taylor free(raw_pfi);
3219e39c5baSBill Taylor free(raw_sfi);
3229e39c5baSBill Taylor return (FWFLASH_FAILURE);
3239e39c5baSBill Taylor } else {
3249e39c5baSBill Taylor fprintf(stdout, " .\n");
3259e39c5baSBill Taylor }
3269e39c5baSBill Taylor
3279e39c5baSBill Taylor fprintf(stdout,
3289e39c5baSBill Taylor gettext("Done.\n"));
3299e39c5baSBill Taylor
3309e39c5baSBill Taylor free(raw_pfi);
3319e39c5baSBill Taylor free(raw_sfi);
3329e39c5baSBill Taylor /*
3339e39c5baSBill Taylor * this should succeed, but we don't just blindly ignore
3349e39c5baSBill Taylor * the return code cos that would be obnoxious.
3359e39c5baSBill Taylor */
3369e39c5baSBill Taylor return (tavor_close(flashdev));
3379e39c5baSBill Taylor }
3389e39c5baSBill Taylor
3399e39c5baSBill Taylor
3409e39c5baSBill Taylor /*
3419e39c5baSBill Taylor * If we're invoking fw_writefw, then flashdev is a valid,
3429e39c5baSBill Taylor * flashable device as determined by fw_identify().
3439e39c5baSBill Taylor *
3449e39c5baSBill Taylor * If verifier is null, then we haven't been called following a firmware
3459e39c5baSBill Taylor * image verification load operation.
3469e39c5baSBill Taylor */
3479e39c5baSBill Taylor int
fw_writefw(struct devicelist * flashdev)3489e39c5baSBill Taylor fw_writefw(struct devicelist *flashdev)
3499e39c5baSBill Taylor {
3509e39c5baSBill Taylor
3519e39c5baSBill Taylor int rv;
3529e39c5baSBill Taylor uint32_t j, sectsz, hpfia, hsfia;
3539e39c5baSBill Taylor uint32_t ipfia, isfia, ipfis, isfis;
3549e39c5baSBill Taylor struct ib_encap_ident *manuf;
3559e39c5baSBill Taylor struct mlx_is *iinv;
3569e39c5baSBill Taylor struct mlx_xps *ipps, *lpps;
3579e39c5baSBill Taylor struct mlx_xps *isps, *lsps;
3589e39c5baSBill Taylor struct mlx_xfi *ipfi, *isfi;
3599e39c5baSBill Taylor
3609e39c5baSBill Taylor /*
3619e39c5baSBill Taylor * linv, lpps/lsps are from the HCA whereas
3629e39c5baSBill Taylor * iinv/ipps/isps are in the on-disk firmware image that
3639e39c5baSBill Taylor * we've read in to the verifier->fwimage field, and are
3649e39c5baSBill Taylor * about to do some hand-waving with.
3659e39c5baSBill Taylor */
3669e39c5baSBill Taylor
3679e39c5baSBill Taylor /*
3689e39c5baSBill Taylor * From the Mellanox HCA Flash programming app note,
3699e39c5baSBill Taylor * start of ch4, page36:
3709e39c5baSBill Taylor * ===========================================================
3719e39c5baSBill Taylor * Failsafe firmware programming ensures that an HCA device
3729e39c5baSBill Taylor * can boot up in a functional mode even if the burn process
3739e39c5baSBill Taylor * was interrupted (because of a power failure, reboot, user
3749e39c5baSBill Taylor * interrupt, etc.). This can be implemented by burning the
3759e39c5baSBill Taylor * new image to a vacant region on the Flash, and erasing the
3769e39c5baSBill Taylor * old image only after the new image is successfully burnt.
3779e39c5baSBill Taylor * This method ensures that there is at least one valid firmware
3789e39c5baSBill Taylor * image on the Flash at all times. Thus, in case a firmware
3799e39c5baSBill Taylor * image programming process is aborted for any reason, the HCA
3809e39c5baSBill Taylor * will still be able to boot up properly using the valid image
3819e39c5baSBill Taylor * on the Flash.
3829e39c5baSBill Taylor * ...
3839e39c5baSBill Taylor *
3849e39c5baSBill Taylor * 4.1 Notes on Image Programming of HCA Flashes
3859e39c5baSBill Taylor * Following are some general notes regarding the Flash memory
3869e39c5baSBill Taylor * in the context of Mellanox HCA devices:
3879e39c5baSBill Taylor * > The Flash memory is divided into sectors, and each sector
3889e39c5baSBill Taylor * must be erased prior to its programming.
3899e39c5baSBill Taylor * > The image to be burnt is byte packed and should be programmed
3909e39c5baSBill Taylor * into the Flash byte by byte, preserving the byte order, starting
3919e39c5baSBill Taylor * at offset zero. No amendments are needed for endianess.
3929e39c5baSBill Taylor * > It is recommended to program the Flash while the device is idle.
3939e39c5baSBill Taylor * ===========================================================
3949e39c5baSBill Taylor *
3959e39c5baSBill Taylor * The comment about endianness is particularly important for us
3969e39c5baSBill Taylor * since we operate on both big- and litte-endian hosts - it means
3979e39c5baSBill Taylor * we have to do some byte-swapping gymnastics
3989e39c5baSBill Taylor */
3999e39c5baSBill Taylor
4009e39c5baSBill Taylor /*
4019e39c5baSBill Taylor * From the Mellanox HCA Flash programming app note,
4029e39c5baSBill Taylor * section 4.2.5 on page 41/42:
4039e39c5baSBill Taylor * ===========================================================
4049e39c5baSBill Taylor * 4.2.5 Failsafe Programming Example
4059e39c5baSBill Taylor * This section provides an example of a programming utility
4069e39c5baSBill Taylor * that performs a Failsafe firmware image update. The flow
4079e39c5baSBill Taylor * ensures that there is at least one valid firmware image on
4089e39c5baSBill Taylor * the Flash at all times. Thus, in case a firmware image pro-
4099e39c5baSBill Taylor * gramming process is aborted for any reason, the HCA will
4109e39c5baSBill Taylor * still be able to boot up properly using the valid image on
4119e39c5baSBill Taylor * the Flash. Any other flow that ensures the above is also
4129e39c5baSBill Taylor * considered a Failsafe firmware update.
4139e39c5baSBill Taylor *
4149e39c5baSBill Taylor * Update Flow:
4159e39c5baSBill Taylor * * Check the validity of the PPS and SPS:
4169e39c5baSBill Taylor * > If both PSs are valid, arbitrarily invalidate one of them
4179e39c5baSBill Taylor * > If both PSs are invalid, the image on flash is corrupted
4189e39c5baSBill Taylor * and cannot be updated in a Failsafe way. The user must
4199e39c5baSBill Taylor * burn a full image in a non-failsafe way.
4209e39c5baSBill Taylor *
4219e39c5baSBill Taylor * > If only the PPS is valid:
4229e39c5baSBill Taylor * i.Burn the secondary image (erase each sector first)
4239e39c5baSBill Taylor * ii.Burn the SPS with the correct image address (FIA field)
4249e39c5baSBill Taylor * iii.Invalidate the PPS
4259e39c5baSBill Taylor *
4269e39c5baSBill Taylor * > If only the SPS is valid:
4279e39c5baSBill Taylor * i.Burn the primary image (erase each sector first)
4289e39c5baSBill Taylor * ii.Burn the PPS with the correct image address (FIA field)
4299e39c5baSBill Taylor * iii.Invalidate the SPS
4309e39c5baSBill Taylor * ===========================================================
4319e39c5baSBill Taylor */
4329e39c5baSBill Taylor
4339e39c5baSBill Taylor /*
4349e39c5baSBill Taylor * Other required tasks called from this function:
4359e39c5baSBill Taylor *
4369e39c5baSBill Taylor * * check for CISCO boot extensions in the current xPS, and
4379e39c5baSBill Taylor * if found, set them in the new xPS
4389e39c5baSBill Taylor *
4399e39c5baSBill Taylor * * update the xPS CRC field
4409e39c5baSBill Taylor *
4419e39c5baSBill Taylor * _then_ you can setup the outbound transfer to the HCA flash.
4429e39c5baSBill Taylor */
4439e39c5baSBill Taylor
4449e39c5baSBill Taylor /*
4459e39c5baSBill Taylor * VERY IMPORTANT NOTE:
4469e39c5baSBill Taylor * The above text from the app note programming guide v1.44 does
4479e39c5baSBill Taylor * NOT match reality. If you try to do exactly what the above
4489e39c5baSBill Taylor * text specifies then you'll wind up with a warm, brick-like
4499e39c5baSBill Taylor * HCA that if you're really lucky has booted up in maintenance
4509e39c5baSBill Taylor * mode for you to re-flash.
4519e39c5baSBill Taylor *
4529e39c5baSBill Taylor * What you need to do is follow the example of the previous
4539e39c5baSBill Taylor * (v1.2 etc) version from the ON gate - which is what happens
4549e39c5baSBill Taylor * in this file. Basically - don't erase prior to writing a new
4559e39c5baSBill Taylor * sector, and _read back_ each sector after writing it. Especially
4569e39c5baSBill Taylor * the pointer sectors. Otherwise you'll get a warm brick.
4579e39c5baSBill Taylor */
4589e39c5baSBill Taylor
4599e39c5baSBill Taylor manuf =
4609e39c5baSBill Taylor (struct ib_encap_ident *)(uintptr_t)flashdev->ident->encap_ident;
4619e39c5baSBill Taylor lpps = (struct mlx_xps *)(uintptr_t)manuf->pps;
4629e39c5baSBill Taylor lsps = (struct mlx_xps *)(uintptr_t)manuf->sps;
4639e39c5baSBill Taylor iinv = (struct mlx_is *)&verifier->fwimage[0];
4649e39c5baSBill Taylor sectsz = 1 << MLXSWAPBITS16(iinv->log2sectsz + iinv->log2sectszp);
4659e39c5baSBill Taylor ipps = (struct mlx_xps *)&verifier->fwimage[sectsz/4];
4669e39c5baSBill Taylor isps = (struct mlx_xps *)&verifier->fwimage[sectsz/2];
4679e39c5baSBill Taylor
4689e39c5baSBill Taylor /*
4699e39c5baSBill Taylor * If we get here, then the verifier has _already_ checked that
4709e39c5baSBill Taylor * the part number in the firmware image matches that in the HCA,
4719e39c5baSBill Taylor * so we only need this check if there's no hardware info available
4729e39c5baSBill Taylor * already after running through fw_identify().
4739e39c5baSBill Taylor */
4749e39c5baSBill Taylor if (manuf->pn_len == 0) {
4759e39c5baSBill Taylor int resp;
4769e39c5baSBill Taylor
4779e39c5baSBill Taylor (void) printf("\nUnable to completely verify that this "
4789e39c5baSBill Taylor "firmware image\n\t(%s)\nis compatible with your "
4799e39c5baSBill Taylor "HCA\n\t%s\n",
4809e39c5baSBill Taylor verifier->imgfile, flashdev->access_devname);
4819e39c5baSBill Taylor (void) printf("\n\tDo you really want to continue? (Y/N): ");
4829e39c5baSBill Taylor
4839e39c5baSBill Taylor (void) fflush(stdin);
4849e39c5baSBill Taylor resp = getchar();
4859e39c5baSBill Taylor if (resp != 'Y' && resp != 'y') {
4869e39c5baSBill Taylor (void) printf("\nNot proceeding with flash "
4879e39c5baSBill Taylor "operation of %s on %s\n",
4889e39c5baSBill Taylor verifier->imgfile, flashdev->access_devname);
4899e39c5baSBill Taylor return (FWFLASH_FAILURE);
4909e39c5baSBill Taylor }
4919e39c5baSBill Taylor }
4929e39c5baSBill Taylor
4939e39c5baSBill Taylor /* stash these for later */
4949e39c5baSBill Taylor hpfia = MLXSWAPBITS32(lpps->fia);
4959e39c5baSBill Taylor hsfia = MLXSWAPBITS32(lsps->fia);
4969e39c5baSBill Taylor
4979e39c5baSBill Taylor /* where does the on-disk image think everything is at? */
4989e39c5baSBill Taylor ipfia = MLXSWAPBITS32(ipps->fia);
4999e39c5baSBill Taylor isfia = MLXSWAPBITS32(isps->fia);
5009e39c5baSBill Taylor ipfis = MLXSWAPBITS32(ipps->fis);
5019e39c5baSBill Taylor isfis = MLXSWAPBITS32(isps->fis);
5029e39c5baSBill Taylor
5039e39c5baSBill Taylor logmsg(MSG_INFO, "tavor: hpfia 0x%0x hsfia 0x%0x "
5049e39c5baSBill Taylor "ipfia 0x%0x isfia 0x%0x ipfis 0x%0x isfis 0x%0x\n",
5059e39c5baSBill Taylor hpfia, hsfia, ipfia, isfia, ipfis, isfis);
5069e39c5baSBill Taylor
5079e39c5baSBill Taylor if ((ipfis + isfis) > manuf->device_sz) {
5089e39c5baSBill Taylor /*
5099e39c5baSBill Taylor * This is bad - don't flash an image which is larger
5109e39c5baSBill Taylor * than the size of the HCA's flash
5119e39c5baSBill Taylor */
5129e39c5baSBill Taylor logmsg(MSG_ERROR,
5139e39c5baSBill Taylor gettext("tavor: on-disk firmware image size (0x%lx bytes) "
5149e39c5baSBill Taylor "exceeds HCA's flash memory size (0x%lx bytes)!\n"),
5159e39c5baSBill Taylor ipfis + isfis, manuf->device_sz);
5169e39c5baSBill Taylor logmsg(MSG_ERROR,
5179e39c5baSBill Taylor gettext("tavor: not flashing this image (%s)\n"),
5189e39c5baSBill Taylor verifier->imgfile);
5199e39c5baSBill Taylor return (FWFLASH_FAILURE);
5209e39c5baSBill Taylor }
5219e39c5baSBill Taylor
5229e39c5baSBill Taylor /*
5239e39c5baSBill Taylor * The Mellanox HCA Flash app programming note does _not_
5249e39c5baSBill Taylor * specify that you have to insert the HCA's guid section
5259e39c5baSBill Taylor * into the flash image before burning it.
5269e39c5baSBill Taylor *
5279e39c5baSBill Taylor * HOWEVER it was determined during testing that this is
5289e39c5baSBill Taylor * actually required (otherwise your HCA's GUIDs revert to
5299e39c5baSBill Taylor * the manufacturer's defaults, ugh!), so we'll do it too.
5309e39c5baSBill Taylor */
5319e39c5baSBill Taylor
5329e39c5baSBill Taylor ipfi = (struct mlx_xfi *)&verifier->fwimage[ipfia/4];
5339e39c5baSBill Taylor isfi = (struct mlx_xfi *)&verifier->fwimage[isfia/4];
5349e39c5baSBill Taylor
5359e39c5baSBill Taylor /*
5369e39c5baSBill Taylor * Here we check against our stored, properly-bitwise-munged copy
5379e39c5baSBill Taylor * of the HCA's GUIDS. If they're not set to default AND the OUI
5389e39c5baSBill Taylor * is MLX_OUI, then they're ok so we copy the HCA's version into
5399e39c5baSBill Taylor * our in-memory copy and blat it. If the GUIDs don't match this
5409e39c5baSBill Taylor * condition, then we use the default GUIDs which are in the on-disk
5419e39c5baSBill Taylor * firmware image instead.
5429e39c5baSBill Taylor */
5439e39c5baSBill Taylor if (((manuf->ibguids[0] != MLX_DEFAULT_NODE_GUID) &&
5449e39c5baSBill Taylor (manuf->ibguids[1] != MLX_DEFAULT_P1_GUID) &&
5459e39c5baSBill Taylor (manuf->ibguids[2] != MLX_DEFAULT_P2_GUID) &&
5469e39c5baSBill Taylor (manuf->ibguids[3] != MLX_DEFAULT_SYSIMG_GUID)) &&
5479e39c5baSBill Taylor ((((manuf->ibguids[0] & HIGHBITS64) >> OUISHIFT) == MLX_OUI) ||
5489e39c5baSBill Taylor (((manuf->ibguids[1] & HIGHBITS64) >> OUISHIFT) == MLX_OUI) ||
5499e39c5baSBill Taylor (((manuf->ibguids[2] & HIGHBITS64) >> OUISHIFT) == MLX_OUI) ||
5509e39c5baSBill Taylor (((manuf->ibguids[3] & HIGHBITS64) >> OUISHIFT) == MLX_OUI))) {
5519e39c5baSBill Taylor /* The GUIDs are ok, blat them into the in-memory image */
5529e39c5baSBill Taylor j = ((ipfia + MLXSWAPBITS32(ipfi->nguidptr)) / 4) - 4;
5539e39c5baSBill Taylor bcopy(manuf->pri_guid_section, &verifier->fwimage[j],
5549e39c5baSBill Taylor sizeof (struct mlx_guid_sect));
5559e39c5baSBill Taylor j = ((isfia + MLXSWAPBITS32(isfi->nguidptr)) / 4) - 4;
5569e39c5baSBill Taylor bcopy(manuf->sec_guid_section, &verifier->fwimage[j],
5579e39c5baSBill Taylor sizeof (struct mlx_guid_sect));
5589e39c5baSBill Taylor } else {
5599e39c5baSBill Taylor /*
5609e39c5baSBill Taylor * The GUIDs are hosed, we'll have to use
5619e39c5baSBill Taylor * the vendor defaults in the image instead
5629e39c5baSBill Taylor */
5639e39c5baSBill Taylor logmsg(MSG_ERROR,
5649e39c5baSBill Taylor gettext("tavor: HCA's GUID section is set to defaults or "
5659e39c5baSBill Taylor " is invalid, using firmware image manufacturer's "
5669e39c5baSBill Taylor "default GUID section instead\n"));
5679e39c5baSBill Taylor }
5689e39c5baSBill Taylor
5699e39c5baSBill Taylor /* Just in case somebody is booting from this card... */
5709e39c5baSBill Taylor tavor_cisco_extensions(lpps, ipps);
5719e39c5baSBill Taylor tavor_cisco_extensions(lsps, isps);
5729e39c5baSBill Taylor
5739e39c5baSBill Taylor /* first we write the secondary image and SPS, then the primary */
5749e39c5baSBill Taylor rv = tavor_blast_image(manuf->fd, 2, hsfia, manuf->sector_sz, isps);
5759e39c5baSBill Taylor if (rv != FWFLASH_SUCCESS) {
5769e39c5baSBill Taylor logmsg(MSG_INFO,
5779e39c5baSBill Taylor "tavor: failed to update #2 firmware image\n");
5789e39c5baSBill Taylor (void) tavor_close(flashdev);
5799e39c5baSBill Taylor return (FWFLASH_FAILURE);
5809e39c5baSBill Taylor }
5819e39c5baSBill Taylor
5829e39c5baSBill Taylor rv = tavor_blast_image(manuf->fd, 1, hpfia, manuf->sector_sz, ipps);
5839e39c5baSBill Taylor if (rv != FWFLASH_SUCCESS) {
5849e39c5baSBill Taylor logmsg(MSG_INFO,
5859e39c5baSBill Taylor "tavor: failed to update #1 firmware image\n");
5869e39c5baSBill Taylor (void) tavor_close(flashdev);
5879e39c5baSBill Taylor return (FWFLASH_FAILURE);
5889e39c5baSBill Taylor }
5899e39c5baSBill Taylor
5909e39c5baSBill Taylor /* final update marker to the user */
5919e39c5baSBill Taylor (void) printf(" +\n");
5929e39c5baSBill Taylor return (tavor_close(flashdev));
5939e39c5baSBill Taylor }
5949e39c5baSBill Taylor
5959e39c5baSBill Taylor
5969e39c5baSBill Taylor /*
5979e39c5baSBill Taylor * The fw_identify() function walks the device
5989e39c5baSBill Taylor * tree trying to find devices which this plugin
5999e39c5baSBill Taylor * can work with.
6009e39c5baSBill Taylor *
6019e39c5baSBill Taylor * The parameter "start" gives us the starting index number
6029e39c5baSBill Taylor * to give the device when we add it to the fw_devices list.
6039e39c5baSBill Taylor *
6049e39c5baSBill Taylor * firstdev is allocated by us and we add space as necessary
6059e39c5baSBill Taylor *
6069e39c5baSBill Taylor */
6079e39c5baSBill Taylor int
fw_identify(int start)6089e39c5baSBill Taylor fw_identify(int start)
6099e39c5baSBill Taylor {
6109e39c5baSBill Taylor int rv = FWFLASH_FAILURE;
6119e39c5baSBill Taylor di_node_t thisnode;
6129e39c5baSBill Taylor struct devicelist *newdev;
6139e39c5baSBill Taylor char *devpath;
6149e39c5baSBill Taylor int idx = start;
6159e39c5baSBill Taylor int devlength = 0;
6169e39c5baSBill Taylor
6179e39c5baSBill Taylor thisnode = di_drv_first_node(drivername, rootnode);
6189e39c5baSBill Taylor
6199e39c5baSBill Taylor if (thisnode == DI_NODE_NIL) {
6209e39c5baSBill Taylor logmsg(MSG_INFO, gettext("No %s nodes in this system\n"),
6219e39c5baSBill Taylor drivername);
6229e39c5baSBill Taylor return (rv);
6239e39c5baSBill Taylor }
6249e39c5baSBill Taylor
6259e39c5baSBill Taylor /* we've found one, at least */
6269e39c5baSBill Taylor for (; thisnode != DI_NODE_NIL; thisnode = di_drv_next_node(thisnode)) {
6279e39c5baSBill Taylor
6289e39c5baSBill Taylor devpath = di_devfs_path(thisnode);
6299e39c5baSBill Taylor
6309e39c5baSBill Taylor if ((newdev = calloc(1, sizeof (struct devicelist)))
6319e39c5baSBill Taylor == NULL) {
6329e39c5baSBill Taylor logmsg(MSG_ERROR,
633ee5d8455SShantkumar Hiremath gettext("tavor identification function: unable "
6349e39c5baSBill Taylor "to allocate space for device entry\n"));
6359e39c5baSBill Taylor di_devfs_path_free(devpath);
6369e39c5baSBill Taylor return (rv);
6379e39c5baSBill Taylor }
6389e39c5baSBill Taylor
6399e39c5baSBill Taylor /* calloc enough for /devices + devpath + ":devctl" + '\0' */
6409e39c5baSBill Taylor devlength = strlen(devpath) + strlen(devprefix) +
6419e39c5baSBill Taylor strlen(devsuffix) + 2;
6429e39c5baSBill Taylor
6439e39c5baSBill Taylor if ((newdev->access_devname = calloc(1, devlength)) == NULL) {
6449e39c5baSBill Taylor logmsg(MSG_ERROR, gettext("Unable to calloc space "
6459e39c5baSBill Taylor "for a devfs name\n"));
6469e39c5baSBill Taylor di_devfs_path_free(devpath);
6479e39c5baSBill Taylor (void) free(newdev);
6489e39c5baSBill Taylor return (FWFLASH_FAILURE);
6499e39c5baSBill Taylor }
6509e39c5baSBill Taylor snprintf(newdev->access_devname, devlength,
6519e39c5baSBill Taylor "%s%s%s", devprefix, devpath, devsuffix);
6529e39c5baSBill Taylor
6539e39c5baSBill Taylor /* CHECK VARIOUS IB THINGS HERE */
6549e39c5baSBill Taylor
6559e39c5baSBill Taylor if ((newdev->ident = calloc(1, sizeof (struct vpr))) == NULL) {
6569e39c5baSBill Taylor logmsg(MSG_ERROR,
6579e39c5baSBill Taylor gettext("tavor: Unable to allocate space for a "
6589e39c5baSBill Taylor "device identification record\n"));
6599e39c5baSBill Taylor (void) free(newdev->access_devname);
6609e39c5baSBill Taylor (void) free(newdev);
6619e39c5baSBill Taylor di_devfs_path_free(devpath);
6629e39c5baSBill Taylor return (FWFLASH_FAILURE);
6639e39c5baSBill Taylor }
6649e39c5baSBill Taylor
6659e39c5baSBill Taylor rv = tavor_identify(newdev);
6669e39c5baSBill Taylor if (rv == FWFLASH_FAILURE) {
6679e39c5baSBill Taylor (void) free(newdev->ident);
6689e39c5baSBill Taylor (void) free(newdev->access_devname);
6699e39c5baSBill Taylor (void) free(newdev);
6709e39c5baSBill Taylor di_devfs_path_free(devpath);
6719e39c5baSBill Taylor continue;
6729e39c5baSBill Taylor }
6739e39c5baSBill Taylor
6749e39c5baSBill Taylor if ((newdev->drvname = calloc(1, strlen(drivername) + 1))
6759e39c5baSBill Taylor == NULL) {
6769e39c5baSBill Taylor logmsg(MSG_ERROR, gettext("Unable to allocate space "
6779e39c5baSBill Taylor "for a driver name\n"));
6789e39c5baSBill Taylor (void) free(newdev->ident);
6799e39c5baSBill Taylor (void) free(newdev->access_devname);
6809e39c5baSBill Taylor (void) free(newdev);
6819e39c5baSBill Taylor di_devfs_path_free(devpath);
6829e39c5baSBill Taylor return (FWFLASH_FAILURE);
6839e39c5baSBill Taylor }
6849e39c5baSBill Taylor
6859e39c5baSBill Taylor (void) strlcpy(newdev->drvname, drivername,
6869e39c5baSBill Taylor strlen(drivername) + 1);
6879e39c5baSBill Taylor
6889e39c5baSBill Taylor /* this next bit is backwards compatibility - "IB\0" */
6899e39c5baSBill Taylor if ((newdev->classname = calloc(1, 3)) == NULL) {
6909e39c5baSBill Taylor logmsg(MSG_ERROR, gettext("Unable to allocate space "
6919e39c5baSBill Taylor "for a class name\n"));
6929e39c5baSBill Taylor (void) free(newdev->drvname);
6939e39c5baSBill Taylor (void) free(newdev->ident);
6949e39c5baSBill Taylor (void) free(newdev->access_devname);
6959e39c5baSBill Taylor (void) free(newdev);
6969e39c5baSBill Taylor di_devfs_path_free(devpath);
6979e39c5baSBill Taylor return (FWFLASH_FAILURE);
6989e39c5baSBill Taylor }
6999e39c5baSBill Taylor (void) strlcpy(newdev->classname, "IB", 3);
7009e39c5baSBill Taylor
7019e39c5baSBill Taylor newdev->index = idx;
7029e39c5baSBill Taylor ++idx;
7039e39c5baSBill Taylor newdev->plugin = self;
7049e39c5baSBill Taylor
7059e39c5baSBill Taylor di_devfs_path_free(devpath);
7069e39c5baSBill Taylor TAILQ_INSERT_TAIL(fw_devices, newdev, nextdev);
7079e39c5baSBill Taylor }
7089e39c5baSBill Taylor
7099e39c5baSBill Taylor if (fwflash_debug != 0) {
7109e39c5baSBill Taylor struct devicelist *tempdev;
7119e39c5baSBill Taylor
7129e39c5baSBill Taylor TAILQ_FOREACH(tempdev, fw_devices, nextdev) {
713*b67a60d6SShantkumar Hiremath logmsg(MSG_INFO, "fw_identify:\n");
7149e39c5baSBill Taylor logmsg(MSG_INFO, "\ttempdev @ 0x%lx\n"
7159e39c5baSBill Taylor "\t\taccess_devname: %s\n"
7169e39c5baSBill Taylor "\t\tdrvname: %s\tclassname: %s\n"
7179e39c5baSBill Taylor "\t\tident->vid: %s\n"
7189e39c5baSBill Taylor "\t\tident->pid: %s\n"
7199e39c5baSBill Taylor "\t\tident->revid: %s\n"
7209e39c5baSBill Taylor "\t\tindex: %d\n"
7219e39c5baSBill Taylor "\t\tguid0: %s\n"
7229e39c5baSBill Taylor "\t\tguid1: %s\n"
7239e39c5baSBill Taylor "\t\tguid2: %s\n"
7249e39c5baSBill Taylor "\t\tguid3: %s\n"
7259e39c5baSBill Taylor "\t\tplugin @ 0x%lx\n\n",
7269e39c5baSBill Taylor &tempdev,
7279e39c5baSBill Taylor tempdev->access_devname,
7289e39c5baSBill Taylor tempdev->drvname, newdev->classname,
7299e39c5baSBill Taylor tempdev->ident->vid,
7309e39c5baSBill Taylor tempdev->ident->pid,
7319e39c5baSBill Taylor tempdev->ident->revid,
7329e39c5baSBill Taylor tempdev->index,
733*b67a60d6SShantkumar Hiremath (tempdev->addresses[0] ? tempdev->addresses[0] :
734*b67a60d6SShantkumar Hiremath "(not supported)"),
735*b67a60d6SShantkumar Hiremath (tempdev->addresses[1] ? tempdev->addresses[1] :
736*b67a60d6SShantkumar Hiremath "(not supported)"),
737*b67a60d6SShantkumar Hiremath (tempdev->addresses[2] ? tempdev->addresses[2] :
738*b67a60d6SShantkumar Hiremath "(not supported)"),
739*b67a60d6SShantkumar Hiremath (tempdev->addresses[3] ? tempdev->addresses[3] :
740*b67a60d6SShantkumar Hiremath "(not supported)"),
7419e39c5baSBill Taylor tempdev->plugin);
7429e39c5baSBill Taylor }
7439e39c5baSBill Taylor }
7449e39c5baSBill Taylor
7459e39c5baSBill Taylor return (FWFLASH_SUCCESS);
7469e39c5baSBill Taylor }
7479e39c5baSBill Taylor
7489e39c5baSBill Taylor
7499e39c5baSBill Taylor
7509e39c5baSBill Taylor int
fw_devinfo(struct devicelist * thisdev)7519e39c5baSBill Taylor fw_devinfo(struct devicelist *thisdev)
7529e39c5baSBill Taylor {
7539e39c5baSBill Taylor
7549e39c5baSBill Taylor struct ib_encap_ident *encap;
7559e39c5baSBill Taylor
7569e39c5baSBill Taylor
7579e39c5baSBill Taylor encap = (struct ib_encap_ident *)thisdev->ident->encap_ident;
7589e39c5baSBill Taylor
7599e39c5baSBill Taylor fprintf(stdout, gettext("Device[%d] %s\n Class [%s]\n"),
7609e39c5baSBill Taylor thisdev->index, thisdev->access_devname, thisdev->classname);
7619e39c5baSBill Taylor
7629e39c5baSBill Taylor fprintf(stdout, "\t");
7639e39c5baSBill Taylor
7649e39c5baSBill Taylor /* Mellanox HCA Flash app note, p40, #4.2.3 table 9 */
7659e39c5baSBill Taylor fprintf(stdout,
7669e39c5baSBill Taylor gettext("GUID: System Image - %s\n"),
7679e39c5baSBill Taylor thisdev->addresses[3]);
7689e39c5baSBill Taylor fprintf(stdout,
7699e39c5baSBill Taylor gettext("\t\tNode Image - %s\n"),
7709e39c5baSBill Taylor thisdev->addresses[0]);
7719e39c5baSBill Taylor fprintf(stdout,
7729e39c5baSBill Taylor gettext("\t\tPort 1\t - %s\n"),
7739e39c5baSBill Taylor thisdev->addresses[1]);
7749e39c5baSBill Taylor fprintf(stdout,
7759e39c5baSBill Taylor gettext("\t\tPort 2\t - %s\n"),
7769e39c5baSBill Taylor thisdev->addresses[2]);
7779e39c5baSBill Taylor
7789e39c5baSBill Taylor if (encap->pn_len != 0) {
7799e39c5baSBill Taylor fprintf(stdout,
7809e39c5baSBill Taylor gettext("\tFirmware revision : %s\n"
781*b67a60d6SShantkumar Hiremath "\tProduct\t\t: %s %X\n"
7829e39c5baSBill Taylor "\tPSID\t\t: %s\n"),
7839e39c5baSBill Taylor thisdev->ident->revid,
7849e39c5baSBill Taylor encap->info.mlx_pn,
785*b67a60d6SShantkumar Hiremath encap->hwrev,
7869e39c5baSBill Taylor encap->info.mlx_psid);
787*b67a60d6SShantkumar Hiremath } else {
7889e39c5baSBill Taylor fprintf(stdout,
7899e39c5baSBill Taylor gettext("\tFirmware revision : %s\n"
7909e39c5baSBill Taylor "\tNo hardware information available for this "
7919e39c5baSBill Taylor "device\n"), thisdev->ident->revid);
7929e39c5baSBill Taylor }
7939e39c5baSBill Taylor fprintf(stdout, "\n\n");
7949e39c5baSBill Taylor
7959e39c5baSBill Taylor return (tavor_close(thisdev));
7969e39c5baSBill Taylor }
7979e39c5baSBill Taylor
7989e39c5baSBill Taylor
7999e39c5baSBill Taylor /*
8009e39c5baSBill Taylor * Helper functions lurk beneath this point
8019e39c5baSBill Taylor */
8029e39c5baSBill Taylor
8039e39c5baSBill Taylor
8049e39c5baSBill Taylor /*
8059e39c5baSBill Taylor * tavor_identify performs the following actions:
8069e39c5baSBill Taylor *
8079e39c5baSBill Taylor * allocates and assigns thisdev->vpr
8089e39c5baSBill Taylor *
8099e39c5baSBill Taylor * allocates space for the 4 GUIDs which each IB device must have
8109e39c5baSBill Taylor * queries the tavor driver for this device's GUIDs
8119e39c5baSBill Taylor *
8129e39c5baSBill Taylor * determines the hardware vendor, so that thisdev->vpr->vid
8139e39c5baSBill Taylor * can be set correctly
8149e39c5baSBill Taylor */
8159e39c5baSBill Taylor static int
tavor_identify(struct devicelist * thisdev)8169e39c5baSBill Taylor tavor_identify(struct devicelist *thisdev)
8179e39c5baSBill Taylor {
8189e39c5baSBill Taylor int rv = FWFLASH_SUCCESS;
8199e39c5baSBill Taylor int fd, ret, i;
8209e39c5baSBill Taylor
8219e39c5baSBill Taylor tavor_flash_init_ioctl_t init_ioctl;
8229e39c5baSBill Taylor tavor_flash_ioctl_t info;
8239e39c5baSBill Taylor struct ib_encap_ident *manuf;
8249e39c5baSBill Taylor cfi_t cfi;
8259e39c5baSBill Taylor char temppsid[17];
8269e39c5baSBill Taylor char rawpsid[16];
8279e39c5baSBill Taylor
8289e39c5baSBill Taylor #if defined(_LITTLE_ENDIAN)
8299e39c5baSBill Taylor uint32_t *ptr;
8309e39c5baSBill Taylor #endif
8319e39c5baSBill Taylor
8329e39c5baSBill Taylor /* open the device */
8339e39c5baSBill Taylor /* hook thisdev->ident->encap_ident to ib_encap_ident */
8349e39c5baSBill Taylor /* check that all the bits are sane */
8359e39c5baSBill Taylor /* return success, if warranted */
8369e39c5baSBill Taylor
8379e39c5baSBill Taylor errno = 0;
8389e39c5baSBill Taylor if ((fd = open(thisdev->access_devname, O_RDONLY)) < 0) {
8399e39c5baSBill Taylor logmsg(MSG_INFO,
8409e39c5baSBill Taylor gettext("tavor: Unable to open a %s-attached "
8419e39c5baSBill Taylor "device node: %s: %s\n"), drivername,
8429e39c5baSBill Taylor thisdev->access_devname, strerror(errno));
8439e39c5baSBill Taylor return (FWFLASH_FAILURE);
8449e39c5baSBill Taylor }
8459e39c5baSBill Taylor
8469e39c5baSBill Taylor if ((manuf = calloc(1, sizeof (ib_encap_ident_t))) == NULL) {
8479e39c5baSBill Taylor logmsg(MSG_ERROR,
8489e39c5baSBill Taylor gettext("tavor: Unable to calloc space for a "
8499e39c5baSBill Taylor "%s-attached handle structure\n"),
8509e39c5baSBill Taylor drivername);
8519e39c5baSBill Taylor return (FWFLASH_FAILURE);
8529e39c5baSBill Taylor }
8539e39c5baSBill Taylor manuf->magic = FWFLASH_IB_MAGIC_NUMBER;
8549e39c5baSBill Taylor manuf->state = FWFLASH_IB_STATE_NONE;
8559e39c5baSBill Taylor manuf->fd = fd;
8569e39c5baSBill Taylor
8579e39c5baSBill Taylor thisdev->ident->encap_ident = manuf;
8589e39c5baSBill Taylor
859ee5d8455SShantkumar Hiremath bzero(&init_ioctl, sizeof (tavor_flash_init_ioctl_t));
860ee5d8455SShantkumar Hiremath bzero(&cfi, sizeof (cfi_t));
8619e39c5baSBill Taylor /*
8629e39c5baSBill Taylor * Inform driver that this command supports the Intel Extended
8639e39c5baSBill Taylor * CFI command set.
8649e39c5baSBill Taylor */
8659e39c5baSBill Taylor cfi.cfi_char[0x10] = 'M';
8669e39c5baSBill Taylor cfi.cfi_char[0x11] = 'X';
8679e39c5baSBill Taylor cfi.cfi_char[0x12] = '2';
8689e39c5baSBill Taylor init_ioctl.tf_cfi_info[0x4] = MLXSWAPBITS32(cfi.cfi_int[0x4]);
8699e39c5baSBill Taylor
8709e39c5baSBill Taylor errno = 0;
8719e39c5baSBill Taylor ret = ioctl(fd, TAVOR_IOCTL_FLASH_INIT, &init_ioctl);
8729e39c5baSBill Taylor if (ret < 0) {
8739e39c5baSBill Taylor logmsg(MSG_ERROR,
8749e39c5baSBill Taylor gettext("ib: TAVOR_IOCTL_FLASH_INIT failed: %s\n"),
8759e39c5baSBill Taylor strerror(errno));
8769e39c5baSBill Taylor free(manuf);
8779e39c5baSBill Taylor close(fd);
8789e39c5baSBill Taylor return (FWFLASH_FAILURE);
8799e39c5baSBill Taylor }
8809e39c5baSBill Taylor
8819e39c5baSBill Taylor manuf->hwrev = init_ioctl.tf_hwrev;
8829e39c5baSBill Taylor
883*b67a60d6SShantkumar Hiremath logmsg(MSG_INFO, "tavor_identify: init_ioctl: hwrev: %X, "
884*b67a60d6SShantkumar Hiremath "fwver: %d.%d.%04d\n", init_ioctl.tf_hwrev,
885*b67a60d6SShantkumar Hiremath init_ioctl.tf_fwrev.tfi_maj, init_ioctl.tf_fwrev.tfi_min,
886*b67a60d6SShantkumar Hiremath init_ioctl.tf_fwrev.tfi_sub);
887*b67a60d6SShantkumar Hiremath
8889e39c5baSBill Taylor /*
8899e39c5baSBill Taylor * Determine whether the attached driver supports the Intel or
8909e39c5baSBill Taylor * AMD Extended CFI command sets. If it doesn't support either,
8919e39c5baSBill Taylor * then we're hosed, so error out.
8929e39c5baSBill Taylor */
8939e39c5baSBill Taylor for (i = 0; i < TAVOR_FLASH_CFI_SIZE_QUADLET; i++) {
8949e39c5baSBill Taylor cfi.cfi_int[i] = MLXSWAPBITS32(init_ioctl.tf_cfi_info[i]);
8959e39c5baSBill Taylor }
8969e39c5baSBill Taylor manuf->cmd_set = cfi.cfi_char[0x13];
8979e39c5baSBill Taylor
8989e39c5baSBill Taylor if (cfi.cfi_char[0x10] == 'Q' &&
8999e39c5baSBill Taylor cfi.cfi_char[0x11] == 'R' &&
9009e39c5baSBill Taylor cfi.cfi_char[0x12] == 'Y') {
9019e39c5baSBill Taylor /* make sure the cmd set is AMD */
9029e39c5baSBill Taylor if (manuf->cmd_set != TAVOR_FLASH_AMD_CMDSET) {
9039e39c5baSBill Taylor logmsg(MSG_ERROR,
9049e39c5baSBill Taylor gettext("tavor: Unsupported flash device "
9059e39c5baSBill Taylor "command set\n"));
9069e39c5baSBill Taylor free(manuf);
9079e39c5baSBill Taylor close(fd);
9089e39c5baSBill Taylor return (FWFLASH_FAILURE);
9099e39c5baSBill Taylor }
9109e39c5baSBill Taylor /* set some defaults */
911ee5d8455SShantkumar Hiremath manuf->sector_sz = TAVOR_FLASH_SECTOR_SZ_DEFAULT;
9129e39c5baSBill Taylor manuf->device_sz = TAVOR_FLASH_DEVICE_SZ_DEFAULT;
913ee5d8455SShantkumar Hiremath logmsg(MSG_INFO, "tavor_identify: CMDSET is AMD, SectorSz "
914ee5d8455SShantkumar Hiremath "are default \n");
9159e39c5baSBill Taylor } else {
9169e39c5baSBill Taylor if (manuf->cmd_set != TAVOR_FLASH_AMD_CMDSET &&
9179e39c5baSBill Taylor manuf->cmd_set != TAVOR_FLASH_INTEL_CMDSET) {
9189e39c5baSBill Taylor logmsg(MSG_ERROR,
9199e39c5baSBill Taylor gettext("ib: Unknown flash device command set\n"));
9209e39c5baSBill Taylor free(manuf);
9219e39c5baSBill Taylor close(fd);
9229e39c5baSBill Taylor return (FWFLASH_FAILURE);
9239e39c5baSBill Taylor }
9249e39c5baSBill Taylor /* read from the CFI data */
9259e39c5baSBill Taylor manuf->sector_sz = ((cfi.cfi_char[0x30] << 8) |
9269e39c5baSBill Taylor cfi.cfi_char[0x2F]) << 8;
9279e39c5baSBill Taylor manuf->device_sz = 0x1 << cfi.cfi_char[0x27];
928ee5d8455SShantkumar Hiremath logmsg(MSG_INFO, "tavor_identify: SectorSz is from CFI Data\n");
9299e39c5baSBill Taylor }
9309e39c5baSBill Taylor
931ee5d8455SShantkumar Hiremath logmsg(MSG_INFO, "tavor_identify: sector_sz: 0x%08x dev_sz: 0x%08x\n",
9329e39c5baSBill Taylor manuf->sector_sz, manuf->device_sz);
9339e39c5baSBill Taylor
9349e39c5baSBill Taylor manuf->state |= FWFLASH_IB_STATE_MMAP;
9359e39c5baSBill Taylor
9369e39c5baSBill Taylor /* set firmware revision */
9379e39c5baSBill Taylor manuf->fw_rev.major = init_ioctl.tf_fwrev.tfi_maj;
9389e39c5baSBill Taylor manuf->fw_rev.minor = init_ioctl.tf_fwrev.tfi_min;
9399e39c5baSBill Taylor manuf->fw_rev.subminor = init_ioctl.tf_fwrev.tfi_sub;
9409e39c5baSBill Taylor
941ee5d8455SShantkumar Hiremath logmsg(MSG_INFO, "tavor_identify: pn_len %d hwpn %s \n",
942ee5d8455SShantkumar Hiremath init_ioctl.tf_pn_len,
943ee5d8455SShantkumar Hiremath (init_ioctl.tf_pn_len != 0) ? init_ioctl.tf_hwpn : "(null)");
944ee5d8455SShantkumar Hiremath
9459e39c5baSBill Taylor if (((thisdev->ident->vid = calloc(1, MLX_VPR_VIDLEN + 1)) == NULL) ||
9469e39c5baSBill Taylor ((thisdev->ident->revid = calloc(1, MLX_VPR_REVLEN + 1)) == NULL)) {
9479e39c5baSBill Taylor
9489e39c5baSBill Taylor logmsg(MSG_ERROR,
9499e39c5baSBill Taylor gettext("ib: Unable to allocate space for a VPR "
9509e39c5baSBill Taylor "record.\n"));
9519e39c5baSBill Taylor free(thisdev->ident);
9529e39c5baSBill Taylor free(manuf->info.mlx_pn);
9539e39c5baSBill Taylor free(manuf->info.mlx_psid);
9549e39c5baSBill Taylor free(manuf->info.mlx_id);
9559e39c5baSBill Taylor free(manuf);
9569e39c5baSBill Taylor close(fd);
9579e39c5baSBill Taylor return (FWFLASH_FAILURE);
9589e39c5baSBill Taylor }
9599e39c5baSBill Taylor (void) strlcpy(thisdev->ident->vid, "MELLANOX", MLX_VPR_VIDLEN);
9609e39c5baSBill Taylor /*
9619e39c5baSBill Taylor * We actually want the hwrev field from the ioctl above.
9629e39c5baSBill Taylor * Until we find out otherwise, add it onto the end of the
9639e39c5baSBill Taylor * firmware version details.
9649e39c5baSBill Taylor */
9659e39c5baSBill Taylor
966ee5d8455SShantkumar Hiremath snprintf(thisdev->ident->revid, MLX_VPR_REVLEN, "%d.%d.%03d",
9679e39c5baSBill Taylor manuf->fw_rev.major, manuf->fw_rev.minor,
9689e39c5baSBill Taylor manuf->fw_rev.subminor);
9699e39c5baSBill Taylor
9709e39c5baSBill Taylor bzero(manuf->ibguids, sizeof (manuf->ibguids));
9719e39c5baSBill Taylor
9729e39c5baSBill Taylor /*
9739e39c5baSBill Taylor * For convenience we read in the Invariant Sector as
9749e39c5baSBill Taylor * well as both the Primary and Secondary Pointer Sectors
9759e39c5baSBill Taylor */
9769e39c5baSBill Taylor
9779e39c5baSBill Taylor if ((manuf->inv = calloc(1, manuf->sector_sz)) == NULL) {
9789e39c5baSBill Taylor logmsg(MSG_ERROR,
9799e39c5baSBill Taylor gettext("tavor: Unable to allocate space for storing "
9809e39c5baSBill Taylor "the HCA's Invariant Sector\n"));
9819e39c5baSBill Taylor return (FWFLASH_FAILURE);
9829e39c5baSBill Taylor }
9839e39c5baSBill Taylor bzero(&info, sizeof (tavor_flash_ioctl_t));
9849e39c5baSBill Taylor
9859e39c5baSBill Taylor info.tf_type = TAVOR_FLASH_READ_SECTOR;
9869e39c5baSBill Taylor info.tf_sector = (caddr_t)manuf->inv;
9879e39c5baSBill Taylor info.tf_sector_num = 0;
9889e39c5baSBill Taylor
9899e39c5baSBill Taylor errno = 0;
9909e39c5baSBill Taylor
9919e39c5baSBill Taylor if ((rv = ioctl(manuf->fd, TAVOR_IOCTL_FLASH_READ, &info))
9929e39c5baSBill Taylor < 0) {
9939e39c5baSBill Taylor logmsg(MSG_ERROR,
9949e39c5baSBill Taylor gettext("tavor: Unable to read HCA Invariant Sector\n"));
9959e39c5baSBill Taylor return (FWFLASH_FAILURE);
9969e39c5baSBill Taylor }
9979e39c5baSBill Taylor
9989e39c5baSBill Taylor #if defined(_LITTLE_ENDIAN)
9999e39c5baSBill Taylor ptr = (uint32_t *)(uintptr_t)manuf->inv;
10009e39c5baSBill Taylor for (i = 0; i < (manuf->sector_sz / 4); i++) {
10019e39c5baSBill Taylor ptr[i] = htonl(ptr[i]);
10029e39c5baSBill Taylor }
10039e39c5baSBill Taylor #endif
10049e39c5baSBill Taylor
10059e39c5baSBill Taylor if ((manuf->pps = calloc(1, manuf->sector_sz)) == NULL) {
10069e39c5baSBill Taylor logmsg(MSG_ERROR,
10079e39c5baSBill Taylor gettext("tavor: Unable to allocate space for storing "
10089e39c5baSBill Taylor "the HCA's Primary Pointer Sector\n"));
10099e39c5baSBill Taylor return (FWFLASH_FAILURE);
10109e39c5baSBill Taylor }
10119e39c5baSBill Taylor bzero(&info, sizeof (tavor_flash_ioctl_t));
10129e39c5baSBill Taylor
10139e39c5baSBill Taylor info.tf_type = TAVOR_FLASH_READ_SECTOR;
10149e39c5baSBill Taylor info.tf_sector = (caddr_t)manuf->pps;
10159e39c5baSBill Taylor info.tf_sector_num = 1;
10169e39c5baSBill Taylor
10179e39c5baSBill Taylor errno = 0;
10189e39c5baSBill Taylor
10199e39c5baSBill Taylor if ((rv = ioctl(manuf->fd, TAVOR_IOCTL_FLASH_READ, &info))
10209e39c5baSBill Taylor < 0) {
10219e39c5baSBill Taylor logmsg(MSG_ERROR,
10229e39c5baSBill Taylor gettext("tavor: Unable to read HCA Primary "
10239e39c5baSBill Taylor "Pointer Sector\n"));
10249e39c5baSBill Taylor return (FWFLASH_FAILURE);
10259e39c5baSBill Taylor }
10269e39c5baSBill Taylor
10279e39c5baSBill Taylor #if defined(_LITTLE_ENDIAN)
10289e39c5baSBill Taylor ptr = (uint32_t *)(uintptr_t)manuf->pps;
10299e39c5baSBill Taylor for (i = 0; i < (manuf->sector_sz / 4); i++) {
10309e39c5baSBill Taylor ptr[i] = htonl(ptr[i]);
10319e39c5baSBill Taylor }
10329e39c5baSBill Taylor #endif
10339e39c5baSBill Taylor
10349e39c5baSBill Taylor if ((manuf->sps = calloc(1, manuf->sector_sz)) == NULL) {
10359e39c5baSBill Taylor logmsg(MSG_ERROR,
10369e39c5baSBill Taylor gettext("tavor: Unable to allocate space for storing "
10379e39c5baSBill Taylor "the HCA's Secondary Pointer Sector\n"));
10389e39c5baSBill Taylor return (FWFLASH_FAILURE);
10399e39c5baSBill Taylor }
10409e39c5baSBill Taylor bzero(&info, sizeof (tavor_flash_ioctl_t));
10419e39c5baSBill Taylor
10429e39c5baSBill Taylor info.tf_type = TAVOR_FLASH_READ_SECTOR;
10439e39c5baSBill Taylor info.tf_sector = (caddr_t)manuf->sps;
10449e39c5baSBill Taylor info.tf_sector_num = 2;
10459e39c5baSBill Taylor
10469e39c5baSBill Taylor errno = 0;
10479e39c5baSBill Taylor
10489e39c5baSBill Taylor if ((rv = ioctl(manuf->fd, TAVOR_IOCTL_FLASH_READ, &info))
10499e39c5baSBill Taylor < 0) {
10509e39c5baSBill Taylor logmsg(MSG_ERROR,
10519e39c5baSBill Taylor gettext("tavor: Unable to read HCA Secondary "
10529e39c5baSBill Taylor "Pointer Sector\n"));
10539e39c5baSBill Taylor return (FWFLASH_FAILURE);
10549e39c5baSBill Taylor }
10559e39c5baSBill Taylor
10569e39c5baSBill Taylor #if defined(_LITTLE_ENDIAN)
10579e39c5baSBill Taylor ptr = (uint32_t *)(uintptr_t)manuf->sps;
10589e39c5baSBill Taylor for (i = 0; i < (manuf->sector_sz / 4); i++) {
10599e39c5baSBill Taylor ptr[i] = htonl(ptr[i]);
10609e39c5baSBill Taylor }
10619e39c5baSBill Taylor #endif
10629e39c5baSBill Taylor
10639e39c5baSBill Taylor if ((ret = tavor_get_guids(manuf)) != FWFLASH_SUCCESS) {
10649e39c5baSBill Taylor logmsg(MSG_INFO,
10659e39c5baSBill Taylor gettext("ib: No guids found for device %s!\n"),
10669e39c5baSBill Taylor thisdev->access_devname);
10679e39c5baSBill Taylor }
10689e39c5baSBill Taylor
10699e39c5baSBill Taylor /* set hw part number, psid, and name in handle */
10709e39c5baSBill Taylor bzero(temppsid, 17);
10719e39c5baSBill Taylor bcopy(manuf->pps+FLASH_PS_PSID_OFFSET, &rawpsid, 16);
10729e39c5baSBill Taylor
10739e39c5baSBill Taylor for (i = 0; i < 16; i += 4) {
10749e39c5baSBill Taylor temppsid[i] = rawpsid[i+3];
10759e39c5baSBill Taylor temppsid[i+1] = rawpsid[i+2];
10769e39c5baSBill Taylor temppsid[i+2] = rawpsid[i+1];
10779e39c5baSBill Taylor temppsid[i+3] = rawpsid[i];
10789e39c5baSBill Taylor }
10799e39c5baSBill Taylor logmsg(MSG_INFO,
10809e39c5baSBill Taylor "tavor: have raw '%s', want munged '%s'\n",
10819e39c5baSBill Taylor rawpsid, temppsid);
10829e39c5baSBill Taylor
10839e39c5baSBill Taylor /* now walk the magic decoder ring table */
10849e39c5baSBill Taylor manuf->info.mlx_pn = NULL;
10859e39c5baSBill Taylor manuf->info.mlx_psid = NULL;
10869e39c5baSBill Taylor manuf->info.mlx_id = NULL;
10879e39c5baSBill Taylor manuf->pn_len = 0;
10889e39c5baSBill Taylor
10899e39c5baSBill Taylor for (i = 0; i < MLX_MAX_ID; i++) {
10909e39c5baSBill Taylor if ((strncmp(temppsid, mlx_mdr[i].mlx_psid,
10919e39c5baSBill Taylor MLX_PSID_SZ)) == 0) {
10929e39c5baSBill Taylor /* matched */
10939e39c5baSBill Taylor if ((manuf->info.mlx_pn = calloc(1,
10949e39c5baSBill Taylor strlen(mlx_mdr[i].mlx_pn) + 1)) == NULL) {
10959e39c5baSBill Taylor logmsg(MSG_INFO,
10969e39c5baSBill Taylor "tavor: no space available for the "
10979e39c5baSBill Taylor "HCA PSID record (1)\n");
10989e39c5baSBill Taylor } else {
10999e39c5baSBill Taylor (void) strlcpy(manuf->info.mlx_pn,
11009e39c5baSBill Taylor mlx_mdr[i].mlx_pn,
11019e39c5baSBill Taylor strlen(mlx_mdr[i].mlx_pn) + 1);
11029e39c5baSBill Taylor manuf->pn_len = strlen(mlx_mdr[i].mlx_pn);
11039e39c5baSBill Taylor }
11049e39c5baSBill Taylor
11059e39c5baSBill Taylor if ((manuf->info.mlx_psid = calloc(1,
11069e39c5baSBill Taylor strlen(mlx_mdr[i].mlx_psid) + 1)) == NULL) {
11079e39c5baSBill Taylor logmsg(MSG_INFO,
11089e39c5baSBill Taylor "tavor: no space available for the "
11099e39c5baSBill Taylor "HCA PSID record (2)\n");
11109e39c5baSBill Taylor } else {
11119e39c5baSBill Taylor (void) strlcpy(manuf->info.mlx_psid,
11129e39c5baSBill Taylor mlx_mdr[i].mlx_psid,
11139e39c5baSBill Taylor strlen(mlx_mdr[i].mlx_psid) + 1);
11149e39c5baSBill Taylor }
11159e39c5baSBill Taylor if ((manuf->info.mlx_id = calloc(1,
11169e39c5baSBill Taylor strlen(mlx_mdr[i].mlx_id) + 1)) == NULL) {
11179e39c5baSBill Taylor logmsg(MSG_INFO,
11189e39c5baSBill Taylor "tavor: no space available for the "
11199e39c5baSBill Taylor "HCA PSID record (3)\n");
11209e39c5baSBill Taylor } else {
11219e39c5baSBill Taylor (void) strlcpy(manuf->info.mlx_id,
11229e39c5baSBill Taylor mlx_mdr[i].mlx_id,
11239e39c5baSBill Taylor strlen(mlx_mdr[i].mlx_id) + 1);
11249e39c5baSBill Taylor }
11259e39c5baSBill Taylor }
11269e39c5baSBill Taylor }
11279e39c5baSBill Taylor if ((manuf->pn_len == 0) || (i == MLX_MAX_ID)) {
11289e39c5baSBill Taylor logmsg(MSG_INFO,
11299e39c5baSBill Taylor "tavor: No hardware part number information available "
11309e39c5baSBill Taylor "for this HCA\n");
11319e39c5baSBill Taylor /* Until we deliver the arbel driver, it's all Mellanox */
11329e39c5baSBill Taylor i = strlen("No hardware information available for this device");
11339e39c5baSBill Taylor
11349e39c5baSBill Taylor thisdev->ident->pid = calloc(1, i + 2);
11359e39c5baSBill Taylor sprintf(thisdev->ident->pid, "No hardware information "
11369e39c5baSBill Taylor "available for this device");
11379e39c5baSBill Taylor } else {
11389e39c5baSBill Taylor if ((thisdev->ident->pid = calloc(1,
11399e39c5baSBill Taylor strlen(manuf->info.mlx_psid) + 1)) != NULL) {
11409e39c5baSBill Taylor (void) strlcpy(thisdev->ident->pid,
11419e39c5baSBill Taylor manuf->info.mlx_psid,
11429e39c5baSBill Taylor strlen(manuf->info.mlx_psid) + 1);
11439e39c5baSBill Taylor } else {
11449e39c5baSBill Taylor logmsg(MSG_ERROR,
11459e39c5baSBill Taylor gettext("ib: Unable to allocate space for a "
11469e39c5baSBill Taylor "hardware identifier\n"));
11479e39c5baSBill Taylor free(thisdev->ident);
11489e39c5baSBill Taylor free(manuf->info.mlx_pn);
11499e39c5baSBill Taylor free(manuf->info.mlx_psid);
11509e39c5baSBill Taylor free(manuf->info.mlx_id);
11519e39c5baSBill Taylor free(manuf);
11529e39c5baSBill Taylor close(fd);
11539e39c5baSBill Taylor return (FWFLASH_FAILURE);
11549e39c5baSBill Taylor }
11559e39c5baSBill Taylor }
11569e39c5baSBill Taylor
11579e39c5baSBill Taylor for (i = 0; i < 4; i++) {
11589e39c5baSBill Taylor if ((thisdev->addresses[i] = calloc(1,
11599e39c5baSBill Taylor (2 * sizeof (uint64_t)) + 1)) == NULL) {
11609e39c5baSBill Taylor logmsg(MSG_ERROR,
11619e39c5baSBill Taylor gettext("tavor: Unable to allocate space for a "
11629e39c5baSBill Taylor "human-readable HCA guid\n"));
11639e39c5baSBill Taylor return (FWFLASH_FAILURE);
11649e39c5baSBill Taylor }
11659e39c5baSBill Taylor (void) sprintf(thisdev->addresses[i], "%016llx",
11669e39c5baSBill Taylor manuf->ibguids[i]);
11679e39c5baSBill Taylor }
11689e39c5baSBill Taylor
11699e39c5baSBill Taylor /*
11709e39c5baSBill Taylor * We do NOT close the fd here, since we can close it
11719e39c5baSBill Taylor * at the end of the fw_readfw() or fw_writefw() functions
11729e39c5baSBill Taylor * instead and not get the poor dear confused about whether
11739e39c5baSBill Taylor * it's been inited already.
11749e39c5baSBill Taylor */
11759e39c5baSBill Taylor
11769e39c5baSBill Taylor return (rv);
11779e39c5baSBill Taylor }
11789e39c5baSBill Taylor
11799e39c5baSBill Taylor /*ARGSUSED*/
11809e39c5baSBill Taylor static int
tavor_get_guids(struct ib_encap_ident * handle)11819e39c5baSBill Taylor tavor_get_guids(struct ib_encap_ident *handle)
11829e39c5baSBill Taylor {
11839e39c5baSBill Taylor int rv, j;
11849e39c5baSBill Taylor uint32_t i = 0x00;
11859e39c5baSBill Taylor tavor_flash_ioctl_t info;
11869e39c5baSBill Taylor struct mlx_guid_sect *p, *s;
11879e39c5baSBill Taylor
11889e39c5baSBill Taylor #if defined(_LITTLE_ENDIAN)
11899e39c5baSBill Taylor uint32_t *ptr, tmp;
11909e39c5baSBill Taylor #endif
11919e39c5baSBill Taylor
11929e39c5baSBill Taylor /*
11939e39c5baSBill Taylor * The reference for this function is the
11949e39c5baSBill Taylor * Mellanox HCA Flash Programming Application Note
11959e39c5baSBill Taylor * rev 1.44, 2007. Chapter 4 in particular.
11969e39c5baSBill Taylor *
11979e39c5baSBill Taylor * NOTE: this Mellanox document is labelled Confidential
11989e39c5baSBill Taylor * so DO NOT move this file out of usr/closed without
11999e39c5baSBill Taylor * explicit approval from Sun Legal.
12009e39c5baSBill Taylor */
12019e39c5baSBill Taylor
12029e39c5baSBill Taylor /*
12039e39c5baSBill Taylor * We need to check for both the Primary and Secondary
12049e39c5baSBill Taylor * Image GUIDs. handle->pps and handle->sps should be
12059e39c5baSBill Taylor * non-NULL by the time we're called, since we depend
12069e39c5baSBill Taylor * on them being stashed in handle. Saves on an ioctl().
12079e39c5baSBill Taylor */
12089e39c5baSBill Taylor
12099e39c5baSBill Taylor /* make sure we've got our fallback position organised */
12109e39c5baSBill Taylor for (i = 0; i < 4; i++) {
12119e39c5baSBill Taylor handle->ibguids[i] = 0x00000000;
12129e39c5baSBill Taylor }
12139e39c5baSBill Taylor
12149e39c5baSBill Taylor /* convenience .... */
12159e39c5baSBill Taylor
12169e39c5baSBill Taylor if ((p = calloc(1, sizeof (mlx_guid_sect_t))) == NULL) {
12179e39c5baSBill Taylor logmsg(MSG_ERROR,
12189e39c5baSBill Taylor gettext("tavor: Unable to allocate space for "
12199e39c5baSBill Taylor "HCA guid record (1)\n"));
12209e39c5baSBill Taylor return (FWFLASH_FAILURE);
12219e39c5baSBill Taylor }
12229e39c5baSBill Taylor if ((s = calloc(1, sizeof (mlx_guid_sect_t))) == NULL) {
12239e39c5baSBill Taylor logmsg(MSG_ERROR,
12249e39c5baSBill Taylor gettext("tavor: Unable to allocate space for "
12259e39c5baSBill Taylor "HCA guid record (2)\n"));
12269e39c5baSBill Taylor free(p);
12279e39c5baSBill Taylor return (FWFLASH_FAILURE);
12289e39c5baSBill Taylor }
12299e39c5baSBill Taylor
12309e39c5baSBill Taylor bcopy(&handle->pps[0], &i, 4);
12319e39c5baSBill Taylor handle->pfi_guid_addr = MLXSWAPBITS32(i) + FLASH_GUID_PTR;
12329e39c5baSBill Taylor bcopy(&handle->sps[0], &i, 4);
12339e39c5baSBill Taylor handle->sfi_guid_addr = MLXSWAPBITS32(i) + FLASH_GUID_PTR;
12349e39c5baSBill Taylor
12359e39c5baSBill Taylor bzero(&info, sizeof (tavor_flash_ioctl_t));
12369e39c5baSBill Taylor info.tf_type = TAVOR_FLASH_READ_QUADLET;
12379e39c5baSBill Taylor info.tf_addr = handle->pfi_guid_addr;
12389e39c5baSBill Taylor
12399e39c5baSBill Taylor errno = 0;
12409e39c5baSBill Taylor
12419e39c5baSBill Taylor rv = ioctl(handle->fd, TAVOR_IOCTL_FLASH_READ, &info);
12429e39c5baSBill Taylor if (rv < 0) {
12439e39c5baSBill Taylor logmsg(MSG_ERROR,
12449e39c5baSBill Taylor gettext("tavor: Unable to read Primary Image "
12459e39c5baSBill Taylor "guid offset\n"));
12469e39c5baSBill Taylor free(p);
12479e39c5baSBill Taylor free(s);
12489e39c5baSBill Taylor return (FWFLASH_FAILURE);
12499e39c5baSBill Taylor }
12509e39c5baSBill Taylor
12519e39c5baSBill Taylor /*
12529e39c5baSBill Taylor * This is because we want the whole of the section
12539e39c5baSBill Taylor * including the 16 reserved bytes at the front so
12549e39c5baSBill Taylor * that if we recalculate the CRC we've got the correct
12559e39c5baSBill Taylor * data to do it with
12569e39c5baSBill Taylor */
12579e39c5baSBill Taylor info.tf_addr = handle->pfi_guid_addr + info.tf_quadlet
12589e39c5baSBill Taylor - FLASH_GUID_PTR - 16;
12599e39c5baSBill Taylor
12609e39c5baSBill Taylor bzero(handle->pri_guid_section, sizeof (mlx_guid_sect_t));
12619e39c5baSBill Taylor
12629e39c5baSBill Taylor for (j = 0; j < 13; j++) {
12639e39c5baSBill Taylor errno = 0;
12649e39c5baSBill Taylor if ((rv = ioctl(handle->fd, TAVOR_IOCTL_FLASH_READ,
12659e39c5baSBill Taylor &info)) < 0) {
12669e39c5baSBill Taylor logmsg(MSG_ERROR,
12679e39c5baSBill Taylor gettext("tavor: Unable to read Primary Image "
12689e39c5baSBill Taylor "guid chunk %d\n"), j);
12699e39c5baSBill Taylor }
12709e39c5baSBill Taylor handle->pri_guid_section[j] = info.tf_quadlet;
12719e39c5baSBill Taylor info.tf_addr += 4;
12729e39c5baSBill Taylor }
12739e39c5baSBill Taylor bcopy(&handle->pri_guid_section, p, sizeof (struct mlx_guid_sect));
12749e39c5baSBill Taylor
12759e39c5baSBill Taylor /* now grab the secondary guid set */
12769e39c5baSBill Taylor bzero(&info, sizeof (tavor_flash_ioctl_t));
12779e39c5baSBill Taylor info.tf_type = TAVOR_FLASH_READ_QUADLET;
12789e39c5baSBill Taylor info.tf_addr = handle->sfi_guid_addr;
12799e39c5baSBill Taylor
12809e39c5baSBill Taylor errno = 0;
12819e39c5baSBill Taylor
12829e39c5baSBill Taylor if ((rv = ioctl(handle->fd, TAVOR_IOCTL_FLASH_READ,
12839e39c5baSBill Taylor &info)) < 0) {
12849e39c5baSBill Taylor logmsg(MSG_ERROR,
12859e39c5baSBill Taylor gettext("tavor: Unable to read Secondary Image "
12869e39c5baSBill Taylor "guid offset (%s)\n"), strerror(errno));
12879e39c5baSBill Taylor free(p);
12889e39c5baSBill Taylor free(s);
12899e39c5baSBill Taylor return (FWFLASH_FAILURE);
12909e39c5baSBill Taylor }
12919e39c5baSBill Taylor
12929e39c5baSBill Taylor info.tf_addr = handle->sfi_guid_addr + info.tf_quadlet
12939e39c5baSBill Taylor - FLASH_GUID_PTR - 16;
12949e39c5baSBill Taylor
12959e39c5baSBill Taylor bzero(handle->sec_guid_section, sizeof (mlx_guid_sect_t));
12969e39c5baSBill Taylor
12979e39c5baSBill Taylor for (j = 0; j < 13; j++) {
12989e39c5baSBill Taylor errno = 0;
12999e39c5baSBill Taylor if ((rv = ioctl(handle->fd, TAVOR_IOCTL_FLASH_READ,
13009e39c5baSBill Taylor &info)) < 0) {
13019e39c5baSBill Taylor logmsg(MSG_ERROR,
13029e39c5baSBill Taylor gettext("tavor: Unable to read Secondary Image "
13039e39c5baSBill Taylor "guid chunk %d (%s)\n"), j, strerror(errno));
13049e39c5baSBill Taylor return (FWFLASH_FAILURE);
13059e39c5baSBill Taylor }
13069e39c5baSBill Taylor handle->sec_guid_section[j] = info.tf_quadlet;
13079e39c5baSBill Taylor info.tf_addr += 4;
13089e39c5baSBill Taylor }
13099e39c5baSBill Taylor
13109e39c5baSBill Taylor bcopy(&handle->sec_guid_section, s, sizeof (struct mlx_guid_sect));
13119e39c5baSBill Taylor
13129e39c5baSBill Taylor #if defined(_LITTLE_ENDIAN)
13139e39c5baSBill Taylor
13149e39c5baSBill Taylor /*
13159e39c5baSBill Taylor * We don't actually care about p or s later on if we
13169e39c5baSBill Taylor * write to the HCA - we've already stored the binary
13179e39c5baSBill Taylor * form in handle->pri_guid_section and handle->sec_guid_section.
13189e39c5baSBill Taylor * What we're doing here is creating human-readable forms.
13199e39c5baSBill Taylor */
13209e39c5baSBill Taylor
13219e39c5baSBill Taylor ptr = (uint32_t *)(uintptr_t)p;
13229e39c5baSBill Taylor for (j = 0; j < 14; j += 2) {
13239e39c5baSBill Taylor tmp = ptr[j];
13249e39c5baSBill Taylor ptr[j] = ptr[j+1];
13259e39c5baSBill Taylor ptr[j+1] = tmp;
13269e39c5baSBill Taylor }
13279e39c5baSBill Taylor
13289e39c5baSBill Taylor ptr = (uint32_t *)(uintptr_t)s;
13299e39c5baSBill Taylor for (j = 0; j < 14; j += 2) {
13309e39c5baSBill Taylor tmp = ptr[j];
13319e39c5baSBill Taylor ptr[j] = ptr[j+1];
13329e39c5baSBill Taylor ptr[j+1] = tmp;
13339e39c5baSBill Taylor }
13349e39c5baSBill Taylor #endif
13359e39c5baSBill Taylor
13369e39c5baSBill Taylor /*
13379e39c5baSBill Taylor * We don't check and munge the GUIDs to the manufacturer's
13389e39c5baSBill Taylor * defaults, because if the GUIDs are actually set incorrectly
13399e39c5baSBill Taylor * at identify time, we really need to know that.
13409e39c5baSBill Taylor *
13419e39c5baSBill Taylor * If the GUIDs are bogus, then we'll fix that in fw_writefw()
13429e39c5baSBill Taylor * by blatting the manufacturer's defaults from the firmware
13439e39c5baSBill Taylor * image file instead.
13449e39c5baSBill Taylor */
13459e39c5baSBill Taylor if ((p->nodeguid == s->nodeguid) &&
13469e39c5baSBill Taylor (p->port1guid == s->port1guid) &&
13479e39c5baSBill Taylor (p->port2guid == s->port2guid) &&
13489e39c5baSBill Taylor (p->sysimguid == s->sysimguid)) {
13499e39c5baSBill Taylor logmsg(MSG_INFO,
13509e39c5baSBill Taylor "tavor: primary and secondary guids are the same\n");
13519e39c5baSBill Taylor handle->ibguids[0] = p->nodeguid;
13529e39c5baSBill Taylor handle->ibguids[1] = p->port1guid;
13539e39c5baSBill Taylor handle->ibguids[2] = p->port2guid;
13549e39c5baSBill Taylor handle->ibguids[3] = p->sysimguid;
13559e39c5baSBill Taylor } else {
13569e39c5baSBill Taylor /*
13579e39c5baSBill Taylor * We're going to assume that the guids which are numerically
13589e39c5baSBill Taylor * larger than the others are correct and copy them to
13599e39c5baSBill Taylor * handle->ibguids.
13609e39c5baSBill Taylor *
13619e39c5baSBill Taylor * For those in the know wrt InfiniBand, if this assumption
13629e39c5baSBill Taylor * is incorrect, _please_ bug this and fix it, adding a
13639e39c5baSBill Taylor * comment or two to indicate why
13649e39c5baSBill Taylor */
13659e39c5baSBill Taylor logmsg(MSG_INFO,
13669e39c5baSBill Taylor "tavor: primary and secondary guids don't all match\n");
13679e39c5baSBill Taylor
13689e39c5baSBill Taylor if (s->nodeguid > p->nodeguid) {
13699e39c5baSBill Taylor handle->ibguids[0] = s->nodeguid;
13709e39c5baSBill Taylor handle->ibguids[1] = s->port1guid;
13719e39c5baSBill Taylor handle->ibguids[2] = s->port2guid;
13729e39c5baSBill Taylor handle->ibguids[3] = s->sysimguid;
13739e39c5baSBill Taylor bzero(p, sizeof (struct mlx_guid_sect));
13749e39c5baSBill Taylor } else {
13759e39c5baSBill Taylor handle->ibguids[0] = p->nodeguid;
13769e39c5baSBill Taylor handle->ibguids[1] = p->port1guid;
13779e39c5baSBill Taylor handle->ibguids[2] = p->port2guid;
13789e39c5baSBill Taylor handle->ibguids[3] = p->sysimguid;
13799e39c5baSBill Taylor bzero(s, sizeof (struct mlx_guid_sect));
13809e39c5baSBill Taylor }
13819e39c5baSBill Taylor }
13829e39c5baSBill Taylor
13839e39c5baSBill Taylor free(p);
13849e39c5baSBill Taylor free(s);
13859e39c5baSBill Taylor
13869e39c5baSBill Taylor if (fwflash_debug) {
13879e39c5baSBill Taylor for (i = 0; i < 4; i++) {
13889e39c5baSBill Taylor logmsg(MSG_INFO, "ibguids[%d] %0llx\n", i,
13899e39c5baSBill Taylor handle->ibguids[i]);
13909e39c5baSBill Taylor }
13919e39c5baSBill Taylor }
13929e39c5baSBill Taylor
13939e39c5baSBill Taylor return (FWFLASH_SUCCESS);
13949e39c5baSBill Taylor }
13959e39c5baSBill Taylor
13969e39c5baSBill Taylor
13979e39c5baSBill Taylor int
tavor_close(struct devicelist * flashdev)13989e39c5baSBill Taylor tavor_close(struct devicelist *flashdev)
13999e39c5baSBill Taylor {
14009e39c5baSBill Taylor
14019e39c5baSBill Taylor struct ib_encap_ident *handle;
14029e39c5baSBill Taylor
14039e39c5baSBill Taylor handle = (struct ib_encap_ident *)flashdev->ident->encap_ident;
14049e39c5baSBill Taylor if (handle->fd > 0) {
14059e39c5baSBill Taylor (void) ioctl(handle->fd, TAVOR_IOCTL_FLASH_FINI);
14069e39c5baSBill Taylor errno = 0;
14079e39c5baSBill Taylor if (close(handle->fd) != 0) {
14089e39c5baSBill Taylor logmsg(MSG_ERROR,
14099e39c5baSBill Taylor gettext("tavor: Unable to properly close "
14109e39c5baSBill Taylor "device %s! (%s)\n"),
14119e39c5baSBill Taylor flashdev->access_devname,
14129e39c5baSBill Taylor strerror(errno));
14139e39c5baSBill Taylor return (FWFLASH_FAILURE);
14149e39c5baSBill Taylor }
14159e39c5baSBill Taylor return (FWFLASH_SUCCESS);
14169e39c5baSBill Taylor } else
14179e39c5baSBill Taylor return (FWFLASH_FAILURE);
14189e39c5baSBill Taylor }
14199e39c5baSBill Taylor
14209e39c5baSBill Taylor
14219e39c5baSBill Taylor /*
14229e39c5baSBill Taylor * We would not need this if it were not for Cisco's image using the
14239e39c5baSBill Taylor * VSD to store boot options and flags for their PXE boot extension,
14249e39c5baSBill Taylor * but not setting the proper default values for the extension in
14259e39c5baSBill Taylor * their image. As it turns out, some of the data for the extension
14269e39c5baSBill Taylor * is stored in the VSD in the firmware file, and the rest is set by
14279e39c5baSBill Taylor * their firmware utility. That's not very nice for us, since it could
14289e39c5baSBill Taylor * change at any time without our knowledge. Well, for the time being,
14299e39c5baSBill Taylor * we can use this to examine and fix up anything in the VSD that we might
14309e39c5baSBill Taylor * need to handle, for any vendor specific settings.
14319e39c5baSBill Taylor */
14329e39c5baSBill Taylor static void
tavor_cisco_extensions(mlx_xps_t * hcaxps,mlx_xps_t * diskxps)14339e39c5baSBill Taylor tavor_cisco_extensions(mlx_xps_t *hcaxps, mlx_xps_t *diskxps)
14349e39c5baSBill Taylor {
14359e39c5baSBill Taylor uint16_t sig1, sig2;
14369e39c5baSBill Taylor uint32_t i;
14379e39c5baSBill Taylor
14389e39c5baSBill Taylor
14399e39c5baSBill Taylor bcopy(hcaxps->vsdpsid, &i, 4);
14409e39c5baSBill Taylor sig1 = htonl(i);
14419e39c5baSBill Taylor bcopy(&hcaxps->vsdpsid[223], &i, 4);
14429e39c5baSBill Taylor sig2 = htonl(i);
14439e39c5baSBill Taylor
14449e39c5baSBill Taylor
14459e39c5baSBill Taylor if (sig1 == FLASH_VSD_CISCO_SIGNATURE &&
14469e39c5baSBill Taylor sig2 == FLASH_VSD_CISCO_SIGNATURE) {
14479e39c5baSBill Taylor logmsg(MSG_INFO,
14489e39c5baSBill Taylor "tavor: CISCO signature found in HCA's VSD, copying to "
14499e39c5baSBill Taylor "new image's VSD\n");
14509e39c5baSBill Taylor
14519e39c5baSBill Taylor i = htonl(FLASH_VSD_CISCO_SIGNATURE);
14529e39c5baSBill Taylor bcopy(&i, diskxps->vsdpsid, 2);
14539e39c5baSBill Taylor
14549e39c5baSBill Taylor /*
14559e39c5baSBill Taylor * Set the boot_version field to '2'. This value is
14569e39c5baSBill Taylor * located in the 2nd byte of the last uint32_t.
14579e39c5baSBill Taylor * Per the previous version of fwflash, we just or
14589e39c5baSBill Taylor * the bit in and get on with it.
14599e39c5baSBill Taylor */
14609e39c5baSBill Taylor
14619e39c5baSBill Taylor i = (diskxps->vsdpsid[222] | FLASH_VSD_CISCO_BOOT_VERSION);
14629e39c5baSBill Taylor bcopy(&i, &diskxps->vsdpsid[222], 2);
14639e39c5baSBill Taylor /*
14649e39c5baSBill Taylor * Now set some defaults for the SRP boot extension,
14659e39c5baSBill Taylor * currently the only extension we support. These flags
14669e39c5baSBill Taylor * are located in the second uint32_t of the VSD.
14679e39c5baSBill Taylor */
14689e39c5baSBill Taylor
14699e39c5baSBill Taylor logmsg(MSG_INFO, "tavor: CISCO boot flags currently set "
14709e39c5baSBill Taylor "to 0x%08x\n",
14719e39c5baSBill Taylor diskxps->vsdpsid[1]);
14729e39c5baSBill Taylor
14739e39c5baSBill Taylor diskxps->vsdpsid[1] =
14749e39c5baSBill Taylor htonl(diskxps->vsdpsid[1] |
14759e39c5baSBill Taylor FLASH_VSD_CISCO_FLAG_AUTOUPGRADE |
14769e39c5baSBill Taylor FLASH_VSD_CISCO_BOOT_OPTIONS |
14779e39c5baSBill Taylor FLASH_VSD_CISCO_FLAG_BOOT_ENABLE_PORT_1 |
14789e39c5baSBill Taylor FLASH_VSD_CISCO_FLAG_BOOT_ENABLE_PORT_2 |
14799e39c5baSBill Taylor FLASH_VSD_CISCO_FLAG_BOOT_ENABLE_SCAN |
14809e39c5baSBill Taylor FLASH_VSD_CISCO_FLAG_BOOT_TYPE_WELL_KNOWN |
14819e39c5baSBill Taylor FLASH_VSD_CISCO_FLAG_BOOT_TRY_FOREVER);
14829e39c5baSBill Taylor
14839e39c5baSBill Taylor logmsg(MSG_INFO, "tavor: CISCO boot flags now set "
14849e39c5baSBill Taylor "to 0x%08x\n",
14859e39c5baSBill Taylor diskxps->vsdpsid[1]);
14869e39c5baSBill Taylor } else
14879e39c5baSBill Taylor logmsg(MSG_INFO,
14889e39c5baSBill Taylor "tavor: CISCO signature not found in HCA's VSD\n");
14899e39c5baSBill Taylor }
14909e39c5baSBill Taylor
14919e39c5baSBill Taylor
14929e39c5baSBill Taylor static int
tavor_write_sector(int fd,int sectnum,int32_t * data)14939e39c5baSBill Taylor tavor_write_sector(int fd, int sectnum, int32_t *data)
14949e39c5baSBill Taylor {
14959e39c5baSBill Taylor int rv, i;
14969e39c5baSBill Taylor tavor_flash_ioctl_t cmd;
14979e39c5baSBill Taylor
14989e39c5baSBill Taylor
14999e39c5baSBill Taylor bzero(&cmd, sizeof (tavor_flash_ioctl_t));
15009e39c5baSBill Taylor
15019e39c5baSBill Taylor cmd.tf_type = TAVOR_FLASH_WRITE_SECTOR;
15029e39c5baSBill Taylor cmd.tf_sector_num = sectnum;
15039e39c5baSBill Taylor cmd.tf_sector = (caddr_t)data;
15049e39c5baSBill Taylor
15059e39c5baSBill Taylor errno = 0;
15069e39c5baSBill Taylor
15079e39c5baSBill Taylor logmsg(MSG_INFO,
15089e39c5baSBill Taylor "tavor: tavor_write_sector(fd %d, sectnum 0x%x, data 0x%lx)\n",
15099e39c5baSBill Taylor fd, sectnum, data);
15109e39c5baSBill Taylor logmsg(MSG_INFO,
15119e39c5baSBill Taylor "tavor:\n"
15129e39c5baSBill Taylor "\tcmd.tf_type %d\n"
15139e39c5baSBill Taylor "\tcmd.tf_sector 0x%lx\n"
15149e39c5baSBill Taylor "\tcmd.tf_sector_num %d\n",
15159e39c5baSBill Taylor cmd.tf_type, data, cmd.tf_sector_num);
15169e39c5baSBill Taylor
15179e39c5baSBill Taylor /*
15189e39c5baSBill Taylor * If we're debugging, dump the first 64 uint32_t that we've
15199e39c5baSBill Taylor * been passed
15209e39c5baSBill Taylor */
15219e39c5baSBill Taylor if (fwflash_debug > 0) {
15229e39c5baSBill Taylor i = 0;
15239e39c5baSBill Taylor while (i < 64) {
15249e39c5baSBill Taylor logmsg(MSG_INFO,
15259e39c5baSBill Taylor "%02x: %08x %08x %08x %08x\n",
15269e39c5baSBill Taylor i, data[i], data[i+1],
15279e39c5baSBill Taylor data[i+2], data[i+3]);
15289e39c5baSBill Taylor i += 4;
15299e39c5baSBill Taylor }
15309e39c5baSBill Taylor }
15319e39c5baSBill Taylor
15329e39c5baSBill Taylor rv = ioctl(fd, TAVOR_IOCTL_FLASH_WRITE, &cmd);
15339e39c5baSBill Taylor if (rv < 0) {
15349e39c5baSBill Taylor logmsg(MSG_ERROR,
15359e39c5baSBill Taylor gettext("tavor: WRITE SECTOR failed for sector "
15369e39c5baSBill Taylor "%d: %s\n"),
15379e39c5baSBill Taylor sectnum, strerror(errno));
15389e39c5baSBill Taylor return (FWFLASH_FAILURE);
15399e39c5baSBill Taylor } else
15409e39c5baSBill Taylor return (FWFLASH_SUCCESS);
15419e39c5baSBill Taylor }
15429e39c5baSBill Taylor
15439e39c5baSBill Taylor /*
15449e39c5baSBill Taylor * Write zeros to the on-HCA signature and CRC16 fields of sector.
15459e39c5baSBill Taylor *
15469e39c5baSBill Taylor * NOTE we do _not_ divide start by 4 because we're talking to the
15479e39c5baSBill Taylor * HCA, and not finding an offset into verifier->fwimage.
15489e39c5baSBill Taylor */
15499e39c5baSBill Taylor
15509e39c5baSBill Taylor static int
tavor_zero_sig_crc(int fd,uint32_t start)15519e39c5baSBill Taylor tavor_zero_sig_crc(int fd, uint32_t start)
15529e39c5baSBill Taylor {
15539e39c5baSBill Taylor int i, rv;
15549e39c5baSBill Taylor tavor_flash_ioctl_t cmd;
15559e39c5baSBill Taylor
15569e39c5baSBill Taylor /* signature first, then CRC16 */
15579e39c5baSBill Taylor bzero(&cmd, sizeof (tavor_flash_ioctl_t));
15589e39c5baSBill Taylor cmd.tf_type = TAVOR_FLASH_WRITE_BYTE;
15599e39c5baSBill Taylor cmd.tf_byte = 0x00;
15609e39c5baSBill Taylor
15619e39c5baSBill Taylor logmsg(MSG_INFO,
15629e39c5baSBill Taylor "tavor: tavor_zero_sig_crc(fd %d, start 0x%04x)\n",
15639e39c5baSBill Taylor fd, start);
15649e39c5baSBill Taylor
15659e39c5baSBill Taylor for (i = 0; i < 4; i++) {
15669e39c5baSBill Taylor cmd.tf_addr = start + FLASH_PS_SIGNATURE_OFFSET + i;
15679e39c5baSBill Taylor
15689e39c5baSBill Taylor logmsg(MSG_INFO,
15699e39c5baSBill Taylor "tavor: invalidating xPS sig (offset from IS 0x%04x) "
15709e39c5baSBill Taylor "byte %d\n",
15719e39c5baSBill Taylor cmd.tf_addr, i);
15729e39c5baSBill Taylor errno = 0;
15739e39c5baSBill Taylor
15749e39c5baSBill Taylor rv = ioctl(fd, TAVOR_IOCTL_FLASH_WRITE, &cmd);
15759e39c5baSBill Taylor if (rv < 0) {
15769e39c5baSBill Taylor logmsg(MSG_INFO,
15779e39c5baSBill Taylor gettext("tavor: Unable to write 0x00 to "
15789e39c5baSBill Taylor "offset 0x%04x from IS (sig byte %d): %s\n"),
15799e39c5baSBill Taylor cmd.tf_addr, i, strerror(errno));
15809e39c5baSBill Taylor return (FWFLASH_FAILURE);
15819e39c5baSBill Taylor }
15829e39c5baSBill Taylor }
15839e39c5baSBill Taylor
15849e39c5baSBill Taylor cmd.tf_byte = 0x00;
15859e39c5baSBill Taylor for (i = 0; i < 2; i++) {
15869e39c5baSBill Taylor cmd.tf_addr = start + FLASH_PS_CRC16_OFFSET + i;
15879e39c5baSBill Taylor
15889e39c5baSBill Taylor logmsg(MSG_INFO,
15899e39c5baSBill Taylor "tavor: invalidating xPS CRC16 (offset from IS 0x%04x) "
15909e39c5baSBill Taylor "byte %d\n",
15919e39c5baSBill Taylor cmd.tf_addr, i);
15929e39c5baSBill Taylor errno = 0;
15939e39c5baSBill Taylor
15949e39c5baSBill Taylor rv = ioctl(fd, TAVOR_IOCTL_FLASH_WRITE, &cmd);
15959e39c5baSBill Taylor if (rv < 0) {
15969e39c5baSBill Taylor logmsg(MSG_INFO,
15979e39c5baSBill Taylor gettext("tavor: Unable to write 0x00 to "
15989e39c5baSBill Taylor "offset 0x%04x from IS (CRC16 byte %d): %s\n"),
15999e39c5baSBill Taylor cmd.tf_addr, i, strerror(errno));
16009e39c5baSBill Taylor return (FWFLASH_FAILURE);
16019e39c5baSBill Taylor }
16029e39c5baSBill Taylor }
16039e39c5baSBill Taylor return (FWFLASH_SUCCESS);
16049e39c5baSBill Taylor }
16059e39c5baSBill Taylor
16069e39c5baSBill Taylor
16079e39c5baSBill Taylor /*
16089e39c5baSBill Taylor * Write a new FIA for the given xPS. The _caller_ handles
16099e39c5baSBill Taylor * any required byte-swapping for us.
16109e39c5baSBill Taylor *
16119e39c5baSBill Taylor * NOTE we do _not_ divide start by 4 because we're talking to the
16129e39c5baSBill Taylor * HCA, and not finding an offset into verifier->fwimage.
16139e39c5baSBill Taylor */
16149e39c5baSBill Taylor static int
tavor_write_xps_fia(int fd,uint32_t offset,uint32_t start)16159e39c5baSBill Taylor tavor_write_xps_fia(int fd, uint32_t offset, uint32_t start)
16169e39c5baSBill Taylor {
16179e39c5baSBill Taylor int i, rv;
16189e39c5baSBill Taylor uint8_t *addrbytep;
16199e39c5baSBill Taylor tavor_flash_ioctl_t cmd;
16209e39c5baSBill Taylor
16219e39c5baSBill Taylor logmsg(MSG_INFO,
16229e39c5baSBill Taylor "tavor: tavor_write_xps_fia(fd %d, offset 0x%04x, "
16239e39c5baSBill Taylor "start 0x%04x)\n",
16249e39c5baSBill Taylor fd, offset, start);
16259e39c5baSBill Taylor
16269e39c5baSBill Taylor addrbytep = (uint8_t *)&start;
16279e39c5baSBill Taylor
16289e39c5baSBill Taylor bzero(&cmd, sizeof (tavor_flash_ioctl_t));
16299e39c5baSBill Taylor cmd.tf_type = TAVOR_FLASH_WRITE_BYTE;
16309e39c5baSBill Taylor for (i = 0; i < 4; i++) {
16319e39c5baSBill Taylor cmd.tf_byte = addrbytep[i];
16329e39c5baSBill Taylor cmd.tf_addr = offset + FLASH_PS_FI_ADDR_OFFSET + i;
16339e39c5baSBill Taylor logmsg(MSG_INFO,
16349e39c5baSBill Taylor "tavor: writing xPS' new FIA, byte %d (0x%0x) at "
16359e39c5baSBill Taylor "offset from IS 0x%04x\n",
16369e39c5baSBill Taylor i, cmd.tf_byte, cmd.tf_addr);
16379e39c5baSBill Taylor errno = 0;
16389e39c5baSBill Taylor
16399e39c5baSBill Taylor rv = ioctl(fd, TAVOR_IOCTL_FLASH_WRITE, &cmd);
16409e39c5baSBill Taylor if (rv < 0) {
16419e39c5baSBill Taylor logmsg(MSG_INFO,
16429e39c5baSBill Taylor gettext("tavor: Unable to write byte %d "
16439e39c5baSBill Taylor "of xPS new FIA (0x%0x, offset from IS "
16449e39c5baSBill Taylor "0x%04x): %s\n"),
16459e39c5baSBill Taylor i, cmd.tf_byte, cmd.tf_addr, strerror(errno));
16469e39c5baSBill Taylor return (FWFLASH_FAILURE);
16479e39c5baSBill Taylor }
16489e39c5baSBill Taylor }
16499e39c5baSBill Taylor return (FWFLASH_SUCCESS);
16509e39c5baSBill Taylor }
16519e39c5baSBill Taylor
16529e39c5baSBill Taylor
16539e39c5baSBill Taylor /*
16549e39c5baSBill Taylor * Write the new CRC16 and Signature to the given xPS. The caller
16559e39c5baSBill Taylor * has already byte-swapped newcrc if that's necessary.
16569e39c5baSBill Taylor *
16579e39c5baSBill Taylor * NOTE we do _not_ divide start by 4 because we're talking to the
16589e39c5baSBill Taylor * HCA, and not finding an offset into verifier->fwimage.
16599e39c5baSBill Taylor */
16609e39c5baSBill Taylor static int
tavor_write_xps_crc_sig(int fd,uint32_t offset,uint16_t newcrc)16619e39c5baSBill Taylor tavor_write_xps_crc_sig(int fd, uint32_t offset, uint16_t newcrc)
16629e39c5baSBill Taylor {
16639e39c5baSBill Taylor int i, rv;
16649e39c5baSBill Taylor uint8_t *bytep;
16659e39c5baSBill Taylor uint32_t tempsig;
16669e39c5baSBill Taylor tavor_flash_ioctl_t cmd;
16679e39c5baSBill Taylor
16689e39c5baSBill Taylor logmsg(MSG_INFO,
16699e39c5baSBill Taylor "tavor: tavor_write_xps_crc_sig(fd %d, offset 0x%04x, "
16709e39c5baSBill Taylor "newcrc 0x%04x)\n",
16719e39c5baSBill Taylor fd, offset, newcrc);
16729e39c5baSBill Taylor
16739e39c5baSBill Taylor bytep = (uint8_t *)&newcrc;
16749e39c5baSBill Taylor
16759e39c5baSBill Taylor bzero(&cmd, sizeof (tavor_flash_ioctl_t));
16769e39c5baSBill Taylor cmd.tf_type = TAVOR_FLASH_WRITE_BYTE;
16779e39c5baSBill Taylor for (i = 0; i < 2; i++) {
16789e39c5baSBill Taylor cmd.tf_byte = bytep[i];
16799e39c5baSBill Taylor cmd.tf_addr = offset + FLASH_PS_CRC16_OFFSET + i;
16809e39c5baSBill Taylor logmsg(MSG_INFO,
16819e39c5baSBill Taylor "tavor: writing new XPS CRC16, byte %d (0x%0x) at "
16829e39c5baSBill Taylor "offset from IS 0x%04x\n",
16839e39c5baSBill Taylor i, bytep[i], cmd.tf_addr);
16849e39c5baSBill Taylor errno = 0;
16859e39c5baSBill Taylor
16869e39c5baSBill Taylor rv = ioctl(fd, TAVOR_IOCTL_FLASH_WRITE, &cmd);
16879e39c5baSBill Taylor if (rv < 0) {
16889e39c5baSBill Taylor logmsg(MSG_INFO,
16899e39c5baSBill Taylor gettext("tavor: Unable to write byte %d "
16909e39c5baSBill Taylor "(0x%0x) of xPS' new CRC16 to offset "
16919e39c5baSBill Taylor "from IS 0x%04x: %s\n"),
16929e39c5baSBill Taylor i, bytep[i], cmd.tf_addr, strerror(errno));
16939e39c5baSBill Taylor return (FWFLASH_FAILURE);
16949e39c5baSBill Taylor }
16959e39c5baSBill Taylor }
16969e39c5baSBill Taylor
16979e39c5baSBill Taylor tempsig = htonl(FLASH_PS_SIGNATURE);
16989e39c5baSBill Taylor bytep = (uint8_t *)&tempsig;
16999e39c5baSBill Taylor
17009e39c5baSBill Taylor for (i = 0; i < 4; i++) {
17019e39c5baSBill Taylor cmd.tf_byte = bytep[i];
17029e39c5baSBill Taylor cmd.tf_addr = offset + FLASH_PS_SIGNATURE_OFFSET + i;
17039e39c5baSBill Taylor logmsg(MSG_INFO,
17049e39c5baSBill Taylor "tavor: writing new xPS Signature, byte %d (0x%0x) at "
17059e39c5baSBill Taylor "offset from IS 0x%04x\n",
17069e39c5baSBill Taylor i, bytep[i], cmd.tf_addr);
17079e39c5baSBill Taylor errno = 0;
17089e39c5baSBill Taylor
17099e39c5baSBill Taylor rv = ioctl(fd, TAVOR_IOCTL_FLASH_WRITE, &cmd);
17109e39c5baSBill Taylor if (rv < 0) {
17119e39c5baSBill Taylor logmsg(MSG_INFO,
17129e39c5baSBill Taylor gettext("tavor: Unable to write byte %d (0x%0x) "
17139e39c5baSBill Taylor "of xPS' signature at offset from IS 0x%04x: %s\n"),
17149e39c5baSBill Taylor i, bytep[i], cmd.tf_addr, strerror(errno));
17159e39c5baSBill Taylor return (FWFLASH_FAILURE);
17169e39c5baSBill Taylor }
17179e39c5baSBill Taylor }
17189e39c5baSBill Taylor return (FWFLASH_SUCCESS);
17199e39c5baSBill Taylor }
17209e39c5baSBill Taylor
17219e39c5baSBill Taylor
17229e39c5baSBill Taylor
17239e39c5baSBill Taylor /*
17249e39c5baSBill Taylor * This function contains "Begin/End documentation departure point"
17259e39c5baSBill Taylor * because the reality of what actually _works_ is quite, quite
17269e39c5baSBill Taylor * different to what is written in the Mellanox HCA Flash Application
17279e39c5baSBill Taylor * Programming Guide.
17289e39c5baSBill Taylor */
17299e39c5baSBill Taylor static int
tavor_blast_image(int fd,int prisec,uint32_t hcafia,uint32_t sectsz,struct mlx_xps * newxps)17309e39c5baSBill Taylor tavor_blast_image(int fd, int prisec, uint32_t hcafia, uint32_t sectsz,
17319e39c5baSBill Taylor struct mlx_xps *newxps)
17329e39c5baSBill Taylor {
17339e39c5baSBill Taylor uint32_t i, j, rv;
17349e39c5baSBill Taylor uint32_t startsectimg, startsecthca, numsect;
17359e39c5baSBill Taylor
17369e39c5baSBill Taylor if ((prisec != 1) && (prisec != 2)) {
17379e39c5baSBill Taylor logmsg(MSG_ERROR,
1738ee5d8455SShantkumar Hiremath gettext("tavor: invalid image number requested (%d)\n"),
1739ee5d8455SShantkumar Hiremath prisec);
17409e39c5baSBill Taylor return (FWFLASH_FAILURE);
17419e39c5baSBill Taylor }
17429e39c5baSBill Taylor
17439e39c5baSBill Taylor /* Begin documentation departure point */
17449e39c5baSBill Taylor
17459e39c5baSBill Taylor /* zero the HCA's PPS signature and CRC */
17469e39c5baSBill Taylor if (tavor_zero_sig_crc(fd, (prisec * sectsz))
17479e39c5baSBill Taylor != FWFLASH_SUCCESS) {
17489e39c5baSBill Taylor logmsg(MSG_INFO,
17499e39c5baSBill Taylor "tavor: Unable zero HCA's %s signature "
17509e39c5baSBill Taylor "and CRC16 fields\n",
17519e39c5baSBill Taylor ((prisec == 1) ? "PPS" : "SPS"));
17529e39c5baSBill Taylor return (FWFLASH_FAILURE);
17539e39c5baSBill Taylor }
17549e39c5baSBill Taylor
17559e39c5baSBill Taylor logmsg(MSG_INFO, "tavor: zeroing HCA's %s sig and crc\n",
17569e39c5baSBill Taylor (prisec == 1) ? "pps" : "sps");
17579e39c5baSBill Taylor
17589e39c5baSBill Taylor /* End documentation departure point */
17599e39c5baSBill Taylor
17609e39c5baSBill Taylor /* make sure we don't inadvertently overwrite bits */
17619e39c5baSBill Taylor
17629e39c5baSBill Taylor startsectimg = MLXSWAPBITS32(newxps->fia) / sectsz;
17639e39c5baSBill Taylor startsecthca = hcafia / sectsz;
17649e39c5baSBill Taylor
17659e39c5baSBill Taylor numsect = (MLXSWAPBITS32(newxps->fis) / sectsz) +
17669e39c5baSBill Taylor ((MLXSWAPBITS32(newxps->fis) % sectsz) ? 1 : 0);
17679e39c5baSBill Taylor
17689e39c5baSBill Taylor logmsg(MSG_INFO, "tavor: %s imgsize 0x%0x startsecthca %d, "
17699e39c5baSBill Taylor "startsectimg %d, num sectors %d\n",
17709e39c5baSBill Taylor (prisec == 1) ? "PFI" : "SFI", MLXSWAPBITS32(newxps->fis),
17719e39c5baSBill Taylor startsecthca, startsectimg, numsect);
17729e39c5baSBill Taylor
17739e39c5baSBill Taylor for (i = 0; i < numsect; i++) {
17749e39c5baSBill Taylor
17759e39c5baSBill Taylor j = (MLXSWAPBITS32(newxps->fia) + (i * sectsz)) / 4;
17769e39c5baSBill Taylor
17779e39c5baSBill Taylor logmsg(MSG_INFO, "tavor: image offset 0x%0x\n", j);
17789e39c5baSBill Taylor logmsg(MSG_INFO, "tavor: writing HCA sector %d\n",
17799e39c5baSBill Taylor i + startsecthca);
17809e39c5baSBill Taylor
17819e39c5baSBill Taylor if (tavor_write_sector(fd, i + startsecthca,
17829e39c5baSBill Taylor &verifier->fwimage[j])
17839e39c5baSBill Taylor != FWFLASH_SUCCESS) {
17849e39c5baSBill Taylor logmsg(MSG_ERROR,
17859e39c5baSBill Taylor gettext("tavor: Unable to write "
17869e39c5baSBill Taylor "sector %d to HCA\n"),
17879e39c5baSBill Taylor i + startsecthca);
17889e39c5baSBill Taylor return (FWFLASH_FAILURE);
17899e39c5baSBill Taylor }
17909e39c5baSBill Taylor (void) printf(" .");
17919e39c5baSBill Taylor
17929e39c5baSBill Taylor rv = tavor_readback(fd, i + startsecthca, sectsz);
17939e39c5baSBill Taylor if (rv != FWFLASH_SUCCESS) {
17949e39c5baSBill Taylor logmsg(MSG_ERROR,
17959e39c5baSBill Taylor gettext("tavor: Unable to read sector %d "
17969e39c5baSBill Taylor "back from HCA\n"), i + startsecthca);
17979e39c5baSBill Taylor return (FWFLASH_FAILURE);
17989e39c5baSBill Taylor }
17999e39c5baSBill Taylor (void) printf(" | ");
18009e39c5baSBill Taylor }
18019e39c5baSBill Taylor
18029e39c5baSBill Taylor /* Begin documentation departure point */
18039e39c5baSBill Taylor
18049e39c5baSBill Taylor /* invalidate the xps signature and fia fields */
18059e39c5baSBill Taylor newxps->signature = 0xffffffff;
18069e39c5baSBill Taylor newxps->crc16 = 0xffff;
18079e39c5baSBill Taylor /* we put the fia back to imgfia later */
18089e39c5baSBill Taylor newxps->fia = 0xffffffff;
18099e39c5baSBill Taylor /* End documentation departure point */
18109e39c5baSBill Taylor
18119e39c5baSBill Taylor /* success so far, now burn the new xPS */
18129e39c5baSBill Taylor if (tavor_write_sector(fd, prisec, (int *)newxps)
18139e39c5baSBill Taylor != FWFLASH_SUCCESS) {
18149e39c5baSBill Taylor logmsg(MSG_ERROR,
18159e39c5baSBill Taylor gettext("tavor: Unable to write new %s "
18169e39c5baSBill Taylor "pointer sector to HCA\n"),
18179e39c5baSBill Taylor (prisec == 1) ? "primary" : "secondary");
18189e39c5baSBill Taylor return (FWFLASH_FAILURE);
18199e39c5baSBill Taylor }
18209e39c5baSBill Taylor (void) printf(" .");
18219e39c5baSBill Taylor
18229e39c5baSBill Taylor /* Begin documentation departure point */
18239e39c5baSBill Taylor
18249e39c5baSBill Taylor /* write new fia to the HCA's pps */
18259e39c5baSBill Taylor logmsg(MSG_INFO, "tavor: writing new fia (0x%0x) to HCA\n",
18269e39c5baSBill Taylor MLXSWAPBITS32(newxps->fia));
18279e39c5baSBill Taylor
18289e39c5baSBill Taylor if (tavor_write_xps_fia(fd, (prisec * sectsz),
18299e39c5baSBill Taylor MLXSWAPBITS32(hcafia)) != FWFLASH_SUCCESS) {
18309e39c5baSBill Taylor logmsg(MSG_ERROR,
18319e39c5baSBill Taylor gettext("tavor: Unable to update HCA's %s "
18329e39c5baSBill Taylor "pointer sector FIA record\n"),
18339e39c5baSBill Taylor (prisec == 1) ? "primary" : "secondary");
18349e39c5baSBill Taylor return (FWFLASH_FAILURE);
18359e39c5baSBill Taylor }
18369e39c5baSBill Taylor
18379e39c5baSBill Taylor /* don't forget the byte-swapping */
18389e39c5baSBill Taylor newxps->fia = MLXSWAPBITS32(hcafia);
18399e39c5baSBill Taylor newxps->signature =
18409e39c5baSBill Taylor (uint32_t)MLXSWAPBITS32(FLASH_PS_SIGNATURE);
18419e39c5baSBill Taylor newxps->crc16 =
18429e39c5baSBill Taylor MLXSWAPBITS16(crc16((uint8_t *)newxps, FLASH_PS_CRC16_SIZE));
18439e39c5baSBill Taylor
18449e39c5baSBill Taylor logmsg(MSG_INFO, "tavor: writing new fia 0x%0x, "
18459e39c5baSBill Taylor "sig 0x%0x and new crc16 0x%0x\n",
18469e39c5baSBill Taylor newxps->fia, MLXSWAPBITS32(newxps->signature),
18479e39c5baSBill Taylor newxps->crc16);
18489e39c5baSBill Taylor
18499e39c5baSBill Taylor if (tavor_write_xps_crc_sig(fd, (prisec * sectsz),
18509e39c5baSBill Taylor newxps->crc16) != FWFLASH_SUCCESS) {
18519e39c5baSBill Taylor /*
18529e39c5baSBill Taylor * Now we're REALLY hosed. If the card comes up at all,
18539e39c5baSBill Taylor * expect it to be in "Maintenance Mode".
18549e39c5baSBill Taylor */
18559e39c5baSBill Taylor logmsg(MSG_ERROR,
18569e39c5baSBill Taylor gettext("tavor: Unable to update HCA's %s CRC "
18579e39c5baSBill Taylor "and Firmware Image signature fields\n"),
18589e39c5baSBill Taylor (prisec == 1) ? "PPS" : "SPS");
18599e39c5baSBill Taylor return (FWFLASH_FAILURE);
18609e39c5baSBill Taylor }
18619e39c5baSBill Taylor
18629e39c5baSBill Taylor rv = tavor_readback(fd, prisec, sectsz);
18639e39c5baSBill Taylor if (rv != FWFLASH_SUCCESS) {
18649e39c5baSBill Taylor logmsg(MSG_ERROR,
18659e39c5baSBill Taylor gettext("tavor: Unable to read %s pointer sector "
18669e39c5baSBill Taylor "from HCA\n"),
18679e39c5baSBill Taylor (prisec == 1) ? "Primary" : "Secondary");
18689e39c5baSBill Taylor return (FWFLASH_FAILURE);
18699e39c5baSBill Taylor }
18709e39c5baSBill Taylor (void) printf(" |");
18719e39c5baSBill Taylor /* End documentation departure point */
18729e39c5baSBill Taylor return (FWFLASH_SUCCESS);
18739e39c5baSBill Taylor }
18749e39c5baSBill Taylor
18759e39c5baSBill Taylor
18769e39c5baSBill Taylor static int
tavor_readback(int infd,int whichsect,int sectsz)18779e39c5baSBill Taylor tavor_readback(int infd, int whichsect, int sectsz)
18789e39c5baSBill Taylor {
18799e39c5baSBill Taylor uint32_t *data;
18809e39c5baSBill Taylor tavor_flash_ioctl_t cmd;
18819e39c5baSBill Taylor int rv;
18829e39c5baSBill Taylor
18839e39c5baSBill Taylor bzero(&cmd, sizeof (tavor_flash_ioctl_t));
18849e39c5baSBill Taylor data = calloc(1, sectsz); /* assumption! */
18859e39c5baSBill Taylor
18869e39c5baSBill Taylor cmd.tf_type = TAVOR_FLASH_READ_SECTOR;
18879e39c5baSBill Taylor cmd.tf_sector_num = whichsect;
18889e39c5baSBill Taylor cmd.tf_sector = (caddr_t)data;
18899e39c5baSBill Taylor rv = ioctl(infd, TAVOR_IOCTL_FLASH_READ, &cmd);
18909e39c5baSBill Taylor if (rv < 0) {
18919e39c5baSBill Taylor logmsg(MSG_INFO,
18929e39c5baSBill Taylor "tavor: UNABLE TO READ BACK SECTOR %d from HCA\n",
18939e39c5baSBill Taylor whichsect);
18949e39c5baSBill Taylor return (FWFLASH_FAILURE);
18959e39c5baSBill Taylor }
18969e39c5baSBill Taylor free(data);
18979e39c5baSBill Taylor return (FWFLASH_SUCCESS);
18989e39c5baSBill Taylor }
18999e39c5baSBill Taylor
19009e39c5baSBill Taylor
19019e39c5baSBill Taylor /*
19029e39c5baSBill Taylor * crc16 - computes 16 bit crc of supplied buffer.
19039e39c5baSBill Taylor * image should be in network byteorder
19049e39c5baSBill Taylor * result is returned in host byteorder form
19059e39c5baSBill Taylor */
19069e39c5baSBill Taylor static uint16_t
crc16(uint8_t * image,uint32_t size)19079e39c5baSBill Taylor crc16(uint8_t *image, uint32_t size)
19089e39c5baSBill Taylor {
19099e39c5baSBill Taylor const uint16_t poly = 0x100b;
19109e39c5baSBill Taylor uint32_t crc = 0xFFFF;
19119e39c5baSBill Taylor uint32_t word;
19129e39c5baSBill Taylor uint32_t i, j;
19139e39c5baSBill Taylor
19149e39c5baSBill Taylor for (i = 0; i < size / 4; i++) {
19159e39c5baSBill Taylor word = (image[4 * i] << 24) |
19169e39c5baSBill Taylor (image[4 * i + 1] << 16) |
19179e39c5baSBill Taylor (image[4 * i + 2] << 8) |
19189e39c5baSBill Taylor (image[4 * i + 3]);
19199e39c5baSBill Taylor
19209e39c5baSBill Taylor for (j = 0; j < 32; j++) {
19219e39c5baSBill Taylor if (crc & 0x8000) {
19229e39c5baSBill Taylor crc = (((crc << 1) |
19239e39c5baSBill Taylor (word >> 31)) ^ poly) & 0xFFFF;
19249e39c5baSBill Taylor } else {
19259e39c5baSBill Taylor crc = ((crc << 1) | (word >> 31)) & 0xFFFF;
19269e39c5baSBill Taylor }
19279e39c5baSBill Taylor word = (word << 1) & 0xFFFFFFFF;
19289e39c5baSBill Taylor }
19299e39c5baSBill Taylor }
19309e39c5baSBill Taylor
19319e39c5baSBill Taylor for (i = 0; i < 16; i++) {
19329e39c5baSBill Taylor if (crc & 0x8000) {
19339e39c5baSBill Taylor crc = ((crc << 1) ^ poly) & 0xFFFF;
19349e39c5baSBill Taylor } else {
19359e39c5baSBill Taylor crc = (crc << 1) & 0xFFFF;
19369e39c5baSBill Taylor }
19379e39c5baSBill Taylor }
19389e39c5baSBill Taylor
19399e39c5baSBill Taylor crc = crc ^ 0xFFFF;
19409e39c5baSBill Taylor return (crc & 0xFFFF);
19419e39c5baSBill Taylor }
1942