1293901Sarybchik/*-
2300607Sarybchik * Copyright (c) 2009-2016 Solarflare Communications Inc.
3293901Sarybchik * All rights reserved.
4293901Sarybchik *
5293901Sarybchik * Redistribution and use in source and binary forms, with or without
6293901Sarybchik * modification, are permitted provided that the following conditions are met:
7293901Sarybchik *
8293901Sarybchik * 1. Redistributions of source code must retain the above copyright notice,
9293901Sarybchik *    this list of conditions and the following disclaimer.
10293901Sarybchik * 2. Redistributions in binary form must reproduce the above copyright notice,
11293901Sarybchik *    this list of conditions and the following disclaimer in the documentation
12293901Sarybchik *    and/or other materials provided with the distribution.
13293901Sarybchik *
14293901Sarybchik * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
15293901Sarybchik * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
16293901Sarybchik * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17293901Sarybchik * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
18293901Sarybchik * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19293901Sarybchik * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20293901Sarybchik * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
21293901Sarybchik * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
22293901Sarybchik * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
23293901Sarybchik * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
24293901Sarybchik * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25293901Sarybchik *
26293901Sarybchik * The views and conclusions contained in the software and documentation are
27293901Sarybchik * those of the authors and should not be interpreted as representing official
28293901Sarybchik * policies, either expressed or implied, of the FreeBSD Project.
29293901Sarybchik */
30293901Sarybchik
31293901Sarybchik#include <sys/cdefs.h>
32293901Sarybchik__FBSDID("$FreeBSD: stable/11/sys/dev/sfxge/common/efx_lic.c 342445 2018-12-25 07:27:45Z arybchik $");
33293901Sarybchik
34293901Sarybchik#include "efx.h"
35293901Sarybchik#include "efx_impl.h"
36293901Sarybchik
37293901Sarybchik#if EFSYS_OPT_LICENSING
38293901Sarybchik
39299898Sarybchik#include "ef10_tlv_layout.h"
40299898Sarybchik
41299898Sarybchik#if EFSYS_OPT_SIENA | EFSYS_OPT_HUNTINGTON
42299898Sarybchik
43299898Sarybchik	__checkReturn		efx_rc_t
44299898Sarybchikefx_lic_v1v2_find_start(
45299898Sarybchik	__in			efx_nic_t *enp,
46299898Sarybchik	__in_bcount(buffer_size)
47299898Sarybchik				caddr_t bufferp,
48299898Sarybchik	__in			size_t buffer_size,
49299898Sarybchik	__out			uint32_t *startp
50299898Sarybchik	);
51299898Sarybchik
52299898Sarybchik	__checkReturn		efx_rc_t
53299898Sarybchikefx_lic_v1v2_find_end(
54299898Sarybchik	__in			efx_nic_t *enp,
55299898Sarybchik	__in_bcount(buffer_size)
56299898Sarybchik				caddr_t bufferp,
57299898Sarybchik	__in			size_t buffer_size,
58299898Sarybchik	__in			uint32_t offset,
59299898Sarybchik	__out			uint32_t *endp
60299898Sarybchik	);
61299898Sarybchik
62299898Sarybchik	__checkReturn	__success(return != B_FALSE)	boolean_t
63299898Sarybchikefx_lic_v1v2_find_key(
64299898Sarybchik	__in			efx_nic_t *enp,
65299898Sarybchik	__in_bcount(buffer_size)
66299898Sarybchik				caddr_t bufferp,
67299898Sarybchik	__in			size_t buffer_size,
68299898Sarybchik	__in			uint32_t offset,
69299898Sarybchik	__out			uint32_t *startp,
70299898Sarybchik	__out			uint32_t *lengthp
71299898Sarybchik	);
72299898Sarybchik
73299898Sarybchik	__checkReturn	__success(return != B_FALSE)	boolean_t
74299898Sarybchikefx_lic_v1v2_validate_key(
75299898Sarybchik	__in			efx_nic_t *enp,
76299898Sarybchik	__in_bcount(length)	caddr_t keyp,
77299898Sarybchik	__in			uint32_t length
78299898Sarybchik	);
79299898Sarybchik
80299898Sarybchik	__checkReturn		efx_rc_t
81299898Sarybchikefx_lic_v1v2_read_key(
82299898Sarybchik	__in			efx_nic_t *enp,
83299898Sarybchik	__in_bcount(buffer_size)
84299898Sarybchik				caddr_t bufferp,
85299898Sarybchik	__in			size_t buffer_size,
86299898Sarybchik	__in			uint32_t offset,
87299898Sarybchik	__in			uint32_t length,
88299898Sarybchik	__out_bcount_part(key_max_size, *lengthp)
89299898Sarybchik				caddr_t keyp,
90299898Sarybchik	__in			size_t key_max_size,
91299898Sarybchik	__out			uint32_t *lengthp
92299898Sarybchik	);
93299898Sarybchik
94299898Sarybchik	__checkReturn		efx_rc_t
95299898Sarybchikefx_lic_v1v2_write_key(
96299898Sarybchik	__in			efx_nic_t *enp,
97299898Sarybchik	__in_bcount(buffer_size)
98299898Sarybchik				caddr_t bufferp,
99299898Sarybchik	__in			size_t buffer_size,
100299898Sarybchik	__in			uint32_t offset,
101299898Sarybchik	__in_bcount(length)	caddr_t keyp,
102299898Sarybchik	__in			uint32_t length,
103299898Sarybchik	__out			uint32_t *lengthp
104299898Sarybchik	);
105299898Sarybchik
106299898Sarybchik	__checkReturn		efx_rc_t
107299898Sarybchikefx_lic_v1v2_delete_key(
108299898Sarybchik	__in			efx_nic_t *enp,
109299898Sarybchik	__in_bcount(buffer_size)
110299898Sarybchik				caddr_t bufferp,
111299898Sarybchik	__in			size_t buffer_size,
112299898Sarybchik	__in			uint32_t offset,
113299898Sarybchik	__in			uint32_t length,
114299898Sarybchik	__in			uint32_t end,
115299898Sarybchik	__out			uint32_t *deltap
116299898Sarybchik	);
117299898Sarybchik
118299898Sarybchik	__checkReturn		efx_rc_t
119299898Sarybchikefx_lic_v1v2_create_partition(
120299898Sarybchik	__in			efx_nic_t *enp,
121299898Sarybchik	__in_bcount(buffer_size)
122299898Sarybchik				caddr_t bufferp,
123299898Sarybchik	__in			size_t buffer_size
124299898Sarybchik	);
125299898Sarybchik
126299898Sarybchik	__checkReturn		efx_rc_t
127299898Sarybchikefx_lic_v1v2_finish_partition(
128299898Sarybchik	__in			efx_nic_t *enp,
129299898Sarybchik	__in_bcount(buffer_size)
130299898Sarybchik				caddr_t bufferp,
131299898Sarybchik	__in			size_t buffer_size
132299898Sarybchik	);
133299898Sarybchik
134299898Sarybchik#endif	/* EFSYS_OPT_HUNTINGTON | EFSYS_OPT_SIENA */
135299898Sarybchik
136299898Sarybchik
137293901Sarybchik#if EFSYS_OPT_SIENA
138293901Sarybchik
139293901Sarybchikstatic	__checkReturn	efx_rc_t
140293901Sarybchikefx_mcdi_fc_license_update_license(
141293901Sarybchik	__in		efx_nic_t *enp);
142293901Sarybchik
143293901Sarybchikstatic	__checkReturn	efx_rc_t
144293901Sarybchikefx_mcdi_fc_license_get_key_stats(
145293901Sarybchik	__in		efx_nic_t *enp,
146293901Sarybchik	__out		efx_key_stats_t *eksp);
147293901Sarybchik
148299517Sarybchikstatic const efx_lic_ops_t	__efx_lic_v1_ops = {
149293901Sarybchik	efx_mcdi_fc_license_update_license,	/* elo_update_licenses */
150293901Sarybchik	efx_mcdi_fc_license_get_key_stats,	/* elo_get_key_stats */
151293901Sarybchik	NULL,					/* elo_app_state */
152293901Sarybchik	NULL,					/* elo_get_id */
153299898Sarybchik	efx_lic_v1v2_find_start,		/* elo_find_start */
154299898Sarybchik	efx_lic_v1v2_find_end,			/* elo_find_end */
155299898Sarybchik	efx_lic_v1v2_find_key,			/* elo_find_key */
156299898Sarybchik	efx_lic_v1v2_validate_key,		/* elo_validate_key */
157299898Sarybchik	efx_lic_v1v2_read_key,			/* elo_read_key */
158299898Sarybchik	efx_lic_v1v2_write_key,			/* elo_write_key */
159299898Sarybchik	efx_lic_v1v2_delete_key,		/* elo_delete_key */
160299898Sarybchik	efx_lic_v1v2_create_partition,		/* elo_create_partition */
161299898Sarybchik	efx_lic_v1v2_finish_partition,		/* elo_finish_partition */
162293901Sarybchik};
163293901Sarybchik
164293901Sarybchik#endif	/* EFSYS_OPT_SIENA */
165293901Sarybchik
166293901Sarybchik#if EFSYS_OPT_HUNTINGTON
167293901Sarybchik
168293901Sarybchikstatic	__checkReturn	efx_rc_t
169293901Sarybchikefx_mcdi_licensing_update_licenses(
170293901Sarybchik	__in		efx_nic_t *enp);
171293901Sarybchik
172293901Sarybchikstatic	__checkReturn	efx_rc_t
173293901Sarybchikefx_mcdi_licensing_get_key_stats(
174293901Sarybchik	__in		efx_nic_t *enp,
175293901Sarybchik	__out		efx_key_stats_t *eksp);
176293901Sarybchik
177293901Sarybchikstatic	__checkReturn	efx_rc_t
178293901Sarybchikefx_mcdi_licensed_app_state(
179293901Sarybchik	__in		efx_nic_t *enp,
180293901Sarybchik	__in		uint64_t app_id,
181293901Sarybchik	__out		boolean_t *licensedp);
182293901Sarybchik
183299517Sarybchikstatic const efx_lic_ops_t	__efx_lic_v2_ops = {
184293901Sarybchik	efx_mcdi_licensing_update_licenses,	/* elo_update_licenses */
185293901Sarybchik	efx_mcdi_licensing_get_key_stats,	/* elo_get_key_stats */
186293901Sarybchik	efx_mcdi_licensed_app_state,		/* elo_app_state */
187293901Sarybchik	NULL,					/* elo_get_id */
188299898Sarybchik	efx_lic_v1v2_find_start,		/* elo_find_start */
189299898Sarybchik	efx_lic_v1v2_find_end,			/* elo_find_end */
190299898Sarybchik	efx_lic_v1v2_find_key,			/* elo_find_key */
191299898Sarybchik	efx_lic_v1v2_validate_key,		/* elo_validate_key */
192299898Sarybchik	efx_lic_v1v2_read_key,			/* elo_read_key */
193299898Sarybchik	efx_lic_v1v2_write_key,			/* elo_write_key */
194299898Sarybchik	efx_lic_v1v2_delete_key,		/* elo_delete_key */
195299898Sarybchik	efx_lic_v1v2_create_partition,		/* elo_create_partition */
196299898Sarybchik	efx_lic_v1v2_finish_partition,		/* elo_finish_partition */
197293901Sarybchik};
198293901Sarybchik
199293901Sarybchik#endif	/* EFSYS_OPT_HUNTINGTON */
200293901Sarybchik
201293901Sarybchik#if EFSYS_OPT_MEDFORD
202293901Sarybchik
203293901Sarybchikstatic	__checkReturn	efx_rc_t
204293901Sarybchikefx_mcdi_licensing_v3_update_licenses(
205293901Sarybchik	__in		efx_nic_t *enp);
206293901Sarybchik
207293901Sarybchikstatic	__checkReturn	efx_rc_t
208293901Sarybchikefx_mcdi_licensing_v3_report_license(
209293901Sarybchik	__in		efx_nic_t *enp,
210293901Sarybchik	__out		efx_key_stats_t *eksp);
211293901Sarybchik
212293901Sarybchikstatic	__checkReturn	efx_rc_t
213293901Sarybchikefx_mcdi_licensing_v3_app_state(
214293901Sarybchik	__in		efx_nic_t *enp,
215293901Sarybchik	__in		uint64_t app_id,
216293901Sarybchik	__out		boolean_t *licensedp);
217293901Sarybchik
218293901Sarybchikstatic	__checkReturn	efx_rc_t
219293901Sarybchikefx_mcdi_licensing_v3_get_id(
220293901Sarybchik	__in		efx_nic_t *enp,
221293901Sarybchik	__in		size_t buffer_size,
222293901Sarybchik	__out		uint32_t *typep,
223293901Sarybchik	__out		size_t *lengthp,
224293901Sarybchik	__out_bcount_part_opt(buffer_size, *lengthp)
225293901Sarybchik			uint8_t *bufferp);
226293901Sarybchik
227299898Sarybchik	__checkReturn		efx_rc_t
228299898Sarybchikefx_lic_v3_find_start(
229299898Sarybchik	__in			efx_nic_t *enp,
230299898Sarybchik	__in_bcount(buffer_size)
231299898Sarybchik				caddr_t bufferp,
232299898Sarybchik	__in			size_t buffer_size,
233299898Sarybchik	__out			uint32_t *startp
234299898Sarybchik	);
235299898Sarybchik
236299898Sarybchik	__checkReturn		efx_rc_t
237299898Sarybchikefx_lic_v3_find_end(
238299898Sarybchik	__in			efx_nic_t *enp,
239299898Sarybchik	__in_bcount(buffer_size)
240299898Sarybchik				caddr_t bufferp,
241299898Sarybchik	__in			size_t buffer_size,
242299898Sarybchik	__in			uint32_t offset,
243299898Sarybchik	__out			uint32_t *endp
244299898Sarybchik	);
245299898Sarybchik
246299898Sarybchik	__checkReturn	__success(return != B_FALSE)	boolean_t
247299898Sarybchikefx_lic_v3_find_key(
248299898Sarybchik	__in			efx_nic_t *enp,
249299898Sarybchik	__in_bcount(buffer_size)
250299898Sarybchik				caddr_t bufferp,
251299898Sarybchik	__in			size_t buffer_size,
252299898Sarybchik	__in			uint32_t offset,
253299898Sarybchik	__out			uint32_t *startp,
254299898Sarybchik	__out			uint32_t *lengthp
255299898Sarybchik	);
256299898Sarybchik
257299898Sarybchik	__checkReturn	__success(return != B_FALSE)	boolean_t
258299898Sarybchikefx_lic_v3_validate_key(
259299898Sarybchik	__in			efx_nic_t *enp,
260299898Sarybchik	__in_bcount(length)	caddr_t keyp,
261299898Sarybchik	__in			uint32_t length
262299898Sarybchik	);
263299898Sarybchik
264299898Sarybchik	__checkReturn		efx_rc_t
265299898Sarybchikefx_lic_v3_read_key(
266299898Sarybchik	__in			efx_nic_t *enp,
267299898Sarybchik	__in_bcount(buffer_size)
268299898Sarybchik				caddr_t bufferp,
269299898Sarybchik	__in			size_t buffer_size,
270299898Sarybchik	__in			uint32_t offset,
271299898Sarybchik	__in			uint32_t length,
272299898Sarybchik	__out_bcount_part(key_max_size, *lengthp)
273299898Sarybchik				caddr_t keyp,
274299898Sarybchik	__in			size_t key_max_size,
275299898Sarybchik	__out			uint32_t *lengthp
276299898Sarybchik	);
277299898Sarybchik
278299898Sarybchik	__checkReturn		efx_rc_t
279299898Sarybchikefx_lic_v3_write_key(
280299898Sarybchik	__in			efx_nic_t *enp,
281299898Sarybchik	__in_bcount(buffer_size)
282299898Sarybchik				caddr_t bufferp,
283299898Sarybchik	__in			size_t buffer_size,
284299898Sarybchik	__in			uint32_t offset,
285299898Sarybchik	__in_bcount(length)	caddr_t keyp,
286299898Sarybchik	__in			uint32_t length,
287299898Sarybchik	__out			uint32_t *lengthp
288299898Sarybchik	);
289299898Sarybchik
290299898Sarybchik	__checkReturn		efx_rc_t
291299898Sarybchikefx_lic_v3_delete_key(
292299898Sarybchik	__in			efx_nic_t *enp,
293299898Sarybchik	__in_bcount(buffer_size)
294299898Sarybchik				caddr_t bufferp,
295299898Sarybchik	__in			size_t buffer_size,
296299898Sarybchik	__in			uint32_t offset,
297299898Sarybchik	__in			uint32_t length,
298299898Sarybchik	__in			uint32_t end,
299299898Sarybchik	__out			uint32_t *deltap
300299898Sarybchik	);
301299898Sarybchik
302299898Sarybchik	__checkReturn		efx_rc_t
303299898Sarybchikefx_lic_v3_create_partition(
304299898Sarybchik	__in			efx_nic_t *enp,
305299898Sarybchik	__in_bcount(buffer_size)
306299898Sarybchik				caddr_t bufferp,
307299898Sarybchik	__in			size_t buffer_size
308299898Sarybchik	);
309299898Sarybchik
310299898Sarybchik	__checkReturn		efx_rc_t
311299898Sarybchikefx_lic_v3_finish_partition(
312299898Sarybchik	__in			efx_nic_t *enp,
313299898Sarybchik	__in_bcount(buffer_size)
314299898Sarybchik				caddr_t bufferp,
315299898Sarybchik	__in			size_t buffer_size
316299898Sarybchik	);
317299898Sarybchik
318299517Sarybchikstatic const efx_lic_ops_t	__efx_lic_v3_ops = {
319293901Sarybchik	efx_mcdi_licensing_v3_update_licenses,	/* elo_update_licenses */
320293901Sarybchik	efx_mcdi_licensing_v3_report_license,	/* elo_get_key_stats */
321293901Sarybchik	efx_mcdi_licensing_v3_app_state,	/* elo_app_state */
322293901Sarybchik	efx_mcdi_licensing_v3_get_id,		/* elo_get_id */
323299898Sarybchik	efx_lic_v3_find_start,			/* elo_find_start*/
324299898Sarybchik	efx_lic_v3_find_end,			/* elo_find_end */
325299898Sarybchik	efx_lic_v3_find_key,			/* elo_find_key */
326299898Sarybchik	efx_lic_v3_validate_key,		/* elo_validate_key */
327299898Sarybchik	efx_lic_v3_read_key,			/* elo_read_key */
328299898Sarybchik	efx_lic_v3_write_key,			/* elo_write_key */
329299898Sarybchik	efx_lic_v3_delete_key,			/* elo_delete_key */
330299898Sarybchik	efx_lic_v3_create_partition,		/* elo_create_partition */
331299898Sarybchik	efx_lic_v3_finish_partition,		/* elo_finish_partition */
332293901Sarybchik};
333293901Sarybchik
334293901Sarybchik#endif	/* EFSYS_OPT_MEDFORD */
335293901Sarybchik
336293901Sarybchik
337293901Sarybchik/* V1 Licensing - used in Siena Modena only */
338293901Sarybchik
339293901Sarybchik#if EFSYS_OPT_SIENA
340293901Sarybchik
341293901Sarybchikstatic	__checkReturn	efx_rc_t
342293901Sarybchikefx_mcdi_fc_license_update_license(
343293901Sarybchik	__in		efx_nic_t *enp)
344293901Sarybchik{
345293901Sarybchik	efx_mcdi_req_t req;
346342445Sarybchik	EFX_MCDI_DECLARE_BUF(payload, MC_CMD_FC_IN_LICENSE_LEN, 0);
347293901Sarybchik	efx_rc_t rc;
348293901Sarybchik
349293901Sarybchik	EFSYS_ASSERT(enp->en_family == EFX_FAMILY_SIENA);
350293901Sarybchik
351299905Sarybchik	req.emr_cmd = MC_CMD_FC;
352293901Sarybchik	req.emr_in_buf = payload;
353293901Sarybchik	req.emr_in_length = MC_CMD_FC_IN_LICENSE_LEN;
354293901Sarybchik	req.emr_out_buf = payload;
355293901Sarybchik	req.emr_out_length = 0;
356293901Sarybchik
357299905Sarybchik	MCDI_IN_SET_DWORD(req, FC_IN_CMD,
358299905Sarybchik	    MC_CMD_FC_OP_LICENSE);
359299905Sarybchik
360293901Sarybchik	MCDI_IN_SET_DWORD(req, FC_IN_LICENSE_OP,
361293901Sarybchik	    MC_CMD_FC_IN_LICENSE_UPDATE_LICENSE);
362293901Sarybchik
363293901Sarybchik	efx_mcdi_execute(enp, &req);
364293901Sarybchik
365293901Sarybchik	if (req.emr_rc != 0) {
366293901Sarybchik		rc = req.emr_rc;
367293901Sarybchik		goto fail1;
368293901Sarybchik	}
369293901Sarybchik
370293901Sarybchik	if (req.emr_out_length_used != 0) {
371293901Sarybchik		rc = EIO;
372293901Sarybchik		goto fail2;
373293901Sarybchik	}
374293901Sarybchik
375293901Sarybchik	return (0);
376293901Sarybchik
377293901Sarybchikfail2:
378293901Sarybchik	EFSYS_PROBE(fail2);
379293901Sarybchikfail1:
380293901Sarybchik	EFSYS_PROBE1(fail1, efx_rc_t, rc);
381293901Sarybchik
382293901Sarybchik	return (rc);
383293901Sarybchik}
384293901Sarybchik
385293901Sarybchikstatic	__checkReturn	efx_rc_t
386293901Sarybchikefx_mcdi_fc_license_get_key_stats(
387293901Sarybchik	__in		efx_nic_t *enp,
388293901Sarybchik	__out		efx_key_stats_t *eksp)
389293901Sarybchik{
390293901Sarybchik	efx_mcdi_req_t req;
391342445Sarybchik	EFX_MCDI_DECLARE_BUF(payload, MC_CMD_FC_IN_LICENSE_LEN,
392342445Sarybchik		MC_CMD_FC_OUT_LICENSE_LEN);
393293901Sarybchik	efx_rc_t rc;
394293901Sarybchik
395293901Sarybchik	EFSYS_ASSERT(enp->en_family == EFX_FAMILY_SIENA);
396293901Sarybchik
397299905Sarybchik	req.emr_cmd = MC_CMD_FC;
398293901Sarybchik	req.emr_in_buf = payload;
399293901Sarybchik	req.emr_in_length = MC_CMD_FC_IN_LICENSE_LEN;
400293901Sarybchik	req.emr_out_buf = payload;
401293901Sarybchik	req.emr_out_length = MC_CMD_FC_OUT_LICENSE_LEN;
402293901Sarybchik
403299905Sarybchik	MCDI_IN_SET_DWORD(req, FC_IN_CMD,
404299905Sarybchik	    MC_CMD_FC_OP_LICENSE);
405299905Sarybchik
406293901Sarybchik	MCDI_IN_SET_DWORD(req, FC_IN_LICENSE_OP,
407293901Sarybchik	    MC_CMD_FC_IN_LICENSE_GET_KEY_STATS);
408293901Sarybchik
409299923Sarybchik	efx_mcdi_execute_quiet(enp, &req);
410293901Sarybchik
411293901Sarybchik	if (req.emr_rc != 0) {
412293901Sarybchik		rc = req.emr_rc;
413293901Sarybchik		goto fail1;
414293901Sarybchik	}
415293901Sarybchik
416293901Sarybchik	if (req.emr_out_length_used < MC_CMD_FC_OUT_LICENSE_LEN) {
417293901Sarybchik		rc = EMSGSIZE;
418293901Sarybchik		goto fail2;
419293901Sarybchik	}
420293901Sarybchik
421293901Sarybchik	eksp->eks_valid =
422293901Sarybchik		MCDI_OUT_DWORD(req, FC_OUT_LICENSE_VALID_KEYS);
423293901Sarybchik	eksp->eks_invalid =
424293901Sarybchik		MCDI_OUT_DWORD(req, FC_OUT_LICENSE_INVALID_KEYS);
425293901Sarybchik	eksp->eks_blacklisted =
426293901Sarybchik		MCDI_OUT_DWORD(req, FC_OUT_LICENSE_BLACKLISTED_KEYS);
427293901Sarybchik	eksp->eks_unverifiable = 0;
428293901Sarybchik	eksp->eks_wrong_node = 0;
429293901Sarybchik	eksp->eks_licensed_apps_lo = 0;
430293901Sarybchik	eksp->eks_licensed_apps_hi = 0;
431293901Sarybchik	eksp->eks_licensed_features_lo = 0;
432293901Sarybchik	eksp->eks_licensed_features_hi = 0;
433293901Sarybchik
434293901Sarybchik	return (0);
435293901Sarybchik
436293901Sarybchikfail2:
437293901Sarybchik	EFSYS_PROBE(fail2);
438293901Sarybchikfail1:
439293901Sarybchik	EFSYS_PROBE1(fail1, efx_rc_t, rc);
440293901Sarybchik
441293901Sarybchik	return (rc);
442293901Sarybchik}
443293901Sarybchik
444293901Sarybchik#endif	/* EFSYS_OPT_SIENA */
445293901Sarybchik
446299898Sarybchik/* V1 and V2 Partition format - based on a 16-bit TLV format */
447299898Sarybchik
448299898Sarybchik#if EFSYS_OPT_SIENA | EFSYS_OPT_HUNTINGTON
449299898Sarybchik
450299898Sarybchik/*
451299898Sarybchik * V1/V2 format - defined in SF-108542-TC section 4.2:
452299898Sarybchik *  Type (T):   16bit - revision/HMAC algorithm
453299898Sarybchik *  Length (L): 16bit - value length in bytes
454299898Sarybchik *  Value (V):  L bytes - payload
455299898Sarybchik */
456299898Sarybchik#define EFX_LICENSE_V1V2_PAYLOAD_LENGTH_MAX    (256)
457310841Sarybchik#define EFX_LICENSE_V1V2_HEADER_LENGTH         (2 * sizeof(uint16_t))
458299898Sarybchik
459299898Sarybchik	__checkReturn		efx_rc_t
460299898Sarybchikefx_lic_v1v2_find_start(
461299898Sarybchik	__in			efx_nic_t *enp,
462299898Sarybchik	__in_bcount(buffer_size)
463299898Sarybchik				caddr_t bufferp,
464299898Sarybchik	__in			size_t buffer_size,
465299898Sarybchik	__out			uint32_t *startp
466299898Sarybchik	)
467299898Sarybchik{
468299898Sarybchik	_NOTE(ARGUNUSED(enp, bufferp, buffer_size))
469299898Sarybchik
470299898Sarybchik	*startp = 0;
471299898Sarybchik	return (0);
472299898Sarybchik}
473299898Sarybchik
474299898Sarybchik	__checkReturn		efx_rc_t
475299898Sarybchikefx_lic_v1v2_find_end(
476299898Sarybchik	__in			efx_nic_t *enp,
477299898Sarybchik	__in_bcount(buffer_size)
478299898Sarybchik				caddr_t bufferp,
479299898Sarybchik	__in			size_t buffer_size,
480299898Sarybchik	__in			uint32_t offset,
481299898Sarybchik	__out			uint32_t *endp
482299898Sarybchik	)
483299898Sarybchik{
484299898Sarybchik	_NOTE(ARGUNUSED(enp, bufferp, buffer_size))
485299898Sarybchik
486299898Sarybchik	*endp = offset + EFX_LICENSE_V1V2_HEADER_LENGTH;
487299898Sarybchik	return (0);
488299898Sarybchik}
489299898Sarybchik
490299898Sarybchik	__checkReturn	__success(return != B_FALSE)	boolean_t
491299898Sarybchikefx_lic_v1v2_find_key(
492299898Sarybchik	__in			efx_nic_t *enp,
493299898Sarybchik	__in_bcount(buffer_size)
494299898Sarybchik				caddr_t bufferp,
495299898Sarybchik	__in			size_t buffer_size,
496299898Sarybchik	__in			uint32_t offset,
497299898Sarybchik	__out			uint32_t *startp,
498299898Sarybchik	__out			uint32_t *lengthp
499299898Sarybchik	)
500299898Sarybchik{
501299898Sarybchik	boolean_t found;
502299898Sarybchik	uint16_t tlv_type;
503299898Sarybchik	uint16_t tlv_length;
504299898Sarybchik
505299898Sarybchik	_NOTE(ARGUNUSED(enp))
506299898Sarybchik
507301125Sarybchik	if ((size_t)buffer_size - offset < EFX_LICENSE_V1V2_HEADER_LENGTH)
508299898Sarybchik		goto fail1;
509299898Sarybchik
510310922Sarybchik	tlv_type = __LE_TO_CPU_16(((uint16_t *)&bufferp[offset])[0]);
511310922Sarybchik	tlv_length = __LE_TO_CPU_16(((uint16_t *)&bufferp[offset])[1]);
512299898Sarybchik	if ((tlv_length > EFX_LICENSE_V1V2_PAYLOAD_LENGTH_MAX) ||
513299898Sarybchik	    (tlv_type == 0 && tlv_length == 0)) {
514299898Sarybchik		found = B_FALSE;
515299898Sarybchik	} else {
516299898Sarybchik		*startp = offset;
517299898Sarybchik		*lengthp = tlv_length + EFX_LICENSE_V1V2_HEADER_LENGTH;
518299898Sarybchik		found = B_TRUE;
519299898Sarybchik	}
520299898Sarybchik	return (found);
521299898Sarybchik
522299898Sarybchikfail1:
523342426Sarybchik	EFSYS_PROBE1(fail1, boolean_t, B_FALSE);
524299898Sarybchik
525299898Sarybchik	return (B_FALSE);
526299898Sarybchik}
527299898Sarybchik
528299898Sarybchik	__checkReturn	__success(return != B_FALSE)	boolean_t
529299898Sarybchikefx_lic_v1v2_validate_key(
530299898Sarybchik	__in			efx_nic_t *enp,
531299898Sarybchik	__in_bcount(length)	caddr_t keyp,
532299898Sarybchik	__in			uint32_t length
533299898Sarybchik	)
534299898Sarybchik{
535299898Sarybchik	uint16_t tlv_type;
536299898Sarybchik	uint16_t tlv_length;
537299898Sarybchik
538299898Sarybchik	_NOTE(ARGUNUSED(enp))
539299898Sarybchik
540299898Sarybchik	if (length < EFX_LICENSE_V1V2_HEADER_LENGTH) {
541299898Sarybchik		goto fail1;
542299898Sarybchik	}
543299898Sarybchik
544310922Sarybchik	tlv_type = __LE_TO_CPU_16(((uint16_t *)keyp)[0]);
545310922Sarybchik	tlv_length = __LE_TO_CPU_16(((uint16_t *)keyp)[1]);
546299898Sarybchik
547301125Sarybchik	if (tlv_length > EFX_LICENSE_V1V2_PAYLOAD_LENGTH_MAX) {
548299898Sarybchik		goto fail2;
549299898Sarybchik	}
550299898Sarybchik	if (tlv_type == 0) {
551299898Sarybchik		goto fail3;
552299898Sarybchik	}
553299898Sarybchik	if ((tlv_length + EFX_LICENSE_V1V2_HEADER_LENGTH) != length) {
554299898Sarybchik		goto fail4;
555299898Sarybchik	}
556299898Sarybchik
557299898Sarybchik	return (B_TRUE);
558299898Sarybchik
559299898Sarybchikfail4:
560299898Sarybchik	EFSYS_PROBE(fail4);
561299898Sarybchikfail3:
562299898Sarybchik	EFSYS_PROBE(fail3);
563299898Sarybchikfail2:
564299898Sarybchik	EFSYS_PROBE(fail2);
565299898Sarybchikfail1:
566342426Sarybchik	EFSYS_PROBE1(fail1, boolean_t, B_FALSE);
567299898Sarybchik
568299898Sarybchik	return (B_FALSE);
569299898Sarybchik}
570299898Sarybchik
571299898Sarybchik
572299898Sarybchik	__checkReturn		efx_rc_t
573299898Sarybchikefx_lic_v1v2_read_key(
574299898Sarybchik	__in			efx_nic_t *enp,
575299898Sarybchik	__in_bcount(buffer_size)
576299898Sarybchik				caddr_t bufferp,
577299898Sarybchik	__in			size_t buffer_size,
578299898Sarybchik	__in			uint32_t offset,
579299898Sarybchik	__in			uint32_t length,
580299898Sarybchik	__out_bcount_part(key_max_size, *lengthp)
581299898Sarybchik				caddr_t keyp,
582299898Sarybchik	__in			size_t key_max_size,
583299898Sarybchik	__out			uint32_t *lengthp
584299898Sarybchik	)
585299898Sarybchik{
586299898Sarybchik	efx_rc_t rc;
587299898Sarybchik
588342430Sarybchik	_NOTE(ARGUNUSED(enp, buffer_size))
589299898Sarybchik	EFSYS_ASSERT(length <= (EFX_LICENSE_V1V2_PAYLOAD_LENGTH_MAX +
590299898Sarybchik	    EFX_LICENSE_V1V2_HEADER_LENGTH));
591299898Sarybchik
592299898Sarybchik	if (key_max_size < length) {
593299898Sarybchik		rc = ENOSPC;
594299898Sarybchik		goto fail1;
595299898Sarybchik	}
596299898Sarybchik	memcpy(keyp, &bufferp[offset], length);
597299898Sarybchik
598299898Sarybchik	*lengthp = length;
599299898Sarybchik
600299898Sarybchik	return (0);
601299898Sarybchik
602299898Sarybchikfail1:
603299898Sarybchik	EFSYS_PROBE1(fail1, efx_rc_t, rc);
604299898Sarybchik
605299898Sarybchik	return (rc);
606299898Sarybchik}
607299898Sarybchik
608299898Sarybchik	__checkReturn		efx_rc_t
609299898Sarybchikefx_lic_v1v2_write_key(
610299898Sarybchik	__in			efx_nic_t *enp,
611299898Sarybchik	__in_bcount(buffer_size)
612299898Sarybchik				caddr_t bufferp,
613299898Sarybchik	__in			size_t buffer_size,
614299898Sarybchik	__in			uint32_t offset,
615299898Sarybchik	__in_bcount(length)	caddr_t keyp,
616299898Sarybchik	__in			uint32_t length,
617299898Sarybchik	__out			uint32_t *lengthp
618299898Sarybchik	)
619299898Sarybchik{
620299898Sarybchik	efx_rc_t rc;
621299898Sarybchik
622299898Sarybchik	_NOTE(ARGUNUSED(enp))
623299898Sarybchik	EFSYS_ASSERT(length <= (EFX_LICENSE_V1V2_PAYLOAD_LENGTH_MAX +
624299898Sarybchik	    EFX_LICENSE_V1V2_HEADER_LENGTH));
625299898Sarybchik
626310916Sarybchik	/* Ensure space for terminator remains */
627299898Sarybchik	if ((offset + length) >
628310919Sarybchik	    (buffer_size - EFX_LICENSE_V1V2_HEADER_LENGTH)) {
629299898Sarybchik		rc = ENOSPC;
630299898Sarybchik		goto fail1;
631299898Sarybchik	}
632299898Sarybchik
633299898Sarybchik	memcpy(bufferp + offset, keyp, length);
634299898Sarybchik
635299898Sarybchik	*lengthp = length;
636299898Sarybchik
637299898Sarybchik	return (0);
638299898Sarybchik
639299898Sarybchikfail1:
640299898Sarybchik	EFSYS_PROBE1(fail1, efx_rc_t, rc);
641299898Sarybchik
642299898Sarybchik	return (rc);
643299898Sarybchik}
644299898Sarybchik
645299898Sarybchik	__checkReturn		efx_rc_t
646299898Sarybchikefx_lic_v1v2_delete_key(
647299898Sarybchik	__in			efx_nic_t *enp,
648299898Sarybchik	__in_bcount(buffer_size)
649299898Sarybchik				caddr_t bufferp,
650299898Sarybchik	__in			size_t buffer_size,
651299898Sarybchik	__in			uint32_t offset,
652299898Sarybchik	__in			uint32_t length,
653299898Sarybchik	__in			uint32_t end,
654299898Sarybchik	__out			uint32_t *deltap
655299898Sarybchik	)
656299898Sarybchik{
657299898Sarybchik	uint32_t move_start = offset + length;
658299898Sarybchik	uint32_t move_length = end - move_start;
659299898Sarybchik
660342430Sarybchik	_NOTE(ARGUNUSED(enp, buffer_size))
661299898Sarybchik	EFSYS_ASSERT(end <= buffer_size);
662299898Sarybchik
663310916Sarybchik	/* Shift everything after the key down */
664299898Sarybchik	memmove(bufferp + offset, bufferp + move_start, move_length);
665299898Sarybchik
666299898Sarybchik	*deltap = length;
667299898Sarybchik
668299898Sarybchik	return (0);
669299898Sarybchik}
670299898Sarybchik
671299898Sarybchik	__checkReturn		efx_rc_t
672299898Sarybchikefx_lic_v1v2_create_partition(
673299898Sarybchik	__in			efx_nic_t *enp,
674299898Sarybchik	__in_bcount(buffer_size)
675299898Sarybchik				caddr_t bufferp,
676299898Sarybchik	__in			size_t buffer_size
677299898Sarybchik	)
678299898Sarybchik{
679342430Sarybchik	_NOTE(ARGUNUSED(enp, buffer_size))
680299898Sarybchik	EFSYS_ASSERT(EFX_LICENSE_V1V2_HEADER_LENGTH <= buffer_size);
681299898Sarybchik
682310916Sarybchik	/* Write terminator */
683299898Sarybchik	memset(bufferp, '\0', EFX_LICENSE_V1V2_HEADER_LENGTH);
684299898Sarybchik	return (0);
685299898Sarybchik}
686299898Sarybchik
687299898Sarybchik
688299898Sarybchik	__checkReturn		efx_rc_t
689299898Sarybchikefx_lic_v1v2_finish_partition(
690299898Sarybchik	__in			efx_nic_t *enp,
691299898Sarybchik	__in_bcount(buffer_size)
692299898Sarybchik				caddr_t bufferp,
693299898Sarybchik	__in			size_t buffer_size
694299898Sarybchik	)
695299898Sarybchik{
696299898Sarybchik	_NOTE(ARGUNUSED(enp, bufferp, buffer_size))
697299898Sarybchik
698299898Sarybchik	return (0);
699299898Sarybchik}
700299898Sarybchik
701299898Sarybchik#endif	/* EFSYS_OPT_HUNTINGTON | EFSYS_OPT_SIENA */
702299898Sarybchik
703299898Sarybchik
704293901Sarybchik/* V2 Licensing - used by Huntington family only. See SF-113611-TC */
705293901Sarybchik
706293901Sarybchik#if EFSYS_OPT_HUNTINGTON
707293901Sarybchik
708293901Sarybchikstatic	__checkReturn	efx_rc_t
709293901Sarybchikefx_mcdi_licensed_app_state(
710293901Sarybchik	__in		efx_nic_t *enp,
711293901Sarybchik	__in		uint64_t app_id,
712293901Sarybchik	__out		boolean_t *licensedp)
713293901Sarybchik{
714293901Sarybchik	efx_mcdi_req_t req;
715342445Sarybchik	EFX_MCDI_DECLARE_BUF(payload, MC_CMD_GET_LICENSED_APP_STATE_IN_LEN,
716342445Sarybchik		MC_CMD_GET_LICENSED_APP_STATE_OUT_LEN);
717293901Sarybchik	uint32_t app_state;
718293901Sarybchik	efx_rc_t rc;
719293901Sarybchik
720293901Sarybchik	EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON);
721293901Sarybchik
722293901Sarybchik	/* V2 licensing supports 32bit app id only */
723293901Sarybchik	if ((app_id >> 32) != 0) {
724293901Sarybchik		rc = EINVAL;
725293901Sarybchik		goto fail1;
726293901Sarybchik	}
727293901Sarybchik
728293901Sarybchik	req.emr_cmd = MC_CMD_GET_LICENSED_APP_STATE;
729293901Sarybchik	req.emr_in_buf = payload;
730293901Sarybchik	req.emr_in_length = MC_CMD_GET_LICENSED_APP_STATE_IN_LEN;
731293901Sarybchik	req.emr_out_buf = payload;
732293901Sarybchik	req.emr_out_length = MC_CMD_GET_LICENSED_APP_STATE_OUT_LEN;
733293901Sarybchik
734293901Sarybchik	MCDI_IN_SET_DWORD(req, GET_LICENSED_APP_STATE_IN_APP_ID,
735293901Sarybchik		    app_id & 0xffffffff);
736293901Sarybchik
737293901Sarybchik	efx_mcdi_execute(enp, &req);
738293901Sarybchik
739293901Sarybchik	if (req.emr_rc != 0) {
740293901Sarybchik		rc = req.emr_rc;
741293901Sarybchik		goto fail2;
742293901Sarybchik	}
743293901Sarybchik
744293901Sarybchik	if (req.emr_out_length_used < MC_CMD_GET_LICENSED_APP_STATE_OUT_LEN) {
745293901Sarybchik		rc = EMSGSIZE;
746293901Sarybchik		goto fail3;
747293901Sarybchik	}
748293901Sarybchik
749293901Sarybchik	app_state = (MCDI_OUT_DWORD(req, GET_LICENSED_APP_STATE_OUT_STATE));
750293901Sarybchik	if (app_state != MC_CMD_GET_LICENSED_APP_STATE_OUT_NOT_LICENSED) {
751293901Sarybchik		*licensedp = B_TRUE;
752293901Sarybchik	} else {
753293901Sarybchik		*licensedp = B_FALSE;
754293901Sarybchik	}
755293901Sarybchik
756293901Sarybchik	return (0);
757293901Sarybchik
758293901Sarybchikfail3:
759293901Sarybchik	EFSYS_PROBE(fail3);
760293901Sarybchikfail2:
761293901Sarybchik	EFSYS_PROBE(fail2);
762293901Sarybchikfail1:
763293901Sarybchik	EFSYS_PROBE1(fail1, efx_rc_t, rc);
764293901Sarybchik
765293901Sarybchik	return (rc);
766293901Sarybchik}
767293901Sarybchik
768293901Sarybchikstatic	__checkReturn	efx_rc_t
769293901Sarybchikefx_mcdi_licensing_update_licenses(
770293901Sarybchik	__in		efx_nic_t *enp)
771293901Sarybchik{
772293901Sarybchik	efx_mcdi_req_t req;
773342445Sarybchik	EFX_MCDI_DECLARE_BUF(payload, MC_CMD_LICENSING_IN_LEN, 0);
774293901Sarybchik	efx_rc_t rc;
775293901Sarybchik
776293901Sarybchik	EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON);
777293901Sarybchik
778293901Sarybchik	req.emr_cmd = MC_CMD_LICENSING;
779293901Sarybchik	req.emr_in_buf = payload;
780293901Sarybchik	req.emr_in_length = MC_CMD_LICENSING_IN_LEN;
781293901Sarybchik	req.emr_out_buf = payload;
782293901Sarybchik	req.emr_out_length = 0;
783293901Sarybchik
784293901Sarybchik	MCDI_IN_SET_DWORD(req, LICENSING_IN_OP,
785293901Sarybchik	    MC_CMD_LICENSING_IN_OP_UPDATE_LICENSE);
786293901Sarybchik
787293901Sarybchik	efx_mcdi_execute(enp, &req);
788293901Sarybchik
789293901Sarybchik	if (req.emr_rc != 0) {
790293901Sarybchik		rc = req.emr_rc;
791293901Sarybchik		goto fail1;
792293901Sarybchik	}
793293901Sarybchik
794293901Sarybchik	if (req.emr_out_length_used != 0) {
795293901Sarybchik		rc = EIO;
796293901Sarybchik		goto fail2;
797293901Sarybchik	}
798293901Sarybchik
799293901Sarybchik	return (0);
800293901Sarybchik
801293901Sarybchikfail2:
802293901Sarybchik	EFSYS_PROBE(fail2);
803293901Sarybchikfail1:
804293901Sarybchik	EFSYS_PROBE1(fail1, efx_rc_t, rc);
805293901Sarybchik
806293901Sarybchik	return (rc);
807293901Sarybchik}
808293901Sarybchik
809293901Sarybchikstatic	__checkReturn	efx_rc_t
810293901Sarybchikefx_mcdi_licensing_get_key_stats(
811293901Sarybchik	__in		efx_nic_t *enp,
812293901Sarybchik	__out		efx_key_stats_t *eksp)
813293901Sarybchik{
814293901Sarybchik	efx_mcdi_req_t req;
815342445Sarybchik	EFX_MCDI_DECLARE_BUF(payload, MC_CMD_LICENSING_IN_LEN,
816342445Sarybchik		MC_CMD_LICENSING_OUT_LEN);
817293901Sarybchik	efx_rc_t rc;
818293901Sarybchik
819293901Sarybchik	EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON);
820293901Sarybchik
821293901Sarybchik	req.emr_cmd = MC_CMD_LICENSING;
822293901Sarybchik	req.emr_in_buf = payload;
823293901Sarybchik	req.emr_in_length = MC_CMD_LICENSING_IN_LEN;
824293901Sarybchik	req.emr_out_buf = payload;
825293901Sarybchik	req.emr_out_length = MC_CMD_LICENSING_OUT_LEN;
826293901Sarybchik
827293901Sarybchik	MCDI_IN_SET_DWORD(req, LICENSING_IN_OP,
828293901Sarybchik	    MC_CMD_LICENSING_IN_OP_GET_KEY_STATS);
829293901Sarybchik
830293901Sarybchik	efx_mcdi_execute(enp, &req);
831293901Sarybchik
832293901Sarybchik	if (req.emr_rc != 0) {
833293901Sarybchik		rc = req.emr_rc;
834293901Sarybchik		goto fail1;
835293901Sarybchik	}
836293901Sarybchik
837293901Sarybchik	if (req.emr_out_length_used < MC_CMD_LICENSING_OUT_LEN) {
838293901Sarybchik		rc = EMSGSIZE;
839293901Sarybchik		goto fail2;
840293901Sarybchik	}
841293901Sarybchik
842293901Sarybchik	eksp->eks_valid =
843293901Sarybchik		MCDI_OUT_DWORD(req, LICENSING_OUT_VALID_APP_KEYS);
844293901Sarybchik	eksp->eks_invalid =
845293901Sarybchik		MCDI_OUT_DWORD(req, LICENSING_OUT_INVALID_APP_KEYS);
846293901Sarybchik	eksp->eks_blacklisted =
847293901Sarybchik		MCDI_OUT_DWORD(req, LICENSING_OUT_BLACKLISTED_APP_KEYS);
848293901Sarybchik	eksp->eks_unverifiable =
849293901Sarybchik		MCDI_OUT_DWORD(req, LICENSING_OUT_UNVERIFIABLE_APP_KEYS);
850293901Sarybchik	eksp->eks_wrong_node =
851293901Sarybchik		MCDI_OUT_DWORD(req, LICENSING_OUT_WRONG_NODE_APP_KEYS);
852293901Sarybchik	eksp->eks_licensed_apps_lo = 0;
853293901Sarybchik	eksp->eks_licensed_apps_hi = 0;
854293901Sarybchik	eksp->eks_licensed_features_lo = 0;
855293901Sarybchik	eksp->eks_licensed_features_hi = 0;
856293901Sarybchik
857293901Sarybchik	return (0);
858293901Sarybchik
859293901Sarybchikfail2:
860293901Sarybchik	EFSYS_PROBE(fail2);
861293901Sarybchikfail1:
862293901Sarybchik	EFSYS_PROBE1(fail1, efx_rc_t, rc);
863293901Sarybchik
864293901Sarybchik	return (rc);
865293901Sarybchik}
866293901Sarybchik
867293901Sarybchik#endif	/* EFSYS_OPT_HUNTINGTON */
868293901Sarybchik
869293901Sarybchik/* V3 Licensing - used starting from Medford family. See SF-114884-SW */
870293901Sarybchik
871293901Sarybchik#if EFSYS_OPT_MEDFORD
872293901Sarybchik
873293901Sarybchikstatic	__checkReturn	efx_rc_t
874293901Sarybchikefx_mcdi_licensing_v3_update_licenses(
875293901Sarybchik	__in		efx_nic_t *enp)
876293901Sarybchik{
877293901Sarybchik	efx_mcdi_req_t req;
878342445Sarybchik	EFX_MCDI_DECLARE_BUF(payload, MC_CMD_LICENSING_V3_IN_LEN, 0);
879293901Sarybchik	efx_rc_t rc;
880293901Sarybchik
881293901Sarybchik	EFSYS_ASSERT(enp->en_family == EFX_FAMILY_MEDFORD);
882293901Sarybchik
883293901Sarybchik	req.emr_cmd = MC_CMD_LICENSING_V3;
884293901Sarybchik	req.emr_in_buf = payload;
885293901Sarybchik	req.emr_in_length = MC_CMD_LICENSING_V3_IN_LEN;
886293901Sarybchik	req.emr_out_buf = NULL;
887293901Sarybchik	req.emr_out_length = 0;
888293901Sarybchik
889293901Sarybchik	MCDI_IN_SET_DWORD(req, LICENSING_V3_IN_OP,
890293901Sarybchik	    MC_CMD_LICENSING_V3_IN_OP_UPDATE_LICENSE);
891293901Sarybchik
892293901Sarybchik	efx_mcdi_execute(enp, &req);
893293901Sarybchik
894293901Sarybchik	if (req.emr_rc != 0) {
895293901Sarybchik		rc = req.emr_rc;
896293901Sarybchik		goto fail1;
897293901Sarybchik	}
898293901Sarybchik
899293901Sarybchik	return (0);
900293901Sarybchik
901293901Sarybchikfail1:
902293901Sarybchik	EFSYS_PROBE1(fail1, efx_rc_t, rc);
903293901Sarybchik
904293901Sarybchik	return (rc);
905293901Sarybchik}
906293901Sarybchik
907293901Sarybchikstatic	__checkReturn	efx_rc_t
908293901Sarybchikefx_mcdi_licensing_v3_report_license(
909293901Sarybchik	__in		efx_nic_t *enp,
910293901Sarybchik	__out		efx_key_stats_t *eksp)
911293901Sarybchik{
912293901Sarybchik	efx_mcdi_req_t req;
913342445Sarybchik	EFX_MCDI_DECLARE_BUF(payload, MC_CMD_LICENSING_V3_IN_LEN,
914342445Sarybchik		MC_CMD_LICENSING_V3_OUT_LEN);
915293901Sarybchik	efx_rc_t rc;
916293901Sarybchik
917293901Sarybchik	EFSYS_ASSERT(enp->en_family == EFX_FAMILY_MEDFORD);
918293901Sarybchik
919293901Sarybchik	req.emr_cmd = MC_CMD_LICENSING_V3;
920293901Sarybchik	req.emr_in_buf = payload;
921293901Sarybchik	req.emr_in_length = MC_CMD_LICENSING_V3_IN_LEN;
922293901Sarybchik	req.emr_out_buf = payload;
923293901Sarybchik	req.emr_out_length = MC_CMD_LICENSING_V3_OUT_LEN;
924293901Sarybchik
925293901Sarybchik	MCDI_IN_SET_DWORD(req, LICENSING_V3_IN_OP,
926293901Sarybchik	    MC_CMD_LICENSING_V3_IN_OP_REPORT_LICENSE);
927293901Sarybchik
928299923Sarybchik	efx_mcdi_execute_quiet(enp, &req);
929293901Sarybchik
930293901Sarybchik	if (req.emr_rc != 0) {
931293901Sarybchik		rc = req.emr_rc;
932293901Sarybchik		goto fail1;
933293901Sarybchik	}
934293901Sarybchik
935293901Sarybchik	if (req.emr_out_length_used < MC_CMD_LICENSING_V3_OUT_LEN) {
936293901Sarybchik		rc = EMSGSIZE;
937293901Sarybchik		goto fail2;
938293901Sarybchik	}
939293901Sarybchik
940293901Sarybchik	eksp->eks_valid =
941293901Sarybchik		MCDI_OUT_DWORD(req, LICENSING_V3_OUT_VALID_KEYS);
942293901Sarybchik	eksp->eks_invalid =
943293901Sarybchik		MCDI_OUT_DWORD(req, LICENSING_V3_OUT_INVALID_KEYS);
944293901Sarybchik	eksp->eks_blacklisted = 0;
945293901Sarybchik	eksp->eks_unverifiable =
946293901Sarybchik		MCDI_OUT_DWORD(req, LICENSING_V3_OUT_UNVERIFIABLE_KEYS);
947293901Sarybchik	eksp->eks_wrong_node =
948293901Sarybchik		MCDI_OUT_DWORD(req, LICENSING_V3_OUT_WRONG_NODE_KEYS);
949293901Sarybchik	eksp->eks_licensed_apps_lo =
950293901Sarybchik		MCDI_OUT_DWORD(req, LICENSING_V3_OUT_LICENSED_APPS_LO);
951293901Sarybchik	eksp->eks_licensed_apps_hi =
952293901Sarybchik		MCDI_OUT_DWORD(req, LICENSING_V3_OUT_LICENSED_APPS_HI);
953293901Sarybchik	eksp->eks_licensed_features_lo =
954293901Sarybchik		MCDI_OUT_DWORD(req, LICENSING_V3_OUT_LICENSED_FEATURES_LO);
955293901Sarybchik	eksp->eks_licensed_features_hi =
956293901Sarybchik		MCDI_OUT_DWORD(req, LICENSING_V3_OUT_LICENSED_FEATURES_HI);
957293901Sarybchik
958293901Sarybchik	return (0);
959293901Sarybchik
960293901Sarybchikfail2:
961293901Sarybchik	EFSYS_PROBE(fail2);
962293901Sarybchikfail1:
963293901Sarybchik	EFSYS_PROBE1(fail1, efx_rc_t, rc);
964293901Sarybchik
965293901Sarybchik	return (rc);
966293901Sarybchik}
967293901Sarybchik
968293901Sarybchikstatic	__checkReturn	efx_rc_t
969293901Sarybchikefx_mcdi_licensing_v3_app_state(
970293901Sarybchik	__in		efx_nic_t *enp,
971293901Sarybchik	__in		uint64_t app_id,
972293901Sarybchik	__out		boolean_t *licensedp)
973293901Sarybchik{
974293901Sarybchik	efx_mcdi_req_t req;
975342445Sarybchik	EFX_MCDI_DECLARE_BUF(payload, MC_CMD_GET_LICENSED_V3_APP_STATE_IN_LEN,
976342445Sarybchik		MC_CMD_GET_LICENSED_V3_APP_STATE_OUT_LEN);
977293901Sarybchik	uint32_t app_state;
978293901Sarybchik	efx_rc_t rc;
979293901Sarybchik
980293901Sarybchik	EFSYS_ASSERT(enp->en_family == EFX_FAMILY_MEDFORD);
981293901Sarybchik
982293901Sarybchik	req.emr_cmd = MC_CMD_GET_LICENSED_V3_APP_STATE;
983293901Sarybchik	req.emr_in_buf = payload;
984293901Sarybchik	req.emr_in_length = MC_CMD_GET_LICENSED_V3_APP_STATE_IN_LEN;
985293901Sarybchik	req.emr_out_buf = payload;
986293901Sarybchik	req.emr_out_length = MC_CMD_GET_LICENSED_V3_APP_STATE_OUT_LEN;
987293901Sarybchik
988293901Sarybchik	MCDI_IN_SET_DWORD(req, GET_LICENSED_V3_APP_STATE_IN_APP_ID_LO,
989293901Sarybchik		    app_id & 0xffffffff);
990293901Sarybchik	MCDI_IN_SET_DWORD(req, GET_LICENSED_V3_APP_STATE_IN_APP_ID_HI,
991293901Sarybchik		    app_id >> 32);
992293901Sarybchik
993293901Sarybchik	efx_mcdi_execute(enp, &req);
994293901Sarybchik
995293901Sarybchik	if (req.emr_rc != 0) {
996293901Sarybchik		rc = req.emr_rc;
997293901Sarybchik		goto fail1;
998293901Sarybchik	}
999293901Sarybchik
1000293901Sarybchik	if (req.emr_out_length_used < MC_CMD_GET_LICENSED_V3_APP_STATE_OUT_LEN) {
1001293901Sarybchik		rc = EMSGSIZE;
1002293901Sarybchik		goto fail2;
1003293901Sarybchik	}
1004293901Sarybchik
1005293901Sarybchik	app_state = (MCDI_OUT_DWORD(req, GET_LICENSED_V3_APP_STATE_OUT_STATE));
1006293901Sarybchik	if (app_state != MC_CMD_GET_LICENSED_V3_APP_STATE_OUT_NOT_LICENSED) {
1007293901Sarybchik		*licensedp = B_TRUE;
1008293901Sarybchik	} else {
1009293901Sarybchik		*licensedp = B_FALSE;
1010293901Sarybchik	}
1011293901Sarybchik
1012293901Sarybchik	return (0);
1013293901Sarybchik
1014293901Sarybchikfail2:
1015293901Sarybchik	EFSYS_PROBE(fail2);
1016293901Sarybchikfail1:
1017293901Sarybchik	EFSYS_PROBE1(fail1, efx_rc_t, rc);
1018293901Sarybchik
1019293901Sarybchik	return (rc);
1020293901Sarybchik}
1021293901Sarybchik
1022293901Sarybchikstatic	__checkReturn	efx_rc_t
1023293901Sarybchikefx_mcdi_licensing_v3_get_id(
1024293901Sarybchik	__in		efx_nic_t *enp,
1025293901Sarybchik	__in		size_t buffer_size,
1026293901Sarybchik	__out		uint32_t *typep,
1027293901Sarybchik	__out		size_t *lengthp,
1028293901Sarybchik	__out_bcount_part_opt(buffer_size, *lengthp)
1029293901Sarybchik			uint8_t *bufferp)
1030293901Sarybchik{
1031293901Sarybchik	efx_mcdi_req_t req;
1032342445Sarybchik	EFX_MCDI_DECLARE_BUF(payload, MC_CMD_LICENSING_GET_ID_V3_IN_LEN,
1033342445Sarybchik		MC_CMD_LICENSING_GET_ID_V3_OUT_LENMIN);
1034293901Sarybchik	efx_rc_t rc;
1035293901Sarybchik
1036293901Sarybchik	req.emr_cmd = MC_CMD_LICENSING_GET_ID_V3;
1037293901Sarybchik
1038293901Sarybchik	if (bufferp == NULL) {
1039293901Sarybchik		/* Request id type and length only */
1040293901Sarybchik		req.emr_in_buf = bufferp;
1041293901Sarybchik		req.emr_in_length = MC_CMD_LICENSING_GET_ID_V3_IN_LEN;
1042293901Sarybchik		req.emr_out_buf = bufferp;
1043293901Sarybchik		req.emr_out_length = MC_CMD_LICENSING_GET_ID_V3_OUT_LENMIN;
1044293901Sarybchik	} else {
1045293901Sarybchik		/* Request full buffer */
1046293901Sarybchik		req.emr_in_buf = bufferp;
1047293901Sarybchik		req.emr_in_length = MC_CMD_LICENSING_GET_ID_V3_IN_LEN;
1048293901Sarybchik		req.emr_out_buf = bufferp;
1049299898Sarybchik		req.emr_out_length = MIN(buffer_size, MC_CMD_LICENSING_GET_ID_V3_OUT_LENMAX);
1050293901Sarybchik		(void) memset(bufferp, 0, req.emr_out_length);
1051293901Sarybchik	}
1052293901Sarybchik
1053299923Sarybchik	efx_mcdi_execute_quiet(enp, &req);
1054293901Sarybchik
1055293901Sarybchik	if (req.emr_rc != 0) {
1056293901Sarybchik		rc = req.emr_rc;
1057293901Sarybchik		goto fail1;
1058293901Sarybchik	}
1059293901Sarybchik
1060293901Sarybchik	if (req.emr_out_length_used < MC_CMD_LICENSING_GET_ID_V3_OUT_LENMIN) {
1061293901Sarybchik		rc = EMSGSIZE;
1062293901Sarybchik		goto fail2;
1063293901Sarybchik	}
1064293901Sarybchik
1065293901Sarybchik	*typep = MCDI_OUT_DWORD(req, LICENSING_GET_ID_V3_OUT_LICENSE_TYPE);
1066293901Sarybchik	*lengthp = MCDI_OUT_DWORD(req, LICENSING_GET_ID_V3_OUT_LICENSE_ID_LENGTH);
1067293901Sarybchik
1068293901Sarybchik	if (bufferp == NULL) {
1069293901Sarybchik		/* modify length requirements to indicate to caller the extra buffering
1070293901Sarybchik		** needed to read the complete output.
1071293901Sarybchik		*/
1072293901Sarybchik		*lengthp += MC_CMD_LICENSING_GET_ID_V3_OUT_LENMIN;
1073293901Sarybchik	} else {
1074293901Sarybchik		/* Shift ID down to start of buffer */
1075293901Sarybchik		memmove(bufferp,
1076310841Sarybchik		    bufferp + MC_CMD_LICENSING_GET_ID_V3_OUT_LICENSE_ID_OFST,
1077310841Sarybchik		    *lengthp);
1078310841Sarybchik		memset(bufferp + (*lengthp), 0,
1079310841Sarybchik		    MC_CMD_LICENSING_GET_ID_V3_OUT_LICENSE_ID_OFST);
1080293901Sarybchik	}
1081293901Sarybchik
1082293901Sarybchik	return (0);
1083293901Sarybchik
1084293901Sarybchikfail2:
1085293901Sarybchik	EFSYS_PROBE(fail2);
1086293901Sarybchikfail1:
1087293901Sarybchik	EFSYS_PROBE1(fail1, efx_rc_t, rc);
1088293901Sarybchik
1089293901Sarybchik	return (rc);
1090293901Sarybchik}
1091293901Sarybchik
1092299898Sarybchik/* V3 format uses Huntington TLV format partition. See SF-108797-SW */
1093299898Sarybchik#define EFX_LICENSE_V3_KEY_LENGTH_MIN    (64)
1094299907Sarybchik#define EFX_LICENSE_V3_KEY_LENGTH_MAX    (160)
1095293901Sarybchik
1096299898Sarybchik	__checkReturn		efx_rc_t
1097299898Sarybchikefx_lic_v3_find_start(
1098299898Sarybchik	__in			efx_nic_t *enp,
1099299898Sarybchik	__in_bcount(buffer_size)
1100299898Sarybchik				caddr_t bufferp,
1101299898Sarybchik	__in			size_t buffer_size,
1102299898Sarybchik	__out			uint32_t *startp
1103299898Sarybchik	)
1104299898Sarybchik{
1105299898Sarybchik	_NOTE(ARGUNUSED(enp))
1106299898Sarybchik
1107299898Sarybchik	return ef10_nvram_buffer_find_item_start(bufferp, buffer_size, startp);
1108299898Sarybchik}
1109299898Sarybchik
1110299898Sarybchik	__checkReturn		efx_rc_t
1111299898Sarybchikefx_lic_v3_find_end(
1112299898Sarybchik	__in			efx_nic_t *enp,
1113299898Sarybchik	__in_bcount(buffer_size)
1114299898Sarybchik				caddr_t bufferp,
1115299898Sarybchik	__in			size_t buffer_size,
1116299898Sarybchik	__in			uint32_t offset,
1117299898Sarybchik	__out			uint32_t *endp
1118299898Sarybchik	)
1119299898Sarybchik{
1120299898Sarybchik	_NOTE(ARGUNUSED(enp))
1121299898Sarybchik
1122299898Sarybchik	return ef10_nvram_buffer_find_end(bufferp, buffer_size, offset, endp);
1123299898Sarybchik}
1124299898Sarybchik
1125299898Sarybchik	__checkReturn	__success(return != B_FALSE)	boolean_t
1126299898Sarybchikefx_lic_v3_find_key(
1127299898Sarybchik	__in			efx_nic_t *enp,
1128299898Sarybchik	__in_bcount(buffer_size)
1129299898Sarybchik				caddr_t bufferp,
1130299898Sarybchik	__in			size_t buffer_size,
1131299898Sarybchik	__in			uint32_t offset,
1132299898Sarybchik	__out			uint32_t *startp,
1133299898Sarybchik	__out			uint32_t *lengthp
1134299898Sarybchik	)
1135299898Sarybchik{
1136299898Sarybchik	_NOTE(ARGUNUSED(enp))
1137299898Sarybchik
1138299898Sarybchik	return ef10_nvram_buffer_find_item(bufferp, buffer_size,
1139299898Sarybchik	    offset, startp, lengthp);
1140299898Sarybchik}
1141299898Sarybchik
1142299898Sarybchik	__checkReturn	__success(return != B_FALSE)	boolean_t
1143299898Sarybchikefx_lic_v3_validate_key(
1144299898Sarybchik	__in			efx_nic_t *enp,
1145299898Sarybchik	__in_bcount(length)	caddr_t keyp,
1146299898Sarybchik	__in			uint32_t length
1147299898Sarybchik	)
1148299898Sarybchik{
1149310916Sarybchik	/* Check key is a valid V3 key */
1150299898Sarybchik	uint8_t key_type;
1151299898Sarybchik	uint8_t key_length;
1152299898Sarybchik
1153299898Sarybchik	_NOTE(ARGUNUSED(enp))
1154299898Sarybchik
1155299898Sarybchik	if (length < EFX_LICENSE_V3_KEY_LENGTH_MIN) {
1156299898Sarybchik		goto fail1;
1157299898Sarybchik	}
1158299898Sarybchik
1159299911Sarybchik	if (length > EFX_LICENSE_V3_KEY_LENGTH_MAX) {
1160299911Sarybchik		goto fail2;
1161299911Sarybchik	}
1162299911Sarybchik
1163310922Sarybchik	key_type = ((uint8_t *)keyp)[0];
1164310922Sarybchik	key_length = ((uint8_t *)keyp)[1];
1165299898Sarybchik
1166299898Sarybchik	if (key_type < 3) {
1167299898Sarybchik		goto fail3;
1168299898Sarybchik	}
1169299911Sarybchik	if (key_length > length) {
1170299898Sarybchik		goto fail4;
1171299898Sarybchik	}
1172299898Sarybchik	return (B_TRUE);
1173299898Sarybchik
1174299898Sarybchikfail4:
1175299898Sarybchik	EFSYS_PROBE(fail4);
1176299898Sarybchikfail3:
1177299898Sarybchik	EFSYS_PROBE(fail3);
1178299898Sarybchikfail2:
1179299898Sarybchik	EFSYS_PROBE(fail2);
1180299898Sarybchikfail1:
1181342426Sarybchik	EFSYS_PROBE1(fail1, boolean_t, B_FALSE);
1182299898Sarybchik
1183299898Sarybchik	return (B_FALSE);
1184299898Sarybchik}
1185299898Sarybchik
1186299898Sarybchik	__checkReturn		efx_rc_t
1187299898Sarybchikefx_lic_v3_read_key(
1188299898Sarybchik	__in			efx_nic_t *enp,
1189299898Sarybchik	__in_bcount(buffer_size)
1190299898Sarybchik				caddr_t bufferp,
1191299898Sarybchik	__in			size_t buffer_size,
1192299898Sarybchik	__in			uint32_t offset,
1193299898Sarybchik	__in			uint32_t length,
1194299898Sarybchik	__out_bcount_part(key_max_size, *lengthp)
1195299898Sarybchik				caddr_t keyp,
1196299898Sarybchik	__in			size_t key_max_size,
1197299898Sarybchik	__out			uint32_t *lengthp
1198299898Sarybchik	)
1199299898Sarybchik{
1200299898Sarybchik	_NOTE(ARGUNUSED(enp))
1201299898Sarybchik
1202299898Sarybchik	return ef10_nvram_buffer_get_item(bufferp, buffer_size,
1203299898Sarybchik		    offset, length, keyp, key_max_size, lengthp);
1204299898Sarybchik}
1205299898Sarybchik
1206299898Sarybchik	__checkReturn		efx_rc_t
1207299898Sarybchikefx_lic_v3_write_key(
1208299898Sarybchik	__in			efx_nic_t *enp,
1209299898Sarybchik	__in_bcount(buffer_size)
1210299898Sarybchik				caddr_t bufferp,
1211299898Sarybchik	__in			size_t buffer_size,
1212299898Sarybchik	__in			uint32_t offset,
1213299898Sarybchik	__in_bcount(length)	caddr_t keyp,
1214299898Sarybchik	__in			uint32_t length,
1215299898Sarybchik	__out			uint32_t *lengthp
1216299898Sarybchik	)
1217299898Sarybchik{
1218299898Sarybchik	_NOTE(ARGUNUSED(enp))
1219299898Sarybchik	EFSYS_ASSERT(length <= EFX_LICENSE_V3_KEY_LENGTH_MAX);
1220299898Sarybchik
1221299898Sarybchik	return ef10_nvram_buffer_insert_item(bufferp, buffer_size,
1222299898Sarybchik		    offset, keyp, length, lengthp);
1223299898Sarybchik}
1224299898Sarybchik
1225299898Sarybchik	__checkReturn		efx_rc_t
1226299898Sarybchikefx_lic_v3_delete_key(
1227299898Sarybchik	__in			efx_nic_t *enp,
1228299898Sarybchik	__in_bcount(buffer_size)
1229299898Sarybchik				caddr_t bufferp,
1230299898Sarybchik	__in			size_t buffer_size,
1231299898Sarybchik	__in			uint32_t offset,
1232299898Sarybchik	__in			uint32_t length,
1233299898Sarybchik	__in			uint32_t end,
1234299898Sarybchik	__out			uint32_t *deltap
1235299898Sarybchik	)
1236299898Sarybchik{
1237299898Sarybchik	efx_rc_t rc;
1238299898Sarybchik
1239299898Sarybchik	_NOTE(ARGUNUSED(enp))
1240299898Sarybchik
1241299898Sarybchik	if ((rc = ef10_nvram_buffer_delete_item(bufferp,
1242299898Sarybchik			buffer_size, offset, length, end)) != 0) {
1243299898Sarybchik		goto fail1;
1244299898Sarybchik	}
1245299898Sarybchik
1246299898Sarybchik	*deltap = length;
1247299898Sarybchik
1248299898Sarybchik	return (0);
1249299898Sarybchik
1250299898Sarybchikfail1:
1251299898Sarybchik	EFSYS_PROBE1(fail1, efx_rc_t, rc);
1252299898Sarybchik
1253299898Sarybchik	return (rc);
1254299898Sarybchik}
1255299898Sarybchik
1256299898Sarybchik	__checkReturn		efx_rc_t
1257299898Sarybchikefx_lic_v3_create_partition(
1258299898Sarybchik	__in			efx_nic_t *enp,
1259299898Sarybchik	__in_bcount(buffer_size)
1260299898Sarybchik				caddr_t bufferp,
1261299898Sarybchik	__in			size_t buffer_size
1262299898Sarybchik	)
1263299898Sarybchik{
1264299898Sarybchik	efx_rc_t rc;
1265299898Sarybchik
1266310916Sarybchik	/* Construct empty partition */
1267299898Sarybchik	if ((rc = ef10_nvram_buffer_create(enp,
1268299898Sarybchik	    NVRAM_PARTITION_TYPE_LICENSE,
1269299898Sarybchik	    bufferp, buffer_size)) != 0) {
1270299898Sarybchik		rc = EFAULT;
1271299898Sarybchik		goto fail1;
1272299898Sarybchik	}
1273299898Sarybchik
1274299898Sarybchik	return (0);
1275299898Sarybchik
1276299898Sarybchikfail1:
1277299898Sarybchik	EFSYS_PROBE1(fail1, efx_rc_t, rc);
1278299898Sarybchik
1279299898Sarybchik	return (rc);
1280299898Sarybchik}
1281299898Sarybchik
1282299898Sarybchik	__checkReturn		efx_rc_t
1283299898Sarybchikefx_lic_v3_finish_partition(
1284299898Sarybchik	__in			efx_nic_t *enp,
1285299898Sarybchik	__in_bcount(buffer_size)
1286299898Sarybchik				caddr_t bufferp,
1287299898Sarybchik	__in			size_t buffer_size
1288299898Sarybchik	)
1289299898Sarybchik{
1290299898Sarybchik	efx_rc_t rc;
1291299898Sarybchik
1292299898Sarybchik	if ((rc = ef10_nvram_buffer_finish(bufferp,
1293299898Sarybchik			buffer_size)) != 0) {
1294299898Sarybchik		goto fail1;
1295299898Sarybchik	}
1296299898Sarybchik
1297310916Sarybchik	/* Validate completed partition */
1298299898Sarybchik	if ((rc = ef10_nvram_buffer_validate(enp, NVRAM_PARTITION_TYPE_LICENSE,
1299299898Sarybchik					bufferp, buffer_size)) != 0) {
1300299898Sarybchik		goto fail2;
1301299898Sarybchik	}
1302299898Sarybchik
1303299898Sarybchik	return (0);
1304299898Sarybchik
1305299898Sarybchikfail2:
1306299898Sarybchik	EFSYS_PROBE(fail2);
1307299898Sarybchikfail1:
1308299898Sarybchik	EFSYS_PROBE1(fail1, efx_rc_t, rc);
1309299898Sarybchik
1310299898Sarybchik	return (rc);
1311299898Sarybchik}
1312299898Sarybchik
1313299898Sarybchik
1314293901Sarybchik#endif	/* EFSYS_OPT_MEDFORD */
1315293901Sarybchik
1316293901Sarybchik	__checkReturn		efx_rc_t
1317293901Sarybchikefx_lic_init(
1318293901Sarybchik	__in			efx_nic_t *enp)
1319293901Sarybchik{
1320299517Sarybchik	const efx_lic_ops_t *elop;
1321300007Sarybchik	efx_key_stats_t eks;
1322293901Sarybchik	efx_rc_t rc;
1323293901Sarybchik
1324293901Sarybchik	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1325293901Sarybchik	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
1326293901Sarybchik	EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_LIC));
1327293901Sarybchik
1328293901Sarybchik	switch (enp->en_family) {
1329293901Sarybchik
1330293901Sarybchik#if EFSYS_OPT_SIENA
1331293901Sarybchik	case EFX_FAMILY_SIENA:
1332299517Sarybchik		elop = &__efx_lic_v1_ops;
1333293901Sarybchik		break;
1334293901Sarybchik#endif	/* EFSYS_OPT_SIENA */
1335293901Sarybchik
1336293901Sarybchik#if EFSYS_OPT_HUNTINGTON
1337293901Sarybchik	case EFX_FAMILY_HUNTINGTON:
1338299517Sarybchik		elop = &__efx_lic_v2_ops;
1339293901Sarybchik		break;
1340293901Sarybchik#endif	/* EFSYS_OPT_HUNTINGTON */
1341293901Sarybchik
1342293901Sarybchik#if EFSYS_OPT_MEDFORD
1343293901Sarybchik	case EFX_FAMILY_MEDFORD:
1344299517Sarybchik		elop = &__efx_lic_v3_ops;
1345293901Sarybchik		break;
1346293901Sarybchik#endif	/* EFSYS_OPT_MEDFORD */
1347293901Sarybchik
1348293901Sarybchik	default:
1349293901Sarybchik		EFSYS_ASSERT(0);
1350293901Sarybchik		rc = ENOTSUP;
1351293901Sarybchik		goto fail1;
1352293901Sarybchik	}
1353293901Sarybchik
1354293901Sarybchik	enp->en_elop = elop;
1355293901Sarybchik	enp->en_mod_flags |= EFX_MOD_LIC;
1356293901Sarybchik
1357300007Sarybchik	/* Probe for support */
1358300007Sarybchik	if (efx_lic_get_key_stats(enp, &eks) == 0) {
1359300007Sarybchik		enp->en_licensing_supported = B_TRUE;
1360300007Sarybchik	} else {
1361300007Sarybchik		enp->en_licensing_supported = B_FALSE;
1362300007Sarybchik	}
1363300007Sarybchik
1364293901Sarybchik	return (0);
1365293901Sarybchik
1366293901Sarybchikfail1:
1367293901Sarybchik	EFSYS_PROBE1(fail1, efx_rc_t, rc);
1368293901Sarybchik
1369293901Sarybchik	return (rc);
1370293901Sarybchik}
1371293901Sarybchik
1372300007Sarybchikextern	__checkReturn	boolean_t
1373300007Sarybchikefx_lic_check_support(
1374300007Sarybchik	__in			efx_nic_t *enp)
1375300007Sarybchik{
1376300007Sarybchik	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1377300007Sarybchik	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
1378300007Sarybchik	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1379300007Sarybchik
1380300007Sarybchik	return enp->en_licensing_supported;
1381300007Sarybchik}
1382300007Sarybchik
1383293901Sarybchik				void
1384293901Sarybchikefx_lic_fini(
1385293901Sarybchik	__in			efx_nic_t *enp)
1386293901Sarybchik{
1387293901Sarybchik	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1388293901Sarybchik	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
1389293901Sarybchik	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1390293901Sarybchik
1391293901Sarybchik	enp->en_elop = NULL;
1392293901Sarybchik	enp->en_mod_flags &= ~EFX_MOD_LIC;
1393293901Sarybchik}
1394293901Sarybchik
1395293901Sarybchik
1396293901Sarybchik	__checkReturn	efx_rc_t
1397293901Sarybchikefx_lic_update_licenses(
1398293901Sarybchik	__in		efx_nic_t *enp)
1399293901Sarybchik{
1400299517Sarybchik	const efx_lic_ops_t *elop = enp->en_elop;
1401293901Sarybchik	efx_rc_t rc;
1402293901Sarybchik
1403293901Sarybchik	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1404293901Sarybchik	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1405293901Sarybchik
1406293901Sarybchik	if ((rc = elop->elo_update_licenses(enp)) != 0)
1407293901Sarybchik		goto fail1;
1408293901Sarybchik
1409293901Sarybchik	return (0);
1410293901Sarybchik
1411293901Sarybchikfail1:
1412293901Sarybchik	EFSYS_PROBE1(fail1, efx_rc_t, rc);
1413293901Sarybchik
1414293901Sarybchik	return (rc);
1415293901Sarybchik}
1416293901Sarybchik
1417293901Sarybchik	__checkReturn	efx_rc_t
1418293901Sarybchikefx_lic_get_key_stats(
1419293901Sarybchik	__in		efx_nic_t *enp,
1420293901Sarybchik	__out		efx_key_stats_t *eksp)
1421293901Sarybchik{
1422299517Sarybchik	const efx_lic_ops_t *elop = enp->en_elop;
1423293901Sarybchik	efx_rc_t rc;
1424293901Sarybchik
1425293901Sarybchik	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1426293901Sarybchik	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1427293901Sarybchik
1428293901Sarybchik	if ((rc = elop->elo_get_key_stats(enp, eksp)) != 0)
1429293901Sarybchik		goto fail1;
1430293901Sarybchik
1431293901Sarybchik	return (0);
1432293901Sarybchik
1433293901Sarybchikfail1:
1434293901Sarybchik	EFSYS_PROBE1(fail1, efx_rc_t, rc);
1435293901Sarybchik
1436293901Sarybchik	return (rc);
1437293901Sarybchik}
1438293901Sarybchik
1439293901Sarybchik	__checkReturn	efx_rc_t
1440293901Sarybchikefx_lic_app_state(
1441293901Sarybchik	__in		efx_nic_t *enp,
1442293901Sarybchik	__in		uint64_t app_id,
1443293901Sarybchik	__out		boolean_t *licensedp)
1444293901Sarybchik{
1445299517Sarybchik	const efx_lic_ops_t *elop = enp->en_elop;
1446293901Sarybchik	efx_rc_t rc;
1447293901Sarybchik
1448293901Sarybchik	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1449293901Sarybchik	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1450293901Sarybchik
1451299899Sarybchik	if (elop->elo_app_state == NULL)
1452299899Sarybchik		return (ENOTSUP);
1453299899Sarybchik
1454299899Sarybchik	if ((rc = elop->elo_app_state(enp, app_id, licensedp)) != 0)
1455293901Sarybchik		goto fail1;
1456293901Sarybchik
1457293901Sarybchik	return (0);
1458293901Sarybchik
1459293901Sarybchikfail1:
1460293901Sarybchik	EFSYS_PROBE1(fail1, efx_rc_t, rc);
1461293901Sarybchik
1462293901Sarybchik	return (rc);
1463293901Sarybchik}
1464293901Sarybchik
1465293901Sarybchik	__checkReturn	efx_rc_t
1466293901Sarybchikefx_lic_get_id(
1467293901Sarybchik	__in		efx_nic_t *enp,
1468293901Sarybchik	__in		size_t buffer_size,
1469293901Sarybchik	__out		uint32_t *typep,
1470293901Sarybchik	__out		size_t *lengthp,
1471293901Sarybchik	__out_opt	uint8_t *bufferp
1472293901Sarybchik	)
1473293901Sarybchik{
1474299517Sarybchik	const efx_lic_ops_t *elop = enp->en_elop;
1475293901Sarybchik	efx_rc_t rc;
1476293901Sarybchik
1477293901Sarybchik	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1478293901Sarybchik	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1479293901Sarybchik
1480299899Sarybchik	if (elop->elo_get_id == NULL)
1481299899Sarybchik		return (ENOTSUP);
1482293901Sarybchik
1483293901Sarybchik	if ((rc = elop->elo_get_id(enp, buffer_size, typep,
1484293901Sarybchik				    lengthp, bufferp)) != 0)
1485299899Sarybchik		goto fail1;
1486293901Sarybchik
1487293901Sarybchik	return (0);
1488293901Sarybchik
1489293901Sarybchikfail1:
1490293901Sarybchik	EFSYS_PROBE1(fail1, efx_rc_t, rc);
1491293901Sarybchik
1492293901Sarybchik	return (rc);
1493293901Sarybchik}
1494293901Sarybchik
1495299898Sarybchik/* Buffer management API - abstracts varying TLV format used for License partition */
1496299898Sarybchik
1497299898Sarybchik	__checkReturn		efx_rc_t
1498299898Sarybchikefx_lic_find_start(
1499299898Sarybchik	__in			efx_nic_t *enp,
1500299898Sarybchik	__in_bcount(buffer_size)
1501299898Sarybchik				caddr_t bufferp,
1502299898Sarybchik	__in			size_t buffer_size,
1503299898Sarybchik	__out			uint32_t *startp
1504299898Sarybchik	)
1505299898Sarybchik{
1506299898Sarybchik	const efx_lic_ops_t *elop = enp->en_elop;
1507299898Sarybchik	efx_rc_t rc;
1508299898Sarybchik
1509299898Sarybchik	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1510299898Sarybchik	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1511299898Sarybchik
1512299898Sarybchik	if ((rc = elop->elo_find_start(enp, bufferp, buffer_size, startp)) != 0)
1513299898Sarybchik		goto fail1;
1514299898Sarybchik
1515299898Sarybchik	return (0);
1516299898Sarybchik
1517299898Sarybchikfail1:
1518299898Sarybchik	EFSYS_PROBE1(fail1, efx_rc_t, rc);
1519299898Sarybchik
1520299898Sarybchik	return (rc);
1521299898Sarybchik}
1522299898Sarybchik
1523299898Sarybchik	__checkReturn		efx_rc_t
1524299898Sarybchikefx_lic_find_end(
1525299898Sarybchik	__in			efx_nic_t *enp,
1526299898Sarybchik	__in_bcount(buffer_size)
1527299898Sarybchik				caddr_t bufferp,
1528299898Sarybchik	__in			size_t buffer_size,
1529299898Sarybchik	__in			uint32_t offset,
1530299898Sarybchik	__out			uint32_t *endp
1531299898Sarybchik	)
1532299898Sarybchik{
1533299898Sarybchik	const efx_lic_ops_t *elop = enp->en_elop;
1534299898Sarybchik	efx_rc_t rc;
1535299898Sarybchik
1536299898Sarybchik	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1537299898Sarybchik	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1538299898Sarybchik
1539299898Sarybchik	if ((rc = elop->elo_find_end(enp, bufferp, buffer_size, offset, endp)) != 0)
1540299898Sarybchik		goto fail1;
1541299898Sarybchik
1542299898Sarybchik	return (0);
1543299898Sarybchik
1544299898Sarybchikfail1:
1545299898Sarybchik	EFSYS_PROBE1(fail1, efx_rc_t, rc);
1546299898Sarybchik
1547299898Sarybchik	return (rc);
1548299898Sarybchik}
1549299898Sarybchik
1550299898Sarybchik	__checkReturn	__success(return != B_FALSE)	boolean_t
1551299898Sarybchikefx_lic_find_key(
1552299898Sarybchik	__in			efx_nic_t *enp,
1553299898Sarybchik	__in_bcount(buffer_size)
1554299898Sarybchik				caddr_t bufferp,
1555299898Sarybchik	__in			size_t buffer_size,
1556299898Sarybchik	__in			uint32_t offset,
1557299898Sarybchik	__out			uint32_t *startp,
1558299898Sarybchik	__out			uint32_t *lengthp
1559299898Sarybchik	)
1560299898Sarybchik{
1561299898Sarybchik	const efx_lic_ops_t *elop = enp->en_elop;
1562299898Sarybchik
1563299898Sarybchik	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1564299898Sarybchik	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1565299898Sarybchik
1566299898Sarybchik	EFSYS_ASSERT(bufferp);
1567299898Sarybchik	EFSYS_ASSERT(startp);
1568299898Sarybchik	EFSYS_ASSERT(lengthp);
1569299898Sarybchik
1570299898Sarybchik	return (elop->elo_find_key(enp, bufferp, buffer_size, offset,
1571299898Sarybchik				    startp, lengthp));
1572299898Sarybchik}
1573299898Sarybchik
1574299898Sarybchik
1575299898Sarybchik/* Validate that the buffer contains a single key in a recognised format.
1576299898Sarybchik** An empty or terminator buffer is not accepted as a valid key.
1577299898Sarybchik*/
1578299898Sarybchik	__checkReturn	__success(return != B_FALSE)	boolean_t
1579299898Sarybchikefx_lic_validate_key(
1580299898Sarybchik	__in			efx_nic_t *enp,
1581299898Sarybchik	__in_bcount(length)	caddr_t keyp,
1582299898Sarybchik	__in			uint32_t length
1583299898Sarybchik	)
1584299898Sarybchik{
1585299898Sarybchik	const efx_lic_ops_t *elop = enp->en_elop;
1586299898Sarybchik	boolean_t rc;
1587299898Sarybchik
1588299898Sarybchik	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1589299898Sarybchik	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1590299898Sarybchik
1591299898Sarybchik	if ((rc = elop->elo_validate_key(enp, keyp, length)) == B_FALSE)
1592299898Sarybchik		goto fail1;
1593299898Sarybchik
1594299898Sarybchik	return (B_TRUE);
1595299898Sarybchik
1596299898Sarybchikfail1:
1597299898Sarybchik	EFSYS_PROBE1(fail1, efx_rc_t, rc);
1598299898Sarybchik
1599299898Sarybchik	return (rc);
1600299898Sarybchik}
1601299898Sarybchik
1602299898Sarybchik	__checkReturn		efx_rc_t
1603299898Sarybchikefx_lic_read_key(
1604299898Sarybchik	__in			efx_nic_t *enp,
1605299898Sarybchik	__in_bcount(buffer_size)
1606299898Sarybchik				caddr_t bufferp,
1607299898Sarybchik	__in			size_t buffer_size,
1608299898Sarybchik	__in			uint32_t offset,
1609299898Sarybchik	__in			uint32_t length,
1610299898Sarybchik	__out_bcount_part(key_max_size, *lengthp)
1611299898Sarybchik				caddr_t keyp,
1612299898Sarybchik	__in			size_t key_max_size,
1613299898Sarybchik	__out			uint32_t *lengthp
1614299898Sarybchik	)
1615299898Sarybchik{
1616299898Sarybchik	const efx_lic_ops_t *elop = enp->en_elop;
1617299898Sarybchik	efx_rc_t rc;
1618299898Sarybchik
1619299898Sarybchik	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1620299898Sarybchik	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1621299898Sarybchik
1622299898Sarybchik	if ((rc = elop->elo_read_key(enp, bufferp, buffer_size, offset,
1623299898Sarybchik				    length, keyp, key_max_size, lengthp)) != 0)
1624299898Sarybchik		goto fail1;
1625299898Sarybchik
1626299898Sarybchik	return (0);
1627299898Sarybchik
1628299898Sarybchikfail1:
1629299898Sarybchik	EFSYS_PROBE1(fail1, efx_rc_t, rc);
1630299898Sarybchik
1631299898Sarybchik	return (rc);
1632299898Sarybchik}
1633299898Sarybchik
1634299898Sarybchik	__checkReturn		efx_rc_t
1635299898Sarybchikefx_lic_write_key(
1636299898Sarybchik	__in			efx_nic_t *enp,
1637299898Sarybchik	__in_bcount(buffer_size)
1638299898Sarybchik				caddr_t bufferp,
1639299898Sarybchik	__in			size_t buffer_size,
1640299898Sarybchik	__in			uint32_t offset,
1641299898Sarybchik	__in_bcount(length)	caddr_t keyp,
1642299898Sarybchik	__in			uint32_t length,
1643299898Sarybchik	__out			uint32_t *lengthp
1644299898Sarybchik	)
1645299898Sarybchik{
1646299898Sarybchik	const efx_lic_ops_t *elop = enp->en_elop;
1647299898Sarybchik	efx_rc_t rc;
1648299898Sarybchik
1649299898Sarybchik	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1650299898Sarybchik	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1651299898Sarybchik
1652299898Sarybchik	if ((rc = elop->elo_write_key(enp, bufferp, buffer_size, offset,
1653299898Sarybchik				    keyp, length, lengthp)) != 0)
1654299898Sarybchik		goto fail1;
1655299898Sarybchik
1656299898Sarybchik	return (0);
1657299898Sarybchik
1658299898Sarybchikfail1:
1659299898Sarybchik	EFSYS_PROBE1(fail1, efx_rc_t, rc);
1660299898Sarybchik
1661299898Sarybchik	return (rc);
1662299898Sarybchik}
1663299898Sarybchik
1664299898Sarybchik	__checkReturn		efx_rc_t
1665299898Sarybchikefx_lic_delete_key(
1666299898Sarybchik	__in			efx_nic_t *enp,
1667299898Sarybchik	__in_bcount(buffer_size)
1668299898Sarybchik				caddr_t bufferp,
1669299898Sarybchik	__in			size_t buffer_size,
1670299898Sarybchik	__in			uint32_t offset,
1671299898Sarybchik	__in			uint32_t length,
1672299898Sarybchik	__in			uint32_t end,
1673299898Sarybchik	__out			uint32_t *deltap
1674299898Sarybchik	)
1675299898Sarybchik{
1676299898Sarybchik	const efx_lic_ops_t *elop = enp->en_elop;
1677299898Sarybchik	efx_rc_t rc;
1678299898Sarybchik
1679299898Sarybchik	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1680299898Sarybchik	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1681299898Sarybchik
1682299898Sarybchik	if ((rc = elop->elo_delete_key(enp, bufferp, buffer_size, offset,
1683299898Sarybchik				    length, end, deltap)) != 0)
1684299898Sarybchik		goto fail1;
1685299898Sarybchik
1686299898Sarybchik	return (0);
1687299898Sarybchik
1688299898Sarybchikfail1:
1689299898Sarybchik	EFSYS_PROBE1(fail1, efx_rc_t, rc);
1690299898Sarybchik
1691299898Sarybchik	return (rc);
1692299898Sarybchik}
1693299898Sarybchik
1694299898Sarybchik	__checkReturn		efx_rc_t
1695299898Sarybchikefx_lic_create_partition(
1696299898Sarybchik	__in			efx_nic_t *enp,
1697299898Sarybchik	__in_bcount(buffer_size)
1698299898Sarybchik				caddr_t bufferp,
1699299898Sarybchik	__in			size_t buffer_size
1700299898Sarybchik	)
1701299898Sarybchik{
1702299898Sarybchik	const efx_lic_ops_t *elop = enp->en_elop;
1703299898Sarybchik	efx_rc_t rc;
1704299898Sarybchik
1705299898Sarybchik	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1706299898Sarybchik	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1707299898Sarybchik
1708299898Sarybchik	if ((rc = elop->elo_create_partition(enp, bufferp, buffer_size)) != 0)
1709299898Sarybchik		goto fail1;
1710299898Sarybchik
1711299898Sarybchik	return (0);
1712299898Sarybchik
1713299898Sarybchikfail1:
1714299898Sarybchik	EFSYS_PROBE1(fail1, efx_rc_t, rc);
1715299898Sarybchik
1716299898Sarybchik	return (rc);
1717299898Sarybchik}
1718299898Sarybchik
1719299898Sarybchik
1720299898Sarybchik	__checkReturn		efx_rc_t
1721299898Sarybchikefx_lic_finish_partition(
1722299898Sarybchik	__in			efx_nic_t *enp,
1723299898Sarybchik	__in_bcount(buffer_size)
1724299898Sarybchik				caddr_t bufferp,
1725299898Sarybchik	__in			size_t buffer_size
1726299898Sarybchik	)
1727299898Sarybchik{
1728299898Sarybchik	const efx_lic_ops_t *elop = enp->en_elop;
1729299898Sarybchik	efx_rc_t rc;
1730299898Sarybchik
1731299898Sarybchik	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1732299898Sarybchik	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1733299898Sarybchik
1734299898Sarybchik	if ((rc = elop->elo_finish_partition(enp, bufferp, buffer_size)) != 0)
1735299898Sarybchik		goto fail1;
1736299898Sarybchik
1737299898Sarybchik	return (0);
1738299898Sarybchik
1739299898Sarybchikfail1:
1740299898Sarybchik	EFSYS_PROBE1(fail1, efx_rc_t, rc);
1741299898Sarybchik
1742299898Sarybchik	return (rc);
1743299898Sarybchik}
1744299898Sarybchik
1745293901Sarybchik#endif	/* EFSYS_OPT_LICENSING */
1746