4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
27 * ConnectX (hermon) firmware image verification plugin
33 #include <sys/types.h>
35 #include <sys/sysmacros.h>
37 #include <sys/condvar.h>
41 #include <sys/byteorder.h>
43 #include <libintl.h> /* for gettext(3c) */
45 #include <fwflash/fwflash.h>
46 #include "../hdrs/hermon_ib.h"
48 char vendor
[] = "MELLANOX\0";
50 extern struct vrfyplugin
*verifier
;
53 /* required functions for this plugin */
54 int vendorvrfy(struct devicelist
*devicenode
);
56 /* helper functions */
57 static uint16_t cnx_check_hwver_img(ib_cnx_encap_ident_t
*handle
);
58 static void cnx_flash_verify_flash_match_img(ib_cnx_encap_ident_t
*handle
);
59 static void cnx_flash_verify_flash_pn_img(ib_cnx_encap_ident_t
*handle
,
60 uchar_t
*psid
, int psid_size
);
61 static uchar_t
*cnx_flash_get_psid_img(ib_cnx_encap_ident_t
*handle
);
62 static void cnx_display_fwver(ib_cnx_encap_ident_t
*handle
);
63 static int cnx_check_guid_section();
67 vendorvrfy(struct devicelist
*devicenode
)
69 struct ib_cnx_encap_ident_s
*handle
;
72 logmsg(MSG_INFO
, "hermon: vendorvrfy \n");
74 handle
= (struct ib_cnx_encap_ident_s
*)devicenode
->ident
->encap_ident
;
76 if (CNX_I_CHECK_HANDLE(handle
)) {
77 logmsg(MSG_ERROR
, gettext("hermon: Invalid Handle for "
78 "device %s! \n"), devicenode
->access_devname
);
79 return (FWFLASH_FAILURE
);
83 * NOTE verifier->fwimage is where file is read to.
85 if (cnx_is_magic_pattern_present(&verifier
->fwimage
[0], 1) !=
87 logmsg(MSG_ERROR
, gettext("%s firmware image verifier: "
88 "No magic pattern found in firmware file %s \n"),
89 verifier
->vendor
, verifier
->imgfile
);
90 return (FWFLASH_FAILURE
);
93 if (cnx_check_guid_section() == FWFLASH_FAILURE
) {
94 logmsg(MSG_INFO
, "%s firmware image verifier: "
95 "Firmware Image GUID section is invalid\n",
99 cnx_flash_verify_flash_match_img(handle
);
101 /* Check Hardware Rev */
102 ver
= cnx_check_hwver_img(handle
);
104 logmsg(MSG_ERROR
, gettext("hermon: Firmware mismatch: "
105 "ver(0x%X) hw_ver(0x%X)\n"), (ver
>> 8), ver
& 0xFF);
106 return (FWFLASH_FAILURE
);
109 if (handle
->hwfw_match
== 0) {
112 if (handle
->pn_len
!= 0) {
113 /* HW VPD exist and a mismatch was found */
114 logmsg(MSG_ERROR
, gettext("hermon: Please verify that "
115 "the firmware image is intended for use with this "
118 logmsg(MSG_ERROR
, gettext("hermon: Unable to verify "
119 "firmware is appropriate for the hardware\n"));
121 logmsg(MSG_ERROR
, gettext("Do you want to continue? (Y/N): "));
122 (void) fflush(stdin
);
124 if (resp
!= 'Y' && resp
!= 'y') {
125 logmsg(MSG_ERROR
, gettext("Not proceeding with "
126 "flash operation of %s on %s \n"),
127 verifier
->imgfile
, devicenode
->drvname
);
128 return (FWFLASH_FAILURE
);
131 logmsg(MSG_INFO
, "%s firmware image verifier: HCA PSID (%s) "
132 "matches firmware image %s's PSID\n", verifier
->vendor
,
133 handle
->info
.mlx_psid
, verifier
->imgfile
);
135 cnx_display_fwver(handle
);
138 return (FWFLASH_SUCCESS
);
142 cnx_check_hwver_img(ib_cnx_encap_ident_t
*handle
)
147 logmsg(MSG_INFO
, "hermon: verify: cnx_check_hwver_img\n");
148 if ((handle
->state
& FWFLASH_IB_STATE_IMAGE_PRI
) == 0 &&
149 (handle
->state
& FWFLASH_IB_STATE_IMAGE_SEC
) == 0) {
150 logmsg(MSG_ERROR
, gettext("hermon: Must read in image "
155 /* Read Flash HW Version */
156 hwver
= (uint8_t)handle
->hwrev
;
157 local_hwver
= (ntohl(verifier
->fwimage
[CNX_HWVER_OFFSET
/ 4]) &
158 CNX_HWVER_MASK
) >> 24;
160 logmsg(MSG_INFO
, "local_hwver: %x, hwver: %x\n", local_hwver
, hwver
);
162 if ((hwver
== 0xA0 || hwver
== 0x00 || hwver
== 0x20) &&
163 (local_hwver
== 0x00 || local_hwver
== 0xA0 ||
164 local_hwver
== 0x20)) {
165 logmsg(MSG_INFO
, ("A0 board found.\r\n"));
166 } else if (hwver
== 0xA1 && local_hwver
== 0xA1) {
167 logmsg(MSG_INFO
, ("A1 board found.\r\n"));
168 } else if (hwver
== 0xA2 && local_hwver
== 0xA2) {
169 logmsg(MSG_INFO
, ("A2 board found.\r\n"));
170 } else if (hwver
== 0xA3 && local_hwver
== 0xA3) {
171 logmsg(MSG_INFO
, ("A3 board found.\r\n"));
172 } else if (hwver
== 0xB0 && local_hwver
== 0xB0) {
173 logmsg(MSG_INFO
, ("B0 board found.\r\n"));
174 } else if (hwver
!= local_hwver
) {
175 return ((uint16_t)(local_hwver
<< 8) | hwver
);
181 cnx_display_fwver(ib_cnx_encap_ident_t
*handle
)
183 logmsg(MSG_INFO
, "hermon: verify: cnx_display_fwver\n");
185 (void) fprintf(stdout
, gettext(" The current HCA firmware version "
186 "is : %d.%d.%03d\n"),
187 handle
->hwfw_img_info
.fw_rev
.major
,
188 handle
->hwfw_img_info
.fw_rev
.minor
,
189 handle
->hwfw_img_info
.fw_rev
.subminor
);
190 (void) fprintf(stdout
, gettext(" Will be updated to HCA firmware "
191 "ver of : %d.%d.%03d\n"),
192 handle
->file_img_info
.fw_rev
.major
,
193 handle
->file_img_info
.fw_rev
.minor
,
194 handle
->file_img_info
.fw_rev
.subminor
);
198 cnx_flash_get_psid_img(ib_cnx_encap_ident_t
*handle
)
200 uint32_t ii_ptr_addr
;
203 logmsg(MSG_INFO
, "hermon: verify: cnx_flash_get_psid_img\n");
205 /* Get the image info pointer */
206 ii_ptr_addr
= ntohl(verifier
->fwimage
[CNX_IMG_INF_PTR_OFFSET
/ 4]);
207 ii_ptr_addr
&= 0xffffff; /* Bits 23:0 - Image Info Data Pointer */
209 /* Get the image info size, a negative offset from the image info ptr */
211 ntohl(verifier
->fwimage
[(ii_ptr_addr
+ CNX_IMG_INF_SZ_OFFSET
) / 4]);
212 /* size is in dwords--convert it to bytes */
215 logmsg(MSG_INFO
, "ImgInfo_ptr_addr: 0x%lx, ImgInfo_size: 0x%x\n",
216 ii_ptr_addr
, ii_size
);
218 /* Parse the image info section */
219 if (cnx_parse_img_info(&verifier
->fwimage
[ii_ptr_addr
/ 4], ii_size
,
220 &handle
->file_img_info
, CNX_FILE_IMG
) != FWFLASH_SUCCESS
) {
221 logmsg(MSG_WARN
, gettext("hermon: Failed to parse ImageInfo "
226 return (handle
->file_img_info
.psid
);
230 cnx_flash_verify_flash_pn_img(ib_cnx_encap_ident_t
*handle
, uchar_t
*psid
,
236 logmsg(MSG_INFO
, "hermon: verify: cnx_flash_verify_flash_pn_img\n");
237 /* verify fw matches the hardware */
238 if (handle
->hwfw_match
== 1) {
239 /* already been verified */
243 /* find the PSID from FW in the mlx table */
244 for (i
= 0; i
< MLX_MAX_ID
; i
++) {
245 if (handle
->hwfw_match
== 1) {
247 * Need this check here and the 'continue's below
248 * because there are some cards that have a
249 * 'new' part number but the same PSID value.
255 if (strncmp((const char *)psid
, mlx_mdr
[i
].mlx_psid
,
257 logmsg(MSG_INFO
, "Found Matching firmware image's "
258 "PSID (%s) entry in MDR Table\n", psid
);
260 logmsg(MSG_INFO
, "Search for firmware image's part# "
261 "(%s), MDR/HW PN (%s) \n",
262 handle
->info
.mlx_pn
, mlx_mdr
[i
].mlx_pn
);
264 /* match part numbers */
265 if (strncmp(handle
->info
.mlx_pn
, mlx_mdr
[i
].mlx_pn
,
266 handle
->pn_len
) == 0) {
267 handle
->hwfw_match
= 1;
268 logmsg(MSG_INFO
, "Match Found \n");
271 handle
->hwfw_match
= 0;
273 logmsg(MSG_INFO
, "Match NOT Found \n");
278 if (i
== MLX_MAX_ID
&& no_match
== 0) {
280 handle
->hwfw_match
= 0;
282 logmsg(MSG_WARN
, gettext("hermon: No PSID match found\n"));
284 if (handle
->hwfw_match
== 0) {
285 logmsg(MSG_WARN
, gettext("WARNING: Firmware "
286 "image is meant for %s but the hardware "
287 "is %s\n"), mlx_mdr
[no_match
].mlx_pn
,
288 handle
->info
.mlx_pn
);
294 cnx_flash_verify_flash_match_img(ib_cnx_encap_ident_t
*handle
)
298 logmsg(MSG_INFO
, "hermon: verify: cnx_flash_verify_flash_match_img\n");
299 /* get PSID of firmware file */
300 psid
= cnx_flash_get_psid_img(handle
);
302 handle
->hwfw_match
= 0;
306 logmsg(MSG_INFO
, "FW PSID (%s)\n", psid
);
309 * Check the part number of the hardware against the part number
310 * of the firmware file. If the hardware information is not
311 * available, check the currently loaded firmware against the
312 * firmware file to be uploaded.
314 if (handle
->pn_len
!= 0) {
315 cnx_flash_verify_flash_pn_img(handle
, psid
, CNX_PSID_SZ
);
321 cnx_check_guid_section()
323 struct mlx_cnx_xfi xfisect
;
324 struct mlx_cnx_guid_sect guidsect
;
325 uint32_t nguidptr_addr
;
326 uint16_t calculated_crc
;
328 logmsg(MSG_INFO
, "cnx_check_guid_section: \n");
330 bcopy(&verifier
->fwimage
[0], &xfisect
, sizeof (struct mlx_cnx_xfi
));
331 logmsg(MSG_INFO
, "FailSafeChunkSz: 0x%08x, ImageInfoPtr: 0x%08x\n",
332 MLXSWAPBITS32(xfisect
.failsafechunkinfo
),
333 MLXSWAPBITS32(xfisect
.imageinfoptr
) & CNX_XFI_IMGINFO_PTR_MASK
);
334 logmsg(MSG_INFO
, "FW Size: 0x%08x NGUIDPTR: 0x%08x\n",
335 MLXSWAPBITS32(xfisect
.fwimagesz
), MLXSWAPBITS32(xfisect
.nguidptr
));
337 nguidptr_addr
= (MLXSWAPBITS32(xfisect
.nguidptr
) - 0x10) / 4;
338 bcopy(&verifier
->fwimage
[nguidptr_addr
], &guidsect
,
339 sizeof (struct mlx_cnx_guid_sect
));
341 logmsg(MSG_INFO
, "Node GUID : 0x%016llx \n",
342 MLXSWAPBITS64(guidsect
.nodeguid
));
343 logmsg(MSG_INFO
, "Port1 GUID: 0x%016llx \n",
344 MLXSWAPBITS64(guidsect
.port1guid
));
345 logmsg(MSG_INFO
, "Port2 GUID: 0x%016llx \n",
346 MLXSWAPBITS64(guidsect
.port2guid
));
347 logmsg(MSG_INFO
, "SysIm GUID: 0x%016llx \n",
348 MLXSWAPBITS64(guidsect
.sysimguid
));
349 logmsg(MSG_INFO
, "Port 1 MAC: 0x%016llx \n",
350 MLXSWAPBITS64(guidsect
.port1_mac
));
351 logmsg(MSG_INFO
, "Port 2 MAC: 0x%016llx \n",
352 MLXSWAPBITS64(guidsect
.port2_mac
));
354 calculated_crc
= cnx_crc16((uint8_t *)&verifier
->fwimage
[nguidptr_addr
],
355 CNX_GUID_CRC16_SIZE
, CNX_FILE_IMG
);
356 if (calculated_crc
!= ntohs(guidsect
.guidcrc
)) {
357 logmsg(MSG_WARN
, gettext("hermon: calculated crc value 0x%x "
358 "differs from GUID section 0x%x\n"), calculated_crc
,
359 ntohs(guidsect
.guidcrc
));
361 logmsg(MSG_INFO
, "hermon: calculated crc value 0x%x MATCHES "
362 "with GUID section 0x%x\n", calculated_crc
,
363 ntohs(guidsect
.guidcrc
));
366 if ((MLXSWAPBITS64(guidsect
.nodeguid
) == MLX_DEFAULT_NODE_GUID
) &&
367 (MLXSWAPBITS64(guidsect
.port1guid
) == MLX_DEFAULT_P1_GUID
) &&
368 (MLXSWAPBITS64(guidsect
.port2guid
) == MLX_DEFAULT_P2_GUID
) &&
369 ((MLXSWAPBITS64(guidsect
.sysimguid
) == MLX_DEFAULT_SYSIMG_GUID
) ||
370 (MLXSWAPBITS64(guidsect
.sysimguid
) == MLX_DEFAULT_NODE_GUID
)) ||
371 ((((MLXSWAPBITS64(guidsect
.nodeguid
) & HIGHBITS64
) >> 40) ==
373 (((MLXSWAPBITS64(guidsect
.port1guid
) & HIGHBITS64
) >> 40) ==
375 (((MLXSWAPBITS64(guidsect
.port2guid
) & HIGHBITS64
) >> 40) ==
377 (((MLXSWAPBITS64(guidsect
.sysimguid
) & HIGHBITS64
) >> 40) ==
379 ((((MLXSWAPBITS64(guidsect
.nodeguid
) & HIGHBITS64
) >> 40) ==
381 (((MLXSWAPBITS64(guidsect
.port1guid
) & HIGHBITS64
) >> 40) ==
383 (((MLXSWAPBITS64(guidsect
.port2guid
) & HIGHBITS64
) >> 40) ==
385 (((MLXSWAPBITS64(guidsect
.sysimguid
) & HIGHBITS64
) >> 40) ==
387 logmsg(MSG_INFO
, "%s firmware image verifier: GUID Prefix "
388 "is as expected\n", verifier
->vendor
);
389 return (FWFLASH_SUCCESS
);
391 logmsg(MSG_INFO
, "%s firmware image verifier: GUID prefix "
392 "is not as expected\n", verifier
->vendor
);
393 return (FWFLASH_FAILURE
);