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