1*9e39c5baSBill Taylor /* 2*9e39c5baSBill Taylor * CDDL HEADER START 3*9e39c5baSBill Taylor * 4*9e39c5baSBill Taylor * The contents of this file are subject to the terms of the 5*9e39c5baSBill Taylor * Common Development and Distribution License (the "License"). 6*9e39c5baSBill Taylor * You may not use this file except in compliance with the License. 7*9e39c5baSBill Taylor * 8*9e39c5baSBill Taylor * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*9e39c5baSBill Taylor * or http://www.opensolaris.org/os/licensing. 10*9e39c5baSBill Taylor * See the License for the specific language governing permissions 11*9e39c5baSBill Taylor * and limitations under the License. 12*9e39c5baSBill Taylor * 13*9e39c5baSBill Taylor * When distributing Covered Code, include this CDDL HEADER in each 14*9e39c5baSBill Taylor * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*9e39c5baSBill Taylor * If applicable, add the following below this CDDL HEADER, with the 16*9e39c5baSBill Taylor * fields enclosed by brackets "[]" replaced with your own identifying 17*9e39c5baSBill Taylor * information: Portions Copyright [yyyy] [name of copyright owner] 18*9e39c5baSBill Taylor * 19*9e39c5baSBill Taylor * CDDL HEADER END 20*9e39c5baSBill Taylor */ 21*9e39c5baSBill Taylor 22*9e39c5baSBill Taylor /* 23*9e39c5baSBill Taylor * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 24*9e39c5baSBill Taylor * Use is subject to license terms. 25*9e39c5baSBill Taylor */ 26*9e39c5baSBill Taylor 27*9e39c5baSBill Taylor /* 28*9e39c5baSBill Taylor * IB (InfiniBand) specific functions. 29*9e39c5baSBill Taylor */ 30*9e39c5baSBill Taylor 31*9e39c5baSBill Taylor /* 32*9e39c5baSBill Taylor * The reference for the functions in this file is the 33*9e39c5baSBill Taylor * 34*9e39c5baSBill Taylor * Mellanox HCA Flash Programming Application Note 35*9e39c5baSBill Taylor * (Mellanox document number 2205AN) 36*9e39c5baSBill Taylor * rev 1.44, 2007. Chapter 4 in particular. 37*9e39c5baSBill Taylor * 38*9e39c5baSBill Taylor * NOTE: this Mellanox document is labelled Confidential 39*9e39c5baSBill Taylor * so DO NOT move this file out of usr/closed without 40*9e39c5baSBill Taylor * explicit approval from Sun Legal. 41*9e39c5baSBill Taylor */ 42*9e39c5baSBill Taylor 43*9e39c5baSBill Taylor /* 44*9e39c5baSBill Taylor * IMPORTANT NOTE: 45*9e39c5baSBill Taylor * 1. flash read is done in 32 bit quantities, and the driver returns 46*9e39c5baSBill Taylor * data in host byteorder form. 47*9e39c5baSBill Taylor * 2. flash write is done in 8 bit quantities by the driver. 48*9e39c5baSBill Taylor * 3. data in the flash should be in network byteorder (bigendian). 49*9e39c5baSBill Taylor * 4. data in image files is in network byteorder form. 50*9e39c5baSBill Taylor * 5. data in image structures in memory is kept in network byteorder. 51*9e39c5baSBill Taylor * 6. the functions in this file deal with data in host byteorder form. 52*9e39c5baSBill Taylor */ 53*9e39c5baSBill Taylor 54*9e39c5baSBill Taylor 55*9e39c5baSBill Taylor #include <stdio.h> 56*9e39c5baSBill Taylor #include <stdlib.h> 57*9e39c5baSBill Taylor #include <unistd.h> 58*9e39c5baSBill Taylor #include <sys/types.h> 59*9e39c5baSBill Taylor #include <sys/stat.h> 60*9e39c5baSBill Taylor #include <sys/sysmacros.h> 61*9e39c5baSBill Taylor #include <sys/queue.h> 62*9e39c5baSBill Taylor #include <fcntl.h> 63*9e39c5baSBill Taylor #include <ctype.h> 64*9e39c5baSBill Taylor #include <string.h> 65*9e39c5baSBill Taylor #include <strings.h> 66*9e39c5baSBill Taylor 67*9e39c5baSBill Taylor #include <sys/byteorder.h> 68*9e39c5baSBill Taylor 69*9e39c5baSBill Taylor #include <libintl.h> /* for gettext(3c) */ 70*9e39c5baSBill Taylor 71*9e39c5baSBill Taylor #include <fwflash/fwflash.h> 72*9e39c5baSBill Taylor #include "../../hdrs/MELLANOX.h" 73*9e39c5baSBill Taylor #include "../../hdrs/tavor_ib.h" 74*9e39c5baSBill Taylor 75*9e39c5baSBill Taylor 76*9e39c5baSBill Taylor 77*9e39c5baSBill Taylor char *devprefix = "/devices"; 78*9e39c5baSBill Taylor char drivername[] = "tavor\0"; 79*9e39c5baSBill Taylor char *devsuffix = ":devctl"; 80*9e39c5baSBill Taylor 81*9e39c5baSBill Taylor 82*9e39c5baSBill Taylor extern di_node_t rootnode; 83*9e39c5baSBill Taylor extern int errno; 84*9e39c5baSBill Taylor extern struct fw_plugin *self; 85*9e39c5baSBill Taylor extern struct vrfyplugin *verifier; 86*9e39c5baSBill Taylor extern int fwflash_debug; 87*9e39c5baSBill Taylor 88*9e39c5baSBill Taylor 89*9e39c5baSBill Taylor /* required functions for this plugin */ 90*9e39c5baSBill Taylor int fw_readfw(struct devicelist *device, char *filename); 91*9e39c5baSBill Taylor int fw_writefw(struct devicelist *device); 92*9e39c5baSBill Taylor int fw_identify(int start); 93*9e39c5baSBill Taylor int fw_devinfo(); 94*9e39c5baSBill Taylor 95*9e39c5baSBill Taylor 96*9e39c5baSBill Taylor /* helper functions */ 97*9e39c5baSBill Taylor 98*9e39c5baSBill Taylor static int tavor_identify(struct devicelist *thisdev); 99*9e39c5baSBill Taylor static int tavor_get_guids(struct ib_encap_ident *handle); 100*9e39c5baSBill Taylor static int tavor_close(struct devicelist *flashdev); 101*9e39c5baSBill Taylor static void tavor_cisco_extensions(mlx_xps_t *hcaxps, mlx_xps_t *diskxps); 102*9e39c5baSBill Taylor static uint16_t crc16(uint8_t *image, uint32_t size); 103*9e39c5baSBill Taylor static int tavor_write_sector(int fd, int sectnum, int32_t *data); 104*9e39c5baSBill Taylor static int tavor_zero_sig_crc(int fd, uint32_t start); 105*9e39c5baSBill Taylor static int tavor_write_xps_fia(int fd, uint32_t offset, uint32_t start); 106*9e39c5baSBill Taylor static int tavor_write_xps_crc_sig(int fd, uint32_t offset, uint16_t newcrc); 107*9e39c5baSBill Taylor static int tavor_blast_image(int fd, int prisec, uint32_t hcafia, 108*9e39c5baSBill Taylor uint32_t sectsz, struct mlx_xps *newxps); 109*9e39c5baSBill Taylor static int tavor_readback(int infd, int whichsect, int sectsz); 110*9e39c5baSBill Taylor 111*9e39c5baSBill Taylor 112*9e39c5baSBill Taylor 113*9e39c5baSBill Taylor int 114*9e39c5baSBill Taylor fw_readfw(struct devicelist *flashdev, char *filename) 115*9e39c5baSBill Taylor { 116*9e39c5baSBill Taylor 117*9e39c5baSBill Taylor int rv = FWFLASH_SUCCESS; 118*9e39c5baSBill Taylor int fd; 119*9e39c5baSBill Taylor mode_t mode = S_IRUSR | S_IWUSR; 120*9e39c5baSBill Taylor uint8_t pchunks; 121*9e39c5baSBill Taylor uint8_t *raw_pfi; 122*9e39c5baSBill Taylor uint8_t *raw_sfi; 123*9e39c5baSBill Taylor uint32_t j, offset; 124*9e39c5baSBill Taylor uint32_t pfia, sfia, psz, ssz; 125*9e39c5baSBill Taylor tavor_flash_ioctl_t tfi_data; 126*9e39c5baSBill Taylor struct ib_encap_ident *manuf; 127*9e39c5baSBill Taylor struct mlx_xps *lpps; 128*9e39c5baSBill Taylor struct mlx_xps *lsps; 129*9e39c5baSBill Taylor #if defined(_LITTLE_ENDIAN) 130*9e39c5baSBill Taylor uint32_t *ptr; 131*9e39c5baSBill Taylor #endif 132*9e39c5baSBill Taylor 133*9e39c5baSBill Taylor errno = 0; 134*9e39c5baSBill Taylor if ((fd = open(filename, O_RDWR|O_CREAT|O_DSYNC, mode)) < 0) { 135*9e39c5baSBill Taylor logmsg(MSG_ERROR, 136*9e39c5baSBill Taylor gettext("tavor: Unable to open specified file " 137*9e39c5baSBill Taylor "(%s) for writing: %s\n"), filename, strerror(errno)); 138*9e39c5baSBill Taylor return (FWFLASH_FAILURE); 139*9e39c5baSBill Taylor } 140*9e39c5baSBill Taylor 141*9e39c5baSBill Taylor manuf = 142*9e39c5baSBill Taylor (struct ib_encap_ident *)(uintptr_t)flashdev->ident->encap_ident; 143*9e39c5baSBill Taylor lpps = (struct mlx_xps *)(uintptr_t)manuf->pps; 144*9e39c5baSBill Taylor lsps = (struct mlx_xps *)(uintptr_t)manuf->sps; 145*9e39c5baSBill Taylor 146*9e39c5baSBill Taylor /* 147*9e39c5baSBill Taylor * Now that we've got an open, init'd fd, we can read the 148*9e39c5baSBill Taylor * xFI from the device itself. We've already got the IS 149*9e39c5baSBill Taylor * and xPS stored in manuf. 150*9e39c5baSBill Taylor */ 151*9e39c5baSBill Taylor 152*9e39c5baSBill Taylor /* stash some values for later */ 153*9e39c5baSBill Taylor pfia = MLXSWAPBITS32(lpps->fia); 154*9e39c5baSBill Taylor sfia = MLXSWAPBITS32(lsps->fia); 155*9e39c5baSBill Taylor psz = MLXSWAPBITS32(lpps->fis); 156*9e39c5baSBill Taylor ssz = MLXSWAPBITS32(lsps->fis); 157*9e39c5baSBill Taylor 158*9e39c5baSBill Taylor /* Invariant Sector comes first */ 159*9e39c5baSBill Taylor if ((j = write(fd, manuf->inv, manuf->sector_sz)) != 160*9e39c5baSBill Taylor manuf->sector_sz) { 161*9e39c5baSBill Taylor logmsg(MSG_ERROR, 162*9e39c5baSBill Taylor gettext("tavor: Unable to write HCA Invariant Sector " 163*9e39c5baSBill Taylor "(%d of %d bytes)\n"), 164*9e39c5baSBill Taylor j, manuf->sector_sz); 165*9e39c5baSBill Taylor (void) tavor_close(flashdev); 166*9e39c5baSBill Taylor return (FWFLASH_FAILURE); 167*9e39c5baSBill Taylor } else { 168*9e39c5baSBill Taylor fprintf(stdout, gettext("Writing .")); 169*9e39c5baSBill Taylor } 170*9e39c5baSBill Taylor 171*9e39c5baSBill Taylor /* followed by Primary Pointer Sector */ 172*9e39c5baSBill Taylor if ((j = write(fd, manuf->pps, manuf->sector_sz)) != 173*9e39c5baSBill Taylor manuf->sector_sz) { 174*9e39c5baSBill Taylor logmsg(MSG_ERROR, 175*9e39c5baSBill Taylor gettext("tavor: Unable to write HCA Primary Pointer " 176*9e39c5baSBill Taylor "Sector (%d of %d bytes)\n)"), 177*9e39c5baSBill Taylor j, manuf->sector_sz); 178*9e39c5baSBill Taylor (void) tavor_close(flashdev); 179*9e39c5baSBill Taylor return (FWFLASH_FAILURE); 180*9e39c5baSBill Taylor } else { 181*9e39c5baSBill Taylor fprintf(stdout, " ."); 182*9e39c5baSBill Taylor } 183*9e39c5baSBill Taylor 184*9e39c5baSBill Taylor /* followed by Secondary Pointer Sector */ 185*9e39c5baSBill Taylor if ((j = write(fd, manuf->sps, manuf->sector_sz)) != 186*9e39c5baSBill Taylor manuf->sector_sz) { 187*9e39c5baSBill Taylor logmsg(MSG_ERROR, 188*9e39c5baSBill Taylor gettext("tavor: Unable to write HCA Secondary Pointer " 189*9e39c5baSBill Taylor "Sector (%d of %d bytes)\n"), 190*9e39c5baSBill Taylor j, manuf->sector_sz); 191*9e39c5baSBill Taylor (void) tavor_close(flashdev); 192*9e39c5baSBill Taylor return (FWFLASH_FAILURE); 193*9e39c5baSBill Taylor } else { 194*9e39c5baSBill Taylor fprintf(stdout, " ."); 195*9e39c5baSBill Taylor } 196*9e39c5baSBill Taylor 197*9e39c5baSBill Taylor /* Now for the xFI sectors */ 198*9e39c5baSBill Taylor pchunks = psz / manuf->sector_sz; 199*9e39c5baSBill Taylor 200*9e39c5baSBill Taylor if ((psz % manuf->sector_sz) != 0) 201*9e39c5baSBill Taylor pchunks++; 202*9e39c5baSBill Taylor 203*9e39c5baSBill Taylor /* Get the PFI, then the SFI */ 204*9e39c5baSBill Taylor if ((raw_pfi = calloc(1, pchunks * manuf->sector_sz)) == NULL) { 205*9e39c5baSBill Taylor logmsg(MSG_ERROR, 206*9e39c5baSBill Taylor gettext("tavor: Unable to allocate space for " 207*9e39c5baSBill Taylor "device's Primary Firmware Image\n")); 208*9e39c5baSBill Taylor return (FWFLASH_FAILURE); 209*9e39c5baSBill Taylor } 210*9e39c5baSBill Taylor bzero(&tfi_data, sizeof (tavor_flash_ioctl_t)); 211*9e39c5baSBill Taylor tfi_data.tf_type = TAVOR_FLASH_READ_SECTOR; 212*9e39c5baSBill Taylor j = pfia / manuf->sector_sz; 213*9e39c5baSBill Taylor 214*9e39c5baSBill Taylor for (offset = 0; offset < psz; offset += manuf->sector_sz) { 215*9e39c5baSBill Taylor tfi_data.tf_sector_num = j; 216*9e39c5baSBill Taylor tfi_data.tf_sector = (caddr_t)&raw_pfi[offset]; 217*9e39c5baSBill Taylor rv = ioctl(manuf->fd, TAVOR_IOCTL_FLASH_READ, &tfi_data); 218*9e39c5baSBill Taylor if (rv < 0) { 219*9e39c5baSBill Taylor logmsg(MSG_ERROR, 220*9e39c5baSBill Taylor gettext("tavor: Unable to read sector %d of " 221*9e39c5baSBill Taylor "HCA Primary Firmware Image\n"), j); 222*9e39c5baSBill Taylor free(raw_pfi); 223*9e39c5baSBill Taylor (void) tavor_close(flashdev); 224*9e39c5baSBill Taylor return (FWFLASH_FAILURE); 225*9e39c5baSBill Taylor } 226*9e39c5baSBill Taylor ++j; 227*9e39c5baSBill Taylor } 228*9e39c5baSBill Taylor 229*9e39c5baSBill Taylor /* 230*9e39c5baSBill Taylor * It appears that the tavor driver is returning a signed 231*9e39c5baSBill Taylor * -1 (0xffff) in unassigned quadlets if we read a sector 232*9e39c5baSBill Taylor * that isn't full, so for backwards compatibility with 233*9e39c5baSBill Taylor * earlier fwflash versions, we need to zero out what 234*9e39c5baSBill Taylor * remains in the sector. 235*9e39c5baSBill Taylor */ 236*9e39c5baSBill Taylor bzero(&raw_pfi[psz], (pchunks * manuf->sector_sz) - psz); 237*9e39c5baSBill Taylor 238*9e39c5baSBill Taylor #if defined(_LITTLE_ENDIAN) 239*9e39c5baSBill Taylor ptr = (uint32_t *)(uintptr_t)raw_pfi; 240*9e39c5baSBill Taylor for (j = 0; j < (pchunks * manuf->sector_sz / 4); j++) { 241*9e39c5baSBill Taylor ptr[j] = htonl(ptr[j]); 242*9e39c5baSBill Taylor if (j > psz) 243*9e39c5baSBill Taylor break; 244*9e39c5baSBill Taylor } 245*9e39c5baSBill Taylor #endif 246*9e39c5baSBill Taylor 247*9e39c5baSBill Taylor if ((j = write(fd, raw_pfi, pchunks * manuf->sector_sz)) 248*9e39c5baSBill Taylor != pchunks * manuf->sector_sz) { 249*9e39c5baSBill Taylor logmsg(MSG_ERROR, 250*9e39c5baSBill Taylor gettext("tavor: Unable to write HCA Primary Firmware " 251*9e39c5baSBill Taylor "Image data (%d of %d bytes)\n"), 252*9e39c5baSBill Taylor j, pchunks * manuf->sector_sz); 253*9e39c5baSBill Taylor free(raw_pfi); 254*9e39c5baSBill Taylor (void) tavor_close(flashdev); 255*9e39c5baSBill Taylor return (FWFLASH_FAILURE); 256*9e39c5baSBill Taylor } else { 257*9e39c5baSBill Taylor fprintf(stdout, " ."); 258*9e39c5baSBill Taylor } 259*9e39c5baSBill Taylor 260*9e39c5baSBill Taylor pchunks = ssz / manuf->sector_sz; 261*9e39c5baSBill Taylor 262*9e39c5baSBill Taylor if ((ssz % manuf->sector_sz) != 0) 263*9e39c5baSBill Taylor pchunks++; 264*9e39c5baSBill Taylor 265*9e39c5baSBill Taylor /* 266*9e39c5baSBill Taylor * We allocate wholenum sectors, but only write out what we 267*9e39c5baSBill Taylor * really need (ssz bytes) 268*9e39c5baSBill Taylor */ 269*9e39c5baSBill Taylor if ((raw_sfi = calloc(1, pchunks * manuf->sector_sz)) == NULL) { 270*9e39c5baSBill Taylor logmsg(MSG_ERROR, 271*9e39c5baSBill Taylor gettext("tavor: Unable to allocate space for " 272*9e39c5baSBill Taylor "device's Secondary Firmware Image\n")); 273*9e39c5baSBill Taylor free(raw_pfi); 274*9e39c5baSBill Taylor return (FWFLASH_FAILURE); 275*9e39c5baSBill Taylor } 276*9e39c5baSBill Taylor bzero(&tfi_data, sizeof (tavor_flash_ioctl_t)); 277*9e39c5baSBill Taylor tfi_data.tf_type = TAVOR_FLASH_READ_SECTOR; 278*9e39c5baSBill Taylor 279*9e39c5baSBill Taylor /* get our starting sector number */ 280*9e39c5baSBill Taylor j = sfia / manuf->sector_sz; 281*9e39c5baSBill Taylor 282*9e39c5baSBill Taylor for (offset = 0; offset < ssz; offset += manuf->sector_sz) { 283*9e39c5baSBill Taylor tfi_data.tf_sector_num = j; 284*9e39c5baSBill Taylor tfi_data.tf_sector = (caddr_t)&raw_sfi[offset]; 285*9e39c5baSBill Taylor if ((rv = ioctl(manuf->fd, TAVOR_IOCTL_FLASH_READ, 286*9e39c5baSBill Taylor &tfi_data)) < 0) { 287*9e39c5baSBill Taylor logmsg(MSG_ERROR, 288*9e39c5baSBill Taylor gettext("tavor: Unable to read sector %d of " 289*9e39c5baSBill Taylor "HCA Secondary Firmware Image\n"), j); 290*9e39c5baSBill Taylor (void) tavor_close(flashdev); 291*9e39c5baSBill Taylor free(raw_pfi); 292*9e39c5baSBill Taylor free(raw_sfi); 293*9e39c5baSBill Taylor return (FWFLASH_FAILURE); 294*9e39c5baSBill Taylor } 295*9e39c5baSBill Taylor ++j; 296*9e39c5baSBill Taylor } 297*9e39c5baSBill Taylor 298*9e39c5baSBill Taylor /* 299*9e39c5baSBill Taylor * It appears that the tavor driver is returning a signed 300*9e39c5baSBill Taylor * -1 (0xffff) in unassigned quadlets if we read a sector 301*9e39c5baSBill Taylor * that isn't full, so for backwards compatibility with 302*9e39c5baSBill Taylor * earlier fwflash versions, we need to zero out what 303*9e39c5baSBill Taylor * remains in the sector. 304*9e39c5baSBill Taylor */ 305*9e39c5baSBill Taylor bzero(&raw_sfi[ssz], (pchunks * manuf->sector_sz) - ssz); 306*9e39c5baSBill Taylor 307*9e39c5baSBill Taylor #if defined(_LITTLE_ENDIAN) 308*9e39c5baSBill Taylor ptr = (uint32_t *)(uintptr_t)raw_sfi; 309*9e39c5baSBill Taylor for (j = 0; j < ssz / 4; j++) { 310*9e39c5baSBill Taylor ptr[j] = htonl(ptr[j]); 311*9e39c5baSBill Taylor } 312*9e39c5baSBill Taylor #endif 313*9e39c5baSBill Taylor 314*9e39c5baSBill Taylor /* only write out ssz bytes */ 315*9e39c5baSBill Taylor if ((j = write(fd, raw_sfi, ssz)) != ssz) { 316*9e39c5baSBill Taylor logmsg(MSG_ERROR, 317*9e39c5baSBill Taylor gettext("tavor: Unable to write HCA Secondary Firmware " 318*9e39c5baSBill Taylor "Image data (%d of %d bytes)\n"), 319*9e39c5baSBill Taylor j, ssz); 320*9e39c5baSBill Taylor (void) tavor_close(flashdev); 321*9e39c5baSBill Taylor free(raw_pfi); 322*9e39c5baSBill Taylor free(raw_sfi); 323*9e39c5baSBill Taylor return (FWFLASH_FAILURE); 324*9e39c5baSBill Taylor } else { 325*9e39c5baSBill Taylor fprintf(stdout, " .\n"); 326*9e39c5baSBill Taylor } 327*9e39c5baSBill Taylor 328*9e39c5baSBill Taylor fprintf(stdout, 329*9e39c5baSBill Taylor gettext("Done.\n")); 330*9e39c5baSBill Taylor 331*9e39c5baSBill Taylor free(raw_pfi); 332*9e39c5baSBill Taylor free(raw_sfi); 333*9e39c5baSBill Taylor /* 334*9e39c5baSBill Taylor * this should succeed, but we don't just blindly ignore 335*9e39c5baSBill Taylor * the return code cos that would be obnoxious. 336*9e39c5baSBill Taylor */ 337*9e39c5baSBill Taylor return (tavor_close(flashdev)); 338*9e39c5baSBill Taylor } 339*9e39c5baSBill Taylor 340*9e39c5baSBill Taylor 341*9e39c5baSBill Taylor /* 342*9e39c5baSBill Taylor * If we're invoking fw_writefw, then flashdev is a valid, 343*9e39c5baSBill Taylor * flashable device as determined by fw_identify(). 344*9e39c5baSBill Taylor * 345*9e39c5baSBill Taylor * If verifier is null, then we haven't been called following a firmware 346*9e39c5baSBill Taylor * image verification load operation. 347*9e39c5baSBill Taylor */ 348*9e39c5baSBill Taylor int 349*9e39c5baSBill Taylor fw_writefw(struct devicelist *flashdev) 350*9e39c5baSBill Taylor { 351*9e39c5baSBill Taylor 352*9e39c5baSBill Taylor int rv; 353*9e39c5baSBill Taylor uint32_t j, sectsz, hpfia, hsfia; 354*9e39c5baSBill Taylor uint32_t ipfia, isfia, ipfis, isfis; 355*9e39c5baSBill Taylor struct ib_encap_ident *manuf; 356*9e39c5baSBill Taylor struct mlx_is *iinv; 357*9e39c5baSBill Taylor struct mlx_xps *ipps, *lpps; 358*9e39c5baSBill Taylor struct mlx_xps *isps, *lsps; 359*9e39c5baSBill Taylor struct mlx_xfi *ipfi, *isfi; 360*9e39c5baSBill Taylor 361*9e39c5baSBill Taylor /* 362*9e39c5baSBill Taylor * linv, lpps/lsps are from the HCA whereas 363*9e39c5baSBill Taylor * iinv/ipps/isps are in the on-disk firmware image that 364*9e39c5baSBill Taylor * we've read in to the verifier->fwimage field, and are 365*9e39c5baSBill Taylor * about to do some hand-waving with. 366*9e39c5baSBill Taylor */ 367*9e39c5baSBill Taylor 368*9e39c5baSBill Taylor /* 369*9e39c5baSBill Taylor * From the Mellanox HCA Flash programming app note, 370*9e39c5baSBill Taylor * start of ch4, page36: 371*9e39c5baSBill Taylor * =========================================================== 372*9e39c5baSBill Taylor * Failsafe firmware programming ensures that an HCA device 373*9e39c5baSBill Taylor * can boot up in a functional mode even if the burn process 374*9e39c5baSBill Taylor * was interrupted (because of a power failure, reboot, user 375*9e39c5baSBill Taylor * interrupt, etc.). This can be implemented by burning the 376*9e39c5baSBill Taylor * new image to a vacant region on the Flash, and erasing the 377*9e39c5baSBill Taylor * old image only after the new image is successfully burnt. 378*9e39c5baSBill Taylor * This method ensures that there is at least one valid firmware 379*9e39c5baSBill Taylor * image on the Flash at all times. Thus, in case a firmware 380*9e39c5baSBill Taylor * image programming process is aborted for any reason, the HCA 381*9e39c5baSBill Taylor * will still be able to boot up properly using the valid image 382*9e39c5baSBill Taylor * on the Flash. 383*9e39c5baSBill Taylor * ... 384*9e39c5baSBill Taylor * 385*9e39c5baSBill Taylor * 4.1 Notes on Image Programming of HCA Flashes 386*9e39c5baSBill Taylor * Following are some general notes regarding the Flash memory 387*9e39c5baSBill Taylor * in the context of Mellanox HCA devices: 388*9e39c5baSBill Taylor * > The Flash memory is divided into sectors, and each sector 389*9e39c5baSBill Taylor * must be erased prior to its programming. 390*9e39c5baSBill Taylor * > The image to be burnt is byte packed and should be programmed 391*9e39c5baSBill Taylor * into the Flash byte by byte, preserving the byte order, starting 392*9e39c5baSBill Taylor * at offset zero. No amendments are needed for endianess. 393*9e39c5baSBill Taylor * > It is recommended to program the Flash while the device is idle. 394*9e39c5baSBill Taylor * =========================================================== 395*9e39c5baSBill Taylor * 396*9e39c5baSBill Taylor * The comment about endianness is particularly important for us 397*9e39c5baSBill Taylor * since we operate on both big- and litte-endian hosts - it means 398*9e39c5baSBill Taylor * we have to do some byte-swapping gymnastics 399*9e39c5baSBill Taylor */ 400*9e39c5baSBill Taylor 401*9e39c5baSBill Taylor /* 402*9e39c5baSBill Taylor * From the Mellanox HCA Flash programming app note, 403*9e39c5baSBill Taylor * section 4.2.5 on page 41/42: 404*9e39c5baSBill Taylor * =========================================================== 405*9e39c5baSBill Taylor * 4.2.5 Failsafe Programming Example 406*9e39c5baSBill Taylor * This section provides an example of a programming utility 407*9e39c5baSBill Taylor * that performs a Failsafe firmware image update. The flow 408*9e39c5baSBill Taylor * ensures that there is at least one valid firmware image on 409*9e39c5baSBill Taylor * the Flash at all times. Thus, in case a firmware image pro- 410*9e39c5baSBill Taylor * gramming process is aborted for any reason, the HCA will 411*9e39c5baSBill Taylor * still be able to boot up properly using the valid image on 412*9e39c5baSBill Taylor * the Flash. Any other flow that ensures the above is also 413*9e39c5baSBill Taylor * considered a Failsafe firmware update. 414*9e39c5baSBill Taylor * 415*9e39c5baSBill Taylor * Update Flow: 416*9e39c5baSBill Taylor * * Check the validity of the PPS and SPS: 417*9e39c5baSBill Taylor * > If both PSs are valid, arbitrarily invalidate one of them 418*9e39c5baSBill Taylor * > If both PSs are invalid, the image on flash is corrupted 419*9e39c5baSBill Taylor * and cannot be updated in a Failsafe way. The user must 420*9e39c5baSBill Taylor * burn a full image in a non-failsafe way. 421*9e39c5baSBill Taylor * 422*9e39c5baSBill Taylor * > If only the PPS is valid: 423*9e39c5baSBill Taylor * i.Burn the secondary image (erase each sector first) 424*9e39c5baSBill Taylor * ii.Burn the SPS with the correct image address (FIA field) 425*9e39c5baSBill Taylor * iii.Invalidate the PPS 426*9e39c5baSBill Taylor * 427*9e39c5baSBill Taylor * > If only the SPS is valid: 428*9e39c5baSBill Taylor * i.Burn the primary image (erase each sector first) 429*9e39c5baSBill Taylor * ii.Burn the PPS with the correct image address (FIA field) 430*9e39c5baSBill Taylor * iii.Invalidate the SPS 431*9e39c5baSBill Taylor * =========================================================== 432*9e39c5baSBill Taylor */ 433*9e39c5baSBill Taylor 434*9e39c5baSBill Taylor /* 435*9e39c5baSBill Taylor * Other required tasks called from this function: 436*9e39c5baSBill Taylor * 437*9e39c5baSBill Taylor * * check for CISCO boot extensions in the current xPS, and 438*9e39c5baSBill Taylor * if found, set them in the new xPS 439*9e39c5baSBill Taylor * 440*9e39c5baSBill Taylor * * update the xPS CRC field 441*9e39c5baSBill Taylor * 442*9e39c5baSBill Taylor * _then_ you can setup the outbound transfer to the HCA flash. 443*9e39c5baSBill Taylor */ 444*9e39c5baSBill Taylor 445*9e39c5baSBill Taylor /* 446*9e39c5baSBill Taylor * VERY IMPORTANT NOTE: 447*9e39c5baSBill Taylor * The above text from the app note programming guide v1.44 does 448*9e39c5baSBill Taylor * NOT match reality. If you try to do exactly what the above 449*9e39c5baSBill Taylor * text specifies then you'll wind up with a warm, brick-like 450*9e39c5baSBill Taylor * HCA that if you're really lucky has booted up in maintenance 451*9e39c5baSBill Taylor * mode for you to re-flash. 452*9e39c5baSBill Taylor * 453*9e39c5baSBill Taylor * What you need to do is follow the example of the previous 454*9e39c5baSBill Taylor * (v1.2 etc) version from the ON gate - which is what happens 455*9e39c5baSBill Taylor * in this file. Basically - don't erase prior to writing a new 456*9e39c5baSBill Taylor * sector, and _read back_ each sector after writing it. Especially 457*9e39c5baSBill Taylor * the pointer sectors. Otherwise you'll get a warm brick. 458*9e39c5baSBill Taylor */ 459*9e39c5baSBill Taylor 460*9e39c5baSBill Taylor manuf = 461*9e39c5baSBill Taylor (struct ib_encap_ident *)(uintptr_t)flashdev->ident->encap_ident; 462*9e39c5baSBill Taylor lpps = (struct mlx_xps *)(uintptr_t)manuf->pps; 463*9e39c5baSBill Taylor lsps = (struct mlx_xps *)(uintptr_t)manuf->sps; 464*9e39c5baSBill Taylor iinv = (struct mlx_is *)&verifier->fwimage[0]; 465*9e39c5baSBill Taylor sectsz = 1 << MLXSWAPBITS16(iinv->log2sectsz + iinv->log2sectszp); 466*9e39c5baSBill Taylor ipps = (struct mlx_xps *)&verifier->fwimage[sectsz/4]; 467*9e39c5baSBill Taylor isps = (struct mlx_xps *)&verifier->fwimage[sectsz/2]; 468*9e39c5baSBill Taylor 469*9e39c5baSBill Taylor /* 470*9e39c5baSBill Taylor * If we get here, then the verifier has _already_ checked that 471*9e39c5baSBill Taylor * the part number in the firmware image matches that in the HCA, 472*9e39c5baSBill Taylor * so we only need this check if there's no hardware info available 473*9e39c5baSBill Taylor * already after running through fw_identify(). 474*9e39c5baSBill Taylor */ 475*9e39c5baSBill Taylor if (manuf->pn_len == 0) { 476*9e39c5baSBill Taylor int resp; 477*9e39c5baSBill Taylor 478*9e39c5baSBill Taylor (void) printf("\nUnable to completely verify that this " 479*9e39c5baSBill Taylor "firmware image\n\t(%s)\nis compatible with your " 480*9e39c5baSBill Taylor "HCA\n\t%s\n", 481*9e39c5baSBill Taylor verifier->imgfile, flashdev->access_devname); 482*9e39c5baSBill Taylor (void) printf("\n\tDo you really want to continue? (Y/N): "); 483*9e39c5baSBill Taylor 484*9e39c5baSBill Taylor (void) fflush(stdin); 485*9e39c5baSBill Taylor resp = getchar(); 486*9e39c5baSBill Taylor if (resp != 'Y' && resp != 'y') { 487*9e39c5baSBill Taylor (void) printf("\nNot proceeding with flash " 488*9e39c5baSBill Taylor "operation of %s on %s\n", 489*9e39c5baSBill Taylor verifier->imgfile, flashdev->access_devname); 490*9e39c5baSBill Taylor return (FWFLASH_FAILURE); 491*9e39c5baSBill Taylor } 492*9e39c5baSBill Taylor } 493*9e39c5baSBill Taylor 494*9e39c5baSBill Taylor /* stash these for later */ 495*9e39c5baSBill Taylor hpfia = MLXSWAPBITS32(lpps->fia); 496*9e39c5baSBill Taylor hsfia = MLXSWAPBITS32(lsps->fia); 497*9e39c5baSBill Taylor 498*9e39c5baSBill Taylor /* where does the on-disk image think everything is at? */ 499*9e39c5baSBill Taylor ipfia = MLXSWAPBITS32(ipps->fia); 500*9e39c5baSBill Taylor isfia = MLXSWAPBITS32(isps->fia); 501*9e39c5baSBill Taylor ipfis = MLXSWAPBITS32(ipps->fis); 502*9e39c5baSBill Taylor isfis = MLXSWAPBITS32(isps->fis); 503*9e39c5baSBill Taylor 504*9e39c5baSBill Taylor logmsg(MSG_INFO, "tavor: hpfia 0x%0x hsfia 0x%0x " 505*9e39c5baSBill Taylor "ipfia 0x%0x isfia 0x%0x ipfis 0x%0x isfis 0x%0x\n", 506*9e39c5baSBill Taylor hpfia, hsfia, ipfia, isfia, ipfis, isfis); 507*9e39c5baSBill Taylor 508*9e39c5baSBill Taylor if ((ipfis + isfis) > manuf->device_sz) { 509*9e39c5baSBill Taylor /* 510*9e39c5baSBill Taylor * This is bad - don't flash an image which is larger 511*9e39c5baSBill Taylor * than the size of the HCA's flash 512*9e39c5baSBill Taylor */ 513*9e39c5baSBill Taylor logmsg(MSG_ERROR, 514*9e39c5baSBill Taylor gettext("tavor: on-disk firmware image size (0x%lx bytes) " 515*9e39c5baSBill Taylor "exceeds HCA's flash memory size (0x%lx bytes)!\n"), 516*9e39c5baSBill Taylor ipfis + isfis, manuf->device_sz); 517*9e39c5baSBill Taylor logmsg(MSG_ERROR, 518*9e39c5baSBill Taylor gettext("tavor: not flashing this image (%s)\n"), 519*9e39c5baSBill Taylor verifier->imgfile); 520*9e39c5baSBill Taylor return (FWFLASH_FAILURE); 521*9e39c5baSBill Taylor } 522*9e39c5baSBill Taylor 523*9e39c5baSBill Taylor /* 524*9e39c5baSBill Taylor * The Mellanox HCA Flash app programming note does _not_ 525*9e39c5baSBill Taylor * specify that you have to insert the HCA's guid section 526*9e39c5baSBill Taylor * into the flash image before burning it. 527*9e39c5baSBill Taylor * 528*9e39c5baSBill Taylor * HOWEVER it was determined during testing that this is 529*9e39c5baSBill Taylor * actually required (otherwise your HCA's GUIDs revert to 530*9e39c5baSBill Taylor * the manufacturer's defaults, ugh!), so we'll do it too. 531*9e39c5baSBill Taylor */ 532*9e39c5baSBill Taylor 533*9e39c5baSBill Taylor ipfi = (struct mlx_xfi *)&verifier->fwimage[ipfia/4]; 534*9e39c5baSBill Taylor isfi = (struct mlx_xfi *)&verifier->fwimage[isfia/4]; 535*9e39c5baSBill Taylor 536*9e39c5baSBill Taylor /* 537*9e39c5baSBill Taylor * Here we check against our stored, properly-bitwise-munged copy 538*9e39c5baSBill Taylor * of the HCA's GUIDS. If they're not set to default AND the OUI 539*9e39c5baSBill Taylor * is MLX_OUI, then they're ok so we copy the HCA's version into 540*9e39c5baSBill Taylor * our in-memory copy and blat it. If the GUIDs don't match this 541*9e39c5baSBill Taylor * condition, then we use the default GUIDs which are in the on-disk 542*9e39c5baSBill Taylor * firmware image instead. 543*9e39c5baSBill Taylor */ 544*9e39c5baSBill Taylor if (((manuf->ibguids[0] != MLX_DEFAULT_NODE_GUID) && 545*9e39c5baSBill Taylor (manuf->ibguids[1] != MLX_DEFAULT_P1_GUID) && 546*9e39c5baSBill Taylor (manuf->ibguids[2] != MLX_DEFAULT_P2_GUID) && 547*9e39c5baSBill Taylor (manuf->ibguids[3] != MLX_DEFAULT_SYSIMG_GUID)) && 548*9e39c5baSBill Taylor ((((manuf->ibguids[0] & HIGHBITS64) >> OUISHIFT) == MLX_OUI) || 549*9e39c5baSBill Taylor (((manuf->ibguids[1] & HIGHBITS64) >> OUISHIFT) == MLX_OUI) || 550*9e39c5baSBill Taylor (((manuf->ibguids[2] & HIGHBITS64) >> OUISHIFT) == MLX_OUI) || 551*9e39c5baSBill Taylor (((manuf->ibguids[3] & HIGHBITS64) >> OUISHIFT) == MLX_OUI))) { 552*9e39c5baSBill Taylor /* The GUIDs are ok, blat them into the in-memory image */ 553*9e39c5baSBill Taylor j = ((ipfia + MLXSWAPBITS32(ipfi->nguidptr)) / 4) - 4; 554*9e39c5baSBill Taylor bcopy(manuf->pri_guid_section, &verifier->fwimage[j], 555*9e39c5baSBill Taylor sizeof (struct mlx_guid_sect)); 556*9e39c5baSBill Taylor j = ((isfia + MLXSWAPBITS32(isfi->nguidptr)) / 4) - 4; 557*9e39c5baSBill Taylor bcopy(manuf->sec_guid_section, &verifier->fwimage[j], 558*9e39c5baSBill Taylor sizeof (struct mlx_guid_sect)); 559*9e39c5baSBill Taylor } else { 560*9e39c5baSBill Taylor /* 561*9e39c5baSBill Taylor * The GUIDs are hosed, we'll have to use 562*9e39c5baSBill Taylor * the vendor defaults in the image instead 563*9e39c5baSBill Taylor */ 564*9e39c5baSBill Taylor logmsg(MSG_ERROR, 565*9e39c5baSBill Taylor gettext("tavor: HCA's GUID section is set to defaults or " 566*9e39c5baSBill Taylor " is invalid, using firmware image manufacturer's " 567*9e39c5baSBill Taylor "default GUID section instead\n")); 568*9e39c5baSBill Taylor } 569*9e39c5baSBill Taylor 570*9e39c5baSBill Taylor /* Just in case somebody is booting from this card... */ 571*9e39c5baSBill Taylor tavor_cisco_extensions(lpps, ipps); 572*9e39c5baSBill Taylor tavor_cisco_extensions(lsps, isps); 573*9e39c5baSBill Taylor 574*9e39c5baSBill Taylor /* first we write the secondary image and SPS, then the primary */ 575*9e39c5baSBill Taylor rv = tavor_blast_image(manuf->fd, 2, hsfia, manuf->sector_sz, isps); 576*9e39c5baSBill Taylor if (rv != FWFLASH_SUCCESS) { 577*9e39c5baSBill Taylor logmsg(MSG_INFO, 578*9e39c5baSBill Taylor "tavor: failed to update #2 firmware image\n"); 579*9e39c5baSBill Taylor (void) tavor_close(flashdev); 580*9e39c5baSBill Taylor return (FWFLASH_FAILURE); 581*9e39c5baSBill Taylor } 582*9e39c5baSBill Taylor 583*9e39c5baSBill Taylor rv = tavor_blast_image(manuf->fd, 1, hpfia, manuf->sector_sz, ipps); 584*9e39c5baSBill Taylor if (rv != FWFLASH_SUCCESS) { 585*9e39c5baSBill Taylor logmsg(MSG_INFO, 586*9e39c5baSBill Taylor "tavor: failed to update #1 firmware image\n"); 587*9e39c5baSBill Taylor (void) tavor_close(flashdev); 588*9e39c5baSBill Taylor return (FWFLASH_FAILURE); 589*9e39c5baSBill Taylor } 590*9e39c5baSBill Taylor 591*9e39c5baSBill Taylor /* final update marker to the user */ 592*9e39c5baSBill Taylor (void) printf(" +\n"); 593*9e39c5baSBill Taylor return (tavor_close(flashdev)); 594*9e39c5baSBill Taylor } 595*9e39c5baSBill Taylor 596*9e39c5baSBill Taylor 597*9e39c5baSBill Taylor /* 598*9e39c5baSBill Taylor * The fw_identify() function walks the device 599*9e39c5baSBill Taylor * tree trying to find devices which this plugin 600*9e39c5baSBill Taylor * can work with. 601*9e39c5baSBill Taylor * 602*9e39c5baSBill Taylor * The parameter "start" gives us the starting index number 603*9e39c5baSBill Taylor * to give the device when we add it to the fw_devices list. 604*9e39c5baSBill Taylor * 605*9e39c5baSBill Taylor * firstdev is allocated by us and we add space as necessary 606*9e39c5baSBill Taylor * 607*9e39c5baSBill Taylor */ 608*9e39c5baSBill Taylor int 609*9e39c5baSBill Taylor fw_identify(int start) 610*9e39c5baSBill Taylor { 611*9e39c5baSBill Taylor int rv = FWFLASH_FAILURE; 612*9e39c5baSBill Taylor di_node_t thisnode; 613*9e39c5baSBill Taylor struct devicelist *newdev; 614*9e39c5baSBill Taylor char *devpath; 615*9e39c5baSBill Taylor int idx = start; 616*9e39c5baSBill Taylor int devlength = 0; 617*9e39c5baSBill Taylor 618*9e39c5baSBill Taylor thisnode = di_drv_first_node(drivername, rootnode); 619*9e39c5baSBill Taylor 620*9e39c5baSBill Taylor if (thisnode == DI_NODE_NIL) { 621*9e39c5baSBill Taylor logmsg(MSG_INFO, gettext("No %s nodes in this system\n"), 622*9e39c5baSBill Taylor drivername); 623*9e39c5baSBill Taylor return (rv); 624*9e39c5baSBill Taylor } 625*9e39c5baSBill Taylor 626*9e39c5baSBill Taylor /* we've found one, at least */ 627*9e39c5baSBill Taylor for (; thisnode != DI_NODE_NIL; thisnode = di_drv_next_node(thisnode)) { 628*9e39c5baSBill Taylor 629*9e39c5baSBill Taylor devpath = di_devfs_path(thisnode); 630*9e39c5baSBill Taylor 631*9e39c5baSBill Taylor if ((newdev = calloc(1, sizeof (struct devicelist))) 632*9e39c5baSBill Taylor == NULL) { 633*9e39c5baSBill Taylor logmsg(MSG_ERROR, 634*9e39c5baSBill Taylor gettext("%s identification function unable " 635*9e39c5baSBill Taylor "to allocate space for device entry\n")); 636*9e39c5baSBill Taylor di_devfs_path_free(devpath); 637*9e39c5baSBill Taylor return (rv); 638*9e39c5baSBill Taylor } 639*9e39c5baSBill Taylor 640*9e39c5baSBill Taylor /* calloc enough for /devices + devpath + ":devctl" + '\0' */ 641*9e39c5baSBill Taylor devlength = strlen(devpath) + strlen(devprefix) + 642*9e39c5baSBill Taylor strlen(devsuffix) + 2; 643*9e39c5baSBill Taylor 644*9e39c5baSBill Taylor if ((newdev->access_devname = calloc(1, devlength)) == NULL) { 645*9e39c5baSBill Taylor logmsg(MSG_ERROR, gettext("Unable to calloc space " 646*9e39c5baSBill Taylor "for a devfs name\n")); 647*9e39c5baSBill Taylor di_devfs_path_free(devpath); 648*9e39c5baSBill Taylor (void) free(newdev); 649*9e39c5baSBill Taylor return (FWFLASH_FAILURE); 650*9e39c5baSBill Taylor } 651*9e39c5baSBill Taylor snprintf(newdev->access_devname, devlength, 652*9e39c5baSBill Taylor "%s%s%s", devprefix, devpath, devsuffix); 653*9e39c5baSBill Taylor 654*9e39c5baSBill Taylor /* CHECK VARIOUS IB THINGS HERE */ 655*9e39c5baSBill Taylor 656*9e39c5baSBill Taylor if ((newdev->ident = calloc(1, sizeof (struct vpr))) == NULL) { 657*9e39c5baSBill Taylor logmsg(MSG_ERROR, 658*9e39c5baSBill Taylor gettext("tavor: Unable to allocate space for a " 659*9e39c5baSBill Taylor "device identification record\n")); 660*9e39c5baSBill Taylor (void) free(newdev->access_devname); 661*9e39c5baSBill Taylor (void) free(newdev); 662*9e39c5baSBill Taylor di_devfs_path_free(devpath); 663*9e39c5baSBill Taylor return (FWFLASH_FAILURE); 664*9e39c5baSBill Taylor } 665*9e39c5baSBill Taylor 666*9e39c5baSBill Taylor rv = tavor_identify(newdev); 667*9e39c5baSBill Taylor if (rv == FWFLASH_FAILURE) { 668*9e39c5baSBill Taylor (void) free(newdev->ident); 669*9e39c5baSBill Taylor (void) free(newdev->access_devname); 670*9e39c5baSBill Taylor (void) free(newdev); 671*9e39c5baSBill Taylor di_devfs_path_free(devpath); 672*9e39c5baSBill Taylor continue; 673*9e39c5baSBill Taylor } 674*9e39c5baSBill Taylor 675*9e39c5baSBill Taylor if ((newdev->drvname = calloc(1, strlen(drivername) + 1)) 676*9e39c5baSBill Taylor == NULL) { 677*9e39c5baSBill Taylor logmsg(MSG_ERROR, gettext("Unable to allocate space " 678*9e39c5baSBill Taylor "for a driver name\n")); 679*9e39c5baSBill Taylor (void) free(newdev->ident); 680*9e39c5baSBill Taylor (void) free(newdev->access_devname); 681*9e39c5baSBill Taylor (void) free(newdev); 682*9e39c5baSBill Taylor di_devfs_path_free(devpath); 683*9e39c5baSBill Taylor return (FWFLASH_FAILURE); 684*9e39c5baSBill Taylor } 685*9e39c5baSBill Taylor 686*9e39c5baSBill Taylor (void) strlcpy(newdev->drvname, drivername, 687*9e39c5baSBill Taylor strlen(drivername) + 1); 688*9e39c5baSBill Taylor 689*9e39c5baSBill Taylor /* this next bit is backwards compatibility - "IB\0" */ 690*9e39c5baSBill Taylor if ((newdev->classname = calloc(1, 3)) == NULL) { 691*9e39c5baSBill Taylor logmsg(MSG_ERROR, gettext("Unable to allocate space " 692*9e39c5baSBill Taylor "for a class name\n")); 693*9e39c5baSBill Taylor (void) free(newdev->drvname); 694*9e39c5baSBill Taylor (void) free(newdev->ident); 695*9e39c5baSBill Taylor (void) free(newdev->access_devname); 696*9e39c5baSBill Taylor (void) free(newdev); 697*9e39c5baSBill Taylor di_devfs_path_free(devpath); 698*9e39c5baSBill Taylor return (FWFLASH_FAILURE); 699*9e39c5baSBill Taylor } 700*9e39c5baSBill Taylor (void) strlcpy(newdev->classname, "IB", 3); 701*9e39c5baSBill Taylor 702*9e39c5baSBill Taylor newdev->index = idx; 703*9e39c5baSBill Taylor ++idx; 704*9e39c5baSBill Taylor newdev->plugin = self; 705*9e39c5baSBill Taylor 706*9e39c5baSBill Taylor di_devfs_path_free(devpath); 707*9e39c5baSBill Taylor TAILQ_INSERT_TAIL(fw_devices, newdev, nextdev); 708*9e39c5baSBill Taylor } 709*9e39c5baSBill Taylor 710*9e39c5baSBill Taylor if (fwflash_debug != 0) { 711*9e39c5baSBill Taylor struct devicelist *tempdev; 712*9e39c5baSBill Taylor 713*9e39c5baSBill Taylor TAILQ_FOREACH(tempdev, fw_devices, nextdev) { 714*9e39c5baSBill Taylor logmsg(MSG_INFO, "ib:fw_identify:\n"); 715*9e39c5baSBill Taylor logmsg(MSG_INFO, "\ttempdev @ 0x%lx\n" 716*9e39c5baSBill Taylor "\t\taccess_devname: %s\n" 717*9e39c5baSBill Taylor "\t\tdrvname: %s\tclassname: %s\n" 718*9e39c5baSBill Taylor "\t\tident->vid: %s\n" 719*9e39c5baSBill Taylor "\t\tident->pid: %s\n" 720*9e39c5baSBill Taylor "\t\tident->revid: %s\n" 721*9e39c5baSBill Taylor "\t\tindex: %d\n" 722*9e39c5baSBill Taylor "\t\tguid0: %s\n" 723*9e39c5baSBill Taylor "\t\tguid1: %s\n" 724*9e39c5baSBill Taylor "\t\tguid2: %s\n" 725*9e39c5baSBill Taylor "\t\tguid3: %s\n" 726*9e39c5baSBill Taylor "\t\tplugin @ 0x%lx\n\n", 727*9e39c5baSBill Taylor &tempdev, 728*9e39c5baSBill Taylor tempdev->access_devname, 729*9e39c5baSBill Taylor tempdev->drvname, newdev->classname, 730*9e39c5baSBill Taylor tempdev->ident->vid, 731*9e39c5baSBill Taylor tempdev->ident->pid, 732*9e39c5baSBill Taylor tempdev->ident->revid, 733*9e39c5baSBill Taylor tempdev->index, 734*9e39c5baSBill Taylor tempdev->addresses[0], 735*9e39c5baSBill Taylor tempdev->addresses[1], 736*9e39c5baSBill Taylor tempdev->addresses[2], 737*9e39c5baSBill Taylor tempdev->addresses[3], 738*9e39c5baSBill Taylor tempdev->plugin); 739*9e39c5baSBill Taylor } 740*9e39c5baSBill Taylor } 741*9e39c5baSBill Taylor 742*9e39c5baSBill Taylor return (FWFLASH_SUCCESS); 743*9e39c5baSBill Taylor } 744*9e39c5baSBill Taylor 745*9e39c5baSBill Taylor 746*9e39c5baSBill Taylor 747*9e39c5baSBill Taylor int 748*9e39c5baSBill Taylor fw_devinfo(struct devicelist *thisdev) 749*9e39c5baSBill Taylor { 750*9e39c5baSBill Taylor 751*9e39c5baSBill Taylor struct ib_encap_ident *encap; 752*9e39c5baSBill Taylor 753*9e39c5baSBill Taylor 754*9e39c5baSBill Taylor encap = (struct ib_encap_ident *)thisdev->ident->encap_ident; 755*9e39c5baSBill Taylor 756*9e39c5baSBill Taylor fprintf(stdout, gettext("Device[%d] %s\n Class [%s]\n"), 757*9e39c5baSBill Taylor thisdev->index, thisdev->access_devname, thisdev->classname); 758*9e39c5baSBill Taylor 759*9e39c5baSBill Taylor fprintf(stdout, "\t"); 760*9e39c5baSBill Taylor 761*9e39c5baSBill Taylor /* Mellanox HCA Flash app note, p40, #4.2.3 table 9 */ 762*9e39c5baSBill Taylor fprintf(stdout, 763*9e39c5baSBill Taylor gettext("GUID: System Image - %s\n"), 764*9e39c5baSBill Taylor thisdev->addresses[3]); 765*9e39c5baSBill Taylor fprintf(stdout, 766*9e39c5baSBill Taylor gettext("\t\tNode Image - %s\n"), 767*9e39c5baSBill Taylor thisdev->addresses[0]); 768*9e39c5baSBill Taylor fprintf(stdout, 769*9e39c5baSBill Taylor gettext("\t\tPort 1\t - %s\n"), 770*9e39c5baSBill Taylor thisdev->addresses[1]); 771*9e39c5baSBill Taylor fprintf(stdout, 772*9e39c5baSBill Taylor gettext("\t\tPort 2\t - %s\n"), 773*9e39c5baSBill Taylor thisdev->addresses[2]); 774*9e39c5baSBill Taylor 775*9e39c5baSBill Taylor if (encap->pn_len != 0) { 776*9e39c5baSBill Taylor fprintf(stdout, 777*9e39c5baSBill Taylor gettext("\tFirmware revision : %s\n" 778*9e39c5baSBill Taylor "\tProduct\t\t: %s\n" 779*9e39c5baSBill Taylor "\tPSID\t\t: %s\n"), 780*9e39c5baSBill Taylor thisdev->ident->revid, 781*9e39c5baSBill Taylor encap->info.mlx_pn, 782*9e39c5baSBill Taylor encap->info.mlx_psid); 783*9e39c5baSBill Taylor } else { 784*9e39c5baSBill Taylor fprintf(stdout, 785*9e39c5baSBill Taylor gettext("\tFirmware revision : %s\n" 786*9e39c5baSBill Taylor "\tNo hardware information available for this " 787*9e39c5baSBill Taylor "device\n"), thisdev->ident->revid); 788*9e39c5baSBill Taylor } 789*9e39c5baSBill Taylor fprintf(stdout, "\n\n"); 790*9e39c5baSBill Taylor 791*9e39c5baSBill Taylor return (tavor_close(thisdev)); 792*9e39c5baSBill Taylor } 793*9e39c5baSBill Taylor 794*9e39c5baSBill Taylor 795*9e39c5baSBill Taylor /* 796*9e39c5baSBill Taylor * Helper functions lurk beneath this point 797*9e39c5baSBill Taylor */ 798*9e39c5baSBill Taylor 799*9e39c5baSBill Taylor 800*9e39c5baSBill Taylor /* 801*9e39c5baSBill Taylor * tavor_identify performs the following actions: 802*9e39c5baSBill Taylor * 803*9e39c5baSBill Taylor * allocates and assigns thisdev->vpr 804*9e39c5baSBill Taylor * 805*9e39c5baSBill Taylor * allocates space for the 4 GUIDs which each IB device must have 806*9e39c5baSBill Taylor * queries the tavor driver for this device's GUIDs 807*9e39c5baSBill Taylor * 808*9e39c5baSBill Taylor * determines the hardware vendor, so that thisdev->vpr->vid 809*9e39c5baSBill Taylor * can be set correctly 810*9e39c5baSBill Taylor */ 811*9e39c5baSBill Taylor static int 812*9e39c5baSBill Taylor tavor_identify(struct devicelist *thisdev) 813*9e39c5baSBill Taylor { 814*9e39c5baSBill Taylor int rv = FWFLASH_SUCCESS; 815*9e39c5baSBill Taylor int fd, ret, i; 816*9e39c5baSBill Taylor 817*9e39c5baSBill Taylor tavor_flash_init_ioctl_t init_ioctl; 818*9e39c5baSBill Taylor tavor_flash_ioctl_t info; 819*9e39c5baSBill Taylor struct ib_encap_ident *manuf; 820*9e39c5baSBill Taylor cfi_t cfi; 821*9e39c5baSBill Taylor char temppsid[17]; 822*9e39c5baSBill Taylor char rawpsid[16]; 823*9e39c5baSBill Taylor 824*9e39c5baSBill Taylor #if defined(_LITTLE_ENDIAN) 825*9e39c5baSBill Taylor uint32_t *ptr; 826*9e39c5baSBill Taylor #endif 827*9e39c5baSBill Taylor 828*9e39c5baSBill Taylor /* open the device */ 829*9e39c5baSBill Taylor /* hook thisdev->ident->encap_ident to ib_encap_ident */ 830*9e39c5baSBill Taylor /* check that all the bits are sane */ 831*9e39c5baSBill Taylor /* return success, if warranted */ 832*9e39c5baSBill Taylor 833*9e39c5baSBill Taylor errno = 0; 834*9e39c5baSBill Taylor if ((fd = open(thisdev->access_devname, O_RDONLY)) < 0) { 835*9e39c5baSBill Taylor logmsg(MSG_INFO, 836*9e39c5baSBill Taylor gettext("tavor: Unable to open a %s-attached " 837*9e39c5baSBill Taylor "device node: %s: %s\n"), drivername, 838*9e39c5baSBill Taylor thisdev->access_devname, strerror(errno)); 839*9e39c5baSBill Taylor return (FWFLASH_FAILURE); 840*9e39c5baSBill Taylor } 841*9e39c5baSBill Taylor 842*9e39c5baSBill Taylor if ((manuf = calloc(1, sizeof (ib_encap_ident_t))) == NULL) { 843*9e39c5baSBill Taylor logmsg(MSG_ERROR, 844*9e39c5baSBill Taylor gettext("tavor: Unable to calloc space for a " 845*9e39c5baSBill Taylor "%s-attached handle structure\n"), 846*9e39c5baSBill Taylor drivername); 847*9e39c5baSBill Taylor return (FWFLASH_FAILURE); 848*9e39c5baSBill Taylor } 849*9e39c5baSBill Taylor manuf->magic = FWFLASH_IB_MAGIC_NUMBER; 850*9e39c5baSBill Taylor manuf->state = FWFLASH_IB_STATE_NONE; 851*9e39c5baSBill Taylor manuf->fd = fd; 852*9e39c5baSBill Taylor 853*9e39c5baSBill Taylor thisdev->ident->encap_ident = manuf; 854*9e39c5baSBill Taylor 855*9e39c5baSBill Taylor /* 856*9e39c5baSBill Taylor * Inform driver that this command supports the Intel Extended 857*9e39c5baSBill Taylor * CFI command set. 858*9e39c5baSBill Taylor */ 859*9e39c5baSBill Taylor cfi.cfi_char[0x10] = 'M'; 860*9e39c5baSBill Taylor cfi.cfi_char[0x11] = 'X'; 861*9e39c5baSBill Taylor cfi.cfi_char[0x12] = '2'; 862*9e39c5baSBill Taylor init_ioctl.tf_cfi_info[0x4] = MLXSWAPBITS32(cfi.cfi_int[0x4]); 863*9e39c5baSBill Taylor 864*9e39c5baSBill Taylor errno = 0; 865*9e39c5baSBill Taylor ret = ioctl(fd, TAVOR_IOCTL_FLASH_INIT, &init_ioctl); 866*9e39c5baSBill Taylor if (ret < 0) { 867*9e39c5baSBill Taylor logmsg(MSG_ERROR, 868*9e39c5baSBill Taylor gettext("ib: TAVOR_IOCTL_FLASH_INIT failed: %s\n"), 869*9e39c5baSBill Taylor strerror(errno)); 870*9e39c5baSBill Taylor free(manuf); 871*9e39c5baSBill Taylor close(fd); 872*9e39c5baSBill Taylor return (FWFLASH_FAILURE); 873*9e39c5baSBill Taylor } 874*9e39c5baSBill Taylor 875*9e39c5baSBill Taylor manuf->hwrev = init_ioctl.tf_hwrev; 876*9e39c5baSBill Taylor 877*9e39c5baSBill Taylor /* 878*9e39c5baSBill Taylor * Determine whether the attached driver supports the Intel or 879*9e39c5baSBill Taylor * AMD Extended CFI command sets. If it doesn't support either, 880*9e39c5baSBill Taylor * then we're hosed, so error out. 881*9e39c5baSBill Taylor */ 882*9e39c5baSBill Taylor for (i = 0; i < TAVOR_FLASH_CFI_SIZE_QUADLET; i++) { 883*9e39c5baSBill Taylor cfi.cfi_int[i] = MLXSWAPBITS32(init_ioctl.tf_cfi_info[i]); 884*9e39c5baSBill Taylor } 885*9e39c5baSBill Taylor manuf->cmd_set = cfi.cfi_char[0x13]; 886*9e39c5baSBill Taylor 887*9e39c5baSBill Taylor if (cfi.cfi_char[0x10] == 'Q' && 888*9e39c5baSBill Taylor cfi.cfi_char[0x11] == 'R' && 889*9e39c5baSBill Taylor cfi.cfi_char[0x12] == 'Y') { 890*9e39c5baSBill Taylor /* make sure the cmd set is AMD */ 891*9e39c5baSBill Taylor if (manuf->cmd_set != TAVOR_FLASH_AMD_CMDSET) { 892*9e39c5baSBill Taylor logmsg(MSG_ERROR, 893*9e39c5baSBill Taylor gettext("tavor: Unsupported flash device " 894*9e39c5baSBill Taylor "command set\n")); 895*9e39c5baSBill Taylor free(manuf); 896*9e39c5baSBill Taylor close(fd); 897*9e39c5baSBill Taylor return (FWFLASH_FAILURE); 898*9e39c5baSBill Taylor } 899*9e39c5baSBill Taylor /* set some defaults */ 900*9e39c5baSBill Taylor manuf->device_sz = TAVOR_FLASH_DEVICE_SZ_DEFAULT; 901*9e39c5baSBill Taylor } else { 902*9e39c5baSBill Taylor if (manuf->cmd_set != TAVOR_FLASH_AMD_CMDSET && 903*9e39c5baSBill Taylor manuf->cmd_set != TAVOR_FLASH_INTEL_CMDSET) { 904*9e39c5baSBill Taylor logmsg(MSG_ERROR, 905*9e39c5baSBill Taylor gettext("ib: Unknown flash device command set\n")); 906*9e39c5baSBill Taylor free(manuf); 907*9e39c5baSBill Taylor close(fd); 908*9e39c5baSBill Taylor return (FWFLASH_FAILURE); 909*9e39c5baSBill Taylor } 910*9e39c5baSBill Taylor /* read from the CFI data */ 911*9e39c5baSBill Taylor manuf->sector_sz = ((cfi.cfi_char[0x30] << 8) | 912*9e39c5baSBill Taylor cfi.cfi_char[0x2F]) << 8; 913*9e39c5baSBill Taylor manuf->device_sz = 0x1 << cfi.cfi_char[0x27]; 914*9e39c5baSBill Taylor } 915*9e39c5baSBill Taylor 916*9e39c5baSBill Taylor logmsg(MSG_INFO, "sector_sz: 0x%08x\ndevice_sz: 0x%08x\n", 917*9e39c5baSBill Taylor manuf->sector_sz, manuf->device_sz); 918*9e39c5baSBill Taylor 919*9e39c5baSBill Taylor manuf->state |= FWFLASH_IB_STATE_MMAP; 920*9e39c5baSBill Taylor 921*9e39c5baSBill Taylor /* set firmware revision */ 922*9e39c5baSBill Taylor manuf->fw_rev.major = init_ioctl.tf_fwrev.tfi_maj; 923*9e39c5baSBill Taylor manuf->fw_rev.minor = init_ioctl.tf_fwrev.tfi_min; 924*9e39c5baSBill Taylor manuf->fw_rev.subminor = init_ioctl.tf_fwrev.tfi_sub; 925*9e39c5baSBill Taylor 926*9e39c5baSBill Taylor if (((thisdev->ident->vid = calloc(1, MLX_VPR_VIDLEN + 1)) == NULL) || 927*9e39c5baSBill Taylor ((thisdev->ident->revid = calloc(1, MLX_VPR_REVLEN + 1)) == NULL)) { 928*9e39c5baSBill Taylor 929*9e39c5baSBill Taylor logmsg(MSG_ERROR, 930*9e39c5baSBill Taylor gettext("ib: Unable to allocate space for a VPR " 931*9e39c5baSBill Taylor "record.\n")); 932*9e39c5baSBill Taylor free(thisdev->ident); 933*9e39c5baSBill Taylor free(manuf->info.mlx_pn); 934*9e39c5baSBill Taylor free(manuf->info.mlx_psid); 935*9e39c5baSBill Taylor free(manuf->info.mlx_id); 936*9e39c5baSBill Taylor free(manuf); 937*9e39c5baSBill Taylor close(fd); 938*9e39c5baSBill Taylor return (FWFLASH_FAILURE); 939*9e39c5baSBill Taylor } 940*9e39c5baSBill Taylor (void) strlcpy(thisdev->ident->vid, "MELLANOX", MLX_VPR_VIDLEN); 941*9e39c5baSBill Taylor /* 942*9e39c5baSBill Taylor * We actually want the hwrev field from the ioctl above. 943*9e39c5baSBill Taylor * Until we find out otherwise, add it onto the end of the 944*9e39c5baSBill Taylor * firmware version details. 945*9e39c5baSBill Taylor */ 946*9e39c5baSBill Taylor 947*9e39c5baSBill Taylor snprintf(thisdev->ident->revid, MLX_VPR_REVLEN, "%d.%d.%04d", 948*9e39c5baSBill Taylor manuf->fw_rev.major, manuf->fw_rev.minor, 949*9e39c5baSBill Taylor manuf->fw_rev.subminor); 950*9e39c5baSBill Taylor 951*9e39c5baSBill Taylor bzero(manuf->ibguids, sizeof (manuf->ibguids)); 952*9e39c5baSBill Taylor 953*9e39c5baSBill Taylor /* 954*9e39c5baSBill Taylor * For convenience we read in the Invariant Sector as 955*9e39c5baSBill Taylor * well as both the Primary and Secondary Pointer Sectors 956*9e39c5baSBill Taylor */ 957*9e39c5baSBill Taylor 958*9e39c5baSBill Taylor if ((manuf->inv = calloc(1, manuf->sector_sz)) == NULL) { 959*9e39c5baSBill Taylor logmsg(MSG_ERROR, 960*9e39c5baSBill Taylor gettext("tavor: Unable to allocate space for storing " 961*9e39c5baSBill Taylor "the HCA's Invariant Sector\n")); 962*9e39c5baSBill Taylor return (FWFLASH_FAILURE); 963*9e39c5baSBill Taylor } 964*9e39c5baSBill Taylor bzero(&info, sizeof (tavor_flash_ioctl_t)); 965*9e39c5baSBill Taylor 966*9e39c5baSBill Taylor info.tf_type = TAVOR_FLASH_READ_SECTOR; 967*9e39c5baSBill Taylor info.tf_sector = (caddr_t)manuf->inv; 968*9e39c5baSBill Taylor info.tf_sector_num = 0; 969*9e39c5baSBill Taylor 970*9e39c5baSBill Taylor errno = 0; 971*9e39c5baSBill Taylor 972*9e39c5baSBill Taylor if ((rv = ioctl(manuf->fd, TAVOR_IOCTL_FLASH_READ, &info)) 973*9e39c5baSBill Taylor < 0) { 974*9e39c5baSBill Taylor logmsg(MSG_ERROR, 975*9e39c5baSBill Taylor gettext("tavor: Unable to read HCA Invariant Sector\n")); 976*9e39c5baSBill Taylor return (FWFLASH_FAILURE); 977*9e39c5baSBill Taylor } 978*9e39c5baSBill Taylor 979*9e39c5baSBill Taylor #if defined(_LITTLE_ENDIAN) 980*9e39c5baSBill Taylor ptr = (uint32_t *)(uintptr_t)manuf->inv; 981*9e39c5baSBill Taylor for (i = 0; i < (manuf->sector_sz / 4); i++) { 982*9e39c5baSBill Taylor ptr[i] = htonl(ptr[i]); 983*9e39c5baSBill Taylor } 984*9e39c5baSBill Taylor #endif 985*9e39c5baSBill Taylor 986*9e39c5baSBill Taylor if ((manuf->pps = calloc(1, manuf->sector_sz)) == NULL) { 987*9e39c5baSBill Taylor logmsg(MSG_ERROR, 988*9e39c5baSBill Taylor gettext("tavor: Unable to allocate space for storing " 989*9e39c5baSBill Taylor "the HCA's Primary Pointer Sector\n")); 990*9e39c5baSBill Taylor return (FWFLASH_FAILURE); 991*9e39c5baSBill Taylor } 992*9e39c5baSBill Taylor bzero(&info, sizeof (tavor_flash_ioctl_t)); 993*9e39c5baSBill Taylor 994*9e39c5baSBill Taylor info.tf_type = TAVOR_FLASH_READ_SECTOR; 995*9e39c5baSBill Taylor info.tf_sector = (caddr_t)manuf->pps; 996*9e39c5baSBill Taylor info.tf_sector_num = 1; 997*9e39c5baSBill Taylor 998*9e39c5baSBill Taylor errno = 0; 999*9e39c5baSBill Taylor 1000*9e39c5baSBill Taylor if ((rv = ioctl(manuf->fd, TAVOR_IOCTL_FLASH_READ, &info)) 1001*9e39c5baSBill Taylor < 0) { 1002*9e39c5baSBill Taylor logmsg(MSG_ERROR, 1003*9e39c5baSBill Taylor gettext("tavor: Unable to read HCA Primary " 1004*9e39c5baSBill Taylor "Pointer Sector\n")); 1005*9e39c5baSBill Taylor return (FWFLASH_FAILURE); 1006*9e39c5baSBill Taylor } 1007*9e39c5baSBill Taylor 1008*9e39c5baSBill Taylor #if defined(_LITTLE_ENDIAN) 1009*9e39c5baSBill Taylor ptr = (uint32_t *)(uintptr_t)manuf->pps; 1010*9e39c5baSBill Taylor for (i = 0; i < (manuf->sector_sz / 4); i++) { 1011*9e39c5baSBill Taylor ptr[i] = htonl(ptr[i]); 1012*9e39c5baSBill Taylor } 1013*9e39c5baSBill Taylor #endif 1014*9e39c5baSBill Taylor 1015*9e39c5baSBill Taylor if ((manuf->sps = calloc(1, manuf->sector_sz)) == NULL) { 1016*9e39c5baSBill Taylor logmsg(MSG_ERROR, 1017*9e39c5baSBill Taylor gettext("tavor: Unable to allocate space for storing " 1018*9e39c5baSBill Taylor "the HCA's Secondary Pointer Sector\n")); 1019*9e39c5baSBill Taylor return (FWFLASH_FAILURE); 1020*9e39c5baSBill Taylor } 1021*9e39c5baSBill Taylor bzero(&info, sizeof (tavor_flash_ioctl_t)); 1022*9e39c5baSBill Taylor 1023*9e39c5baSBill Taylor info.tf_type = TAVOR_FLASH_READ_SECTOR; 1024*9e39c5baSBill Taylor info.tf_sector = (caddr_t)manuf->sps; 1025*9e39c5baSBill Taylor info.tf_sector_num = 2; 1026*9e39c5baSBill Taylor 1027*9e39c5baSBill Taylor errno = 0; 1028*9e39c5baSBill Taylor 1029*9e39c5baSBill Taylor if ((rv = ioctl(manuf->fd, TAVOR_IOCTL_FLASH_READ, &info)) 1030*9e39c5baSBill Taylor < 0) { 1031*9e39c5baSBill Taylor logmsg(MSG_ERROR, 1032*9e39c5baSBill Taylor gettext("tavor: Unable to read HCA Secondary " 1033*9e39c5baSBill Taylor "Pointer Sector\n")); 1034*9e39c5baSBill Taylor return (FWFLASH_FAILURE); 1035*9e39c5baSBill Taylor } 1036*9e39c5baSBill Taylor 1037*9e39c5baSBill Taylor #if defined(_LITTLE_ENDIAN) 1038*9e39c5baSBill Taylor ptr = (uint32_t *)(uintptr_t)manuf->sps; 1039*9e39c5baSBill Taylor for (i = 0; i < (manuf->sector_sz / 4); i++) { 1040*9e39c5baSBill Taylor ptr[i] = htonl(ptr[i]); 1041*9e39c5baSBill Taylor } 1042*9e39c5baSBill Taylor #endif 1043*9e39c5baSBill Taylor 1044*9e39c5baSBill Taylor if ((ret = tavor_get_guids(manuf)) != FWFLASH_SUCCESS) { 1045*9e39c5baSBill Taylor logmsg(MSG_INFO, 1046*9e39c5baSBill Taylor gettext("ib: No guids found for device %s!\n"), 1047*9e39c5baSBill Taylor thisdev->access_devname); 1048*9e39c5baSBill Taylor } 1049*9e39c5baSBill Taylor 1050*9e39c5baSBill Taylor /* set hw part number, psid, and name in handle */ 1051*9e39c5baSBill Taylor bzero(temppsid, 17); 1052*9e39c5baSBill Taylor bcopy(manuf->pps+FLASH_PS_PSID_OFFSET, &rawpsid, 16); 1053*9e39c5baSBill Taylor 1054*9e39c5baSBill Taylor for (i = 0; i < 16; i += 4) { 1055*9e39c5baSBill Taylor temppsid[i] = rawpsid[i+3]; 1056*9e39c5baSBill Taylor temppsid[i+1] = rawpsid[i+2]; 1057*9e39c5baSBill Taylor temppsid[i+2] = rawpsid[i+1]; 1058*9e39c5baSBill Taylor temppsid[i+3] = rawpsid[i]; 1059*9e39c5baSBill Taylor } 1060*9e39c5baSBill Taylor logmsg(MSG_INFO, 1061*9e39c5baSBill Taylor "tavor: have raw '%s', want munged '%s'\n", 1062*9e39c5baSBill Taylor rawpsid, temppsid); 1063*9e39c5baSBill Taylor 1064*9e39c5baSBill Taylor /* now walk the magic decoder ring table */ 1065*9e39c5baSBill Taylor manuf->info.mlx_pn = NULL; 1066*9e39c5baSBill Taylor manuf->info.mlx_psid = NULL; 1067*9e39c5baSBill Taylor manuf->info.mlx_id = NULL; 1068*9e39c5baSBill Taylor manuf->pn_len = 0; 1069*9e39c5baSBill Taylor 1070*9e39c5baSBill Taylor for (i = 0; i < MLX_MAX_ID; i++) { 1071*9e39c5baSBill Taylor if ((strncmp(temppsid, mlx_mdr[i].mlx_psid, 1072*9e39c5baSBill Taylor MLX_PSID_SZ)) == 0) { 1073*9e39c5baSBill Taylor /* matched */ 1074*9e39c5baSBill Taylor if ((manuf->info.mlx_pn = calloc(1, 1075*9e39c5baSBill Taylor strlen(mlx_mdr[i].mlx_pn) + 1)) == NULL) { 1076*9e39c5baSBill Taylor logmsg(MSG_INFO, 1077*9e39c5baSBill Taylor "tavor: no space available for the " 1078*9e39c5baSBill Taylor "HCA PSID record (1)\n"); 1079*9e39c5baSBill Taylor } else { 1080*9e39c5baSBill Taylor (void) strlcpy(manuf->info.mlx_pn, 1081*9e39c5baSBill Taylor mlx_mdr[i].mlx_pn, 1082*9e39c5baSBill Taylor strlen(mlx_mdr[i].mlx_pn) + 1); 1083*9e39c5baSBill Taylor manuf->pn_len = strlen(mlx_mdr[i].mlx_pn); 1084*9e39c5baSBill Taylor } 1085*9e39c5baSBill Taylor 1086*9e39c5baSBill Taylor if ((manuf->info.mlx_psid = calloc(1, 1087*9e39c5baSBill Taylor strlen(mlx_mdr[i].mlx_psid) + 1)) == NULL) { 1088*9e39c5baSBill Taylor logmsg(MSG_INFO, 1089*9e39c5baSBill Taylor "tavor: no space available for the " 1090*9e39c5baSBill Taylor "HCA PSID record (2)\n"); 1091*9e39c5baSBill Taylor } else { 1092*9e39c5baSBill Taylor (void) strlcpy(manuf->info.mlx_psid, 1093*9e39c5baSBill Taylor mlx_mdr[i].mlx_psid, 1094*9e39c5baSBill Taylor strlen(mlx_mdr[i].mlx_psid) + 1); 1095*9e39c5baSBill Taylor } 1096*9e39c5baSBill Taylor if ((manuf->info.mlx_id = calloc(1, 1097*9e39c5baSBill Taylor strlen(mlx_mdr[i].mlx_id) + 1)) == NULL) { 1098*9e39c5baSBill Taylor logmsg(MSG_INFO, 1099*9e39c5baSBill Taylor "tavor: no space available for the " 1100*9e39c5baSBill Taylor "HCA PSID record (3)\n"); 1101*9e39c5baSBill Taylor } else { 1102*9e39c5baSBill Taylor (void) strlcpy(manuf->info.mlx_id, 1103*9e39c5baSBill Taylor mlx_mdr[i].mlx_id, 1104*9e39c5baSBill Taylor strlen(mlx_mdr[i].mlx_id) + 1); 1105*9e39c5baSBill Taylor } 1106*9e39c5baSBill Taylor } 1107*9e39c5baSBill Taylor } 1108*9e39c5baSBill Taylor if ((manuf->pn_len == 0) || (i == MLX_MAX_ID)) { 1109*9e39c5baSBill Taylor logmsg(MSG_INFO, 1110*9e39c5baSBill Taylor "tavor: No hardware part number information available " 1111*9e39c5baSBill Taylor "for this HCA\n"); 1112*9e39c5baSBill Taylor /* Until we deliver the arbel driver, it's all Mellanox */ 1113*9e39c5baSBill Taylor i = strlen("No hardware information available for this device"); 1114*9e39c5baSBill Taylor 1115*9e39c5baSBill Taylor thisdev->ident->pid = calloc(1, i + 2); 1116*9e39c5baSBill Taylor sprintf(thisdev->ident->pid, "No hardware information " 1117*9e39c5baSBill Taylor "available for this device"); 1118*9e39c5baSBill Taylor } else { 1119*9e39c5baSBill Taylor if ((thisdev->ident->pid = calloc(1, 1120*9e39c5baSBill Taylor strlen(manuf->info.mlx_psid) + 1)) != NULL) { 1121*9e39c5baSBill Taylor (void) strlcpy(thisdev->ident->pid, 1122*9e39c5baSBill Taylor manuf->info.mlx_psid, 1123*9e39c5baSBill Taylor strlen(manuf->info.mlx_psid) + 1); 1124*9e39c5baSBill Taylor } else { 1125*9e39c5baSBill Taylor logmsg(MSG_ERROR, 1126*9e39c5baSBill Taylor gettext("ib: Unable to allocate space for a " 1127*9e39c5baSBill Taylor "hardware identifier\n")); 1128*9e39c5baSBill Taylor free(thisdev->ident); 1129*9e39c5baSBill Taylor free(manuf->info.mlx_pn); 1130*9e39c5baSBill Taylor free(manuf->info.mlx_psid); 1131*9e39c5baSBill Taylor free(manuf->info.mlx_id); 1132*9e39c5baSBill Taylor free(manuf); 1133*9e39c5baSBill Taylor close(fd); 1134*9e39c5baSBill Taylor return (FWFLASH_FAILURE); 1135*9e39c5baSBill Taylor } 1136*9e39c5baSBill Taylor } 1137*9e39c5baSBill Taylor 1138*9e39c5baSBill Taylor for (i = 0; i < 4; i++) { 1139*9e39c5baSBill Taylor if ((thisdev->addresses[i] = calloc(1, 1140*9e39c5baSBill Taylor (2 * sizeof (uint64_t)) + 1)) == NULL) { 1141*9e39c5baSBill Taylor logmsg(MSG_ERROR, 1142*9e39c5baSBill Taylor gettext("tavor: Unable to allocate space for a " 1143*9e39c5baSBill Taylor "human-readable HCA guid\n")); 1144*9e39c5baSBill Taylor return (FWFLASH_FAILURE); 1145*9e39c5baSBill Taylor } 1146*9e39c5baSBill Taylor (void) sprintf(thisdev->addresses[i], "%016llx", 1147*9e39c5baSBill Taylor manuf->ibguids[i]); 1148*9e39c5baSBill Taylor } 1149*9e39c5baSBill Taylor 1150*9e39c5baSBill Taylor /* 1151*9e39c5baSBill Taylor * We do NOT close the fd here, since we can close it 1152*9e39c5baSBill Taylor * at the end of the fw_readfw() or fw_writefw() functions 1153*9e39c5baSBill Taylor * instead and not get the poor dear confused about whether 1154*9e39c5baSBill Taylor * it's been inited already. 1155*9e39c5baSBill Taylor */ 1156*9e39c5baSBill Taylor 1157*9e39c5baSBill Taylor return (rv); 1158*9e39c5baSBill Taylor } 1159*9e39c5baSBill Taylor 1160*9e39c5baSBill Taylor /*ARGSUSED*/ 1161*9e39c5baSBill Taylor static int 1162*9e39c5baSBill Taylor tavor_get_guids(struct ib_encap_ident *handle) 1163*9e39c5baSBill Taylor { 1164*9e39c5baSBill Taylor int rv, j; 1165*9e39c5baSBill Taylor uint32_t i = 0x00; 1166*9e39c5baSBill Taylor tavor_flash_ioctl_t info; 1167*9e39c5baSBill Taylor struct mlx_guid_sect *p, *s; 1168*9e39c5baSBill Taylor 1169*9e39c5baSBill Taylor #if defined(_LITTLE_ENDIAN) 1170*9e39c5baSBill Taylor uint32_t *ptr, tmp; 1171*9e39c5baSBill Taylor #endif 1172*9e39c5baSBill Taylor 1173*9e39c5baSBill Taylor /* 1174*9e39c5baSBill Taylor * The reference for this function is the 1175*9e39c5baSBill Taylor * Mellanox HCA Flash Programming Application Note 1176*9e39c5baSBill Taylor * rev 1.44, 2007. Chapter 4 in particular. 1177*9e39c5baSBill Taylor * 1178*9e39c5baSBill Taylor * NOTE: this Mellanox document is labelled Confidential 1179*9e39c5baSBill Taylor * so DO NOT move this file out of usr/closed without 1180*9e39c5baSBill Taylor * explicit approval from Sun Legal. 1181*9e39c5baSBill Taylor */ 1182*9e39c5baSBill Taylor 1183*9e39c5baSBill Taylor /* 1184*9e39c5baSBill Taylor * We need to check for both the Primary and Secondary 1185*9e39c5baSBill Taylor * Image GUIDs. handle->pps and handle->sps should be 1186*9e39c5baSBill Taylor * non-NULL by the time we're called, since we depend 1187*9e39c5baSBill Taylor * on them being stashed in handle. Saves on an ioctl(). 1188*9e39c5baSBill Taylor */ 1189*9e39c5baSBill Taylor 1190*9e39c5baSBill Taylor /* make sure we've got our fallback position organised */ 1191*9e39c5baSBill Taylor for (i = 0; i < 4; i++) { 1192*9e39c5baSBill Taylor handle->ibguids[i] = 0x00000000; 1193*9e39c5baSBill Taylor } 1194*9e39c5baSBill Taylor 1195*9e39c5baSBill Taylor /* convenience .... */ 1196*9e39c5baSBill Taylor 1197*9e39c5baSBill Taylor if ((p = calloc(1, sizeof (mlx_guid_sect_t))) == NULL) { 1198*9e39c5baSBill Taylor logmsg(MSG_ERROR, 1199*9e39c5baSBill Taylor gettext("tavor: Unable to allocate space for " 1200*9e39c5baSBill Taylor "HCA guid record (1)\n")); 1201*9e39c5baSBill Taylor return (FWFLASH_FAILURE); 1202*9e39c5baSBill Taylor } 1203*9e39c5baSBill Taylor if ((s = calloc(1, sizeof (mlx_guid_sect_t))) == NULL) { 1204*9e39c5baSBill Taylor logmsg(MSG_ERROR, 1205*9e39c5baSBill Taylor gettext("tavor: Unable to allocate space for " 1206*9e39c5baSBill Taylor "HCA guid record (2)\n")); 1207*9e39c5baSBill Taylor free(p); 1208*9e39c5baSBill Taylor return (FWFLASH_FAILURE); 1209*9e39c5baSBill Taylor } 1210*9e39c5baSBill Taylor 1211*9e39c5baSBill Taylor bcopy(&handle->pps[0], &i, 4); 1212*9e39c5baSBill Taylor handle->pfi_guid_addr = MLXSWAPBITS32(i) + FLASH_GUID_PTR; 1213*9e39c5baSBill Taylor bcopy(&handle->sps[0], &i, 4); 1214*9e39c5baSBill Taylor handle->sfi_guid_addr = MLXSWAPBITS32(i) + FLASH_GUID_PTR; 1215*9e39c5baSBill Taylor 1216*9e39c5baSBill Taylor bzero(&info, sizeof (tavor_flash_ioctl_t)); 1217*9e39c5baSBill Taylor info.tf_type = TAVOR_FLASH_READ_QUADLET; 1218*9e39c5baSBill Taylor info.tf_addr = handle->pfi_guid_addr; 1219*9e39c5baSBill Taylor 1220*9e39c5baSBill Taylor errno = 0; 1221*9e39c5baSBill Taylor 1222*9e39c5baSBill Taylor rv = ioctl(handle->fd, TAVOR_IOCTL_FLASH_READ, &info); 1223*9e39c5baSBill Taylor if (rv < 0) { 1224*9e39c5baSBill Taylor logmsg(MSG_ERROR, 1225*9e39c5baSBill Taylor gettext("tavor: Unable to read Primary Image " 1226*9e39c5baSBill Taylor "guid offset\n")); 1227*9e39c5baSBill Taylor free(p); 1228*9e39c5baSBill Taylor free(s); 1229*9e39c5baSBill Taylor return (FWFLASH_FAILURE); 1230*9e39c5baSBill Taylor } 1231*9e39c5baSBill Taylor 1232*9e39c5baSBill Taylor /* 1233*9e39c5baSBill Taylor * This is because we want the whole of the section 1234*9e39c5baSBill Taylor * including the 16 reserved bytes at the front so 1235*9e39c5baSBill Taylor * that if we recalculate the CRC we've got the correct 1236*9e39c5baSBill Taylor * data to do it with 1237*9e39c5baSBill Taylor */ 1238*9e39c5baSBill Taylor info.tf_addr = handle->pfi_guid_addr + info.tf_quadlet 1239*9e39c5baSBill Taylor - FLASH_GUID_PTR - 16; 1240*9e39c5baSBill Taylor 1241*9e39c5baSBill Taylor bzero(handle->pri_guid_section, sizeof (mlx_guid_sect_t)); 1242*9e39c5baSBill Taylor 1243*9e39c5baSBill Taylor for (j = 0; j < 13; j++) { 1244*9e39c5baSBill Taylor errno = 0; 1245*9e39c5baSBill Taylor if ((rv = ioctl(handle->fd, TAVOR_IOCTL_FLASH_READ, 1246*9e39c5baSBill Taylor &info)) < 0) { 1247*9e39c5baSBill Taylor logmsg(MSG_ERROR, 1248*9e39c5baSBill Taylor gettext("tavor: Unable to read Primary Image " 1249*9e39c5baSBill Taylor "guid chunk %d\n"), j); 1250*9e39c5baSBill Taylor } 1251*9e39c5baSBill Taylor handle->pri_guid_section[j] = info.tf_quadlet; 1252*9e39c5baSBill Taylor info.tf_addr += 4; 1253*9e39c5baSBill Taylor } 1254*9e39c5baSBill Taylor bcopy(&handle->pri_guid_section, p, sizeof (struct mlx_guid_sect)); 1255*9e39c5baSBill Taylor 1256*9e39c5baSBill Taylor /* now grab the secondary guid set */ 1257*9e39c5baSBill Taylor bzero(&info, sizeof (tavor_flash_ioctl_t)); 1258*9e39c5baSBill Taylor info.tf_type = TAVOR_FLASH_READ_QUADLET; 1259*9e39c5baSBill Taylor info.tf_addr = handle->sfi_guid_addr; 1260*9e39c5baSBill Taylor 1261*9e39c5baSBill Taylor errno = 0; 1262*9e39c5baSBill Taylor 1263*9e39c5baSBill Taylor if ((rv = ioctl(handle->fd, TAVOR_IOCTL_FLASH_READ, 1264*9e39c5baSBill Taylor &info)) < 0) { 1265*9e39c5baSBill Taylor logmsg(MSG_ERROR, 1266*9e39c5baSBill Taylor gettext("tavor: Unable to read Secondary Image " 1267*9e39c5baSBill Taylor "guid offset (%s)\n"), strerror(errno)); 1268*9e39c5baSBill Taylor free(p); 1269*9e39c5baSBill Taylor free(s); 1270*9e39c5baSBill Taylor return (FWFLASH_FAILURE); 1271*9e39c5baSBill Taylor } 1272*9e39c5baSBill Taylor 1273*9e39c5baSBill Taylor info.tf_addr = handle->sfi_guid_addr + info.tf_quadlet 1274*9e39c5baSBill Taylor - FLASH_GUID_PTR - 16; 1275*9e39c5baSBill Taylor 1276*9e39c5baSBill Taylor bzero(handle->sec_guid_section, sizeof (mlx_guid_sect_t)); 1277*9e39c5baSBill Taylor 1278*9e39c5baSBill Taylor for (j = 0; j < 13; j++) { 1279*9e39c5baSBill Taylor errno = 0; 1280*9e39c5baSBill Taylor if ((rv = ioctl(handle->fd, TAVOR_IOCTL_FLASH_READ, 1281*9e39c5baSBill Taylor &info)) < 0) { 1282*9e39c5baSBill Taylor logmsg(MSG_ERROR, 1283*9e39c5baSBill Taylor gettext("tavor: Unable to read Secondary Image " 1284*9e39c5baSBill Taylor "guid chunk %d (%s)\n"), j, strerror(errno)); 1285*9e39c5baSBill Taylor return (FWFLASH_FAILURE); 1286*9e39c5baSBill Taylor } 1287*9e39c5baSBill Taylor handle->sec_guid_section[j] = info.tf_quadlet; 1288*9e39c5baSBill Taylor info.tf_addr += 4; 1289*9e39c5baSBill Taylor } 1290*9e39c5baSBill Taylor 1291*9e39c5baSBill Taylor bcopy(&handle->sec_guid_section, s, sizeof (struct mlx_guid_sect)); 1292*9e39c5baSBill Taylor 1293*9e39c5baSBill Taylor #if defined(_LITTLE_ENDIAN) 1294*9e39c5baSBill Taylor 1295*9e39c5baSBill Taylor /* 1296*9e39c5baSBill Taylor * We don't actually care about p or s later on if we 1297*9e39c5baSBill Taylor * write to the HCA - we've already stored the binary 1298*9e39c5baSBill Taylor * form in handle->pri_guid_section and handle->sec_guid_section. 1299*9e39c5baSBill Taylor * What we're doing here is creating human-readable forms. 1300*9e39c5baSBill Taylor */ 1301*9e39c5baSBill Taylor 1302*9e39c5baSBill Taylor ptr = (uint32_t *)(uintptr_t)p; 1303*9e39c5baSBill Taylor for (j = 0; j < 14; j += 2) { 1304*9e39c5baSBill Taylor tmp = ptr[j]; 1305*9e39c5baSBill Taylor ptr[j] = ptr[j+1]; 1306*9e39c5baSBill Taylor ptr[j+1] = tmp; 1307*9e39c5baSBill Taylor } 1308*9e39c5baSBill Taylor 1309*9e39c5baSBill Taylor ptr = (uint32_t *)(uintptr_t)s; 1310*9e39c5baSBill Taylor for (j = 0; j < 14; j += 2) { 1311*9e39c5baSBill Taylor tmp = ptr[j]; 1312*9e39c5baSBill Taylor ptr[j] = ptr[j+1]; 1313*9e39c5baSBill Taylor ptr[j+1] = tmp; 1314*9e39c5baSBill Taylor } 1315*9e39c5baSBill Taylor #endif 1316*9e39c5baSBill Taylor 1317*9e39c5baSBill Taylor /* 1318*9e39c5baSBill Taylor * We don't check and munge the GUIDs to the manufacturer's 1319*9e39c5baSBill Taylor * defaults, because if the GUIDs are actually set incorrectly 1320*9e39c5baSBill Taylor * at identify time, we really need to know that. 1321*9e39c5baSBill Taylor * 1322*9e39c5baSBill Taylor * If the GUIDs are bogus, then we'll fix that in fw_writefw() 1323*9e39c5baSBill Taylor * by blatting the manufacturer's defaults from the firmware 1324*9e39c5baSBill Taylor * image file instead. 1325*9e39c5baSBill Taylor */ 1326*9e39c5baSBill Taylor if ((p->nodeguid == s->nodeguid) && 1327*9e39c5baSBill Taylor (p->port1guid == s->port1guid) && 1328*9e39c5baSBill Taylor (p->port2guid == s->port2guid) && 1329*9e39c5baSBill Taylor (p->sysimguid == s->sysimguid)) { 1330*9e39c5baSBill Taylor logmsg(MSG_INFO, 1331*9e39c5baSBill Taylor "tavor: primary and secondary guids are the same\n"); 1332*9e39c5baSBill Taylor handle->ibguids[0] = p->nodeguid; 1333*9e39c5baSBill Taylor handle->ibguids[1] = p->port1guid; 1334*9e39c5baSBill Taylor handle->ibguids[2] = p->port2guid; 1335*9e39c5baSBill Taylor handle->ibguids[3] = p->sysimguid; 1336*9e39c5baSBill Taylor } else { 1337*9e39c5baSBill Taylor /* 1338*9e39c5baSBill Taylor * We're going to assume that the guids which are numerically 1339*9e39c5baSBill Taylor * larger than the others are correct and copy them to 1340*9e39c5baSBill Taylor * handle->ibguids. 1341*9e39c5baSBill Taylor * 1342*9e39c5baSBill Taylor * For those in the know wrt InfiniBand, if this assumption 1343*9e39c5baSBill Taylor * is incorrect, _please_ bug this and fix it, adding a 1344*9e39c5baSBill Taylor * comment or two to indicate why 1345*9e39c5baSBill Taylor */ 1346*9e39c5baSBill Taylor logmsg(MSG_INFO, 1347*9e39c5baSBill Taylor "tavor: primary and secondary guids don't all match\n"); 1348*9e39c5baSBill Taylor 1349*9e39c5baSBill Taylor if (s->nodeguid > p->nodeguid) { 1350*9e39c5baSBill Taylor handle->ibguids[0] = s->nodeguid; 1351*9e39c5baSBill Taylor handle->ibguids[1] = s->port1guid; 1352*9e39c5baSBill Taylor handle->ibguids[2] = s->port2guid; 1353*9e39c5baSBill Taylor handle->ibguids[3] = s->sysimguid; 1354*9e39c5baSBill Taylor bzero(p, sizeof (struct mlx_guid_sect)); 1355*9e39c5baSBill Taylor } else { 1356*9e39c5baSBill Taylor handle->ibguids[0] = p->nodeguid; 1357*9e39c5baSBill Taylor handle->ibguids[1] = p->port1guid; 1358*9e39c5baSBill Taylor handle->ibguids[2] = p->port2guid; 1359*9e39c5baSBill Taylor handle->ibguids[3] = p->sysimguid; 1360*9e39c5baSBill Taylor bzero(s, sizeof (struct mlx_guid_sect)); 1361*9e39c5baSBill Taylor } 1362*9e39c5baSBill Taylor } 1363*9e39c5baSBill Taylor 1364*9e39c5baSBill Taylor free(p); 1365*9e39c5baSBill Taylor free(s); 1366*9e39c5baSBill Taylor 1367*9e39c5baSBill Taylor if (fwflash_debug) { 1368*9e39c5baSBill Taylor for (i = 0; i < 4; i++) { 1369*9e39c5baSBill Taylor logmsg(MSG_INFO, "ibguids[%d] %0llx\n", i, 1370*9e39c5baSBill Taylor handle->ibguids[i]); 1371*9e39c5baSBill Taylor } 1372*9e39c5baSBill Taylor } 1373*9e39c5baSBill Taylor 1374*9e39c5baSBill Taylor return (FWFLASH_SUCCESS); 1375*9e39c5baSBill Taylor } 1376*9e39c5baSBill Taylor 1377*9e39c5baSBill Taylor 1378*9e39c5baSBill Taylor int 1379*9e39c5baSBill Taylor tavor_close(struct devicelist *flashdev) 1380*9e39c5baSBill Taylor { 1381*9e39c5baSBill Taylor 1382*9e39c5baSBill Taylor struct ib_encap_ident *handle; 1383*9e39c5baSBill Taylor 1384*9e39c5baSBill Taylor handle = (struct ib_encap_ident *)flashdev->ident->encap_ident; 1385*9e39c5baSBill Taylor if (handle->fd > 0) { 1386*9e39c5baSBill Taylor (void) ioctl(handle->fd, TAVOR_IOCTL_FLASH_FINI); 1387*9e39c5baSBill Taylor errno = 0; 1388*9e39c5baSBill Taylor if (close(handle->fd) != 0) { 1389*9e39c5baSBill Taylor logmsg(MSG_ERROR, 1390*9e39c5baSBill Taylor gettext("tavor: Unable to properly close " 1391*9e39c5baSBill Taylor "device %s! (%s)\n"), 1392*9e39c5baSBill Taylor flashdev->access_devname, 1393*9e39c5baSBill Taylor strerror(errno)); 1394*9e39c5baSBill Taylor return (FWFLASH_FAILURE); 1395*9e39c5baSBill Taylor } 1396*9e39c5baSBill Taylor return (FWFLASH_SUCCESS); 1397*9e39c5baSBill Taylor } else 1398*9e39c5baSBill Taylor return (FWFLASH_FAILURE); 1399*9e39c5baSBill Taylor } 1400*9e39c5baSBill Taylor 1401*9e39c5baSBill Taylor 1402*9e39c5baSBill Taylor /* 1403*9e39c5baSBill Taylor * We would not need this if it were not for Cisco's image using the 1404*9e39c5baSBill Taylor * VSD to store boot options and flags for their PXE boot extension, 1405*9e39c5baSBill Taylor * but not setting the proper default values for the extension in 1406*9e39c5baSBill Taylor * their image. As it turns out, some of the data for the extension 1407*9e39c5baSBill Taylor * is stored in the VSD in the firmware file, and the rest is set by 1408*9e39c5baSBill Taylor * their firmware utility. That's not very nice for us, since it could 1409*9e39c5baSBill Taylor * change at any time without our knowledge. Well, for the time being, 1410*9e39c5baSBill Taylor * we can use this to examine and fix up anything in the VSD that we might 1411*9e39c5baSBill Taylor * need to handle, for any vendor specific settings. 1412*9e39c5baSBill Taylor */ 1413*9e39c5baSBill Taylor static void 1414*9e39c5baSBill Taylor tavor_cisco_extensions(mlx_xps_t *hcaxps, mlx_xps_t *diskxps) 1415*9e39c5baSBill Taylor { 1416*9e39c5baSBill Taylor uint16_t sig1, sig2; 1417*9e39c5baSBill Taylor uint32_t i; 1418*9e39c5baSBill Taylor 1419*9e39c5baSBill Taylor 1420*9e39c5baSBill Taylor bcopy(hcaxps->vsdpsid, &i, 4); 1421*9e39c5baSBill Taylor sig1 = htonl(i); 1422*9e39c5baSBill Taylor bcopy(&hcaxps->vsdpsid[223], &i, 4); 1423*9e39c5baSBill Taylor sig2 = htonl(i); 1424*9e39c5baSBill Taylor 1425*9e39c5baSBill Taylor 1426*9e39c5baSBill Taylor if (sig1 == FLASH_VSD_CISCO_SIGNATURE && 1427*9e39c5baSBill Taylor sig2 == FLASH_VSD_CISCO_SIGNATURE) { 1428*9e39c5baSBill Taylor logmsg(MSG_INFO, 1429*9e39c5baSBill Taylor "tavor: CISCO signature found in HCA's VSD, copying to " 1430*9e39c5baSBill Taylor "new image's VSD\n"); 1431*9e39c5baSBill Taylor 1432*9e39c5baSBill Taylor i = htonl(FLASH_VSD_CISCO_SIGNATURE); 1433*9e39c5baSBill Taylor bcopy(&i, diskxps->vsdpsid, 2); 1434*9e39c5baSBill Taylor 1435*9e39c5baSBill Taylor /* 1436*9e39c5baSBill Taylor * Set the boot_version field to '2'. This value is 1437*9e39c5baSBill Taylor * located in the 2nd byte of the last uint32_t. 1438*9e39c5baSBill Taylor * Per the previous version of fwflash, we just or 1439*9e39c5baSBill Taylor * the bit in and get on with it. 1440*9e39c5baSBill Taylor */ 1441*9e39c5baSBill Taylor 1442*9e39c5baSBill Taylor i = (diskxps->vsdpsid[222] | FLASH_VSD_CISCO_BOOT_VERSION); 1443*9e39c5baSBill Taylor bcopy(&i, &diskxps->vsdpsid[222], 2); 1444*9e39c5baSBill Taylor /* 1445*9e39c5baSBill Taylor * Now set some defaults for the SRP boot extension, 1446*9e39c5baSBill Taylor * currently the only extension we support. These flags 1447*9e39c5baSBill Taylor * are located in the second uint32_t of the VSD. 1448*9e39c5baSBill Taylor */ 1449*9e39c5baSBill Taylor 1450*9e39c5baSBill Taylor logmsg(MSG_INFO, "tavor: CISCO boot flags currently set " 1451*9e39c5baSBill Taylor "to 0x%08x\n", 1452*9e39c5baSBill Taylor diskxps->vsdpsid[1]); 1453*9e39c5baSBill Taylor 1454*9e39c5baSBill Taylor diskxps->vsdpsid[1] = 1455*9e39c5baSBill Taylor htonl(diskxps->vsdpsid[1] | 1456*9e39c5baSBill Taylor FLASH_VSD_CISCO_FLAG_AUTOUPGRADE | 1457*9e39c5baSBill Taylor FLASH_VSD_CISCO_BOOT_OPTIONS | 1458*9e39c5baSBill Taylor FLASH_VSD_CISCO_FLAG_BOOT_ENABLE_PORT_1 | 1459*9e39c5baSBill Taylor FLASH_VSD_CISCO_FLAG_BOOT_ENABLE_PORT_2 | 1460*9e39c5baSBill Taylor FLASH_VSD_CISCO_FLAG_BOOT_ENABLE_SCAN | 1461*9e39c5baSBill Taylor FLASH_VSD_CISCO_FLAG_BOOT_TYPE_WELL_KNOWN | 1462*9e39c5baSBill Taylor FLASH_VSD_CISCO_FLAG_BOOT_TRY_FOREVER); 1463*9e39c5baSBill Taylor 1464*9e39c5baSBill Taylor logmsg(MSG_INFO, "tavor: CISCO boot flags now set " 1465*9e39c5baSBill Taylor "to 0x%08x\n", 1466*9e39c5baSBill Taylor diskxps->vsdpsid[1]); 1467*9e39c5baSBill Taylor } else 1468*9e39c5baSBill Taylor logmsg(MSG_INFO, 1469*9e39c5baSBill Taylor "tavor: CISCO signature not found in HCA's VSD\n"); 1470*9e39c5baSBill Taylor } 1471*9e39c5baSBill Taylor 1472*9e39c5baSBill Taylor 1473*9e39c5baSBill Taylor static int 1474*9e39c5baSBill Taylor tavor_write_sector(int fd, int sectnum, int32_t *data) 1475*9e39c5baSBill Taylor { 1476*9e39c5baSBill Taylor int rv, i; 1477*9e39c5baSBill Taylor tavor_flash_ioctl_t cmd; 1478*9e39c5baSBill Taylor 1479*9e39c5baSBill Taylor 1480*9e39c5baSBill Taylor bzero(&cmd, sizeof (tavor_flash_ioctl_t)); 1481*9e39c5baSBill Taylor 1482*9e39c5baSBill Taylor cmd.tf_type = TAVOR_FLASH_WRITE_SECTOR; 1483*9e39c5baSBill Taylor cmd.tf_sector_num = sectnum; 1484*9e39c5baSBill Taylor cmd.tf_sector = (caddr_t)data; 1485*9e39c5baSBill Taylor 1486*9e39c5baSBill Taylor errno = 0; 1487*9e39c5baSBill Taylor 1488*9e39c5baSBill Taylor logmsg(MSG_INFO, 1489*9e39c5baSBill Taylor "tavor: tavor_write_sector(fd %d, sectnum 0x%x, data 0x%lx)\n", 1490*9e39c5baSBill Taylor fd, sectnum, data); 1491*9e39c5baSBill Taylor logmsg(MSG_INFO, 1492*9e39c5baSBill Taylor "tavor:\n" 1493*9e39c5baSBill Taylor "\tcmd.tf_type %d\n" 1494*9e39c5baSBill Taylor "\tcmd.tf_sector 0x%lx\n" 1495*9e39c5baSBill Taylor "\tcmd.tf_sector_num %d\n", 1496*9e39c5baSBill Taylor cmd.tf_type, data, cmd.tf_sector_num); 1497*9e39c5baSBill Taylor 1498*9e39c5baSBill Taylor /* 1499*9e39c5baSBill Taylor * If we're debugging, dump the first 64 uint32_t that we've 1500*9e39c5baSBill Taylor * been passed 1501*9e39c5baSBill Taylor */ 1502*9e39c5baSBill Taylor if (fwflash_debug > 0) { 1503*9e39c5baSBill Taylor i = 0; 1504*9e39c5baSBill Taylor while (i < 64) { 1505*9e39c5baSBill Taylor logmsg(MSG_INFO, 1506*9e39c5baSBill Taylor "%02x: %08x %08x %08x %08x\n", 1507*9e39c5baSBill Taylor i, data[i], data[i+1], 1508*9e39c5baSBill Taylor data[i+2], data[i+3]); 1509*9e39c5baSBill Taylor i += 4; 1510*9e39c5baSBill Taylor } 1511*9e39c5baSBill Taylor } 1512*9e39c5baSBill Taylor 1513*9e39c5baSBill Taylor rv = ioctl(fd, TAVOR_IOCTL_FLASH_WRITE, &cmd); 1514*9e39c5baSBill Taylor if (rv < 0) { 1515*9e39c5baSBill Taylor logmsg(MSG_ERROR, 1516*9e39c5baSBill Taylor gettext("tavor: WRITE SECTOR failed for sector " 1517*9e39c5baSBill Taylor "%d: %s\n"), 1518*9e39c5baSBill Taylor sectnum, strerror(errno)); 1519*9e39c5baSBill Taylor return (FWFLASH_FAILURE); 1520*9e39c5baSBill Taylor } else 1521*9e39c5baSBill Taylor return (FWFLASH_SUCCESS); 1522*9e39c5baSBill Taylor } 1523*9e39c5baSBill Taylor 1524*9e39c5baSBill Taylor /* 1525*9e39c5baSBill Taylor * Write zeros to the on-HCA signature and CRC16 fields of sector. 1526*9e39c5baSBill Taylor * 1527*9e39c5baSBill Taylor * NOTE we do _not_ divide start by 4 because we're talking to the 1528*9e39c5baSBill Taylor * HCA, and not finding an offset into verifier->fwimage. 1529*9e39c5baSBill Taylor */ 1530*9e39c5baSBill Taylor 1531*9e39c5baSBill Taylor static int 1532*9e39c5baSBill Taylor tavor_zero_sig_crc(int fd, uint32_t start) 1533*9e39c5baSBill Taylor { 1534*9e39c5baSBill Taylor int i, rv; 1535*9e39c5baSBill Taylor tavor_flash_ioctl_t cmd; 1536*9e39c5baSBill Taylor 1537*9e39c5baSBill Taylor /* signature first, then CRC16 */ 1538*9e39c5baSBill Taylor bzero(&cmd, sizeof (tavor_flash_ioctl_t)); 1539*9e39c5baSBill Taylor cmd.tf_type = TAVOR_FLASH_WRITE_BYTE; 1540*9e39c5baSBill Taylor cmd.tf_byte = 0x00; 1541*9e39c5baSBill Taylor 1542*9e39c5baSBill Taylor logmsg(MSG_INFO, 1543*9e39c5baSBill Taylor "tavor: tavor_zero_sig_crc(fd %d, start 0x%04x)\n", 1544*9e39c5baSBill Taylor fd, start); 1545*9e39c5baSBill Taylor 1546*9e39c5baSBill Taylor for (i = 0; i < 4; i++) { 1547*9e39c5baSBill Taylor cmd.tf_addr = start + FLASH_PS_SIGNATURE_OFFSET + i; 1548*9e39c5baSBill Taylor 1549*9e39c5baSBill Taylor logmsg(MSG_INFO, 1550*9e39c5baSBill Taylor "tavor: invalidating xPS sig (offset from IS 0x%04x) " 1551*9e39c5baSBill Taylor "byte %d\n", 1552*9e39c5baSBill Taylor cmd.tf_addr, i); 1553*9e39c5baSBill Taylor errno = 0; 1554*9e39c5baSBill Taylor 1555*9e39c5baSBill Taylor rv = ioctl(fd, TAVOR_IOCTL_FLASH_WRITE, &cmd); 1556*9e39c5baSBill Taylor if (rv < 0) { 1557*9e39c5baSBill Taylor logmsg(MSG_INFO, 1558*9e39c5baSBill Taylor gettext("tavor: Unable to write 0x00 to " 1559*9e39c5baSBill Taylor "offset 0x%04x from IS (sig byte %d): %s\n"), 1560*9e39c5baSBill Taylor cmd.tf_addr, i, strerror(errno)); 1561*9e39c5baSBill Taylor return (FWFLASH_FAILURE); 1562*9e39c5baSBill Taylor } 1563*9e39c5baSBill Taylor } 1564*9e39c5baSBill Taylor 1565*9e39c5baSBill Taylor cmd.tf_byte = 0x00; 1566*9e39c5baSBill Taylor for (i = 0; i < 2; i++) { 1567*9e39c5baSBill Taylor cmd.tf_addr = start + FLASH_PS_CRC16_OFFSET + i; 1568*9e39c5baSBill Taylor 1569*9e39c5baSBill Taylor logmsg(MSG_INFO, 1570*9e39c5baSBill Taylor "tavor: invalidating xPS CRC16 (offset from IS 0x%04x) " 1571*9e39c5baSBill Taylor "byte %d\n", 1572*9e39c5baSBill Taylor cmd.tf_addr, i); 1573*9e39c5baSBill Taylor errno = 0; 1574*9e39c5baSBill Taylor 1575*9e39c5baSBill Taylor rv = ioctl(fd, TAVOR_IOCTL_FLASH_WRITE, &cmd); 1576*9e39c5baSBill Taylor if (rv < 0) { 1577*9e39c5baSBill Taylor logmsg(MSG_INFO, 1578*9e39c5baSBill Taylor gettext("tavor: Unable to write 0x00 to " 1579*9e39c5baSBill Taylor "offset 0x%04x from IS (CRC16 byte %d): %s\n"), 1580*9e39c5baSBill Taylor cmd.tf_addr, i, strerror(errno)); 1581*9e39c5baSBill Taylor return (FWFLASH_FAILURE); 1582*9e39c5baSBill Taylor } 1583*9e39c5baSBill Taylor } 1584*9e39c5baSBill Taylor return (FWFLASH_SUCCESS); 1585*9e39c5baSBill Taylor } 1586*9e39c5baSBill Taylor 1587*9e39c5baSBill Taylor 1588*9e39c5baSBill Taylor /* 1589*9e39c5baSBill Taylor * Write a new FIA for the given xPS. The _caller_ handles 1590*9e39c5baSBill Taylor * any required byte-swapping for us. 1591*9e39c5baSBill Taylor * 1592*9e39c5baSBill Taylor * NOTE we do _not_ divide start by 4 because we're talking to the 1593*9e39c5baSBill Taylor * HCA, and not finding an offset into verifier->fwimage. 1594*9e39c5baSBill Taylor */ 1595*9e39c5baSBill Taylor static int 1596*9e39c5baSBill Taylor tavor_write_xps_fia(int fd, uint32_t offset, uint32_t start) 1597*9e39c5baSBill Taylor { 1598*9e39c5baSBill Taylor int i, rv; 1599*9e39c5baSBill Taylor uint8_t *addrbytep; 1600*9e39c5baSBill Taylor tavor_flash_ioctl_t cmd; 1601*9e39c5baSBill Taylor 1602*9e39c5baSBill Taylor logmsg(MSG_INFO, 1603*9e39c5baSBill Taylor "tavor: tavor_write_xps_fia(fd %d, offset 0x%04x, " 1604*9e39c5baSBill Taylor "start 0x%04x)\n", 1605*9e39c5baSBill Taylor fd, offset, start); 1606*9e39c5baSBill Taylor 1607*9e39c5baSBill Taylor addrbytep = (uint8_t *)&start; 1608*9e39c5baSBill Taylor 1609*9e39c5baSBill Taylor bzero(&cmd, sizeof (tavor_flash_ioctl_t)); 1610*9e39c5baSBill Taylor cmd.tf_type = TAVOR_FLASH_WRITE_BYTE; 1611*9e39c5baSBill Taylor for (i = 0; i < 4; i++) { 1612*9e39c5baSBill Taylor cmd.tf_byte = addrbytep[i]; 1613*9e39c5baSBill Taylor cmd.tf_addr = offset + FLASH_PS_FI_ADDR_OFFSET + i; 1614*9e39c5baSBill Taylor logmsg(MSG_INFO, 1615*9e39c5baSBill Taylor "tavor: writing xPS' new FIA, byte %d (0x%0x) at " 1616*9e39c5baSBill Taylor "offset from IS 0x%04x\n", 1617*9e39c5baSBill Taylor i, cmd.tf_byte, cmd.tf_addr); 1618*9e39c5baSBill Taylor errno = 0; 1619*9e39c5baSBill Taylor 1620*9e39c5baSBill Taylor rv = ioctl(fd, TAVOR_IOCTL_FLASH_WRITE, &cmd); 1621*9e39c5baSBill Taylor if (rv < 0) { 1622*9e39c5baSBill Taylor logmsg(MSG_INFO, 1623*9e39c5baSBill Taylor gettext("tavor: Unable to write byte %d " 1624*9e39c5baSBill Taylor "of xPS new FIA (0x%0x, offset from IS " 1625*9e39c5baSBill Taylor "0x%04x): %s\n"), 1626*9e39c5baSBill Taylor i, cmd.tf_byte, cmd.tf_addr, strerror(errno)); 1627*9e39c5baSBill Taylor return (FWFLASH_FAILURE); 1628*9e39c5baSBill Taylor } 1629*9e39c5baSBill Taylor } 1630*9e39c5baSBill Taylor return (FWFLASH_SUCCESS); 1631*9e39c5baSBill Taylor } 1632*9e39c5baSBill Taylor 1633*9e39c5baSBill Taylor 1634*9e39c5baSBill Taylor /* 1635*9e39c5baSBill Taylor * Write the new CRC16 and Signature to the given xPS. The caller 1636*9e39c5baSBill Taylor * has already byte-swapped newcrc if that's necessary. 1637*9e39c5baSBill Taylor * 1638*9e39c5baSBill Taylor * NOTE we do _not_ divide start by 4 because we're talking to the 1639*9e39c5baSBill Taylor * HCA, and not finding an offset into verifier->fwimage. 1640*9e39c5baSBill Taylor */ 1641*9e39c5baSBill Taylor static int 1642*9e39c5baSBill Taylor tavor_write_xps_crc_sig(int fd, uint32_t offset, uint16_t newcrc) 1643*9e39c5baSBill Taylor { 1644*9e39c5baSBill Taylor int i, rv; 1645*9e39c5baSBill Taylor uint8_t *bytep; 1646*9e39c5baSBill Taylor uint32_t tempsig; 1647*9e39c5baSBill Taylor tavor_flash_ioctl_t cmd; 1648*9e39c5baSBill Taylor 1649*9e39c5baSBill Taylor logmsg(MSG_INFO, 1650*9e39c5baSBill Taylor "tavor: tavor_write_xps_crc_sig(fd %d, offset 0x%04x, " 1651*9e39c5baSBill Taylor "newcrc 0x%04x)\n", 1652*9e39c5baSBill Taylor fd, offset, newcrc); 1653*9e39c5baSBill Taylor 1654*9e39c5baSBill Taylor bytep = (uint8_t *)&newcrc; 1655*9e39c5baSBill Taylor 1656*9e39c5baSBill Taylor bzero(&cmd, sizeof (tavor_flash_ioctl_t)); 1657*9e39c5baSBill Taylor cmd.tf_type = TAVOR_FLASH_WRITE_BYTE; 1658*9e39c5baSBill Taylor for (i = 0; i < 2; i++) { 1659*9e39c5baSBill Taylor cmd.tf_byte = bytep[i]; 1660*9e39c5baSBill Taylor cmd.tf_addr = offset + FLASH_PS_CRC16_OFFSET + i; 1661*9e39c5baSBill Taylor logmsg(MSG_INFO, 1662*9e39c5baSBill Taylor "tavor: writing new XPS CRC16, byte %d (0x%0x) at " 1663*9e39c5baSBill Taylor "offset from IS 0x%04x\n", 1664*9e39c5baSBill Taylor i, bytep[i], cmd.tf_addr); 1665*9e39c5baSBill Taylor errno = 0; 1666*9e39c5baSBill Taylor 1667*9e39c5baSBill Taylor rv = ioctl(fd, TAVOR_IOCTL_FLASH_WRITE, &cmd); 1668*9e39c5baSBill Taylor if (rv < 0) { 1669*9e39c5baSBill Taylor logmsg(MSG_INFO, 1670*9e39c5baSBill Taylor gettext("tavor: Unable to write byte %d " 1671*9e39c5baSBill Taylor "(0x%0x) of xPS' new CRC16 to offset " 1672*9e39c5baSBill Taylor "from IS 0x%04x: %s\n"), 1673*9e39c5baSBill Taylor i, bytep[i], cmd.tf_addr, strerror(errno)); 1674*9e39c5baSBill Taylor return (FWFLASH_FAILURE); 1675*9e39c5baSBill Taylor } 1676*9e39c5baSBill Taylor } 1677*9e39c5baSBill Taylor 1678*9e39c5baSBill Taylor tempsig = htonl(FLASH_PS_SIGNATURE); 1679*9e39c5baSBill Taylor bytep = (uint8_t *)&tempsig; 1680*9e39c5baSBill Taylor 1681*9e39c5baSBill Taylor for (i = 0; i < 4; i++) { 1682*9e39c5baSBill Taylor cmd.tf_byte = bytep[i]; 1683*9e39c5baSBill Taylor cmd.tf_addr = offset + FLASH_PS_SIGNATURE_OFFSET + i; 1684*9e39c5baSBill Taylor logmsg(MSG_INFO, 1685*9e39c5baSBill Taylor "tavor: writing new xPS Signature, byte %d (0x%0x) at " 1686*9e39c5baSBill Taylor "offset from IS 0x%04x\n", 1687*9e39c5baSBill Taylor i, bytep[i], cmd.tf_addr); 1688*9e39c5baSBill Taylor errno = 0; 1689*9e39c5baSBill Taylor 1690*9e39c5baSBill Taylor rv = ioctl(fd, TAVOR_IOCTL_FLASH_WRITE, &cmd); 1691*9e39c5baSBill Taylor if (rv < 0) { 1692*9e39c5baSBill Taylor logmsg(MSG_INFO, 1693*9e39c5baSBill Taylor gettext("tavor: Unable to write byte %d (0x%0x) " 1694*9e39c5baSBill Taylor "of xPS' signature at offset from IS 0x%04x: %s\n"), 1695*9e39c5baSBill Taylor i, bytep[i], cmd.tf_addr, strerror(errno)); 1696*9e39c5baSBill Taylor return (FWFLASH_FAILURE); 1697*9e39c5baSBill Taylor } 1698*9e39c5baSBill Taylor } 1699*9e39c5baSBill Taylor return (FWFLASH_SUCCESS); 1700*9e39c5baSBill Taylor } 1701*9e39c5baSBill Taylor 1702*9e39c5baSBill Taylor 1703*9e39c5baSBill Taylor 1704*9e39c5baSBill Taylor /* 1705*9e39c5baSBill Taylor * This function contains "Begin/End documentation departure point" 1706*9e39c5baSBill Taylor * because the reality of what actually _works_ is quite, quite 1707*9e39c5baSBill Taylor * different to what is written in the Mellanox HCA Flash Application 1708*9e39c5baSBill Taylor * Programming Guide. 1709*9e39c5baSBill Taylor */ 1710*9e39c5baSBill Taylor static int 1711*9e39c5baSBill Taylor tavor_blast_image(int fd, int prisec, uint32_t hcafia, uint32_t sectsz, 1712*9e39c5baSBill Taylor struct mlx_xps *newxps) 1713*9e39c5baSBill Taylor { 1714*9e39c5baSBill Taylor uint32_t i, j, rv; 1715*9e39c5baSBill Taylor uint32_t startsectimg, startsecthca, numsect; 1716*9e39c5baSBill Taylor 1717*9e39c5baSBill Taylor if ((prisec != 1) && (prisec != 2)) { 1718*9e39c5baSBill Taylor logmsg(MSG_ERROR, 1719*9e39c5baSBill Taylor "tavor: invalid image number requested (%d)\n"); 1720*9e39c5baSBill Taylor return (FWFLASH_FAILURE); 1721*9e39c5baSBill Taylor } 1722*9e39c5baSBill Taylor 1723*9e39c5baSBill Taylor /* Begin documentation departure point */ 1724*9e39c5baSBill Taylor 1725*9e39c5baSBill Taylor /* zero the HCA's PPS signature and CRC */ 1726*9e39c5baSBill Taylor if (tavor_zero_sig_crc(fd, (prisec * sectsz)) 1727*9e39c5baSBill Taylor != FWFLASH_SUCCESS) { 1728*9e39c5baSBill Taylor logmsg(MSG_INFO, 1729*9e39c5baSBill Taylor "tavor: Unable zero HCA's %s signature " 1730*9e39c5baSBill Taylor "and CRC16 fields\n", 1731*9e39c5baSBill Taylor ((prisec == 1) ? "PPS" : "SPS")); 1732*9e39c5baSBill Taylor return (FWFLASH_FAILURE); 1733*9e39c5baSBill Taylor } 1734*9e39c5baSBill Taylor 1735*9e39c5baSBill Taylor logmsg(MSG_INFO, "tavor: zeroing HCA's %s sig and crc\n", 1736*9e39c5baSBill Taylor (prisec == 1) ? "pps" : "sps"); 1737*9e39c5baSBill Taylor 1738*9e39c5baSBill Taylor /* End documentation departure point */ 1739*9e39c5baSBill Taylor 1740*9e39c5baSBill Taylor /* make sure we don't inadvertently overwrite bits */ 1741*9e39c5baSBill Taylor 1742*9e39c5baSBill Taylor startsectimg = MLXSWAPBITS32(newxps->fia) / sectsz; 1743*9e39c5baSBill Taylor startsecthca = hcafia / sectsz; 1744*9e39c5baSBill Taylor 1745*9e39c5baSBill Taylor numsect = (MLXSWAPBITS32(newxps->fis) / sectsz) + 1746*9e39c5baSBill Taylor ((MLXSWAPBITS32(newxps->fis) % sectsz) ? 1 : 0); 1747*9e39c5baSBill Taylor 1748*9e39c5baSBill Taylor logmsg(MSG_INFO, "tavor: %s imgsize 0x%0x startsecthca %d, " 1749*9e39c5baSBill Taylor "startsectimg %d, num sectors %d\n", 1750*9e39c5baSBill Taylor (prisec == 1) ? "PFI" : "SFI", MLXSWAPBITS32(newxps->fis), 1751*9e39c5baSBill Taylor startsecthca, startsectimg, numsect); 1752*9e39c5baSBill Taylor 1753*9e39c5baSBill Taylor for (i = 0; i < numsect; i++) { 1754*9e39c5baSBill Taylor 1755*9e39c5baSBill Taylor j = (MLXSWAPBITS32(newxps->fia) + (i * sectsz)) / 4; 1756*9e39c5baSBill Taylor 1757*9e39c5baSBill Taylor logmsg(MSG_INFO, "tavor: image offset 0x%0x\n", j); 1758*9e39c5baSBill Taylor logmsg(MSG_INFO, "tavor: writing HCA sector %d\n", 1759*9e39c5baSBill Taylor i + startsecthca); 1760*9e39c5baSBill Taylor 1761*9e39c5baSBill Taylor if (tavor_write_sector(fd, i + startsecthca, 1762*9e39c5baSBill Taylor &verifier->fwimage[j]) 1763*9e39c5baSBill Taylor != FWFLASH_SUCCESS) { 1764*9e39c5baSBill Taylor logmsg(MSG_ERROR, 1765*9e39c5baSBill Taylor gettext("tavor: Unable to write " 1766*9e39c5baSBill Taylor "sector %d to HCA\n"), 1767*9e39c5baSBill Taylor i + startsecthca); 1768*9e39c5baSBill Taylor return (FWFLASH_FAILURE); 1769*9e39c5baSBill Taylor } 1770*9e39c5baSBill Taylor (void) printf(" ."); 1771*9e39c5baSBill Taylor 1772*9e39c5baSBill Taylor rv = tavor_readback(fd, i + startsecthca, sectsz); 1773*9e39c5baSBill Taylor if (rv != FWFLASH_SUCCESS) { 1774*9e39c5baSBill Taylor logmsg(MSG_ERROR, 1775*9e39c5baSBill Taylor gettext("tavor: Unable to read sector %d " 1776*9e39c5baSBill Taylor "back from HCA\n"), i + startsecthca); 1777*9e39c5baSBill Taylor return (FWFLASH_FAILURE); 1778*9e39c5baSBill Taylor } 1779*9e39c5baSBill Taylor (void) printf(" | "); 1780*9e39c5baSBill Taylor } 1781*9e39c5baSBill Taylor 1782*9e39c5baSBill Taylor /* Begin documentation departure point */ 1783*9e39c5baSBill Taylor 1784*9e39c5baSBill Taylor /* invalidate the xps signature and fia fields */ 1785*9e39c5baSBill Taylor newxps->signature = 0xffffffff; 1786*9e39c5baSBill Taylor newxps->crc16 = 0xffff; 1787*9e39c5baSBill Taylor /* we put the fia back to imgfia later */ 1788*9e39c5baSBill Taylor newxps->fia = 0xffffffff; 1789*9e39c5baSBill Taylor /* End documentation departure point */ 1790*9e39c5baSBill Taylor 1791*9e39c5baSBill Taylor /* success so far, now burn the new xPS */ 1792*9e39c5baSBill Taylor if (tavor_write_sector(fd, prisec, (int *)newxps) 1793*9e39c5baSBill Taylor != FWFLASH_SUCCESS) { 1794*9e39c5baSBill Taylor logmsg(MSG_ERROR, 1795*9e39c5baSBill Taylor gettext("tavor: Unable to write new %s " 1796*9e39c5baSBill Taylor "pointer sector to HCA\n"), 1797*9e39c5baSBill Taylor (prisec == 1) ? "primary" : "secondary"); 1798*9e39c5baSBill Taylor return (FWFLASH_FAILURE); 1799*9e39c5baSBill Taylor } 1800*9e39c5baSBill Taylor (void) printf(" ."); 1801*9e39c5baSBill Taylor 1802*9e39c5baSBill Taylor /* Begin documentation departure point */ 1803*9e39c5baSBill Taylor 1804*9e39c5baSBill Taylor /* write new fia to the HCA's pps */ 1805*9e39c5baSBill Taylor logmsg(MSG_INFO, "tavor: writing new fia (0x%0x) to HCA\n", 1806*9e39c5baSBill Taylor MLXSWAPBITS32(newxps->fia)); 1807*9e39c5baSBill Taylor 1808*9e39c5baSBill Taylor if (tavor_write_xps_fia(fd, (prisec * sectsz), 1809*9e39c5baSBill Taylor MLXSWAPBITS32(hcafia)) != FWFLASH_SUCCESS) { 1810*9e39c5baSBill Taylor logmsg(MSG_ERROR, 1811*9e39c5baSBill Taylor gettext("tavor: Unable to update HCA's %s " 1812*9e39c5baSBill Taylor "pointer sector FIA record\n"), 1813*9e39c5baSBill Taylor (prisec == 1) ? "primary" : "secondary"); 1814*9e39c5baSBill Taylor return (FWFLASH_FAILURE); 1815*9e39c5baSBill Taylor } 1816*9e39c5baSBill Taylor 1817*9e39c5baSBill Taylor /* don't forget the byte-swapping */ 1818*9e39c5baSBill Taylor newxps->fia = MLXSWAPBITS32(hcafia); 1819*9e39c5baSBill Taylor newxps->signature = 1820*9e39c5baSBill Taylor (uint32_t)MLXSWAPBITS32(FLASH_PS_SIGNATURE); 1821*9e39c5baSBill Taylor newxps->crc16 = 1822*9e39c5baSBill Taylor MLXSWAPBITS16(crc16((uint8_t *)newxps, FLASH_PS_CRC16_SIZE)); 1823*9e39c5baSBill Taylor 1824*9e39c5baSBill Taylor logmsg(MSG_INFO, "tavor: writing new fia 0x%0x, " 1825*9e39c5baSBill Taylor "sig 0x%0x and new crc16 0x%0x\n", 1826*9e39c5baSBill Taylor newxps->fia, MLXSWAPBITS32(newxps->signature), 1827*9e39c5baSBill Taylor newxps->crc16); 1828*9e39c5baSBill Taylor 1829*9e39c5baSBill Taylor if (tavor_write_xps_crc_sig(fd, (prisec * sectsz), 1830*9e39c5baSBill Taylor newxps->crc16) != FWFLASH_SUCCESS) { 1831*9e39c5baSBill Taylor /* 1832*9e39c5baSBill Taylor * Now we're REALLY hosed. If the card comes up at all, 1833*9e39c5baSBill Taylor * expect it to be in "Maintenance Mode". 1834*9e39c5baSBill Taylor */ 1835*9e39c5baSBill Taylor logmsg(MSG_ERROR, 1836*9e39c5baSBill Taylor gettext("tavor: Unable to update HCA's %s CRC " 1837*9e39c5baSBill Taylor "and Firmware Image signature fields\n"), 1838*9e39c5baSBill Taylor (prisec == 1) ? "PPS" : "SPS"); 1839*9e39c5baSBill Taylor return (FWFLASH_FAILURE); 1840*9e39c5baSBill Taylor } 1841*9e39c5baSBill Taylor 1842*9e39c5baSBill Taylor rv = tavor_readback(fd, prisec, sectsz); 1843*9e39c5baSBill Taylor if (rv != FWFLASH_SUCCESS) { 1844*9e39c5baSBill Taylor logmsg(MSG_ERROR, 1845*9e39c5baSBill Taylor gettext("tavor: Unable to read %s pointer sector " 1846*9e39c5baSBill Taylor "from HCA\n"), 1847*9e39c5baSBill Taylor (prisec == 1) ? "Primary" : "Secondary"); 1848*9e39c5baSBill Taylor return (FWFLASH_FAILURE); 1849*9e39c5baSBill Taylor } 1850*9e39c5baSBill Taylor (void) printf(" |"); 1851*9e39c5baSBill Taylor /* End documentation departure point */ 1852*9e39c5baSBill Taylor return (FWFLASH_SUCCESS); 1853*9e39c5baSBill Taylor } 1854*9e39c5baSBill Taylor 1855*9e39c5baSBill Taylor 1856*9e39c5baSBill Taylor static int 1857*9e39c5baSBill Taylor tavor_readback(int infd, int whichsect, int sectsz) 1858*9e39c5baSBill Taylor { 1859*9e39c5baSBill Taylor uint32_t *data; 1860*9e39c5baSBill Taylor tavor_flash_ioctl_t cmd; 1861*9e39c5baSBill Taylor int rv; 1862*9e39c5baSBill Taylor 1863*9e39c5baSBill Taylor bzero(&cmd, sizeof (tavor_flash_ioctl_t)); 1864*9e39c5baSBill Taylor data = calloc(1, sectsz); /* assumption! */ 1865*9e39c5baSBill Taylor 1866*9e39c5baSBill Taylor cmd.tf_type = TAVOR_FLASH_READ_SECTOR; 1867*9e39c5baSBill Taylor cmd.tf_sector_num = whichsect; 1868*9e39c5baSBill Taylor cmd.tf_sector = (caddr_t)data; 1869*9e39c5baSBill Taylor rv = ioctl(infd, TAVOR_IOCTL_FLASH_READ, &cmd); 1870*9e39c5baSBill Taylor if (rv < 0) { 1871*9e39c5baSBill Taylor logmsg(MSG_INFO, 1872*9e39c5baSBill Taylor "tavor: UNABLE TO READ BACK SECTOR %d from HCA\n", 1873*9e39c5baSBill Taylor whichsect); 1874*9e39c5baSBill Taylor return (FWFLASH_FAILURE); 1875*9e39c5baSBill Taylor } 1876*9e39c5baSBill Taylor free(data); 1877*9e39c5baSBill Taylor return (FWFLASH_SUCCESS); 1878*9e39c5baSBill Taylor } 1879*9e39c5baSBill Taylor 1880*9e39c5baSBill Taylor 1881*9e39c5baSBill Taylor /* 1882*9e39c5baSBill Taylor * crc16 - computes 16 bit crc of supplied buffer. 1883*9e39c5baSBill Taylor * image should be in network byteorder 1884*9e39c5baSBill Taylor * result is returned in host byteorder form 1885*9e39c5baSBill Taylor */ 1886*9e39c5baSBill Taylor static uint16_t 1887*9e39c5baSBill Taylor crc16(uint8_t *image, uint32_t size) 1888*9e39c5baSBill Taylor { 1889*9e39c5baSBill Taylor const uint16_t poly = 0x100b; 1890*9e39c5baSBill Taylor uint32_t crc = 0xFFFF; 1891*9e39c5baSBill Taylor uint32_t word; 1892*9e39c5baSBill Taylor uint32_t i, j; 1893*9e39c5baSBill Taylor 1894*9e39c5baSBill Taylor for (i = 0; i < size / 4; i++) { 1895*9e39c5baSBill Taylor word = (image[4 * i] << 24) | 1896*9e39c5baSBill Taylor (image[4 * i + 1] << 16) | 1897*9e39c5baSBill Taylor (image[4 * i + 2] << 8) | 1898*9e39c5baSBill Taylor (image[4 * i + 3]); 1899*9e39c5baSBill Taylor 1900*9e39c5baSBill Taylor for (j = 0; j < 32; j++) { 1901*9e39c5baSBill Taylor if (crc & 0x8000) { 1902*9e39c5baSBill Taylor crc = (((crc << 1) | 1903*9e39c5baSBill Taylor (word >> 31)) ^ poly) & 0xFFFF; 1904*9e39c5baSBill Taylor } else { 1905*9e39c5baSBill Taylor crc = ((crc << 1) | (word >> 31)) & 0xFFFF; 1906*9e39c5baSBill Taylor } 1907*9e39c5baSBill Taylor word = (word << 1) & 0xFFFFFFFF; 1908*9e39c5baSBill Taylor } 1909*9e39c5baSBill Taylor } 1910*9e39c5baSBill Taylor 1911*9e39c5baSBill Taylor for (i = 0; i < 16; i++) { 1912*9e39c5baSBill Taylor if (crc & 0x8000) { 1913*9e39c5baSBill Taylor crc = ((crc << 1) ^ poly) & 0xFFFF; 1914*9e39c5baSBill Taylor } else { 1915*9e39c5baSBill Taylor crc = (crc << 1) & 0xFFFF; 1916*9e39c5baSBill Taylor } 1917*9e39c5baSBill Taylor } 1918*9e39c5baSBill Taylor 1919*9e39c5baSBill Taylor crc = crc ^ 0xFFFF; 1920*9e39c5baSBill Taylor return (crc & 0xFFFF); 1921*9e39c5baSBill Taylor } 1922