xref: /freebsd/sys/dev/sfxge/common/efx_lic.c (revision 8657387683946d0c03e09fe77029edfe309eeb20)
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 
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 	uint16_t tlv_type;
538 	uint16_t tlv_length;
539 
540 	_NOTE(ARGUNUSED(enp))
541 
542 	if (length < EFX_LICENSE_V1V2_HEADER_LENGTH) {
543 		goto fail1;
544 	}
545 
546 	tlv_type = __LE_TO_CPU_16(((uint16_t *)keyp)[0]);
547 	tlv_length = __LE_TO_CPU_16(((uint16_t *)keyp)[1]);
548 
549 	if (tlv_length > EFX_LICENSE_V1V2_PAYLOAD_LENGTH_MAX) {
550 		goto fail2;
551 	}
552 	if (tlv_type == 0) {
553 		goto fail3;
554 	}
555 	if ((tlv_length + EFX_LICENSE_V1V2_HEADER_LENGTH) != length) {
556 		goto fail4;
557 	}
558 
559 	return (B_TRUE);
560 
561 fail4:
562 	EFSYS_PROBE(fail4);
563 fail3:
564 	EFSYS_PROBE(fail3);
565 fail2:
566 	EFSYS_PROBE(fail2);
567 fail1:
568 	EFSYS_PROBE(fail1);
569 
570 	return (B_FALSE);
571 }
572 
573 
574 	__checkReturn		efx_rc_t
575 efx_lic_v1v2_read_key(
576 	__in			efx_nic_t *enp,
577 	__in_bcount(buffer_size)
578 				caddr_t bufferp,
579 	__in			size_t buffer_size,
580 	__in			uint32_t offset,
581 	__in			uint32_t length,
582 	__out_bcount_part(key_max_size, *lengthp)
583 				caddr_t keyp,
584 	__in			size_t key_max_size,
585 	__out			uint32_t *lengthp
586 	)
587 {
588 	efx_rc_t rc;
589 
590 	_NOTE(ARGUNUSED(enp))
591 	EFSYS_ASSERT(length <= (EFX_LICENSE_V1V2_PAYLOAD_LENGTH_MAX +
592 	    EFX_LICENSE_V1V2_HEADER_LENGTH));
593 
594 	if (key_max_size < length) {
595 		rc = ENOSPC;
596 		goto fail1;
597 	}
598 	memcpy(keyp, &bufferp[offset], length);
599 
600 	*lengthp = length;
601 
602 	return (0);
603 
604 fail1:
605 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
606 
607 	return (rc);
608 }
609 
610 	__checkReturn		efx_rc_t
611 efx_lic_v1v2_write_key(
612 	__in			efx_nic_t *enp,
613 	__in_bcount(buffer_size)
614 				caddr_t bufferp,
615 	__in			size_t buffer_size,
616 	__in			uint32_t offset,
617 	__in_bcount(length)	caddr_t keyp,
618 	__in			uint32_t length,
619 	__out			uint32_t *lengthp
620 	)
621 {
622 	efx_rc_t rc;
623 
624 	_NOTE(ARGUNUSED(enp))
625 	EFSYS_ASSERT(length <= (EFX_LICENSE_V1V2_PAYLOAD_LENGTH_MAX +
626 	    EFX_LICENSE_V1V2_HEADER_LENGTH));
627 
628 	/* Ensure space for terminator remains */
629 	if ((offset + length) >
630 	    (buffer_size - EFX_LICENSE_V1V2_HEADER_LENGTH)) {
631 		rc = ENOSPC;
632 		goto fail1;
633 	}
634 
635 	memcpy(bufferp + offset, keyp, length);
636 
637 	*lengthp = length;
638 
639 	return (0);
640 
641 fail1:
642 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
643 
644 	return (rc);
645 }
646 
647 	__checkReturn		efx_rc_t
648 efx_lic_v1v2_delete_key(
649 	__in			efx_nic_t *enp,
650 	__in_bcount(buffer_size)
651 				caddr_t bufferp,
652 	__in			size_t buffer_size,
653 	__in			uint32_t offset,
654 	__in			uint32_t length,
655 	__in			uint32_t end,
656 	__out			uint32_t *deltap
657 	)
658 {
659 	uint32_t move_start = offset + length;
660 	uint32_t move_length = end - move_start;
661 
662 	_NOTE(ARGUNUSED(enp))
663 	EFSYS_ASSERT(end <= buffer_size);
664 
665 	/* Shift everything after the key down */
666 	memmove(bufferp + offset, bufferp + move_start, move_length);
667 
668 	*deltap = length;
669 
670 	return (0);
671 }
672 
673 	__checkReturn		efx_rc_t
674 efx_lic_v1v2_create_partition(
675 	__in			efx_nic_t *enp,
676 	__in_bcount(buffer_size)
677 				caddr_t bufferp,
678 	__in			size_t buffer_size
679 	)
680 {
681 	_NOTE(ARGUNUSED(enp))
682 	EFSYS_ASSERT(EFX_LICENSE_V1V2_HEADER_LENGTH <= buffer_size);
683 
684 	/* Write terminator */
685 	memset(bufferp, '\0', EFX_LICENSE_V1V2_HEADER_LENGTH);
686 	return (0);
687 }
688 
689 
690 	__checkReturn		efx_rc_t
691 efx_lic_v1v2_finish_partition(
692 	__in			efx_nic_t *enp,
693 	__in_bcount(buffer_size)
694 				caddr_t bufferp,
695 	__in			size_t buffer_size
696 	)
697 {
698 	_NOTE(ARGUNUSED(enp, bufferp, buffer_size))
699 
700 	return (0);
701 }
702 
703 #endif	/* EFSYS_OPT_HUNTINGTON | EFSYS_OPT_SIENA */
704 
705 
706 /* V2 Licensing - used by Huntington family only. See SF-113611-TC */
707 
708 #if EFSYS_OPT_HUNTINGTON
709 
710 static	__checkReturn	efx_rc_t
711 efx_mcdi_licensed_app_state(
712 	__in		efx_nic_t *enp,
713 	__in		uint64_t app_id,
714 	__out		boolean_t *licensedp)
715 {
716 	efx_mcdi_req_t req;
717 	uint8_t payload[MAX(MC_CMD_GET_LICENSED_APP_STATE_IN_LEN,
718 			    MC_CMD_GET_LICENSED_APP_STATE_OUT_LEN)];
719 	uint32_t app_state;
720 	efx_rc_t rc;
721 
722 	EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON);
723 
724 	/* V2 licensing supports 32bit app id only */
725 	if ((app_id >> 32) != 0) {
726 		rc = EINVAL;
727 		goto fail1;
728 	}
729 
730 	(void) memset(payload, 0, sizeof (payload));
731 	req.emr_cmd = MC_CMD_GET_LICENSED_APP_STATE;
732 	req.emr_in_buf = payload;
733 	req.emr_in_length = MC_CMD_GET_LICENSED_APP_STATE_IN_LEN;
734 	req.emr_out_buf = payload;
735 	req.emr_out_length = MC_CMD_GET_LICENSED_APP_STATE_OUT_LEN;
736 
737 	MCDI_IN_SET_DWORD(req, GET_LICENSED_APP_STATE_IN_APP_ID,
738 		    app_id & 0xffffffff);
739 
740 	efx_mcdi_execute(enp, &req);
741 
742 	if (req.emr_rc != 0) {
743 		rc = req.emr_rc;
744 		goto fail2;
745 	}
746 
747 	if (req.emr_out_length_used < MC_CMD_GET_LICENSED_APP_STATE_OUT_LEN) {
748 		rc = EMSGSIZE;
749 		goto fail3;
750 	}
751 
752 	app_state = (MCDI_OUT_DWORD(req, GET_LICENSED_APP_STATE_OUT_STATE));
753 	if (app_state != MC_CMD_GET_LICENSED_APP_STATE_OUT_NOT_LICENSED) {
754 		*licensedp = B_TRUE;
755 	} else {
756 		*licensedp = B_FALSE;
757 	}
758 
759 	return (0);
760 
761 fail3:
762 	EFSYS_PROBE(fail3);
763 fail2:
764 	EFSYS_PROBE(fail2);
765 fail1:
766 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
767 
768 	return (rc);
769 }
770 
771 static	__checkReturn	efx_rc_t
772 efx_mcdi_licensing_update_licenses(
773 	__in		efx_nic_t *enp)
774 {
775 	efx_mcdi_req_t req;
776 	uint8_t payload[MC_CMD_LICENSING_IN_LEN];
777 	efx_rc_t rc;
778 
779 	EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON);
780 
781 	(void) memset(payload, 0, sizeof (payload));
782 	req.emr_cmd = MC_CMD_LICENSING;
783 	req.emr_in_buf = payload;
784 	req.emr_in_length = MC_CMD_LICENSING_IN_LEN;
785 	req.emr_out_buf = payload;
786 	req.emr_out_length = 0;
787 
788 	MCDI_IN_SET_DWORD(req, LICENSING_IN_OP,
789 	    MC_CMD_LICENSING_IN_OP_UPDATE_LICENSE);
790 
791 	efx_mcdi_execute(enp, &req);
792 
793 	if (req.emr_rc != 0) {
794 		rc = req.emr_rc;
795 		goto fail1;
796 	}
797 
798 	if (req.emr_out_length_used != 0) {
799 		rc = EIO;
800 		goto fail2;
801 	}
802 
803 	return (0);
804 
805 fail2:
806 	EFSYS_PROBE(fail2);
807 fail1:
808 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
809 
810 	return (rc);
811 }
812 
813 static	__checkReturn	efx_rc_t
814 efx_mcdi_licensing_get_key_stats(
815 	__in		efx_nic_t *enp,
816 	__out		efx_key_stats_t *eksp)
817 {
818 	efx_mcdi_req_t req;
819 	uint8_t payload[MAX(MC_CMD_LICENSING_IN_LEN,
820 			    MC_CMD_LICENSING_OUT_LEN)];
821 	efx_rc_t rc;
822 
823 	EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON);
824 
825 	(void) memset(payload, 0, sizeof (payload));
826 	req.emr_cmd = MC_CMD_LICENSING;
827 	req.emr_in_buf = payload;
828 	req.emr_in_length = MC_CMD_LICENSING_IN_LEN;
829 	req.emr_out_buf = payload;
830 	req.emr_out_length = MC_CMD_LICENSING_OUT_LEN;
831 
832 	MCDI_IN_SET_DWORD(req, LICENSING_IN_OP,
833 	    MC_CMD_LICENSING_IN_OP_GET_KEY_STATS);
834 
835 	efx_mcdi_execute(enp, &req);
836 
837 	if (req.emr_rc != 0) {
838 		rc = req.emr_rc;
839 		goto fail1;
840 	}
841 
842 	if (req.emr_out_length_used < MC_CMD_LICENSING_OUT_LEN) {
843 		rc = EMSGSIZE;
844 		goto fail2;
845 	}
846 
847 	eksp->eks_valid =
848 		MCDI_OUT_DWORD(req, LICENSING_OUT_VALID_APP_KEYS);
849 	eksp->eks_invalid =
850 		MCDI_OUT_DWORD(req, LICENSING_OUT_INVALID_APP_KEYS);
851 	eksp->eks_blacklisted =
852 		MCDI_OUT_DWORD(req, LICENSING_OUT_BLACKLISTED_APP_KEYS);
853 	eksp->eks_unverifiable =
854 		MCDI_OUT_DWORD(req, LICENSING_OUT_UNVERIFIABLE_APP_KEYS);
855 	eksp->eks_wrong_node =
856 		MCDI_OUT_DWORD(req, LICENSING_OUT_WRONG_NODE_APP_KEYS);
857 	eksp->eks_licensed_apps_lo = 0;
858 	eksp->eks_licensed_apps_hi = 0;
859 	eksp->eks_licensed_features_lo = 0;
860 	eksp->eks_licensed_features_hi = 0;
861 
862 	return (0);
863 
864 fail2:
865 	EFSYS_PROBE(fail2);
866 fail1:
867 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
868 
869 	return (rc);
870 }
871 
872 #endif	/* EFSYS_OPT_HUNTINGTON */
873 
874 /* V3 Licensing - used starting from Medford family. See SF-114884-SW */
875 
876 #if EFSYS_OPT_MEDFORD
877 
878 static	__checkReturn	efx_rc_t
879 efx_mcdi_licensing_v3_update_licenses(
880 	__in		efx_nic_t *enp)
881 {
882 	efx_mcdi_req_t req;
883 	uint8_t payload[MC_CMD_LICENSING_V3_IN_LEN];
884 	efx_rc_t rc;
885 
886 	EFSYS_ASSERT(enp->en_family == EFX_FAMILY_MEDFORD);
887 
888 	(void) memset(payload, 0, sizeof (payload));
889 	req.emr_cmd = MC_CMD_LICENSING_V3;
890 	req.emr_in_buf = payload;
891 	req.emr_in_length = MC_CMD_LICENSING_V3_IN_LEN;
892 	req.emr_out_buf = NULL;
893 	req.emr_out_length = 0;
894 
895 	MCDI_IN_SET_DWORD(req, LICENSING_V3_IN_OP,
896 	    MC_CMD_LICENSING_V3_IN_OP_UPDATE_LICENSE);
897 
898 	efx_mcdi_execute(enp, &req);
899 
900 	if (req.emr_rc != 0) {
901 		rc = req.emr_rc;
902 		goto fail1;
903 	}
904 
905 	return (0);
906 
907 fail1:
908 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
909 
910 	return (rc);
911 }
912 
913 static	__checkReturn	efx_rc_t
914 efx_mcdi_licensing_v3_report_license(
915 	__in		efx_nic_t *enp,
916 	__out		efx_key_stats_t *eksp)
917 {
918 	efx_mcdi_req_t req;
919 	uint8_t payload[MAX(MC_CMD_LICENSING_V3_IN_LEN,
920 			    MC_CMD_LICENSING_V3_OUT_LEN)];
921 	efx_rc_t rc;
922 
923 	EFSYS_ASSERT(enp->en_family == EFX_FAMILY_MEDFORD);
924 
925 	(void) memset(payload, 0, sizeof (payload));
926 	req.emr_cmd = MC_CMD_LICENSING_V3;
927 	req.emr_in_buf = payload;
928 	req.emr_in_length = MC_CMD_LICENSING_V3_IN_LEN;
929 	req.emr_out_buf = payload;
930 	req.emr_out_length = MC_CMD_LICENSING_V3_OUT_LEN;
931 
932 	MCDI_IN_SET_DWORD(req, LICENSING_V3_IN_OP,
933 	    MC_CMD_LICENSING_V3_IN_OP_REPORT_LICENSE);
934 
935 	efx_mcdi_execute_quiet(enp, &req);
936 
937 	if (req.emr_rc != 0) {
938 		rc = req.emr_rc;
939 		goto fail1;
940 	}
941 
942 	if (req.emr_out_length_used < MC_CMD_LICENSING_V3_OUT_LEN) {
943 		rc = EMSGSIZE;
944 		goto fail2;
945 	}
946 
947 	eksp->eks_valid =
948 		MCDI_OUT_DWORD(req, LICENSING_V3_OUT_VALID_KEYS);
949 	eksp->eks_invalid =
950 		MCDI_OUT_DWORD(req, LICENSING_V3_OUT_INVALID_KEYS);
951 	eksp->eks_blacklisted = 0;
952 	eksp->eks_unverifiable =
953 		MCDI_OUT_DWORD(req, LICENSING_V3_OUT_UNVERIFIABLE_KEYS);
954 	eksp->eks_wrong_node =
955 		MCDI_OUT_DWORD(req, LICENSING_V3_OUT_WRONG_NODE_KEYS);
956 	eksp->eks_licensed_apps_lo =
957 		MCDI_OUT_DWORD(req, LICENSING_V3_OUT_LICENSED_APPS_LO);
958 	eksp->eks_licensed_apps_hi =
959 		MCDI_OUT_DWORD(req, LICENSING_V3_OUT_LICENSED_APPS_HI);
960 	eksp->eks_licensed_features_lo =
961 		MCDI_OUT_DWORD(req, LICENSING_V3_OUT_LICENSED_FEATURES_LO);
962 	eksp->eks_licensed_features_hi =
963 		MCDI_OUT_DWORD(req, LICENSING_V3_OUT_LICENSED_FEATURES_HI);
964 
965 	return (0);
966 
967 fail2:
968 	EFSYS_PROBE(fail2);
969 fail1:
970 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
971 
972 	return (rc);
973 }
974 
975 static	__checkReturn	efx_rc_t
976 efx_mcdi_licensing_v3_app_state(
977 	__in		efx_nic_t *enp,
978 	__in		uint64_t app_id,
979 	__out		boolean_t *licensedp)
980 {
981 	efx_mcdi_req_t req;
982 	uint8_t payload[MAX(MC_CMD_GET_LICENSED_V3_APP_STATE_IN_LEN,
983 			    MC_CMD_GET_LICENSED_V3_APP_STATE_OUT_LEN)];
984 	uint32_t app_state;
985 	efx_rc_t rc;
986 
987 	EFSYS_ASSERT(enp->en_family == EFX_FAMILY_MEDFORD);
988 
989 	(void) memset(payload, 0, sizeof (payload));
990 	req.emr_cmd = MC_CMD_GET_LICENSED_V3_APP_STATE;
991 	req.emr_in_buf = payload;
992 	req.emr_in_length = MC_CMD_GET_LICENSED_V3_APP_STATE_IN_LEN;
993 	req.emr_out_buf = payload;
994 	req.emr_out_length = MC_CMD_GET_LICENSED_V3_APP_STATE_OUT_LEN;
995 
996 	MCDI_IN_SET_DWORD(req, GET_LICENSED_V3_APP_STATE_IN_APP_ID_LO,
997 		    app_id & 0xffffffff);
998 	MCDI_IN_SET_DWORD(req, GET_LICENSED_V3_APP_STATE_IN_APP_ID_HI,
999 		    app_id >> 32);
1000 
1001 	efx_mcdi_execute(enp, &req);
1002 
1003 	if (req.emr_rc != 0) {
1004 		rc = req.emr_rc;
1005 		goto fail1;
1006 	}
1007 
1008 	if (req.emr_out_length_used < MC_CMD_GET_LICENSED_V3_APP_STATE_OUT_LEN) {
1009 		rc = EMSGSIZE;
1010 		goto fail2;
1011 	}
1012 
1013 	app_state = (MCDI_OUT_DWORD(req, GET_LICENSED_V3_APP_STATE_OUT_STATE));
1014 	if (app_state != MC_CMD_GET_LICENSED_V3_APP_STATE_OUT_NOT_LICENSED) {
1015 		*licensedp = B_TRUE;
1016 	} else {
1017 		*licensedp = B_FALSE;
1018 	}
1019 
1020 	return (0);
1021 
1022 fail2:
1023 	EFSYS_PROBE(fail2);
1024 fail1:
1025 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
1026 
1027 	return (rc);
1028 }
1029 
1030 static	__checkReturn	efx_rc_t
1031 efx_mcdi_licensing_v3_get_id(
1032 	__in		efx_nic_t *enp,
1033 	__in		size_t buffer_size,
1034 	__out		uint32_t *typep,
1035 	__out		size_t *lengthp,
1036 	__out_bcount_part_opt(buffer_size, *lengthp)
1037 			uint8_t *bufferp)
1038 {
1039 	efx_mcdi_req_t req;
1040 	uint8_t payload[MAX(MC_CMD_LICENSING_GET_ID_V3_IN_LEN,
1041 			    MC_CMD_LICENSING_GET_ID_V3_OUT_LENMIN)];
1042 	efx_rc_t rc;
1043 
1044 	req.emr_cmd = MC_CMD_LICENSING_GET_ID_V3;
1045 
1046 	if (bufferp == NULL) {
1047 		/* Request id type and length only */
1048 		req.emr_in_buf = bufferp;
1049 		req.emr_in_length = MC_CMD_LICENSING_GET_ID_V3_IN_LEN;
1050 		req.emr_out_buf = bufferp;
1051 		req.emr_out_length = MC_CMD_LICENSING_GET_ID_V3_OUT_LENMIN;
1052 		(void) memset(payload, 0, sizeof (payload));
1053 	} else {
1054 		/* Request full buffer */
1055 		req.emr_in_buf = bufferp;
1056 		req.emr_in_length = MC_CMD_LICENSING_GET_ID_V3_IN_LEN;
1057 		req.emr_out_buf = bufferp;
1058 		req.emr_out_length = MIN(buffer_size, MC_CMD_LICENSING_GET_ID_V3_OUT_LENMAX);
1059 		(void) memset(bufferp, 0, req.emr_out_length);
1060 	}
1061 
1062 	efx_mcdi_execute_quiet(enp, &req);
1063 
1064 	if (req.emr_rc != 0) {
1065 		rc = req.emr_rc;
1066 		goto fail1;
1067 	}
1068 
1069 	if (req.emr_out_length_used < MC_CMD_LICENSING_GET_ID_V3_OUT_LENMIN) {
1070 		rc = EMSGSIZE;
1071 		goto fail2;
1072 	}
1073 
1074 	*typep = MCDI_OUT_DWORD(req, LICENSING_GET_ID_V3_OUT_LICENSE_TYPE);
1075 	*lengthp = MCDI_OUT_DWORD(req, LICENSING_GET_ID_V3_OUT_LICENSE_ID_LENGTH);
1076 
1077 	if (bufferp == NULL) {
1078 		/* modify length requirements to indicate to caller the extra buffering
1079 		** needed to read the complete output.
1080 		*/
1081 		*lengthp += MC_CMD_LICENSING_GET_ID_V3_OUT_LENMIN;
1082 	} else {
1083 		/* Shift ID down to start of buffer */
1084 		memmove(bufferp,
1085 		    bufferp + MC_CMD_LICENSING_GET_ID_V3_OUT_LICENSE_ID_OFST,
1086 		    *lengthp);
1087 		memset(bufferp + (*lengthp), 0,
1088 		    MC_CMD_LICENSING_GET_ID_V3_OUT_LICENSE_ID_OFST);
1089 	}
1090 
1091 	return (0);
1092 
1093 fail2:
1094 	EFSYS_PROBE(fail2);
1095 fail1:
1096 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
1097 
1098 	return (rc);
1099 }
1100 
1101 /* V3 format uses Huntington TLV format partition. See SF-108797-SW */
1102 #define EFX_LICENSE_V3_KEY_LENGTH_MIN    (64)
1103 #define EFX_LICENSE_V3_KEY_LENGTH_MAX    (160)
1104 
1105 	__checkReturn		efx_rc_t
1106 efx_lic_v3_find_start(
1107 	__in			efx_nic_t *enp,
1108 	__in_bcount(buffer_size)
1109 				caddr_t bufferp,
1110 	__in			size_t buffer_size,
1111 	__out			uint32_t *startp
1112 	)
1113 {
1114 	_NOTE(ARGUNUSED(enp))
1115 
1116 	return ef10_nvram_buffer_find_item_start(bufferp, buffer_size, startp);
1117 }
1118 
1119 	__checkReturn		efx_rc_t
1120 efx_lic_v3_find_end(
1121 	__in			efx_nic_t *enp,
1122 	__in_bcount(buffer_size)
1123 				caddr_t bufferp,
1124 	__in			size_t buffer_size,
1125 	__in			uint32_t offset,
1126 	__out			uint32_t *endp
1127 	)
1128 {
1129 	_NOTE(ARGUNUSED(enp))
1130 
1131 	return ef10_nvram_buffer_find_end(bufferp, buffer_size, offset, endp);
1132 }
1133 
1134 	__checkReturn	__success(return != B_FALSE)	boolean_t
1135 efx_lic_v3_find_key(
1136 	__in			efx_nic_t *enp,
1137 	__in_bcount(buffer_size)
1138 				caddr_t bufferp,
1139 	__in			size_t buffer_size,
1140 	__in			uint32_t offset,
1141 	__out			uint32_t *startp,
1142 	__out			uint32_t *lengthp
1143 	)
1144 {
1145 	_NOTE(ARGUNUSED(enp))
1146 
1147 	return ef10_nvram_buffer_find_item(bufferp, buffer_size,
1148 	    offset, startp, lengthp);
1149 }
1150 
1151 	__checkReturn	__success(return != B_FALSE)	boolean_t
1152 efx_lic_v3_validate_key(
1153 	__in			efx_nic_t *enp,
1154 	__in_bcount(length)	caddr_t keyp,
1155 	__in			uint32_t length
1156 	)
1157 {
1158 	/* Check key is a valid V3 key */
1159 	uint8_t key_type;
1160 	uint8_t key_length;
1161 
1162 	_NOTE(ARGUNUSED(enp))
1163 
1164 	if (length < EFX_LICENSE_V3_KEY_LENGTH_MIN) {
1165 		goto fail1;
1166 	}
1167 
1168 	if (length > EFX_LICENSE_V3_KEY_LENGTH_MAX) {
1169 		goto fail2;
1170 	}
1171 
1172 	key_type = ((uint8_t *)keyp)[0];
1173 	key_length = ((uint8_t *)keyp)[1];
1174 
1175 	if (key_type < 3) {
1176 		goto fail3;
1177 	}
1178 	if (key_length > length) {
1179 		goto fail4;
1180 	}
1181 	return (B_TRUE);
1182 
1183 fail4:
1184 	EFSYS_PROBE(fail4);
1185 fail3:
1186 	EFSYS_PROBE(fail3);
1187 fail2:
1188 	EFSYS_PROBE(fail2);
1189 fail1:
1190 	EFSYS_PROBE(fail1);
1191 
1192 	return (B_FALSE);
1193 }
1194 
1195 	__checkReturn		efx_rc_t
1196 efx_lic_v3_read_key(
1197 	__in			efx_nic_t *enp,
1198 	__in_bcount(buffer_size)
1199 				caddr_t bufferp,
1200 	__in			size_t buffer_size,
1201 	__in			uint32_t offset,
1202 	__in			uint32_t length,
1203 	__out_bcount_part(key_max_size, *lengthp)
1204 				caddr_t keyp,
1205 	__in			size_t key_max_size,
1206 	__out			uint32_t *lengthp
1207 	)
1208 {
1209 	_NOTE(ARGUNUSED(enp))
1210 
1211 	return ef10_nvram_buffer_get_item(bufferp, buffer_size,
1212 		    offset, length, keyp, key_max_size, lengthp);
1213 }
1214 
1215 	__checkReturn		efx_rc_t
1216 efx_lic_v3_write_key(
1217 	__in			efx_nic_t *enp,
1218 	__in_bcount(buffer_size)
1219 				caddr_t bufferp,
1220 	__in			size_t buffer_size,
1221 	__in			uint32_t offset,
1222 	__in_bcount(length)	caddr_t keyp,
1223 	__in			uint32_t length,
1224 	__out			uint32_t *lengthp
1225 	)
1226 {
1227 	_NOTE(ARGUNUSED(enp))
1228 	EFSYS_ASSERT(length <= EFX_LICENSE_V3_KEY_LENGTH_MAX);
1229 
1230 	return ef10_nvram_buffer_insert_item(bufferp, buffer_size,
1231 		    offset, keyp, length, lengthp);
1232 }
1233 
1234 	__checkReturn		efx_rc_t
1235 efx_lic_v3_delete_key(
1236 	__in			efx_nic_t *enp,
1237 	__in_bcount(buffer_size)
1238 				caddr_t bufferp,
1239 	__in			size_t buffer_size,
1240 	__in			uint32_t offset,
1241 	__in			uint32_t length,
1242 	__in			uint32_t end,
1243 	__out			uint32_t *deltap
1244 	)
1245 {
1246 	efx_rc_t rc;
1247 
1248 	_NOTE(ARGUNUSED(enp))
1249 
1250 	if ((rc = ef10_nvram_buffer_delete_item(bufferp,
1251 			buffer_size, offset, length, end)) != 0) {
1252 		goto fail1;
1253 	}
1254 
1255 	*deltap = length;
1256 
1257 	return (0);
1258 
1259 fail1:
1260 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
1261 
1262 	return (rc);
1263 }
1264 
1265 	__checkReturn		efx_rc_t
1266 efx_lic_v3_create_partition(
1267 	__in			efx_nic_t *enp,
1268 	__in_bcount(buffer_size)
1269 				caddr_t bufferp,
1270 	__in			size_t buffer_size
1271 	)
1272 {
1273 	efx_rc_t rc;
1274 
1275 	/* Construct empty partition */
1276 	if ((rc = ef10_nvram_buffer_create(enp,
1277 	    NVRAM_PARTITION_TYPE_LICENSE,
1278 	    bufferp, buffer_size)) != 0) {
1279 		rc = EFAULT;
1280 		goto fail1;
1281 	}
1282 
1283 	return (0);
1284 
1285 fail1:
1286 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
1287 
1288 	return (rc);
1289 }
1290 
1291 	__checkReturn		efx_rc_t
1292 efx_lic_v3_finish_partition(
1293 	__in			efx_nic_t *enp,
1294 	__in_bcount(buffer_size)
1295 				caddr_t bufferp,
1296 	__in			size_t buffer_size
1297 	)
1298 {
1299 	efx_rc_t rc;
1300 
1301 	if ((rc = ef10_nvram_buffer_finish(bufferp,
1302 			buffer_size)) != 0) {
1303 		goto fail1;
1304 	}
1305 
1306 	/* Validate completed partition */
1307 	if ((rc = ef10_nvram_buffer_validate(enp, NVRAM_PARTITION_TYPE_LICENSE,
1308 					bufferp, buffer_size)) != 0) {
1309 		goto fail2;
1310 	}
1311 
1312 	return (0);
1313 
1314 fail2:
1315 	EFSYS_PROBE(fail2);
1316 fail1:
1317 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
1318 
1319 	return (rc);
1320 }
1321 
1322 
1323 #endif	/* EFSYS_OPT_MEDFORD */
1324 
1325 	__checkReturn		efx_rc_t
1326 efx_lic_init(
1327 	__in			efx_nic_t *enp)
1328 {
1329 	const efx_lic_ops_t *elop;
1330 	efx_key_stats_t eks;
1331 	efx_rc_t rc;
1332 
1333 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1334 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
1335 	EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_LIC));
1336 
1337 	switch (enp->en_family) {
1338 
1339 #if EFSYS_OPT_SIENA
1340 	case EFX_FAMILY_SIENA:
1341 		elop = &__efx_lic_v1_ops;
1342 		break;
1343 #endif	/* EFSYS_OPT_SIENA */
1344 
1345 #if EFSYS_OPT_HUNTINGTON
1346 	case EFX_FAMILY_HUNTINGTON:
1347 		elop = &__efx_lic_v2_ops;
1348 		break;
1349 #endif	/* EFSYS_OPT_HUNTINGTON */
1350 
1351 #if EFSYS_OPT_MEDFORD
1352 	case EFX_FAMILY_MEDFORD:
1353 		elop = &__efx_lic_v3_ops;
1354 		break;
1355 #endif	/* EFSYS_OPT_MEDFORD */
1356 
1357 	default:
1358 		EFSYS_ASSERT(0);
1359 		rc = ENOTSUP;
1360 		goto fail1;
1361 	}
1362 
1363 	enp->en_elop = elop;
1364 	enp->en_mod_flags |= EFX_MOD_LIC;
1365 
1366 	/* Probe for support */
1367 	if (efx_lic_get_key_stats(enp, &eks) == 0) {
1368 		enp->en_licensing_supported = B_TRUE;
1369 	} else {
1370 		enp->en_licensing_supported = B_FALSE;
1371 	}
1372 
1373 	return (0);
1374 
1375 fail1:
1376 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
1377 
1378 	return (rc);
1379 }
1380 
1381 extern	__checkReturn	boolean_t
1382 efx_lic_check_support(
1383 	__in			efx_nic_t *enp)
1384 {
1385 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1386 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
1387 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1388 
1389 	return enp->en_licensing_supported;
1390 }
1391 
1392 				void
1393 efx_lic_fini(
1394 	__in			efx_nic_t *enp)
1395 {
1396 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1397 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
1398 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1399 
1400 	enp->en_elop = NULL;
1401 	enp->en_mod_flags &= ~EFX_MOD_LIC;
1402 }
1403 
1404 
1405 	__checkReturn	efx_rc_t
1406 efx_lic_update_licenses(
1407 	__in		efx_nic_t *enp)
1408 {
1409 	const efx_lic_ops_t *elop = enp->en_elop;
1410 	efx_rc_t rc;
1411 
1412 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1413 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1414 
1415 	if ((rc = elop->elo_update_licenses(enp)) != 0)
1416 		goto fail1;
1417 
1418 	return (0);
1419 
1420 fail1:
1421 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
1422 
1423 	return (rc);
1424 }
1425 
1426 	__checkReturn	efx_rc_t
1427 efx_lic_get_key_stats(
1428 	__in		efx_nic_t *enp,
1429 	__out		efx_key_stats_t *eksp)
1430 {
1431 	const efx_lic_ops_t *elop = enp->en_elop;
1432 	efx_rc_t rc;
1433 
1434 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1435 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1436 
1437 	if ((rc = elop->elo_get_key_stats(enp, eksp)) != 0)
1438 		goto fail1;
1439 
1440 	return (0);
1441 
1442 fail1:
1443 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
1444 
1445 	return (rc);
1446 }
1447 
1448 	__checkReturn	efx_rc_t
1449 efx_lic_app_state(
1450 	__in		efx_nic_t *enp,
1451 	__in		uint64_t app_id,
1452 	__out		boolean_t *licensedp)
1453 {
1454 	const efx_lic_ops_t *elop = enp->en_elop;
1455 	efx_rc_t rc;
1456 
1457 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1458 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1459 
1460 	if (elop->elo_app_state == NULL)
1461 		return (ENOTSUP);
1462 
1463 	if ((rc = elop->elo_app_state(enp, app_id, licensedp)) != 0)
1464 		goto fail1;
1465 
1466 	return (0);
1467 
1468 fail1:
1469 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
1470 
1471 	return (rc);
1472 }
1473 
1474 	__checkReturn	efx_rc_t
1475 efx_lic_get_id(
1476 	__in		efx_nic_t *enp,
1477 	__in		size_t buffer_size,
1478 	__out		uint32_t *typep,
1479 	__out		size_t *lengthp,
1480 	__out_opt	uint8_t *bufferp
1481 	)
1482 {
1483 	const efx_lic_ops_t *elop = enp->en_elop;
1484 	efx_rc_t rc;
1485 
1486 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1487 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1488 
1489 	if (elop->elo_get_id == NULL)
1490 		return (ENOTSUP);
1491 
1492 	if ((rc = elop->elo_get_id(enp, buffer_size, typep,
1493 				    lengthp, bufferp)) != 0)
1494 		goto fail1;
1495 
1496 	return (0);
1497 
1498 fail1:
1499 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
1500 
1501 	return (rc);
1502 }
1503 
1504 /* Buffer management API - abstracts varying TLV format used for License partition */
1505 
1506 	__checkReturn		efx_rc_t
1507 efx_lic_find_start(
1508 	__in			efx_nic_t *enp,
1509 	__in_bcount(buffer_size)
1510 				caddr_t bufferp,
1511 	__in			size_t buffer_size,
1512 	__out			uint32_t *startp
1513 	)
1514 {
1515 	const efx_lic_ops_t *elop = enp->en_elop;
1516 	efx_rc_t rc;
1517 
1518 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1519 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1520 
1521 	if ((rc = elop->elo_find_start(enp, bufferp, buffer_size, startp)) != 0)
1522 		goto fail1;
1523 
1524 	return (0);
1525 
1526 fail1:
1527 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
1528 
1529 	return (rc);
1530 }
1531 
1532 	__checkReturn		efx_rc_t
1533 efx_lic_find_end(
1534 	__in			efx_nic_t *enp,
1535 	__in_bcount(buffer_size)
1536 				caddr_t bufferp,
1537 	__in			size_t buffer_size,
1538 	__in			uint32_t offset,
1539 	__out			uint32_t *endp
1540 	)
1541 {
1542 	const efx_lic_ops_t *elop = enp->en_elop;
1543 	efx_rc_t rc;
1544 
1545 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1546 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1547 
1548 	if ((rc = elop->elo_find_end(enp, bufferp, buffer_size, offset, endp)) != 0)
1549 		goto fail1;
1550 
1551 	return (0);
1552 
1553 fail1:
1554 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
1555 
1556 	return (rc);
1557 }
1558 
1559 	__checkReturn	__success(return != B_FALSE)	boolean_t
1560 efx_lic_find_key(
1561 	__in			efx_nic_t *enp,
1562 	__in_bcount(buffer_size)
1563 				caddr_t bufferp,
1564 	__in			size_t buffer_size,
1565 	__in			uint32_t offset,
1566 	__out			uint32_t *startp,
1567 	__out			uint32_t *lengthp
1568 	)
1569 {
1570 	const efx_lic_ops_t *elop = enp->en_elop;
1571 
1572 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1573 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1574 
1575 	EFSYS_ASSERT(bufferp);
1576 	EFSYS_ASSERT(startp);
1577 	EFSYS_ASSERT(lengthp);
1578 
1579 	return (elop->elo_find_key(enp, bufferp, buffer_size, offset,
1580 				    startp, lengthp));
1581 }
1582 
1583 
1584 /* Validate that the buffer contains a single key in a recognised format.
1585 ** An empty or terminator buffer is not accepted as a valid key.
1586 */
1587 	__checkReturn	__success(return != B_FALSE)	boolean_t
1588 efx_lic_validate_key(
1589 	__in			efx_nic_t *enp,
1590 	__in_bcount(length)	caddr_t keyp,
1591 	__in			uint32_t length
1592 	)
1593 {
1594 	const efx_lic_ops_t *elop = enp->en_elop;
1595 	boolean_t rc;
1596 
1597 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1598 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1599 
1600 	if ((rc = elop->elo_validate_key(enp, keyp, length)) == B_FALSE)
1601 		goto fail1;
1602 
1603 	return (B_TRUE);
1604 
1605 fail1:
1606 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
1607 
1608 	return (rc);
1609 }
1610 
1611 	__checkReturn		efx_rc_t
1612 efx_lic_read_key(
1613 	__in			efx_nic_t *enp,
1614 	__in_bcount(buffer_size)
1615 				caddr_t bufferp,
1616 	__in			size_t buffer_size,
1617 	__in			uint32_t offset,
1618 	__in			uint32_t length,
1619 	__out_bcount_part(key_max_size, *lengthp)
1620 				caddr_t keyp,
1621 	__in			size_t key_max_size,
1622 	__out			uint32_t *lengthp
1623 	)
1624 {
1625 	const efx_lic_ops_t *elop = enp->en_elop;
1626 	efx_rc_t rc;
1627 
1628 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1629 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1630 
1631 	if ((rc = elop->elo_read_key(enp, bufferp, buffer_size, offset,
1632 				    length, keyp, key_max_size, lengthp)) != 0)
1633 		goto fail1;
1634 
1635 	return (0);
1636 
1637 fail1:
1638 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
1639 
1640 	return (rc);
1641 }
1642 
1643 	__checkReturn		efx_rc_t
1644 efx_lic_write_key(
1645 	__in			efx_nic_t *enp,
1646 	__in_bcount(buffer_size)
1647 				caddr_t bufferp,
1648 	__in			size_t buffer_size,
1649 	__in			uint32_t offset,
1650 	__in_bcount(length)	caddr_t keyp,
1651 	__in			uint32_t length,
1652 	__out			uint32_t *lengthp
1653 	)
1654 {
1655 	const efx_lic_ops_t *elop = enp->en_elop;
1656 	efx_rc_t rc;
1657 
1658 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1659 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1660 
1661 	if ((rc = elop->elo_write_key(enp, bufferp, buffer_size, offset,
1662 				    keyp, length, lengthp)) != 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_delete_key(
1675 	__in			efx_nic_t *enp,
1676 	__in_bcount(buffer_size)
1677 				caddr_t bufferp,
1678 	__in			size_t buffer_size,
1679 	__in			uint32_t offset,
1680 	__in			uint32_t length,
1681 	__in			uint32_t end,
1682 	__out			uint32_t *deltap
1683 	)
1684 {
1685 	const efx_lic_ops_t *elop = enp->en_elop;
1686 	efx_rc_t rc;
1687 
1688 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1689 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1690 
1691 	if ((rc = elop->elo_delete_key(enp, bufferp, buffer_size, offset,
1692 				    length, end, deltap)) != 0)
1693 		goto fail1;
1694 
1695 	return (0);
1696 
1697 fail1:
1698 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
1699 
1700 	return (rc);
1701 }
1702 
1703 	__checkReturn		efx_rc_t
1704 efx_lic_create_partition(
1705 	__in			efx_nic_t *enp,
1706 	__in_bcount(buffer_size)
1707 				caddr_t bufferp,
1708 	__in			size_t buffer_size
1709 	)
1710 {
1711 	const efx_lic_ops_t *elop = enp->en_elop;
1712 	efx_rc_t rc;
1713 
1714 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1715 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1716 
1717 	if ((rc = elop->elo_create_partition(enp, bufferp, buffer_size)) != 0)
1718 		goto fail1;
1719 
1720 	return (0);
1721 
1722 fail1:
1723 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
1724 
1725 	return (rc);
1726 }
1727 
1728 
1729 	__checkReturn		efx_rc_t
1730 efx_lic_finish_partition(
1731 	__in			efx_nic_t *enp,
1732 	__in_bcount(buffer_size)
1733 				caddr_t bufferp,
1734 	__in			size_t buffer_size
1735 	)
1736 {
1737 	const efx_lic_ops_t *elop = enp->en_elop;
1738 	efx_rc_t rc;
1739 
1740 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1741 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1742 
1743 	if ((rc = elop->elo_finish_partition(enp, bufferp, buffer_size)) != 0)
1744 		goto fail1;
1745 
1746 	return (0);
1747 
1748 fail1:
1749 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
1750 
1751 	return (rc);
1752 }
1753 
1754 #endif	/* EFSYS_OPT_LICENSING */
1755