efx_lic.c revision 300007
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 300007 2016-05-17 06:23:50Z 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_quiet(enp, &req);
412
413	if (req.emr_rc != 0) {
414		rc = req.emr_rc;
415		goto fail1;
416	}
417
418	if (req.emr_out_length_used < MC_CMD_FC_OUT_LICENSE_LEN) {
419		rc = EMSGSIZE;
420		goto fail2;
421	}
422
423	eksp->eks_valid =
424		MCDI_OUT_DWORD(req, FC_OUT_LICENSE_VALID_KEYS);
425	eksp->eks_invalid =
426		MCDI_OUT_DWORD(req, FC_OUT_LICENSE_INVALID_KEYS);
427	eksp->eks_blacklisted =
428		MCDI_OUT_DWORD(req, FC_OUT_LICENSE_BLACKLISTED_KEYS);
429	eksp->eks_unverifiable = 0;
430	eksp->eks_wrong_node = 0;
431	eksp->eks_licensed_apps_lo = 0;
432	eksp->eks_licensed_apps_hi = 0;
433	eksp->eks_licensed_features_lo = 0;
434	eksp->eks_licensed_features_hi = 0;
435
436	return (0);
437
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_quiet(enp, &req);
939
940	if (req.emr_rc != 0) {
941		rc = req.emr_rc;
942		goto fail1;
943	}
944
945	if (req.emr_out_length_used < MC_CMD_LICENSING_V3_OUT_LEN) {
946		rc = EMSGSIZE;
947		goto fail2;
948	}
949
950	eksp->eks_valid =
951		MCDI_OUT_DWORD(req, LICENSING_V3_OUT_VALID_KEYS);
952	eksp->eks_invalid =
953		MCDI_OUT_DWORD(req, LICENSING_V3_OUT_INVALID_KEYS);
954	eksp->eks_blacklisted = 0;
955	eksp->eks_unverifiable =
956		MCDI_OUT_DWORD(req, LICENSING_V3_OUT_UNVERIFIABLE_KEYS);
957	eksp->eks_wrong_node =
958		MCDI_OUT_DWORD(req, LICENSING_V3_OUT_WRONG_NODE_KEYS);
959	eksp->eks_licensed_apps_lo =
960		MCDI_OUT_DWORD(req, LICENSING_V3_OUT_LICENSED_APPS_LO);
961	eksp->eks_licensed_apps_hi =
962		MCDI_OUT_DWORD(req, LICENSING_V3_OUT_LICENSED_APPS_HI);
963	eksp->eks_licensed_features_lo =
964		MCDI_OUT_DWORD(req, LICENSING_V3_OUT_LICENSED_FEATURES_LO);
965	eksp->eks_licensed_features_hi =
966		MCDI_OUT_DWORD(req, LICENSING_V3_OUT_LICENSED_FEATURES_HI);
967
968	return (0);
969
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_quiet(enp, &req);
1066
1067	if (req.emr_rc != 0) {
1068		rc = req.emr_rc;
1069		goto fail1;
1070	}
1071
1072	if (req.emr_out_length_used < MC_CMD_LICENSING_GET_ID_V3_OUT_LENMIN) {
1073		rc = EMSGSIZE;
1074		goto fail2;
1075	}
1076
1077	*typep = MCDI_OUT_DWORD(req, LICENSING_GET_ID_V3_OUT_LICENSE_TYPE);
1078	*lengthp = MCDI_OUT_DWORD(req, LICENSING_GET_ID_V3_OUT_LICENSE_ID_LENGTH);
1079
1080	if (bufferp == NULL) {
1081		/* modify length requirements to indicate to caller the extra buffering
1082		** needed to read the complete output.
1083		*/
1084		*lengthp += MC_CMD_LICENSING_GET_ID_V3_OUT_LENMIN;
1085	} else {
1086		/* Shift ID down to start of buffer */
1087		memmove(bufferp,
1088		  bufferp+MC_CMD_LICENSING_GET_ID_V3_OUT_LICENSE_ID_OFST,
1089		  *lengthp);
1090		memset(bufferp+(*lengthp), 0, MC_CMD_LICENSING_GET_ID_V3_OUT_LICENSE_ID_OFST);
1091	}
1092
1093	return (0);
1094
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_key_stats_t eks;
1334	efx_rc_t rc;
1335
1336	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1337	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
1338	EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_LIC));
1339
1340	switch (enp->en_family) {
1341
1342#if EFSYS_OPT_SIENA
1343	case EFX_FAMILY_SIENA:
1344		elop = &__efx_lic_v1_ops;
1345		break;
1346#endif	/* EFSYS_OPT_SIENA */
1347
1348#if EFSYS_OPT_HUNTINGTON
1349	case EFX_FAMILY_HUNTINGTON:
1350		elop = &__efx_lic_v2_ops;
1351		break;
1352#endif	/* EFSYS_OPT_HUNTINGTON */
1353
1354#if EFSYS_OPT_MEDFORD
1355	case EFX_FAMILY_MEDFORD:
1356		elop = &__efx_lic_v3_ops;
1357		break;
1358#endif	/* EFSYS_OPT_MEDFORD */
1359
1360	default:
1361		EFSYS_ASSERT(0);
1362		rc = ENOTSUP;
1363		goto fail1;
1364	}
1365
1366	enp->en_elop = elop;
1367	enp->en_mod_flags |= EFX_MOD_LIC;
1368
1369	/* Probe for support */
1370	if (efx_lic_get_key_stats(enp, &eks) == 0) {
1371		enp->en_licensing_supported = B_TRUE;
1372	} else {
1373		enp->en_licensing_supported = B_FALSE;
1374	}
1375
1376	return (0);
1377
1378fail1:
1379	EFSYS_PROBE1(fail1, efx_rc_t, rc);
1380
1381	return (rc);
1382}
1383
1384extern	__checkReturn	boolean_t
1385efx_lic_check_support(
1386	__in			efx_nic_t *enp)
1387{
1388	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1389	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
1390	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1391
1392	return enp->en_licensing_supported;
1393}
1394
1395				void
1396efx_lic_fini(
1397	__in			efx_nic_t *enp)
1398{
1399	const efx_lic_ops_t *elop = enp->en_elop;
1400
1401	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1402	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
1403	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1404
1405	enp->en_elop = NULL;
1406	enp->en_mod_flags &= ~EFX_MOD_LIC;
1407}
1408
1409
1410	__checkReturn	efx_rc_t
1411efx_lic_update_licenses(
1412	__in		efx_nic_t *enp)
1413{
1414	const efx_lic_ops_t *elop = enp->en_elop;
1415	efx_rc_t rc;
1416
1417	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1418	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1419
1420	if ((rc = elop->elo_update_licenses(enp)) != 0)
1421		goto fail1;
1422
1423	return (0);
1424
1425fail1:
1426	EFSYS_PROBE1(fail1, efx_rc_t, rc);
1427
1428	return (rc);
1429}
1430
1431	__checkReturn	efx_rc_t
1432efx_lic_get_key_stats(
1433	__in		efx_nic_t *enp,
1434	__out		efx_key_stats_t *eksp)
1435{
1436	const efx_lic_ops_t *elop = enp->en_elop;
1437	efx_rc_t rc;
1438
1439	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1440	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1441
1442	if ((rc = elop->elo_get_key_stats(enp, eksp)) != 0)
1443		goto fail1;
1444
1445	return (0);
1446
1447fail1:
1448	EFSYS_PROBE1(fail1, efx_rc_t, rc);
1449
1450	return (rc);
1451}
1452
1453	__checkReturn	efx_rc_t
1454efx_lic_app_state(
1455	__in		efx_nic_t *enp,
1456	__in		uint64_t app_id,
1457	__out		boolean_t *licensedp)
1458{
1459	const efx_lic_ops_t *elop = enp->en_elop;
1460	efx_rc_t rc;
1461
1462	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1463	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1464
1465	if (elop->elo_app_state == NULL)
1466		return (ENOTSUP);
1467
1468	if ((rc = elop->elo_app_state(enp, app_id, licensedp)) != 0)
1469		goto fail1;
1470
1471	return (0);
1472
1473fail1:
1474	EFSYS_PROBE1(fail1, efx_rc_t, rc);
1475
1476	return (rc);
1477}
1478
1479	__checkReturn	efx_rc_t
1480efx_lic_get_id(
1481	__in		efx_nic_t *enp,
1482	__in		size_t buffer_size,
1483	__out		uint32_t *typep,
1484	__out		size_t *lengthp,
1485	__out_opt	uint8_t *bufferp
1486	)
1487{
1488	const efx_lic_ops_t *elop = enp->en_elop;
1489	efx_rc_t rc;
1490
1491	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1492	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1493
1494	if (elop->elo_get_id == NULL)
1495		return (ENOTSUP);
1496
1497	if ((rc = elop->elo_get_id(enp, buffer_size, typep,
1498				    lengthp, bufferp)) != 0)
1499		goto fail1;
1500
1501	return (0);
1502
1503fail1:
1504	EFSYS_PROBE1(fail1, efx_rc_t, rc);
1505
1506	return (rc);
1507}
1508
1509/* Buffer management API - abstracts varying TLV format used for License partition */
1510
1511	__checkReturn		efx_rc_t
1512efx_lic_find_start(
1513	__in			efx_nic_t *enp,
1514	__in_bcount(buffer_size)
1515				caddr_t bufferp,
1516	__in			size_t buffer_size,
1517	__out			uint32_t *startp
1518	)
1519{
1520	const efx_lic_ops_t *elop = enp->en_elop;
1521	efx_rc_t rc;
1522
1523	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1524	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1525
1526	if ((rc = elop->elo_find_start(enp, bufferp, buffer_size, startp)) != 0)
1527		goto fail1;
1528
1529	return (0);
1530
1531fail1:
1532	EFSYS_PROBE1(fail1, efx_rc_t, rc);
1533
1534	return (rc);
1535}
1536
1537	__checkReturn		efx_rc_t
1538efx_lic_find_end(
1539	__in			efx_nic_t *enp,
1540	__in_bcount(buffer_size)
1541				caddr_t bufferp,
1542	__in			size_t buffer_size,
1543	__in			uint32_t offset,
1544	__out			uint32_t *endp
1545	)
1546{
1547	const efx_lic_ops_t *elop = enp->en_elop;
1548	efx_rc_t rc;
1549
1550	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1551	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1552
1553	if ((rc = elop->elo_find_end(enp, bufferp, buffer_size, offset, endp)) != 0)
1554		goto fail1;
1555
1556	return (0);
1557
1558fail1:
1559	EFSYS_PROBE1(fail1, efx_rc_t, rc);
1560
1561	return (rc);
1562}
1563
1564	__checkReturn	__success(return != B_FALSE)	boolean_t
1565efx_lic_find_key(
1566	__in			efx_nic_t *enp,
1567	__in_bcount(buffer_size)
1568				caddr_t bufferp,
1569	__in			size_t buffer_size,
1570	__in			uint32_t offset,
1571	__out			uint32_t *startp,
1572	__out			uint32_t *lengthp
1573	)
1574{
1575	const efx_lic_ops_t *elop = enp->en_elop;
1576	boolean_t rc;
1577
1578	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1579	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1580
1581	EFSYS_ASSERT(bufferp);
1582	EFSYS_ASSERT(startp);
1583	EFSYS_ASSERT(lengthp);
1584
1585	return (elop->elo_find_key(enp, bufferp, buffer_size, offset,
1586				    startp, lengthp));
1587}
1588
1589
1590/* Validate that the buffer contains a single key in a recognised format.
1591** An empty or terminator buffer is not accepted as a valid key.
1592*/
1593	__checkReturn	__success(return != B_FALSE)	boolean_t
1594efx_lic_validate_key(
1595	__in			efx_nic_t *enp,
1596	__in_bcount(length)	caddr_t keyp,
1597	__in			uint32_t length
1598	)
1599{
1600	const efx_lic_ops_t *elop = enp->en_elop;
1601	boolean_t rc;
1602	uint16_t tlv_type;
1603	uint16_t tlv_length;
1604
1605	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1606	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1607
1608	if ((rc = elop->elo_validate_key(enp, keyp, length)) == B_FALSE)
1609		goto fail1;
1610
1611	return (B_TRUE);
1612
1613fail1:
1614	EFSYS_PROBE1(fail1, efx_rc_t, rc);
1615
1616	return (rc);
1617}
1618
1619	__checkReturn		efx_rc_t
1620efx_lic_read_key(
1621	__in			efx_nic_t *enp,
1622	__in_bcount(buffer_size)
1623				caddr_t bufferp,
1624	__in			size_t buffer_size,
1625	__in			uint32_t offset,
1626	__in			uint32_t length,
1627	__out_bcount_part(key_max_size, *lengthp)
1628				caddr_t keyp,
1629	__in			size_t key_max_size,
1630	__out			uint32_t *lengthp
1631	)
1632{
1633	const efx_lic_ops_t *elop = enp->en_elop;
1634	efx_rc_t rc;
1635
1636	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1637	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1638
1639	if ((rc = elop->elo_read_key(enp, bufferp, buffer_size, offset,
1640				    length, keyp, key_max_size, lengthp)) != 0)
1641		goto fail1;
1642
1643	return (0);
1644
1645fail1:
1646	EFSYS_PROBE1(fail1, efx_rc_t, rc);
1647
1648	return (rc);
1649}
1650
1651	__checkReturn		efx_rc_t
1652efx_lic_write_key(
1653	__in			efx_nic_t *enp,
1654	__in_bcount(buffer_size)
1655				caddr_t bufferp,
1656	__in			size_t buffer_size,
1657	__in			uint32_t offset,
1658	__in_bcount(length)	caddr_t keyp,
1659	__in			uint32_t length,
1660	__out			uint32_t *lengthp
1661	)
1662{
1663	const efx_lic_ops_t *elop = enp->en_elop;
1664	efx_rc_t rc;
1665
1666	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1667	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1668
1669	if ((rc = elop->elo_write_key(enp, bufferp, buffer_size, offset,
1670				    keyp, length, lengthp)) != 0)
1671		goto fail1;
1672
1673	return (0);
1674
1675fail1:
1676	EFSYS_PROBE1(fail1, efx_rc_t, rc);
1677
1678	return (rc);
1679}
1680
1681	__checkReturn		efx_rc_t
1682efx_lic_delete_key(
1683	__in			efx_nic_t *enp,
1684	__in_bcount(buffer_size)
1685				caddr_t bufferp,
1686	__in			size_t buffer_size,
1687	__in			uint32_t offset,
1688	__in			uint32_t length,
1689	__in			uint32_t end,
1690	__out			uint32_t *deltap
1691	)
1692{
1693	const efx_lic_ops_t *elop = enp->en_elop;
1694	efx_rc_t rc;
1695
1696	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1697	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1698
1699	if ((rc = elop->elo_delete_key(enp, bufferp, buffer_size, offset,
1700				    length, end, deltap)) != 0)
1701		goto fail1;
1702
1703	return (0);
1704
1705fail1:
1706	EFSYS_PROBE1(fail1, efx_rc_t, rc);
1707
1708	return (rc);
1709}
1710
1711	__checkReturn		efx_rc_t
1712efx_lic_create_partition(
1713	__in			efx_nic_t *enp,
1714	__in_bcount(buffer_size)
1715				caddr_t bufferp,
1716	__in			size_t buffer_size
1717	)
1718{
1719	const efx_lic_ops_t *elop = enp->en_elop;
1720	efx_rc_t rc;
1721
1722	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1723	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1724
1725	if ((rc = elop->elo_create_partition(enp, bufferp, buffer_size)) != 0)
1726		goto fail1;
1727
1728	return (0);
1729
1730fail1:
1731	EFSYS_PROBE1(fail1, efx_rc_t, rc);
1732
1733	return (rc);
1734}
1735
1736
1737	__checkReturn		efx_rc_t
1738efx_lic_finish_partition(
1739	__in			efx_nic_t *enp,
1740	__in_bcount(buffer_size)
1741				caddr_t bufferp,
1742	__in			size_t buffer_size
1743	)
1744{
1745	const efx_lic_ops_t *elop = enp->en_elop;
1746	efx_rc_t rc;
1747
1748	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1749	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1750
1751	if ((rc = elop->elo_finish_partition(enp, bufferp, buffer_size)) != 0)
1752		goto fail1;
1753
1754	return (0);
1755
1756fail1:
1757	EFSYS_PROBE1(fail1, efx_rc_t, rc);
1758
1759	return (rc);
1760}
1761
1762#endif	/* EFSYS_OPT_LICENSING */
1763