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