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