xref: /freebsd/sys/dev/sfxge/common/efx_lic.c (revision 22cf89c938886d14f5796fc49f9f020c23ea8eaf)
1 /*-
2  * Copyright (c) 2009-2016 Solarflare Communications Inc.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  *
8  * 1. Redistributions of source code must retain the above copyright notice,
9  *    this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright notice,
11  *    this list of conditions and the following disclaimer in the documentation
12  *    and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
15  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
16  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
18  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
21  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
22  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
23  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
24  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25  *
26  * The views and conclusions contained in the software and documentation are
27  * those of the authors and should not be interpreted as representing official
28  * policies, either expressed or implied, of the FreeBSD Project.
29  */
30 
31 #include <sys/cdefs.h>
32 #include "efx.h"
33 #include "efx_impl.h"
34 
35 #if EFSYS_OPT_LICENSING
36 
37 #include "ef10_tlv_layout.h"
38 #if EFSYS_OPT_SIENA
39 #include "efx_regs_mcdi_aoe.h"
40 #endif
41 
42 #if EFSYS_OPT_SIENA | EFSYS_OPT_HUNTINGTON
43 
44 	__checkReturn		efx_rc_t
45 efx_lic_v1v2_find_start(
46 	__in			efx_nic_t *enp,
47 	__in_bcount(buffer_size)
48 				caddr_t bufferp,
49 	__in			size_t buffer_size,
50 	__out			uint32_t *startp);
51 
52 	__checkReturn		efx_rc_t
53 efx_lic_v1v2_find_end(
54 	__in			efx_nic_t *enp,
55 	__in_bcount(buffer_size)
56 				caddr_t bufferp,
57 	__in			size_t buffer_size,
58 	__in			uint32_t offset,
59 	__out			uint32_t *endp);
60 
61 	__checkReturn	__success(return != B_FALSE)	boolean_t
62 efx_lic_v1v2_find_key(
63 	__in			efx_nic_t *enp,
64 	__in_bcount(buffer_size)
65 				caddr_t bufferp,
66 	__in			size_t buffer_size,
67 	__in			uint32_t offset,
68 	__out			uint32_t *startp,
69 	__out			uint32_t *lengthp);
70 
71 	__checkReturn	__success(return != B_FALSE)	boolean_t
72 efx_lic_v1v2_validate_key(
73 	__in			efx_nic_t *enp,
74 	__in_bcount(length)	caddr_t keyp,
75 	__in			uint32_t length);
76 
77 	__checkReturn		efx_rc_t
78 efx_lic_v1v2_read_key(
79 	__in			efx_nic_t *enp,
80 	__in_bcount(buffer_size)
81 				caddr_t bufferp,
82 	__in			size_t buffer_size,
83 	__in			uint32_t offset,
84 	__in			uint32_t length,
85 	__out_bcount_part(key_max_size, *lengthp)
86 				caddr_t keyp,
87 	__in			size_t key_max_size,
88 	__out			uint32_t *lengthp);
89 
90 	__checkReturn		efx_rc_t
91 efx_lic_v1v2_write_key(
92 	__in			efx_nic_t *enp,
93 	__in_bcount(buffer_size)
94 				caddr_t bufferp,
95 	__in			size_t buffer_size,
96 	__in			uint32_t offset,
97 	__in_bcount(length)	caddr_t keyp,
98 	__in			uint32_t length,
99 	__out			uint32_t *lengthp);
100 
101 	__checkReturn		efx_rc_t
102 efx_lic_v1v2_delete_key(
103 	__in			efx_nic_t *enp,
104 	__in_bcount(buffer_size)
105 				caddr_t bufferp,
106 	__in			size_t buffer_size,
107 	__in			uint32_t offset,
108 	__in			uint32_t length,
109 	__in			uint32_t end,
110 	__out			uint32_t *deltap);
111 
112 	__checkReturn		efx_rc_t
113 efx_lic_v1v2_create_partition(
114 	__in			efx_nic_t *enp,
115 	__in_bcount(buffer_size)
116 				caddr_t bufferp,
117 	__in			size_t buffer_size);
118 
119 	__checkReturn		efx_rc_t
120 efx_lic_v1v2_finish_partition(
121 	__in			efx_nic_t *enp,
122 	__in_bcount(buffer_size)
123 				caddr_t bufferp,
124 	__in			size_t buffer_size);
125 
126 #endif	/* EFSYS_OPT_HUNTINGTON | EFSYS_OPT_SIENA */
127 
128 #if EFSYS_OPT_SIENA
129 
130 static	__checkReturn	efx_rc_t
131 efx_mcdi_fc_license_update_license(
132 	__in		efx_nic_t *enp);
133 
134 static	__checkReturn	efx_rc_t
135 efx_mcdi_fc_license_get_key_stats(
136 	__in		efx_nic_t *enp,
137 	__out		efx_key_stats_t *eksp);
138 
139 static const efx_lic_ops_t	__efx_lic_v1_ops = {
140 	efx_mcdi_fc_license_update_license,	/* elo_update_licenses */
141 	efx_mcdi_fc_license_get_key_stats,	/* elo_get_key_stats */
142 	NULL,					/* elo_app_state */
143 	NULL,					/* elo_get_id */
144 	efx_lic_v1v2_find_start,		/* elo_find_start */
145 	efx_lic_v1v2_find_end,			/* elo_find_end */
146 	efx_lic_v1v2_find_key,			/* elo_find_key */
147 	efx_lic_v1v2_validate_key,		/* elo_validate_key */
148 	efx_lic_v1v2_read_key,			/* elo_read_key */
149 	efx_lic_v1v2_write_key,			/* elo_write_key */
150 	efx_lic_v1v2_delete_key,		/* elo_delete_key */
151 	efx_lic_v1v2_create_partition,		/* elo_create_partition */
152 	efx_lic_v1v2_finish_partition,		/* elo_finish_partition */
153 };
154 
155 #endif	/* EFSYS_OPT_SIENA */
156 
157 #if EFSYS_OPT_HUNTINGTON
158 
159 static	__checkReturn	efx_rc_t
160 efx_mcdi_licensing_update_licenses(
161 	__in		efx_nic_t *enp);
162 
163 static	__checkReturn	efx_rc_t
164 efx_mcdi_licensing_get_key_stats(
165 	__in		efx_nic_t *enp,
166 	__out		efx_key_stats_t *eksp);
167 
168 static	__checkReturn	efx_rc_t
169 efx_mcdi_licensed_app_state(
170 	__in		efx_nic_t *enp,
171 	__in		uint64_t app_id,
172 	__out		boolean_t *licensedp);
173 
174 static const efx_lic_ops_t	__efx_lic_v2_ops = {
175 	efx_mcdi_licensing_update_licenses,	/* elo_update_licenses */
176 	efx_mcdi_licensing_get_key_stats,	/* elo_get_key_stats */
177 	efx_mcdi_licensed_app_state,		/* elo_app_state */
178 	NULL,					/* elo_get_id */
179 	efx_lic_v1v2_find_start,		/* elo_find_start */
180 	efx_lic_v1v2_find_end,			/* elo_find_end */
181 	efx_lic_v1v2_find_key,			/* elo_find_key */
182 	efx_lic_v1v2_validate_key,		/* elo_validate_key */
183 	efx_lic_v1v2_read_key,			/* elo_read_key */
184 	efx_lic_v1v2_write_key,			/* elo_write_key */
185 	efx_lic_v1v2_delete_key,		/* elo_delete_key */
186 	efx_lic_v1v2_create_partition,		/* elo_create_partition */
187 	efx_lic_v1v2_finish_partition,		/* elo_finish_partition */
188 };
189 
190 #endif	/* EFSYS_OPT_HUNTINGTON */
191 
192 #if EFSYS_OPT_MEDFORD || EFSYS_OPT_MEDFORD2
193 
194 static	__checkReturn	efx_rc_t
195 efx_mcdi_licensing_v3_update_licenses(
196 	__in		efx_nic_t *enp);
197 
198 static	__checkReturn	efx_rc_t
199 efx_mcdi_licensing_v3_report_license(
200 	__in		efx_nic_t *enp,
201 	__out		efx_key_stats_t *eksp);
202 
203 static	__checkReturn	efx_rc_t
204 efx_mcdi_licensing_v3_app_state(
205 	__in		efx_nic_t *enp,
206 	__in		uint64_t app_id,
207 	__out		boolean_t *licensedp);
208 
209 static	__checkReturn	efx_rc_t
210 efx_mcdi_licensing_v3_get_id(
211 	__in		efx_nic_t *enp,
212 	__in		size_t buffer_size,
213 	__out		uint32_t *typep,
214 	__out		size_t *lengthp,
215 	__out_bcount_part_opt(buffer_size, *lengthp)
216 			uint8_t *bufferp);
217 
218 	__checkReturn		efx_rc_t
219 efx_lic_v3_find_start(
220 	__in			efx_nic_t *enp,
221 	__in_bcount(buffer_size)
222 				caddr_t bufferp,
223 	__in			size_t buffer_size,
224 	__out			uint32_t *startp);
225 
226 	__checkReturn		efx_rc_t
227 efx_lic_v3_find_end(
228 	__in			efx_nic_t *enp,
229 	__in_bcount(buffer_size)
230 				caddr_t bufferp,
231 	__in			size_t buffer_size,
232 	__in			uint32_t offset,
233 	__out			uint32_t *endp);
234 
235 	__checkReturn	__success(return != B_FALSE)	boolean_t
236 efx_lic_v3_find_key(
237 	__in			efx_nic_t *enp,
238 	__in_bcount(buffer_size)
239 				caddr_t bufferp,
240 	__in			size_t buffer_size,
241 	__in			uint32_t offset,
242 	__out			uint32_t *startp,
243 	__out			uint32_t *lengthp);
244 
245 	__checkReturn	__success(return != B_FALSE)	boolean_t
246 efx_lic_v3_validate_key(
247 	__in			efx_nic_t *enp,
248 	__in_bcount(length)	caddr_t keyp,
249 	__in			uint32_t length);
250 
251 	__checkReturn		efx_rc_t
252 efx_lic_v3_read_key(
253 	__in			efx_nic_t *enp,
254 	__in_bcount(buffer_size)
255 				caddr_t bufferp,
256 	__in			size_t buffer_size,
257 	__in			uint32_t offset,
258 	__in			uint32_t length,
259 	__out_bcount_part(key_max_size, *lengthp)
260 				caddr_t keyp,
261 	__in			size_t key_max_size,
262 	__out			uint32_t *lengthp);
263 
264 	__checkReturn		efx_rc_t
265 efx_lic_v3_write_key(
266 	__in			efx_nic_t *enp,
267 	__in_bcount(buffer_size)
268 				caddr_t bufferp,
269 	__in			size_t buffer_size,
270 	__in			uint32_t offset,
271 	__in_bcount(length)	caddr_t keyp,
272 	__in			uint32_t length,
273 	__out			uint32_t *lengthp);
274 
275 	__checkReturn		efx_rc_t
276 efx_lic_v3_delete_key(
277 	__in			efx_nic_t *enp,
278 	__in_bcount(buffer_size)
279 				caddr_t bufferp,
280 	__in			size_t buffer_size,
281 	__in			uint32_t offset,
282 	__in			uint32_t length,
283 	__in			uint32_t end,
284 	__out			uint32_t *deltap);
285 
286 	__checkReturn		efx_rc_t
287 efx_lic_v3_create_partition(
288 	__in			efx_nic_t *enp,
289 	__in_bcount(buffer_size)
290 				caddr_t bufferp,
291 	__in			size_t buffer_size);
292 
293 	__checkReturn		efx_rc_t
294 efx_lic_v3_finish_partition(
295 	__in			efx_nic_t *enp,
296 	__in_bcount(buffer_size)
297 				caddr_t bufferp,
298 	__in			size_t buffer_size);
299 
300 static const efx_lic_ops_t	__efx_lic_v3_ops = {
301 	efx_mcdi_licensing_v3_update_licenses,	/* elo_update_licenses */
302 	efx_mcdi_licensing_v3_report_license,	/* elo_get_key_stats */
303 	efx_mcdi_licensing_v3_app_state,	/* elo_app_state */
304 	efx_mcdi_licensing_v3_get_id,		/* elo_get_id */
305 	efx_lic_v3_find_start,			/* elo_find_start */
306 	efx_lic_v3_find_end,			/* elo_find_end */
307 	efx_lic_v3_find_key,			/* elo_find_key */
308 	efx_lic_v3_validate_key,		/* elo_validate_key */
309 	efx_lic_v3_read_key,			/* elo_read_key */
310 	efx_lic_v3_write_key,			/* elo_write_key */
311 	efx_lic_v3_delete_key,			/* elo_delete_key */
312 	efx_lic_v3_create_partition,		/* elo_create_partition */
313 	efx_lic_v3_finish_partition,		/* elo_finish_partition */
314 };
315 
316 #endif	/* EFSYS_OPT_MEDFORD || EFSYS_OPT_MEDFORD2 */
317 
318 /* V1 Licensing - used in Siena Modena only */
319 
320 #if EFSYS_OPT_SIENA
321 
322 static	__checkReturn	efx_rc_t
323 efx_mcdi_fc_license_update_license(
324 	__in		efx_nic_t *enp)
325 {
326 	efx_mcdi_req_t req;
327 	EFX_MCDI_DECLARE_BUF(payload, MC_CMD_FC_IN_LICENSE_LEN, 0);
328 	efx_rc_t rc;
329 
330 	EFSYS_ASSERT(enp->en_family == EFX_FAMILY_SIENA);
331 
332 	req.emr_cmd = MC_CMD_FC;
333 	req.emr_in_buf = payload;
334 	req.emr_in_length = MC_CMD_FC_IN_LICENSE_LEN;
335 	req.emr_out_buf = payload;
336 	req.emr_out_length = 0;
337 
338 	MCDI_IN_SET_DWORD(req, FC_IN_CMD,
339 	    MC_CMD_FC_OP_LICENSE);
340 
341 	MCDI_IN_SET_DWORD(req, FC_IN_LICENSE_OP,
342 	    MC_CMD_FC_IN_LICENSE_UPDATE_LICENSE);
343 
344 	efx_mcdi_execute(enp, &req);
345 
346 	if (req.emr_rc != 0) {
347 		rc = req.emr_rc;
348 		goto fail1;
349 	}
350 
351 	if (req.emr_out_length_used != 0) {
352 		rc = EIO;
353 		goto fail2;
354 	}
355 
356 	return (0);
357 
358 fail2:
359 	EFSYS_PROBE(fail2);
360 fail1:
361 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
362 
363 	return (rc);
364 }
365 
366 static	__checkReturn	efx_rc_t
367 efx_mcdi_fc_license_get_key_stats(
368 	__in		efx_nic_t *enp,
369 	__out		efx_key_stats_t *eksp)
370 {
371 	efx_mcdi_req_t req;
372 	EFX_MCDI_DECLARE_BUF(payload, MC_CMD_FC_IN_LICENSE_LEN,
373 		MC_CMD_FC_OUT_LICENSE_LEN);
374 	efx_rc_t rc;
375 
376 	EFSYS_ASSERT(enp->en_family == EFX_FAMILY_SIENA);
377 
378 	req.emr_cmd = MC_CMD_FC;
379 	req.emr_in_buf = payload;
380 	req.emr_in_length = MC_CMD_FC_IN_LICENSE_LEN;
381 	req.emr_out_buf = payload;
382 	req.emr_out_length = MC_CMD_FC_OUT_LICENSE_LEN;
383 
384 	MCDI_IN_SET_DWORD(req, FC_IN_CMD,
385 	    MC_CMD_FC_OP_LICENSE);
386 
387 	MCDI_IN_SET_DWORD(req, FC_IN_LICENSE_OP,
388 	    MC_CMD_FC_IN_LICENSE_GET_KEY_STATS);
389 
390 	efx_mcdi_execute_quiet(enp, &req);
391 
392 	if (req.emr_rc != 0) {
393 		rc = req.emr_rc;
394 		goto fail1;
395 	}
396 
397 	if (req.emr_out_length_used < MC_CMD_FC_OUT_LICENSE_LEN) {
398 		rc = EMSGSIZE;
399 		goto fail2;
400 	}
401 
402 	eksp->eks_valid =
403 		MCDI_OUT_DWORD(req, FC_OUT_LICENSE_VALID_KEYS);
404 	eksp->eks_invalid =
405 		MCDI_OUT_DWORD(req, FC_OUT_LICENSE_INVALID_KEYS);
406 	eksp->eks_blacklisted =
407 		MCDI_OUT_DWORD(req, FC_OUT_LICENSE_BLACKLISTED_KEYS);
408 	eksp->eks_unverifiable = 0;
409 	eksp->eks_wrong_node = 0;
410 	eksp->eks_licensed_apps_lo = 0;
411 	eksp->eks_licensed_apps_hi = 0;
412 	eksp->eks_licensed_features_lo = 0;
413 	eksp->eks_licensed_features_hi = 0;
414 
415 	return (0);
416 
417 fail2:
418 	EFSYS_PROBE(fail2);
419 fail1:
420 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
421 
422 	return (rc);
423 }
424 
425 #endif	/* EFSYS_OPT_SIENA */
426 
427 /* V1 and V2 Partition format - based on a 16-bit TLV format */
428 
429 #if EFSYS_OPT_SIENA | EFSYS_OPT_HUNTINGTON
430 
431 /*
432  * V1/V2 format - defined in SF-108542-TC section 4.2:
433  *  Type (T):   16bit - revision/HMAC algorithm
434  *  Length (L): 16bit - value length in bytes
435  *  Value (V):  L bytes - payload
436  */
437 #define	EFX_LICENSE_V1V2_PAYLOAD_LENGTH_MAX	(256)
438 #define	EFX_LICENSE_V1V2_HEADER_LENGTH		(2 * sizeof (uint16_t))
439 
440 	__checkReturn		efx_rc_t
441 efx_lic_v1v2_find_start(
442 	__in			efx_nic_t *enp,
443 	__in_bcount(buffer_size)
444 				caddr_t bufferp,
445 	__in			size_t buffer_size,
446 	__out			uint32_t *startp)
447 {
448 	_NOTE(ARGUNUSED(enp, bufferp, buffer_size))
449 
450 	*startp = 0;
451 	return (0);
452 }
453 
454 	__checkReturn		efx_rc_t
455 efx_lic_v1v2_find_end(
456 	__in			efx_nic_t *enp,
457 	__in_bcount(buffer_size)
458 				caddr_t bufferp,
459 	__in			size_t buffer_size,
460 	__in			uint32_t offset,
461 	__out			uint32_t *endp)
462 {
463 	_NOTE(ARGUNUSED(enp, bufferp, buffer_size))
464 
465 	*endp = offset + EFX_LICENSE_V1V2_HEADER_LENGTH;
466 	return (0);
467 }
468 
469 	__checkReturn	__success(return != B_FALSE)	boolean_t
470 efx_lic_v1v2_find_key(
471 	__in			efx_nic_t *enp,
472 	__in_bcount(buffer_size)
473 				caddr_t bufferp,
474 	__in			size_t buffer_size,
475 	__in			uint32_t offset,
476 	__out			uint32_t *startp,
477 	__out			uint32_t *lengthp)
478 {
479 	boolean_t found;
480 	uint16_t tlv_type;
481 	uint16_t tlv_length;
482 
483 	_NOTE(ARGUNUSED(enp))
484 
485 	if ((size_t)buffer_size - offset < EFX_LICENSE_V1V2_HEADER_LENGTH)
486 		goto fail1;
487 
488 	tlv_type = __LE_TO_CPU_16(((uint16_t *)&bufferp[offset])[0]);
489 	tlv_length = __LE_TO_CPU_16(((uint16_t *)&bufferp[offset])[1]);
490 	if ((tlv_length > EFX_LICENSE_V1V2_PAYLOAD_LENGTH_MAX) ||
491 	    (tlv_type == 0 && tlv_length == 0)) {
492 		found = B_FALSE;
493 	} else {
494 		*startp = offset;
495 		*lengthp = tlv_length + EFX_LICENSE_V1V2_HEADER_LENGTH;
496 		found = B_TRUE;
497 	}
498 	return (found);
499 
500 fail1:
501 	EFSYS_PROBE1(fail1, boolean_t, B_FALSE);
502 
503 	return (B_FALSE);
504 }
505 
506 	__checkReturn	__success(return != B_FALSE)	boolean_t
507 efx_lic_v1v2_validate_key(
508 	__in			efx_nic_t *enp,
509 	__in_bcount(length)	caddr_t keyp,
510 	__in			uint32_t length)
511 {
512 	uint16_t tlv_type;
513 	uint16_t tlv_length;
514 
515 	_NOTE(ARGUNUSED(enp))
516 
517 	if (length < EFX_LICENSE_V1V2_HEADER_LENGTH) {
518 		goto fail1;
519 	}
520 
521 	tlv_type = __LE_TO_CPU_16(((uint16_t *)keyp)[0]);
522 	tlv_length = __LE_TO_CPU_16(((uint16_t *)keyp)[1]);
523 
524 	if (tlv_length > EFX_LICENSE_V1V2_PAYLOAD_LENGTH_MAX) {
525 		goto fail2;
526 	}
527 	if (tlv_type == 0) {
528 		goto fail3;
529 	}
530 	if ((tlv_length + EFX_LICENSE_V1V2_HEADER_LENGTH) != length) {
531 		goto fail4;
532 	}
533 
534 	return (B_TRUE);
535 
536 fail4:
537 	EFSYS_PROBE(fail4);
538 fail3:
539 	EFSYS_PROBE(fail3);
540 fail2:
541 	EFSYS_PROBE(fail2);
542 fail1:
543 	EFSYS_PROBE1(fail1, boolean_t, B_FALSE);
544 
545 	return (B_FALSE);
546 }
547 
548 	__checkReturn		efx_rc_t
549 efx_lic_v1v2_read_key(
550 	__in			efx_nic_t *enp,
551 	__in_bcount(buffer_size)
552 				caddr_t bufferp,
553 	__in			size_t buffer_size,
554 	__in			uint32_t offset,
555 	__in			uint32_t length,
556 	__out_bcount_part(key_max_size, *lengthp)
557 				caddr_t keyp,
558 	__in			size_t key_max_size,
559 	__out			uint32_t *lengthp)
560 {
561 	efx_rc_t rc;
562 
563 	_NOTE(ARGUNUSED(enp, buffer_size))
564 	EFSYS_ASSERT(length <= (EFX_LICENSE_V1V2_PAYLOAD_LENGTH_MAX +
565 	    EFX_LICENSE_V1V2_HEADER_LENGTH));
566 
567 	if (key_max_size < length) {
568 		rc = ENOSPC;
569 		goto fail1;
570 	}
571 	memcpy(keyp, &bufferp[offset], length);
572 
573 	*lengthp = length;
574 
575 	return (0);
576 
577 fail1:
578 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
579 
580 	return (rc);
581 }
582 
583 	__checkReturn		efx_rc_t
584 efx_lic_v1v2_write_key(
585 	__in			efx_nic_t *enp,
586 	__in_bcount(buffer_size)
587 				caddr_t bufferp,
588 	__in			size_t buffer_size,
589 	__in			uint32_t offset,
590 	__in_bcount(length)	caddr_t keyp,
591 	__in			uint32_t length,
592 	__out			uint32_t *lengthp)
593 {
594 	efx_rc_t rc;
595 
596 	_NOTE(ARGUNUSED(enp))
597 	EFSYS_ASSERT(length <= (EFX_LICENSE_V1V2_PAYLOAD_LENGTH_MAX +
598 	    EFX_LICENSE_V1V2_HEADER_LENGTH));
599 
600 	/* Ensure space for terminator remains */
601 	if ((offset + length) >
602 	    (buffer_size - EFX_LICENSE_V1V2_HEADER_LENGTH)) {
603 		rc = ENOSPC;
604 		goto fail1;
605 	}
606 
607 	memcpy(bufferp + offset, keyp, length);
608 
609 	*lengthp = length;
610 
611 	return (0);
612 
613 fail1:
614 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
615 
616 	return (rc);
617 }
618 
619 	__checkReturn		efx_rc_t
620 efx_lic_v1v2_delete_key(
621 	__in			efx_nic_t *enp,
622 	__in_bcount(buffer_size)
623 				caddr_t bufferp,
624 	__in			size_t buffer_size,
625 	__in			uint32_t offset,
626 	__in			uint32_t length,
627 	__in			uint32_t end,
628 	__out			uint32_t *deltap)
629 {
630 	uint32_t move_start = offset + length;
631 	uint32_t move_length = end - move_start;
632 
633 	_NOTE(ARGUNUSED(enp, buffer_size))
634 	EFSYS_ASSERT(end <= buffer_size);
635 
636 	/* Shift everything after the key down */
637 	memmove(bufferp + offset, bufferp + move_start, move_length);
638 
639 	*deltap = length;
640 
641 	return (0);
642 }
643 
644 	__checkReturn		efx_rc_t
645 efx_lic_v1v2_create_partition(
646 	__in			efx_nic_t *enp,
647 	__in_bcount(buffer_size)
648 				caddr_t bufferp,
649 	__in			size_t buffer_size)
650 {
651 	_NOTE(ARGUNUSED(enp, buffer_size))
652 	EFSYS_ASSERT(EFX_LICENSE_V1V2_HEADER_LENGTH <= buffer_size);
653 
654 	/* Write terminator */
655 	memset(bufferp, '\0', EFX_LICENSE_V1V2_HEADER_LENGTH);
656 	return (0);
657 }
658 
659 	__checkReturn		efx_rc_t
660 efx_lic_v1v2_finish_partition(
661 	__in			efx_nic_t *enp,
662 	__in_bcount(buffer_size)
663 				caddr_t bufferp,
664 	__in			size_t buffer_size)
665 {
666 	_NOTE(ARGUNUSED(enp, bufferp, buffer_size))
667 
668 	return (0);
669 }
670 
671 #endif	/* EFSYS_OPT_HUNTINGTON | EFSYS_OPT_SIENA */
672 
673 /* V2 Licensing - used by Huntington family only. See SF-113611-TC */
674 
675 #if EFSYS_OPT_HUNTINGTON
676 
677 static	__checkReturn	efx_rc_t
678 efx_mcdi_licensed_app_state(
679 	__in		efx_nic_t *enp,
680 	__in		uint64_t app_id,
681 	__out		boolean_t *licensedp)
682 {
683 	efx_mcdi_req_t req;
684 	EFX_MCDI_DECLARE_BUF(payload, MC_CMD_GET_LICENSED_APP_STATE_IN_LEN,
685 		MC_CMD_GET_LICENSED_APP_STATE_OUT_LEN);
686 	uint32_t app_state;
687 	efx_rc_t rc;
688 
689 	EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON);
690 
691 	/* V2 licensing supports 32bit app id only */
692 	if ((app_id >> 32) != 0) {
693 		rc = EINVAL;
694 		goto fail1;
695 	}
696 
697 	req.emr_cmd = MC_CMD_GET_LICENSED_APP_STATE;
698 	req.emr_in_buf = payload;
699 	req.emr_in_length = MC_CMD_GET_LICENSED_APP_STATE_IN_LEN;
700 	req.emr_out_buf = payload;
701 	req.emr_out_length = MC_CMD_GET_LICENSED_APP_STATE_OUT_LEN;
702 
703 	MCDI_IN_SET_DWORD(req, GET_LICENSED_APP_STATE_IN_APP_ID,
704 		    app_id & 0xffffffff);
705 
706 	efx_mcdi_execute(enp, &req);
707 
708 	if (req.emr_rc != 0) {
709 		rc = req.emr_rc;
710 		goto fail2;
711 	}
712 
713 	if (req.emr_out_length_used < MC_CMD_GET_LICENSED_APP_STATE_OUT_LEN) {
714 		rc = EMSGSIZE;
715 		goto fail3;
716 	}
717 
718 	app_state = (MCDI_OUT_DWORD(req, GET_LICENSED_APP_STATE_OUT_STATE));
719 	if (app_state != MC_CMD_GET_LICENSED_APP_STATE_OUT_NOT_LICENSED) {
720 		*licensedp = B_TRUE;
721 	} else {
722 		*licensedp = B_FALSE;
723 	}
724 
725 	return (0);
726 
727 fail3:
728 	EFSYS_PROBE(fail3);
729 fail2:
730 	EFSYS_PROBE(fail2);
731 fail1:
732 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
733 
734 	return (rc);
735 }
736 
737 static	__checkReturn	efx_rc_t
738 efx_mcdi_licensing_update_licenses(
739 	__in		efx_nic_t *enp)
740 {
741 	efx_mcdi_req_t req;
742 	EFX_MCDI_DECLARE_BUF(payload, MC_CMD_LICENSING_IN_LEN, 0);
743 	efx_rc_t rc;
744 
745 	EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON);
746 
747 	req.emr_cmd = MC_CMD_LICENSING;
748 	req.emr_in_buf = payload;
749 	req.emr_in_length = MC_CMD_LICENSING_IN_LEN;
750 	req.emr_out_buf = payload;
751 	req.emr_out_length = 0;
752 
753 	MCDI_IN_SET_DWORD(req, LICENSING_IN_OP,
754 	    MC_CMD_LICENSING_IN_OP_UPDATE_LICENSE);
755 
756 	efx_mcdi_execute(enp, &req);
757 
758 	if (req.emr_rc != 0) {
759 		rc = req.emr_rc;
760 		goto fail1;
761 	}
762 
763 	if (req.emr_out_length_used != 0) {
764 		rc = EIO;
765 		goto fail2;
766 	}
767 
768 	return (0);
769 
770 fail2:
771 	EFSYS_PROBE(fail2);
772 fail1:
773 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
774 
775 	return (rc);
776 }
777 
778 static	__checkReturn	efx_rc_t
779 efx_mcdi_licensing_get_key_stats(
780 	__in		efx_nic_t *enp,
781 	__out		efx_key_stats_t *eksp)
782 {
783 	efx_mcdi_req_t req;
784 	EFX_MCDI_DECLARE_BUF(payload, MC_CMD_LICENSING_IN_LEN,
785 		MC_CMD_LICENSING_OUT_LEN);
786 	efx_rc_t rc;
787 
788 	EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON);
789 
790 	req.emr_cmd = MC_CMD_LICENSING;
791 	req.emr_in_buf = payload;
792 	req.emr_in_length = MC_CMD_LICENSING_IN_LEN;
793 	req.emr_out_buf = payload;
794 	req.emr_out_length = MC_CMD_LICENSING_OUT_LEN;
795 
796 	MCDI_IN_SET_DWORD(req, LICENSING_IN_OP,
797 	    MC_CMD_LICENSING_IN_OP_GET_KEY_STATS);
798 
799 	efx_mcdi_execute(enp, &req);
800 
801 	if (req.emr_rc != 0) {
802 		rc = req.emr_rc;
803 		goto fail1;
804 	}
805 
806 	if (req.emr_out_length_used < MC_CMD_LICENSING_OUT_LEN) {
807 		rc = EMSGSIZE;
808 		goto fail2;
809 	}
810 
811 	eksp->eks_valid =
812 		MCDI_OUT_DWORD(req, LICENSING_OUT_VALID_APP_KEYS);
813 	eksp->eks_invalid =
814 		MCDI_OUT_DWORD(req, LICENSING_OUT_INVALID_APP_KEYS);
815 	eksp->eks_blacklisted =
816 		MCDI_OUT_DWORD(req, LICENSING_OUT_BLACKLISTED_APP_KEYS);
817 	eksp->eks_unverifiable =
818 		MCDI_OUT_DWORD(req, LICENSING_OUT_UNVERIFIABLE_APP_KEYS);
819 	eksp->eks_wrong_node =
820 		MCDI_OUT_DWORD(req, LICENSING_OUT_WRONG_NODE_APP_KEYS);
821 	eksp->eks_licensed_apps_lo = 0;
822 	eksp->eks_licensed_apps_hi = 0;
823 	eksp->eks_licensed_features_lo = 0;
824 	eksp->eks_licensed_features_hi = 0;
825 
826 	return (0);
827 
828 fail2:
829 	EFSYS_PROBE(fail2);
830 fail1:
831 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
832 
833 	return (rc);
834 }
835 
836 #endif	/* EFSYS_OPT_HUNTINGTON */
837 
838 /* V3 Licensing - used starting from Medford family. See SF-114884-SW */
839 
840 #if EFSYS_OPT_MEDFORD || EFSYS_OPT_MEDFORD2
841 
842 static	__checkReturn	efx_rc_t
843 efx_mcdi_licensing_v3_update_licenses(
844 	__in		efx_nic_t *enp)
845 {
846 	efx_mcdi_req_t req;
847 	EFX_MCDI_DECLARE_BUF(payload, MC_CMD_LICENSING_V3_IN_LEN, 0);
848 	efx_rc_t rc;
849 
850 	EFSYS_ASSERT((enp->en_family == EFX_FAMILY_MEDFORD) ||
851 	    (enp->en_family == EFX_FAMILY_MEDFORD2));
852 
853 	req.emr_cmd = MC_CMD_LICENSING_V3;
854 	req.emr_in_buf = payload;
855 	req.emr_in_length = MC_CMD_LICENSING_V3_IN_LEN;
856 	req.emr_out_buf = NULL;
857 	req.emr_out_length = 0;
858 
859 	MCDI_IN_SET_DWORD(req, LICENSING_V3_IN_OP,
860 	    MC_CMD_LICENSING_V3_IN_OP_UPDATE_LICENSE);
861 
862 	efx_mcdi_execute(enp, &req);
863 
864 	if (req.emr_rc != 0) {
865 		rc = req.emr_rc;
866 		goto fail1;
867 	}
868 
869 	return (0);
870 
871 fail1:
872 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
873 
874 	return (rc);
875 }
876 
877 static	__checkReturn	efx_rc_t
878 efx_mcdi_licensing_v3_report_license(
879 	__in		efx_nic_t *enp,
880 	__out		efx_key_stats_t *eksp)
881 {
882 	efx_mcdi_req_t req;
883 	EFX_MCDI_DECLARE_BUF(payload, MC_CMD_LICENSING_V3_IN_LEN,
884 		MC_CMD_LICENSING_V3_OUT_LEN);
885 	efx_rc_t rc;
886 
887 	EFSYS_ASSERT((enp->en_family == EFX_FAMILY_MEDFORD) ||
888 	    (enp->en_family == EFX_FAMILY_MEDFORD2));
889 
890 	req.emr_cmd = MC_CMD_LICENSING_V3;
891 	req.emr_in_buf = payload;
892 	req.emr_in_length = MC_CMD_LICENSING_V3_IN_LEN;
893 	req.emr_out_buf = payload;
894 	req.emr_out_length = MC_CMD_LICENSING_V3_OUT_LEN;
895 
896 	MCDI_IN_SET_DWORD(req, LICENSING_V3_IN_OP,
897 	    MC_CMD_LICENSING_V3_IN_OP_REPORT_LICENSE);
898 
899 	efx_mcdi_execute_quiet(enp, &req);
900 
901 	if (req.emr_rc != 0) {
902 		rc = req.emr_rc;
903 		goto fail1;
904 	}
905 
906 	if (req.emr_out_length_used < MC_CMD_LICENSING_V3_OUT_LEN) {
907 		rc = EMSGSIZE;
908 		goto fail2;
909 	}
910 
911 	eksp->eks_valid =
912 		MCDI_OUT_DWORD(req, LICENSING_V3_OUT_VALID_KEYS);
913 	eksp->eks_invalid =
914 		MCDI_OUT_DWORD(req, LICENSING_V3_OUT_INVALID_KEYS);
915 	eksp->eks_blacklisted = 0;
916 	eksp->eks_unverifiable =
917 		MCDI_OUT_DWORD(req, LICENSING_V3_OUT_UNVERIFIABLE_KEYS);
918 	eksp->eks_wrong_node =
919 		MCDI_OUT_DWORD(req, LICENSING_V3_OUT_WRONG_NODE_KEYS);
920 	eksp->eks_licensed_apps_lo =
921 		MCDI_OUT_DWORD(req, LICENSING_V3_OUT_LICENSED_APPS_LO);
922 	eksp->eks_licensed_apps_hi =
923 		MCDI_OUT_DWORD(req, LICENSING_V3_OUT_LICENSED_APPS_HI);
924 	eksp->eks_licensed_features_lo =
925 		MCDI_OUT_DWORD(req, LICENSING_V3_OUT_LICENSED_FEATURES_LO);
926 	eksp->eks_licensed_features_hi =
927 		MCDI_OUT_DWORD(req, LICENSING_V3_OUT_LICENSED_FEATURES_HI);
928 
929 	return (0);
930 
931 fail2:
932 	EFSYS_PROBE(fail2);
933 fail1:
934 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
935 
936 	return (rc);
937 }
938 
939 static	__checkReturn	efx_rc_t
940 efx_mcdi_licensing_v3_app_state(
941 	__in		efx_nic_t *enp,
942 	__in		uint64_t app_id,
943 	__out		boolean_t *licensedp)
944 {
945 	efx_mcdi_req_t req;
946 	EFX_MCDI_DECLARE_BUF(payload, MC_CMD_GET_LICENSED_V3_APP_STATE_IN_LEN,
947 		MC_CMD_GET_LICENSED_V3_APP_STATE_OUT_LEN);
948 	uint32_t app_state;
949 	efx_rc_t rc;
950 
951 	EFSYS_ASSERT((enp->en_family == EFX_FAMILY_MEDFORD) ||
952 	    (enp->en_family == EFX_FAMILY_MEDFORD2));
953 
954 	req.emr_cmd = MC_CMD_GET_LICENSED_V3_APP_STATE;
955 	req.emr_in_buf = payload;
956 	req.emr_in_length = MC_CMD_GET_LICENSED_V3_APP_STATE_IN_LEN;
957 	req.emr_out_buf = payload;
958 	req.emr_out_length = MC_CMD_GET_LICENSED_V3_APP_STATE_OUT_LEN;
959 
960 	MCDI_IN_SET_DWORD(req, GET_LICENSED_V3_APP_STATE_IN_APP_ID_LO,
961 		    app_id & 0xffffffff);
962 	MCDI_IN_SET_DWORD(req, GET_LICENSED_V3_APP_STATE_IN_APP_ID_HI,
963 		    app_id >> 32);
964 
965 	efx_mcdi_execute(enp, &req);
966 
967 	if (req.emr_rc != 0) {
968 		rc = req.emr_rc;
969 		goto fail1;
970 	}
971 
972 	if (req.emr_out_length_used <
973 	    MC_CMD_GET_LICENSED_V3_APP_STATE_OUT_LEN) {
974 		rc = EMSGSIZE;
975 		goto fail2;
976 	}
977 
978 	app_state = (MCDI_OUT_DWORD(req, GET_LICENSED_V3_APP_STATE_OUT_STATE));
979 	if (app_state != MC_CMD_GET_LICENSED_V3_APP_STATE_OUT_NOT_LICENSED) {
980 		*licensedp = B_TRUE;
981 	} else {
982 		*licensedp = B_FALSE;
983 	}
984 
985 	return (0);
986 
987 fail2:
988 	EFSYS_PROBE(fail2);
989 fail1:
990 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
991 
992 	return (rc);
993 }
994 
995 static	__checkReturn	efx_rc_t
996 efx_mcdi_licensing_v3_get_id(
997 	__in		efx_nic_t *enp,
998 	__in		size_t buffer_size,
999 	__out		uint32_t *typep,
1000 	__out		size_t *lengthp,
1001 	__out_bcount_part_opt(buffer_size, *lengthp)
1002 			uint8_t *bufferp)
1003 {
1004 	efx_mcdi_req_t req;
1005 	EFX_MCDI_DECLARE_BUF(payload, MC_CMD_LICENSING_GET_ID_V3_IN_LEN,
1006 		MC_CMD_LICENSING_GET_ID_V3_OUT_LENMAX);
1007 	efx_rc_t rc;
1008 
1009 	req.emr_cmd = MC_CMD_LICENSING_GET_ID_V3;
1010 	req.emr_in_buf = payload;
1011 	req.emr_in_length = MC_CMD_LICENSING_GET_ID_V3_IN_LEN;
1012 	req.emr_out_buf = payload;
1013 	req.emr_out_length = MC_CMD_LICENSING_GET_ID_V3_OUT_LENMAX;
1014 
1015 	efx_mcdi_execute_quiet(enp, &req);
1016 
1017 	if (req.emr_rc != 0) {
1018 		rc = req.emr_rc;
1019 		goto fail1;
1020 	}
1021 
1022 	if (req.emr_out_length_used < MC_CMD_LICENSING_GET_ID_V3_OUT_LENMIN) {
1023 		rc = EMSGSIZE;
1024 		goto fail2;
1025 	}
1026 
1027 	*typep = MCDI_OUT_DWORD(req, LICENSING_GET_ID_V3_OUT_LICENSE_TYPE);
1028 	*lengthp =
1029 	    MCDI_OUT_DWORD(req, LICENSING_GET_ID_V3_OUT_LICENSE_ID_LENGTH);
1030 
1031 	if (bufferp != NULL) {
1032 		memcpy(bufferp,
1033 		    payload + MC_CMD_LICENSING_GET_ID_V3_OUT_LICENSE_ID_OFST,
1034 		    MIN(buffer_size, *lengthp));
1035 	}
1036 
1037 	return (0);
1038 
1039 fail2:
1040 	EFSYS_PROBE(fail2);
1041 fail1:
1042 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
1043 
1044 	return (rc);
1045 }
1046 
1047 /* V3 format uses Huntington TLV format partition. See SF-108797-SW */
1048 #define	EFX_LICENSE_V3_KEY_LENGTH_MIN	(64)
1049 #define	EFX_LICENSE_V3_KEY_LENGTH_MAX	(160)
1050 
1051 	__checkReturn		efx_rc_t
1052 efx_lic_v3_find_start(
1053 	__in			efx_nic_t *enp,
1054 	__in_bcount(buffer_size)
1055 				caddr_t bufferp,
1056 	__in			size_t buffer_size,
1057 	__out			uint32_t *startp)
1058 {
1059 	_NOTE(ARGUNUSED(enp))
1060 
1061 	return (ef10_nvram_buffer_find_item_start(bufferp, buffer_size,
1062 	    startp));
1063 }
1064 
1065 	__checkReturn		efx_rc_t
1066 efx_lic_v3_find_end(
1067 	__in			efx_nic_t *enp,
1068 	__in_bcount(buffer_size)
1069 				caddr_t bufferp,
1070 	__in			size_t buffer_size,
1071 	__in			uint32_t offset,
1072 	__out			uint32_t *endp)
1073 {
1074 	_NOTE(ARGUNUSED(enp))
1075 
1076 	return (ef10_nvram_buffer_find_end(bufferp, buffer_size, offset, endp));
1077 }
1078 
1079 	__checkReturn	__success(return != B_FALSE)	boolean_t
1080 efx_lic_v3_find_key(
1081 	__in			efx_nic_t *enp,
1082 	__in_bcount(buffer_size)
1083 				caddr_t bufferp,
1084 	__in			size_t buffer_size,
1085 	__in			uint32_t offset,
1086 	__out			uint32_t *startp,
1087 	__out			uint32_t *lengthp)
1088 {
1089 	_NOTE(ARGUNUSED(enp))
1090 
1091 	return ef10_nvram_buffer_find_item(bufferp, buffer_size,
1092 	    offset, startp, lengthp);
1093 }
1094 
1095 	__checkReturn	__success(return != B_FALSE)	boolean_t
1096 efx_lic_v3_validate_key(
1097 	__in			efx_nic_t *enp,
1098 	__in_bcount(length)	caddr_t keyp,
1099 	__in			uint32_t length)
1100 {
1101 	/* Check key is a valid V3 key */
1102 	uint8_t key_type;
1103 	uint8_t key_length;
1104 
1105 	_NOTE(ARGUNUSED(enp))
1106 
1107 	if (length < EFX_LICENSE_V3_KEY_LENGTH_MIN) {
1108 		goto fail1;
1109 	}
1110 
1111 	if (length > EFX_LICENSE_V3_KEY_LENGTH_MAX) {
1112 		goto fail2;
1113 	}
1114 
1115 	key_type = ((uint8_t *)keyp)[0];
1116 	key_length = ((uint8_t *)keyp)[1];
1117 
1118 	if (key_type < 3) {
1119 		goto fail3;
1120 	}
1121 	if (key_length > length) {
1122 		goto fail4;
1123 	}
1124 	return (B_TRUE);
1125 
1126 fail4:
1127 	EFSYS_PROBE(fail4);
1128 fail3:
1129 	EFSYS_PROBE(fail3);
1130 fail2:
1131 	EFSYS_PROBE(fail2);
1132 fail1:
1133 	EFSYS_PROBE1(fail1, boolean_t, B_FALSE);
1134 
1135 	return (B_FALSE);
1136 }
1137 
1138 	__checkReturn		efx_rc_t
1139 efx_lic_v3_read_key(
1140 	__in			efx_nic_t *enp,
1141 	__in_bcount(buffer_size)
1142 				caddr_t bufferp,
1143 	__in			size_t buffer_size,
1144 	__in			uint32_t offset,
1145 	__in			uint32_t length,
1146 	__out_bcount_part(key_max_size, *lengthp)
1147 				caddr_t keyp,
1148 	__in			size_t key_max_size,
1149 	__out			uint32_t *lengthp)
1150 {
1151 	uint32_t tag;
1152 
1153 	_NOTE(ARGUNUSED(enp))
1154 
1155 	return ef10_nvram_buffer_get_item(bufferp, buffer_size,
1156 		    offset, length, &tag, keyp, key_max_size, lengthp);
1157 }
1158 
1159 	__checkReturn		efx_rc_t
1160 efx_lic_v3_write_key(
1161 	__in			efx_nic_t *enp,
1162 	__in_bcount(buffer_size)
1163 				caddr_t bufferp,
1164 	__in			size_t buffer_size,
1165 	__in			uint32_t offset,
1166 	__in_bcount(length)	caddr_t keyp,
1167 	__in			uint32_t length,
1168 	__out			uint32_t *lengthp)
1169 {
1170 	_NOTE(ARGUNUSED(enp))
1171 	EFSYS_ASSERT(length <= EFX_LICENSE_V3_KEY_LENGTH_MAX);
1172 
1173 	return ef10_nvram_buffer_insert_item(bufferp, buffer_size,
1174 		    offset, TLV_TAG_LICENSE, keyp, length, lengthp);
1175 }
1176 
1177 	__checkReturn		efx_rc_t
1178 efx_lic_v3_delete_key(
1179 	__in			efx_nic_t *enp,
1180 	__in_bcount(buffer_size)
1181 				caddr_t bufferp,
1182 	__in			size_t buffer_size,
1183 	__in			uint32_t offset,
1184 	__in			uint32_t length,
1185 	__in			uint32_t end,
1186 	__out			uint32_t *deltap)
1187 {
1188 	efx_rc_t rc;
1189 
1190 	_NOTE(ARGUNUSED(enp))
1191 
1192 	if ((rc = ef10_nvram_buffer_delete_item(bufferp,
1193 			buffer_size, offset, length, end)) != 0) {
1194 		goto fail1;
1195 	}
1196 
1197 	*deltap = length;
1198 
1199 	return (0);
1200 
1201 fail1:
1202 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
1203 
1204 	return (rc);
1205 }
1206 
1207 	__checkReturn		efx_rc_t
1208 efx_lic_v3_create_partition(
1209 	__in			efx_nic_t *enp,
1210 	__in_bcount(buffer_size)
1211 				caddr_t bufferp,
1212 	__in			size_t buffer_size)
1213 {
1214 	efx_rc_t rc;
1215 
1216 	_NOTE(ARGUNUSED(enp))
1217 
1218 	/* Construct empty partition */
1219 	if ((rc = ef10_nvram_buffer_create(
1220 	    NVRAM_PARTITION_TYPE_LICENSE,
1221 	    bufferp, buffer_size)) != 0) {
1222 		rc = EFAULT;
1223 		goto fail1;
1224 	}
1225 
1226 	return (0);
1227 
1228 fail1:
1229 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
1230 
1231 	return (rc);
1232 }
1233 
1234 	__checkReturn		efx_rc_t
1235 efx_lic_v3_finish_partition(
1236 	__in			efx_nic_t *enp,
1237 	__in_bcount(buffer_size)
1238 				caddr_t bufferp,
1239 	__in			size_t buffer_size)
1240 {
1241 	efx_rc_t rc;
1242 
1243 	_NOTE(ARGUNUSED(enp))
1244 
1245 	if ((rc = ef10_nvram_buffer_finish(bufferp,
1246 			buffer_size)) != 0) {
1247 		goto fail1;
1248 	}
1249 
1250 	/* Validate completed partition */
1251 	if ((rc = ef10_nvram_buffer_validate(
1252 					NVRAM_PARTITION_TYPE_LICENSE,
1253 					bufferp, buffer_size)) != 0) {
1254 		goto fail2;
1255 	}
1256 
1257 	return (0);
1258 
1259 fail2:
1260 	EFSYS_PROBE(fail2);
1261 fail1:
1262 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
1263 
1264 	return (rc);
1265 }
1266 
1267 #endif	/* EFSYS_OPT_MEDFORD || EFSYS_OPT_MEDFORD2 */
1268 
1269 	__checkReturn		efx_rc_t
1270 efx_lic_init(
1271 	__in			efx_nic_t *enp)
1272 {
1273 	const efx_lic_ops_t *elop;
1274 	efx_key_stats_t eks;
1275 	efx_rc_t rc;
1276 
1277 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1278 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
1279 	EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_LIC));
1280 
1281 	switch (enp->en_family) {
1282 #if EFSYS_OPT_SIENA
1283 	case EFX_FAMILY_SIENA:
1284 		elop = &__efx_lic_v1_ops;
1285 		break;
1286 #endif	/* EFSYS_OPT_SIENA */
1287 
1288 #if EFSYS_OPT_HUNTINGTON
1289 	case EFX_FAMILY_HUNTINGTON:
1290 		elop = &__efx_lic_v2_ops;
1291 		break;
1292 #endif	/* EFSYS_OPT_HUNTINGTON */
1293 
1294 #if EFSYS_OPT_MEDFORD
1295 	case EFX_FAMILY_MEDFORD:
1296 		elop = &__efx_lic_v3_ops;
1297 		break;
1298 #endif	/* EFSYS_OPT_MEDFORD */
1299 
1300 #if EFSYS_OPT_MEDFORD2
1301 	case EFX_FAMILY_MEDFORD2:
1302 		elop = &__efx_lic_v3_ops;
1303 		break;
1304 #endif	/* EFSYS_OPT_MEDFORD2 */
1305 
1306 	default:
1307 		EFSYS_ASSERT(0);
1308 		rc = ENOTSUP;
1309 		goto fail1;
1310 	}
1311 
1312 	enp->en_elop = elop;
1313 	enp->en_mod_flags |= EFX_MOD_LIC;
1314 
1315 	/* Probe for support */
1316 	if (efx_lic_get_key_stats(enp, &eks) == 0) {
1317 		enp->en_licensing_supported = B_TRUE;
1318 	} else {
1319 		enp->en_licensing_supported = B_FALSE;
1320 	}
1321 
1322 	return (0);
1323 
1324 fail1:
1325 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
1326 
1327 	return (rc);
1328 }
1329 
1330 extern	__checkReturn	boolean_t
1331 efx_lic_check_support(
1332 	__in			efx_nic_t *enp)
1333 {
1334 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1335 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
1336 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1337 
1338 	return (enp->en_licensing_supported);
1339 }
1340 
1341 				void
1342 efx_lic_fini(
1343 	__in			efx_nic_t *enp)
1344 {
1345 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1346 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
1347 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1348 
1349 	enp->en_elop = NULL;
1350 	enp->en_mod_flags &= ~EFX_MOD_LIC;
1351 }
1352 
1353 	__checkReturn	efx_rc_t
1354 efx_lic_update_licenses(
1355 	__in		efx_nic_t *enp)
1356 {
1357 	const efx_lic_ops_t *elop = enp->en_elop;
1358 	efx_rc_t rc;
1359 
1360 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1361 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1362 
1363 	if ((rc = elop->elo_update_licenses(enp)) != 0)
1364 		goto fail1;
1365 
1366 	return (0);
1367 
1368 fail1:
1369 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
1370 
1371 	return (rc);
1372 }
1373 
1374 	__checkReturn	efx_rc_t
1375 efx_lic_get_key_stats(
1376 	__in		efx_nic_t *enp,
1377 	__out		efx_key_stats_t *eksp)
1378 {
1379 	const efx_lic_ops_t *elop = enp->en_elop;
1380 	efx_rc_t rc;
1381 
1382 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1383 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1384 
1385 	if ((rc = elop->elo_get_key_stats(enp, eksp)) != 0)
1386 		goto fail1;
1387 
1388 	return (0);
1389 
1390 fail1:
1391 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
1392 
1393 	return (rc);
1394 }
1395 
1396 	__checkReturn	efx_rc_t
1397 efx_lic_app_state(
1398 	__in		efx_nic_t *enp,
1399 	__in		uint64_t app_id,
1400 	__out		boolean_t *licensedp)
1401 {
1402 	const efx_lic_ops_t *elop = enp->en_elop;
1403 	efx_rc_t rc;
1404 
1405 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1406 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1407 
1408 	if (elop->elo_app_state == NULL)
1409 		return (ENOTSUP);
1410 
1411 	if ((rc = elop->elo_app_state(enp, app_id, licensedp)) != 0)
1412 		goto fail1;
1413 
1414 	return (0);
1415 
1416 fail1:
1417 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
1418 
1419 	return (rc);
1420 }
1421 
1422 	__checkReturn	efx_rc_t
1423 efx_lic_get_id(
1424 	__in		efx_nic_t *enp,
1425 	__in		size_t buffer_size,
1426 	__out		uint32_t *typep,
1427 	__out		size_t *lengthp,
1428 	__out_opt	uint8_t *bufferp)
1429 {
1430 	const efx_lic_ops_t *elop = enp->en_elop;
1431 	efx_rc_t rc;
1432 
1433 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1434 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1435 
1436 	if (elop->elo_get_id == NULL)
1437 		return (ENOTSUP);
1438 
1439 	if ((rc = elop->elo_get_id(enp, buffer_size, typep,
1440 				    lengthp, bufferp)) != 0)
1441 		goto fail1;
1442 
1443 	return (0);
1444 
1445 fail1:
1446 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
1447 
1448 	return (rc);
1449 }
1450 
1451 /*
1452  * Buffer management API - abstracts varying TLV format used for License
1453  * partition.
1454  */
1455 
1456 	__checkReturn		efx_rc_t
1457 efx_lic_find_start(
1458 	__in			efx_nic_t *enp,
1459 	__in_bcount(buffer_size)
1460 				caddr_t bufferp,
1461 	__in			size_t buffer_size,
1462 	__out			uint32_t *startp)
1463 {
1464 	const efx_lic_ops_t *elop = enp->en_elop;
1465 	efx_rc_t rc;
1466 
1467 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1468 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1469 
1470 	if ((rc = elop->elo_find_start(enp, bufferp, buffer_size, startp)) != 0)
1471 		goto fail1;
1472 
1473 	return (0);
1474 
1475 fail1:
1476 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
1477 
1478 	return (rc);
1479 }
1480 
1481 	__checkReturn		efx_rc_t
1482 efx_lic_find_end(
1483 	__in			efx_nic_t *enp,
1484 	__in_bcount(buffer_size)
1485 				caddr_t bufferp,
1486 	__in			size_t buffer_size,
1487 	__in			uint32_t offset,
1488 	__out			uint32_t *endp)
1489 {
1490 	const efx_lic_ops_t *elop = enp->en_elop;
1491 	efx_rc_t rc;
1492 
1493 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1494 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1495 
1496 	rc = elop->elo_find_end(enp, bufferp, buffer_size, offset, endp);
1497 	if (rc != 0)
1498 		goto fail1;
1499 
1500 	return (0);
1501 
1502 fail1:
1503 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
1504 
1505 	return (rc);
1506 }
1507 
1508 	__checkReturn	__success(return != B_FALSE)	boolean_t
1509 efx_lic_find_key(
1510 	__in			efx_nic_t *enp,
1511 	__in_bcount(buffer_size)
1512 				caddr_t bufferp,
1513 	__in			size_t buffer_size,
1514 	__in			uint32_t offset,
1515 	__out			uint32_t *startp,
1516 	__out			uint32_t *lengthp)
1517 {
1518 	const efx_lic_ops_t *elop = enp->en_elop;
1519 
1520 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1521 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1522 
1523 	EFSYS_ASSERT(bufferp);
1524 	EFSYS_ASSERT(startp);
1525 	EFSYS_ASSERT(lengthp);
1526 
1527 	return (elop->elo_find_key(enp, bufferp, buffer_size, offset,
1528 				    startp, lengthp));
1529 }
1530 
1531 /*
1532  * Validate that the buffer contains a single key in a recognised format.
1533  * An empty or terminator buffer is not accepted as a valid key.
1534  */
1535 	__checkReturn	__success(return != B_FALSE)	boolean_t
1536 efx_lic_validate_key(
1537 	__in			efx_nic_t *enp,
1538 	__in_bcount(length)	caddr_t keyp,
1539 	__in			uint32_t length)
1540 {
1541 	const efx_lic_ops_t *elop = enp->en_elop;
1542 	boolean_t rc;
1543 
1544 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1545 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1546 
1547 	if ((rc = elop->elo_validate_key(enp, keyp, length)) == B_FALSE)
1548 		goto fail1;
1549 
1550 	return (B_TRUE);
1551 
1552 fail1:
1553 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
1554 
1555 	return (rc);
1556 }
1557 
1558 	__checkReturn		efx_rc_t
1559 efx_lic_read_key(
1560 	__in			efx_nic_t *enp,
1561 	__in_bcount(buffer_size)
1562 				caddr_t bufferp,
1563 	__in			size_t buffer_size,
1564 	__in			uint32_t offset,
1565 	__in			uint32_t length,
1566 	__out_bcount_part(key_max_size, *lengthp)
1567 				caddr_t keyp,
1568 	__in			size_t key_max_size,
1569 	__out			uint32_t *lengthp)
1570 {
1571 	const efx_lic_ops_t *elop = enp->en_elop;
1572 	efx_rc_t rc;
1573 
1574 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1575 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1576 
1577 	if ((rc = elop->elo_read_key(enp, bufferp, buffer_size, offset,
1578 				    length, keyp, key_max_size, lengthp)) != 0)
1579 		goto fail1;
1580 
1581 	return (0);
1582 
1583 fail1:
1584 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
1585 
1586 	return (rc);
1587 }
1588 
1589 	__checkReturn		efx_rc_t
1590 efx_lic_write_key(
1591 	__in			efx_nic_t *enp,
1592 	__in_bcount(buffer_size)
1593 				caddr_t bufferp,
1594 	__in			size_t buffer_size,
1595 	__in			uint32_t offset,
1596 	__in_bcount(length)	caddr_t keyp,
1597 	__in			uint32_t length,
1598 	__out			uint32_t *lengthp)
1599 {
1600 	const efx_lic_ops_t *elop = enp->en_elop;
1601 	efx_rc_t rc;
1602 
1603 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1604 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1605 
1606 	if ((rc = elop->elo_write_key(enp, bufferp, buffer_size, offset,
1607 				    keyp, length, lengthp)) != 0)
1608 		goto fail1;
1609 
1610 	return (0);
1611 
1612 fail1:
1613 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
1614 
1615 	return (rc);
1616 }
1617 
1618 	__checkReturn		efx_rc_t
1619 efx_lic_delete_key(
1620 	__in			efx_nic_t *enp,
1621 	__in_bcount(buffer_size)
1622 				caddr_t bufferp,
1623 	__in			size_t buffer_size,
1624 	__in			uint32_t offset,
1625 	__in			uint32_t length,
1626 	__in			uint32_t end,
1627 	__out			uint32_t *deltap)
1628 {
1629 	const efx_lic_ops_t *elop = enp->en_elop;
1630 	efx_rc_t rc;
1631 
1632 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1633 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1634 
1635 	if ((rc = elop->elo_delete_key(enp, bufferp, buffer_size, offset,
1636 				    length, end, deltap)) != 0)
1637 		goto fail1;
1638 
1639 	return (0);
1640 
1641 fail1:
1642 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
1643 
1644 	return (rc);
1645 }
1646 
1647 	__checkReturn		efx_rc_t
1648 efx_lic_create_partition(
1649 	__in			efx_nic_t *enp,
1650 	__in_bcount(buffer_size)
1651 				caddr_t bufferp,
1652 	__in			size_t buffer_size)
1653 {
1654 	const efx_lic_ops_t *elop = enp->en_elop;
1655 	efx_rc_t rc;
1656 
1657 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1658 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1659 
1660 	if ((rc = elop->elo_create_partition(enp, bufferp, buffer_size)) != 0)
1661 		goto fail1;
1662 
1663 	return (0);
1664 
1665 fail1:
1666 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
1667 
1668 	return (rc);
1669 }
1670 
1671 	__checkReturn		efx_rc_t
1672 efx_lic_finish_partition(
1673 	__in			efx_nic_t *enp,
1674 	__in_bcount(buffer_size)
1675 				caddr_t bufferp,
1676 	__in			size_t buffer_size)
1677 {
1678 	const efx_lic_ops_t *elop = enp->en_elop;
1679 	efx_rc_t rc;
1680 
1681 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1682 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1683 
1684 	if ((rc = elop->elo_finish_partition(enp, bufferp, buffer_size)) != 0)
1685 		goto fail1;
1686 
1687 	return (0);
1688 
1689 fail1:
1690 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
1691 
1692 	return (rc);
1693 }
1694 
1695 #endif	/* EFSYS_OPT_LICENSING */
1696