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