tavor-MELLANOX.c revision ee5d8455d3cff95bf8149073831be4560d60250d
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/*
* Mellanox firmware image verification plugin
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/sysmacros.h>
#include <fcntl.h>
#include <string.h>
#include <strings.h>
#include <sys/byteorder.h>
#include <libintl.h> /* for gettext(3c) */
#include "../hdrs/MELLANOX.h"
#include "../hdrs/tavor_ib.h"
char vendor[] = "MELLANOX\0";
extern int errno;
extern struct vrfyplugin *verifier;
/* required functions for this plugin */
/* helper functions */
int
{
struct ib_encap_ident *encap;
int *firmware;
int i = 0, a, b, c, d;
char temppsid[17];
char rawpsid[16];
int offset;
/*
* NOTE that since verifier->fwimage is an array of ints,
* we have to divide our actual desired number by 4 to get
* the right data.
*/
/*
* The actual location of log2_sector_sz can be calculated
* by adding 0x32 to the value that is written in the
* log2_sector_sz_ptr field. The log2_sector_sz_ptr is located
* at 0x16 byte offset in Invariant Sector.
*/
gettext("%s firmware image verifier: "
"appropriate for this device.\n"));
/* this is fatal */
return (FWFLASH_FAILURE);
}
/* now verify primary pointer sector */
gettext("%s firmware image verifier: "
"Unable to allocate memory for Primary Pointer "
return (FWFLASH_FAILURE);
}
gettext("%s firmware image verifier: "
"Primary Pointer Sector is invalid\n"),
}
/*
* A slight diversion - check the PSID in the last
* 16 bytes of the first 256bytes in the xPS sectors.
* This will give us our part number to match. If the
* part number in the image doesn't match the part number
* in the encap_ident info (and pn_len > 0) then we reject
* this image as being incompatible with the HCA.
*
* In this bit we're only checking the info.mlx_psid field
* of the primary image in the on-disk image. If that's
* invalid we reject the image.
*/
#if defined(_LITTLE_ENDIAN)
for (i = 0; i < 16; i += 4) {
}
"tavor: have raw '%s', want munged '%s'\n",
#else
#endif
int resp;
gettext("%s firmware image verifier: "
"firmware image file %s is not appropriate "
"for device "
"%s (PSID file %s vs PSID device %s)\n"),
gettext("Do you want to continue? (Y/N): "));
"flash operation of %s on %s"),
return (FWFLASH_FAILURE);
}
} else {
"%s firmware image verifier: HCA PSID (%s) "
"matches firmware image %s's PSID\n",
}
}
/* now verify secondary pointer sector */
gettext("%s firmware image verifier: "
"Secondary Pointer Sector is invalid\n"),
}
gettext("%s firmware image verifier: "
"Unable to allocate space for Primary "
"Firmware Image verification\n"),
return (FWFLASH_FAILURE);
}
vp_imginfo = MLXSWAPBITS32(i);
/* for readability only */
d = (vp_imginfo & 0x000000ff);
/*
* It appears to be the case (empirically) that this particular
* check condition for ImageInfoPtr doesn't hold for A1 firmware
* images. So if the ((a+b+c+d)%0x100) fails, don't worry unless
* the contents of the GUID section do not match the Mellanox
* default GUIDs 2c9000100d05[0123]. The A2++ images also have
* these default GUIDS.
*
* Unfortunately we can't depend on the hwrev field of the image's
* Invariant Sector for another level of confirmation, since A2++
* images seem to have that field set to 0xa1 as well as the A1
* images. Annoying!
*/
if ((((a+b+c+d) % 0x100) == 0) &&
(vp_imginfo != 0x00000000)) {
"%s firmware image verifier: "
"Primary Firmware Image Info pointer is valid\n",
} else {
gettext("%s firmware image verifier: "
"Primary Firmware Image Info pointer is invalid "
"(0x%04x)\nChecking GUID section.....\n"),
gettext("%s firmware image verifier: "
"Primary Firmware Image GUID section "
"is invalid\n"),
i = 1;
} else {
"%s firmware image verifier: "
"Primary GUID section is ok\n",
}
}
vs_imginfo = MLXSWAPBITS32(i);
/* for readability only */
d = (vs_imginfo & 0x000000ff);
if ((((a+b+c+d) % 0x100) == 0) &&
(vs_imginfo != 0x00000000)) {
"%s firmware image verifier: "
"Secondary Firmware Image Info pointer is valid\n",
} else {
gettext("%s firmware image verifier: "
"Secondary Firmware Image Info pointer is invalid "
"(0x%04x)\nChecking GUID section.....\n"),
gettext("%s firmware image verifier: "
"Secondary Firmware Image GUID section "
"is invalid\n"),
i++;
}
}
if (i == 2)
}
/*
* Very simple function - we're given an array of bytes,
* we know that we need to read the value at offset FLASH_GUID_PTR
* and jump to that location to read 4x uint64_t of (hopefully)
* GUID data. If we can read that data, and it matches the default
* Mellanox GUIDs, then we return success. We need all 4 default
* GUIDs to match otherwise we return failure.
*/
static int
{
struct mlx_guid_sect guidsect;
== MLX_OUI) ||
== MLX_OUI) ||
== MLX_OUI) ||
== MLX_OUI))) {
return (FWFLASH_SUCCESS);
} else {
return (FWFLASH_FAILURE);
}
}