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