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