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