1293901Sarybchik/*-
2301388Sarybchik * 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/10/sys/dev/sfxge/common/efx_lic.c 342516 2018-12-26 10:25:01Z arybchik $");
33293901Sarybchik
34293901Sarybchik#include "efx.h"
35293901Sarybchik#include "efx_impl.h"
36293901Sarybchik
37293901Sarybchik#if EFSYS_OPT_LICENSING
38293901Sarybchik
39301361Sarybchik#include "ef10_tlv_layout.h"
40301361Sarybchik
41301361Sarybchik#if EFSYS_OPT_SIENA | EFSYS_OPT_HUNTINGTON
42301361Sarybchik
43301361Sarybchik	__checkReturn		efx_rc_t
44301361Sarybchikefx_lic_v1v2_find_start(
45301361Sarybchik	__in			efx_nic_t *enp,
46301361Sarybchik	__in_bcount(buffer_size)
47301361Sarybchik				caddr_t bufferp,
48301361Sarybchik	__in			size_t buffer_size,
49301361Sarybchik	__out			uint32_t *startp
50301361Sarybchik	);
51301361Sarybchik
52301361Sarybchik	__checkReturn		efx_rc_t
53301361Sarybchikefx_lic_v1v2_find_end(
54301361Sarybchik	__in			efx_nic_t *enp,
55301361Sarybchik	__in_bcount(buffer_size)
56301361Sarybchik				caddr_t bufferp,
57301361Sarybchik	__in			size_t buffer_size,
58301361Sarybchik	__in			uint32_t offset,
59301361Sarybchik	__out			uint32_t *endp
60301361Sarybchik	);
61301361Sarybchik
62301361Sarybchik	__checkReturn	__success(return != B_FALSE)	boolean_t
63301361Sarybchikefx_lic_v1v2_find_key(
64301361Sarybchik	__in			efx_nic_t *enp,
65301361Sarybchik	__in_bcount(buffer_size)
66301361Sarybchik				caddr_t bufferp,
67301361Sarybchik	__in			size_t buffer_size,
68301361Sarybchik	__in			uint32_t offset,
69301361Sarybchik	__out			uint32_t *startp,
70301361Sarybchik	__out			uint32_t *lengthp
71301361Sarybchik	);
72301361Sarybchik
73301361Sarybchik	__checkReturn	__success(return != B_FALSE)	boolean_t
74301361Sarybchikefx_lic_v1v2_validate_key(
75301361Sarybchik	__in			efx_nic_t *enp,
76301361Sarybchik	__in_bcount(length)	caddr_t keyp,
77301361Sarybchik	__in			uint32_t length
78301361Sarybchik	);
79301361Sarybchik
80301361Sarybchik	__checkReturn		efx_rc_t
81301361Sarybchikefx_lic_v1v2_read_key(
82301361Sarybchik	__in			efx_nic_t *enp,
83301361Sarybchik	__in_bcount(buffer_size)
84301361Sarybchik				caddr_t bufferp,
85301361Sarybchik	__in			size_t buffer_size,
86301361Sarybchik	__in			uint32_t offset,
87301361Sarybchik	__in			uint32_t length,
88301361Sarybchik	__out_bcount_part(key_max_size, *lengthp)
89301361Sarybchik				caddr_t keyp,
90301361Sarybchik	__in			size_t key_max_size,
91301361Sarybchik	__out			uint32_t *lengthp
92301361Sarybchik	);
93301361Sarybchik
94301361Sarybchik	__checkReturn		efx_rc_t
95301361Sarybchikefx_lic_v1v2_write_key(
96301361Sarybchik	__in			efx_nic_t *enp,
97301361Sarybchik	__in_bcount(buffer_size)
98301361Sarybchik				caddr_t bufferp,
99301361Sarybchik	__in			size_t buffer_size,
100301361Sarybchik	__in			uint32_t offset,
101301361Sarybchik	__in_bcount(length)	caddr_t keyp,
102301361Sarybchik	__in			uint32_t length,
103301361Sarybchik	__out			uint32_t *lengthp
104301361Sarybchik	);
105301361Sarybchik
106301361Sarybchik	__checkReturn		efx_rc_t
107301361Sarybchikefx_lic_v1v2_delete_key(
108301361Sarybchik	__in			efx_nic_t *enp,
109301361Sarybchik	__in_bcount(buffer_size)
110301361Sarybchik				caddr_t bufferp,
111301361Sarybchik	__in			size_t buffer_size,
112301361Sarybchik	__in			uint32_t offset,
113301361Sarybchik	__in			uint32_t length,
114301361Sarybchik	__in			uint32_t end,
115301361Sarybchik	__out			uint32_t *deltap
116301361Sarybchik	);
117301361Sarybchik
118301361Sarybchik	__checkReturn		efx_rc_t
119301361Sarybchikefx_lic_v1v2_create_partition(
120301361Sarybchik	__in			efx_nic_t *enp,
121301361Sarybchik	__in_bcount(buffer_size)
122301361Sarybchik				caddr_t bufferp,
123301361Sarybchik	__in			size_t buffer_size
124301361Sarybchik	);
125301361Sarybchik
126301361Sarybchik	__checkReturn		efx_rc_t
127301361Sarybchikefx_lic_v1v2_finish_partition(
128301361Sarybchik	__in			efx_nic_t *enp,
129301361Sarybchik	__in_bcount(buffer_size)
130301361Sarybchik				caddr_t bufferp,
131301361Sarybchik	__in			size_t buffer_size
132301361Sarybchik	);
133301361Sarybchik
134301361Sarybchik#endif	/* EFSYS_OPT_HUNTINGTON | EFSYS_OPT_SIENA */
135301361Sarybchik
136301361Sarybchik
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
148301340Sarybchikstatic 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 */
153301361Sarybchik	efx_lic_v1v2_find_start,		/* elo_find_start */
154301361Sarybchik	efx_lic_v1v2_find_end,			/* elo_find_end */
155301361Sarybchik	efx_lic_v1v2_find_key,			/* elo_find_key */
156301361Sarybchik	efx_lic_v1v2_validate_key,		/* elo_validate_key */
157301361Sarybchik	efx_lic_v1v2_read_key,			/* elo_read_key */
158301361Sarybchik	efx_lic_v1v2_write_key,			/* elo_write_key */
159301361Sarybchik	efx_lic_v1v2_delete_key,		/* elo_delete_key */
160301361Sarybchik	efx_lic_v1v2_create_partition,		/* elo_create_partition */
161301361Sarybchik	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
183301340Sarybchikstatic 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 */
188301361Sarybchik	efx_lic_v1v2_find_start,		/* elo_find_start */
189301361Sarybchik	efx_lic_v1v2_find_end,			/* elo_find_end */
190301361Sarybchik	efx_lic_v1v2_find_key,			/* elo_find_key */
191301361Sarybchik	efx_lic_v1v2_validate_key,		/* elo_validate_key */
192301361Sarybchik	efx_lic_v1v2_read_key,			/* elo_read_key */
193301361Sarybchik	efx_lic_v1v2_write_key,			/* elo_write_key */
194301361Sarybchik	efx_lic_v1v2_delete_key,		/* elo_delete_key */
195301361Sarybchik	efx_lic_v1v2_create_partition,		/* elo_create_partition */
196301361Sarybchik	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
227301361Sarybchik	__checkReturn		efx_rc_t
228301361Sarybchikefx_lic_v3_find_start(
229301361Sarybchik	__in			efx_nic_t *enp,
230301361Sarybchik	__in_bcount(buffer_size)
231301361Sarybchik				caddr_t bufferp,
232301361Sarybchik	__in			size_t buffer_size,
233301361Sarybchik	__out			uint32_t *startp
234301361Sarybchik	);
235301361Sarybchik
236301361Sarybchik	__checkReturn		efx_rc_t
237301361Sarybchikefx_lic_v3_find_end(
238301361Sarybchik	__in			efx_nic_t *enp,
239301361Sarybchik	__in_bcount(buffer_size)
240301361Sarybchik				caddr_t bufferp,
241301361Sarybchik	__in			size_t buffer_size,
242301361Sarybchik	__in			uint32_t offset,
243301361Sarybchik	__out			uint32_t *endp
244301361Sarybchik	);
245301361Sarybchik
246301361Sarybchik	__checkReturn	__success(return != B_FALSE)	boolean_t
247301361Sarybchikefx_lic_v3_find_key(
248301361Sarybchik	__in			efx_nic_t *enp,
249301361Sarybchik	__in_bcount(buffer_size)
250301361Sarybchik				caddr_t bufferp,
251301361Sarybchik	__in			size_t buffer_size,
252301361Sarybchik	__in			uint32_t offset,
253301361Sarybchik	__out			uint32_t *startp,
254301361Sarybchik	__out			uint32_t *lengthp
255301361Sarybchik	);
256301361Sarybchik
257301361Sarybchik	__checkReturn	__success(return != B_FALSE)	boolean_t
258301361Sarybchikefx_lic_v3_validate_key(
259301361Sarybchik	__in			efx_nic_t *enp,
260301361Sarybchik	__in_bcount(length)	caddr_t keyp,
261301361Sarybchik	__in			uint32_t length
262301361Sarybchik	);
263301361Sarybchik
264301361Sarybchik	__checkReturn		efx_rc_t
265301361Sarybchikefx_lic_v3_read_key(
266301361Sarybchik	__in			efx_nic_t *enp,
267301361Sarybchik	__in_bcount(buffer_size)
268301361Sarybchik				caddr_t bufferp,
269301361Sarybchik	__in			size_t buffer_size,
270301361Sarybchik	__in			uint32_t offset,
271301361Sarybchik	__in			uint32_t length,
272301361Sarybchik	__out_bcount_part(key_max_size, *lengthp)
273301361Sarybchik				caddr_t keyp,
274301361Sarybchik	__in			size_t key_max_size,
275301361Sarybchik	__out			uint32_t *lengthp
276301361Sarybchik	);
277301361Sarybchik
278301361Sarybchik	__checkReturn		efx_rc_t
279301361Sarybchikefx_lic_v3_write_key(
280301361Sarybchik	__in			efx_nic_t *enp,
281301361Sarybchik	__in_bcount(buffer_size)
282301361Sarybchik				caddr_t bufferp,
283301361Sarybchik	__in			size_t buffer_size,
284301361Sarybchik	__in			uint32_t offset,
285301361Sarybchik	__in_bcount(length)	caddr_t keyp,
286301361Sarybchik	__in			uint32_t length,
287301361Sarybchik	__out			uint32_t *lengthp
288301361Sarybchik	);
289301361Sarybchik
290301361Sarybchik	__checkReturn		efx_rc_t
291301361Sarybchikefx_lic_v3_delete_key(
292301361Sarybchik	__in			efx_nic_t *enp,
293301361Sarybchik	__in_bcount(buffer_size)
294301361Sarybchik				caddr_t bufferp,
295301361Sarybchik	__in			size_t buffer_size,
296301361Sarybchik	__in			uint32_t offset,
297301361Sarybchik	__in			uint32_t length,
298301361Sarybchik	__in			uint32_t end,
299301361Sarybchik	__out			uint32_t *deltap
300301361Sarybchik	);
301301361Sarybchik
302301361Sarybchik	__checkReturn		efx_rc_t
303301361Sarybchikefx_lic_v3_create_partition(
304301361Sarybchik	__in			efx_nic_t *enp,
305301361Sarybchik	__in_bcount(buffer_size)
306301361Sarybchik				caddr_t bufferp,
307301361Sarybchik	__in			size_t buffer_size
308301361Sarybchik	);
309301361Sarybchik
310301361Sarybchik	__checkReturn		efx_rc_t
311301361Sarybchikefx_lic_v3_finish_partition(
312301361Sarybchik	__in			efx_nic_t *enp,
313301361Sarybchik	__in_bcount(buffer_size)
314301361Sarybchik				caddr_t bufferp,
315301361Sarybchik	__in			size_t buffer_size
316301361Sarybchik	);
317301361Sarybchik
318301340Sarybchikstatic 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 */
323301361Sarybchik	efx_lic_v3_find_start,			/* elo_find_start*/
324301361Sarybchik	efx_lic_v3_find_end,			/* elo_find_end */
325301361Sarybchik	efx_lic_v3_find_key,			/* elo_find_key */
326301361Sarybchik	efx_lic_v3_validate_key,		/* elo_validate_key */
327301361Sarybchik	efx_lic_v3_read_key,			/* elo_read_key */
328301361Sarybchik	efx_lic_v3_write_key,			/* elo_write_key */
329301361Sarybchik	efx_lic_v3_delete_key,			/* elo_delete_key */
330301361Sarybchik	efx_lic_v3_create_partition,		/* elo_create_partition */
331301361Sarybchik	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;
346342516Sarybchik	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
351301366Sarybchik	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
357301366Sarybchik	MCDI_IN_SET_DWORD(req, FC_IN_CMD,
358301366Sarybchik	    MC_CMD_FC_OP_LICENSE);
359301366Sarybchik
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;
391342516Sarybchik	EFX_MCDI_DECLARE_BUF(payload, MC_CMD_FC_IN_LICENSE_LEN,
392342516Sarybchik		MC_CMD_FC_OUT_LICENSE_LEN);
393293901Sarybchik	efx_rc_t rc;
394293901Sarybchik
395293901Sarybchik	EFSYS_ASSERT(enp->en_family == EFX_FAMILY_SIENA);
396293901Sarybchik
397301366Sarybchik	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
403301366Sarybchik	MCDI_IN_SET_DWORD(req, FC_IN_CMD,
404301366Sarybchik	    MC_CMD_FC_OP_LICENSE);
405301366Sarybchik
406293901Sarybchik	MCDI_IN_SET_DWORD(req, FC_IN_LICENSE_OP,
407293901Sarybchik	    MC_CMD_FC_IN_LICENSE_GET_KEY_STATS);
408293901Sarybchik
409301376Sarybchik	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
446301361Sarybchik/* V1 and V2 Partition format - based on a 16-bit TLV format */
447301361Sarybchik
448301361Sarybchik#if EFSYS_OPT_SIENA | EFSYS_OPT_HUNTINGTON
449301361Sarybchik
450301361Sarybchik/*
451301361Sarybchik * V1/V2 format - defined in SF-108542-TC section 4.2:
452301361Sarybchik *  Type (T):   16bit - revision/HMAC algorithm
453301361Sarybchik *  Length (L): 16bit - value length in bytes
454301361Sarybchik *  Value (V):  L bytes - payload
455301361Sarybchik */
456301361Sarybchik#define EFX_LICENSE_V1V2_PAYLOAD_LENGTH_MAX    (256)
457310839Sarybchik#define EFX_LICENSE_V1V2_HEADER_LENGTH         (2 * sizeof(uint16_t))
458301361Sarybchik
459301361Sarybchik	__checkReturn		efx_rc_t
460301361Sarybchikefx_lic_v1v2_find_start(
461301361Sarybchik	__in			efx_nic_t *enp,
462301361Sarybchik	__in_bcount(buffer_size)
463301361Sarybchik				caddr_t bufferp,
464301361Sarybchik	__in			size_t buffer_size,
465301361Sarybchik	__out			uint32_t *startp
466301361Sarybchik	)
467301361Sarybchik{
468301361Sarybchik	_NOTE(ARGUNUSED(enp, bufferp, buffer_size))
469301361Sarybchik
470301361Sarybchik	*startp = 0;
471301361Sarybchik	return (0);
472301361Sarybchik}
473301361Sarybchik
474301361Sarybchik	__checkReturn		efx_rc_t
475301361Sarybchikefx_lic_v1v2_find_end(
476301361Sarybchik	__in			efx_nic_t *enp,
477301361Sarybchik	__in_bcount(buffer_size)
478301361Sarybchik				caddr_t bufferp,
479301361Sarybchik	__in			size_t buffer_size,
480301361Sarybchik	__in			uint32_t offset,
481301361Sarybchik	__out			uint32_t *endp
482301361Sarybchik	)
483301361Sarybchik{
484301361Sarybchik	_NOTE(ARGUNUSED(enp, bufferp, buffer_size))
485301361Sarybchik
486301361Sarybchik	*endp = offset + EFX_LICENSE_V1V2_HEADER_LENGTH;
487301361Sarybchik	return (0);
488301361Sarybchik}
489301361Sarybchik
490301361Sarybchik	__checkReturn	__success(return != B_FALSE)	boolean_t
491301361Sarybchikefx_lic_v1v2_find_key(
492301361Sarybchik	__in			efx_nic_t *enp,
493301361Sarybchik	__in_bcount(buffer_size)
494301361Sarybchik				caddr_t bufferp,
495301361Sarybchik	__in			size_t buffer_size,
496301361Sarybchik	__in			uint32_t offset,
497301361Sarybchik	__out			uint32_t *startp,
498301361Sarybchik	__out			uint32_t *lengthp
499301361Sarybchik	)
500301361Sarybchik{
501301361Sarybchik	boolean_t found;
502301361Sarybchik	uint16_t tlv_type;
503301361Sarybchik	uint16_t tlv_length;
504301361Sarybchik
505301361Sarybchik	_NOTE(ARGUNUSED(enp))
506301361Sarybchik
507301981Sarybchik	if ((size_t)buffer_size - offset < EFX_LICENSE_V1V2_HEADER_LENGTH)
508301361Sarybchik		goto fail1;
509301361Sarybchik
510311054Sarybchik	tlv_type = __LE_TO_CPU_16(((uint16_t *)&bufferp[offset])[0]);
511311054Sarybchik	tlv_length = __LE_TO_CPU_16(((uint16_t *)&bufferp[offset])[1]);
512301361Sarybchik	if ((tlv_length > EFX_LICENSE_V1V2_PAYLOAD_LENGTH_MAX) ||
513301361Sarybchik	    (tlv_type == 0 && tlv_length == 0)) {
514301361Sarybchik		found = B_FALSE;
515301361Sarybchik	} else {
516301361Sarybchik		*startp = offset;
517301361Sarybchik		*lengthp = tlv_length + EFX_LICENSE_V1V2_HEADER_LENGTH;
518301361Sarybchik		found = B_TRUE;
519301361Sarybchik	}
520301361Sarybchik	return (found);
521301361Sarybchik
522301361Sarybchikfail1:
523342497Sarybchik	EFSYS_PROBE1(fail1, boolean_t, B_FALSE);
524301361Sarybchik
525301361Sarybchik	return (B_FALSE);
526301361Sarybchik}
527301361Sarybchik
528301361Sarybchik	__checkReturn	__success(return != B_FALSE)	boolean_t
529301361Sarybchikefx_lic_v1v2_validate_key(
530301361Sarybchik	__in			efx_nic_t *enp,
531301361Sarybchik	__in_bcount(length)	caddr_t keyp,
532301361Sarybchik	__in			uint32_t length
533301361Sarybchik	)
534301361Sarybchik{
535301361Sarybchik	uint16_t tlv_type;
536301361Sarybchik	uint16_t tlv_length;
537301361Sarybchik
538301361Sarybchik	_NOTE(ARGUNUSED(enp))
539301361Sarybchik
540301361Sarybchik	if (length < EFX_LICENSE_V1V2_HEADER_LENGTH) {
541301361Sarybchik		goto fail1;
542301361Sarybchik	}
543301361Sarybchik
544311054Sarybchik	tlv_type = __LE_TO_CPU_16(((uint16_t *)keyp)[0]);
545311054Sarybchik	tlv_length = __LE_TO_CPU_16(((uint16_t *)keyp)[1]);
546301361Sarybchik
547301981Sarybchik	if (tlv_length > EFX_LICENSE_V1V2_PAYLOAD_LENGTH_MAX) {
548301361Sarybchik		goto fail2;
549301361Sarybchik	}
550301361Sarybchik	if (tlv_type == 0) {
551301361Sarybchik		goto fail3;
552301361Sarybchik	}
553301361Sarybchik	if ((tlv_length + EFX_LICENSE_V1V2_HEADER_LENGTH) != length) {
554301361Sarybchik		goto fail4;
555301361Sarybchik	}
556301361Sarybchik
557301361Sarybchik	return (B_TRUE);
558301361Sarybchik
559301361Sarybchikfail4:
560301361Sarybchik	EFSYS_PROBE(fail4);
561301361Sarybchikfail3:
562301361Sarybchik	EFSYS_PROBE(fail3);
563301361Sarybchikfail2:
564301361Sarybchik	EFSYS_PROBE(fail2);
565301361Sarybchikfail1:
566342497Sarybchik	EFSYS_PROBE1(fail1, boolean_t, B_FALSE);
567301361Sarybchik
568301361Sarybchik	return (B_FALSE);
569301361Sarybchik}
570301361Sarybchik
571301361Sarybchik
572301361Sarybchik	__checkReturn		efx_rc_t
573301361Sarybchikefx_lic_v1v2_read_key(
574301361Sarybchik	__in			efx_nic_t *enp,
575301361Sarybchik	__in_bcount(buffer_size)
576301361Sarybchik				caddr_t bufferp,
577301361Sarybchik	__in			size_t buffer_size,
578301361Sarybchik	__in			uint32_t offset,
579301361Sarybchik	__in			uint32_t length,
580301361Sarybchik	__out_bcount_part(key_max_size, *lengthp)
581301361Sarybchik				caddr_t keyp,
582301361Sarybchik	__in			size_t key_max_size,
583301361Sarybchik	__out			uint32_t *lengthp
584301361Sarybchik	)
585301361Sarybchik{
586301361Sarybchik	efx_rc_t rc;
587301361Sarybchik
588342501Sarybchik	_NOTE(ARGUNUSED(enp, buffer_size))
589301361Sarybchik	EFSYS_ASSERT(length <= (EFX_LICENSE_V1V2_PAYLOAD_LENGTH_MAX +
590301361Sarybchik	    EFX_LICENSE_V1V2_HEADER_LENGTH));
591301361Sarybchik
592301361Sarybchik	if (key_max_size < length) {
593301361Sarybchik		rc = ENOSPC;
594301361Sarybchik		goto fail1;
595301361Sarybchik	}
596301361Sarybchik	memcpy(keyp, &bufferp[offset], length);
597301361Sarybchik
598301361Sarybchik	*lengthp = length;
599301361Sarybchik
600301361Sarybchik	return (0);
601301361Sarybchik
602301361Sarybchikfail1:
603301361Sarybchik	EFSYS_PROBE1(fail1, efx_rc_t, rc);
604301361Sarybchik
605301361Sarybchik	return (rc);
606301361Sarybchik}
607301361Sarybchik
608301361Sarybchik	__checkReturn		efx_rc_t
609301361Sarybchikefx_lic_v1v2_write_key(
610301361Sarybchik	__in			efx_nic_t *enp,
611301361Sarybchik	__in_bcount(buffer_size)
612301361Sarybchik				caddr_t bufferp,
613301361Sarybchik	__in			size_t buffer_size,
614301361Sarybchik	__in			uint32_t offset,
615301361Sarybchik	__in_bcount(length)	caddr_t keyp,
616301361Sarybchik	__in			uint32_t length,
617301361Sarybchik	__out			uint32_t *lengthp
618301361Sarybchik	)
619301361Sarybchik{
620301361Sarybchik	efx_rc_t rc;
621301361Sarybchik
622301361Sarybchik	_NOTE(ARGUNUSED(enp))
623301361Sarybchik	EFSYS_ASSERT(length <= (EFX_LICENSE_V1V2_PAYLOAD_LENGTH_MAX +
624301361Sarybchik	    EFX_LICENSE_V1V2_HEADER_LENGTH));
625301361Sarybchik
626311050Sarybchik	/* Ensure space for terminator remains */
627301361Sarybchik	if ((offset + length) >
628310842Sarybchik	    (buffer_size - EFX_LICENSE_V1V2_HEADER_LENGTH)) {
629301361Sarybchik		rc = ENOSPC;
630301361Sarybchik		goto fail1;
631301361Sarybchik	}
632301361Sarybchik
633301361Sarybchik	memcpy(bufferp + offset, keyp, length);
634301361Sarybchik
635301361Sarybchik	*lengthp = length;
636301361Sarybchik
637301361Sarybchik	return (0);
638301361Sarybchik
639301361Sarybchikfail1:
640301361Sarybchik	EFSYS_PROBE1(fail1, efx_rc_t, rc);
641301361Sarybchik
642301361Sarybchik	return (rc);
643301361Sarybchik}
644301361Sarybchik
645301361Sarybchik	__checkReturn		efx_rc_t
646301361Sarybchikefx_lic_v1v2_delete_key(
647301361Sarybchik	__in			efx_nic_t *enp,
648301361Sarybchik	__in_bcount(buffer_size)
649301361Sarybchik				caddr_t bufferp,
650301361Sarybchik	__in			size_t buffer_size,
651301361Sarybchik	__in			uint32_t offset,
652301361Sarybchik	__in			uint32_t length,
653301361Sarybchik	__in			uint32_t end,
654301361Sarybchik	__out			uint32_t *deltap
655301361Sarybchik	)
656301361Sarybchik{
657301361Sarybchik	uint32_t move_start = offset + length;
658301361Sarybchik	uint32_t move_length = end - move_start;
659301361Sarybchik
660342501Sarybchik	_NOTE(ARGUNUSED(enp, buffer_size))
661301361Sarybchik	EFSYS_ASSERT(end <= buffer_size);
662301361Sarybchik
663311050Sarybchik	/* Shift everything after the key down */
664301361Sarybchik	memmove(bufferp + offset, bufferp + move_start, move_length);
665301361Sarybchik
666301361Sarybchik	*deltap = length;
667301361Sarybchik
668301361Sarybchik	return (0);
669301361Sarybchik}
670301361Sarybchik
671301361Sarybchik	__checkReturn		efx_rc_t
672301361Sarybchikefx_lic_v1v2_create_partition(
673301361Sarybchik	__in			efx_nic_t *enp,
674301361Sarybchik	__in_bcount(buffer_size)
675301361Sarybchik				caddr_t bufferp,
676301361Sarybchik	__in			size_t buffer_size
677301361Sarybchik	)
678301361Sarybchik{
679342501Sarybchik	_NOTE(ARGUNUSED(enp, buffer_size))
680301361Sarybchik	EFSYS_ASSERT(EFX_LICENSE_V1V2_HEADER_LENGTH <= buffer_size);
681301361Sarybchik
682311050Sarybchik	/* Write terminator */
683301361Sarybchik	memset(bufferp, '\0', EFX_LICENSE_V1V2_HEADER_LENGTH);
684301361Sarybchik	return (0);
685301361Sarybchik}
686301361Sarybchik
687301361Sarybchik
688301361Sarybchik	__checkReturn		efx_rc_t
689301361Sarybchikefx_lic_v1v2_finish_partition(
690301361Sarybchik	__in			efx_nic_t *enp,
691301361Sarybchik	__in_bcount(buffer_size)
692301361Sarybchik				caddr_t bufferp,
693301361Sarybchik	__in			size_t buffer_size
694301361Sarybchik	)
695301361Sarybchik{
696301361Sarybchik	_NOTE(ARGUNUSED(enp, bufferp, buffer_size))
697301361Sarybchik
698301361Sarybchik	return (0);
699301361Sarybchik}
700301361Sarybchik
701301361Sarybchik#endif	/* EFSYS_OPT_HUNTINGTON | EFSYS_OPT_SIENA */
702301361Sarybchik
703301361Sarybchik
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;
715342516Sarybchik	EFX_MCDI_DECLARE_BUF(payload, MC_CMD_GET_LICENSED_APP_STATE_IN_LEN,
716342516Sarybchik		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;
773342516Sarybchik	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;
815342516Sarybchik	EFX_MCDI_DECLARE_BUF(payload, MC_CMD_LICENSING_IN_LEN,
816342516Sarybchik		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;
878342516Sarybchik	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;
913342516Sarybchik	EFX_MCDI_DECLARE_BUF(payload, MC_CMD_LICENSING_V3_IN_LEN,
914342516Sarybchik		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
928301376Sarybchik	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;
975342516Sarybchik	EFX_MCDI_DECLARE_BUF(payload, MC_CMD_GET_LICENSED_V3_APP_STATE_IN_LEN,
976342516Sarybchik		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;
1032342516Sarybchik	EFX_MCDI_DECLARE_BUF(payload, MC_CMD_LICENSING_GET_ID_V3_IN_LEN,
1033342516Sarybchik		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;
1049301361Sarybchik		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
1053301376Sarybchik	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,
1076310839Sarybchik		    bufferp + MC_CMD_LICENSING_GET_ID_V3_OUT_LICENSE_ID_OFST,
1077310839Sarybchik		    *lengthp);
1078310839Sarybchik		memset(bufferp + (*lengthp), 0,
1079310839Sarybchik		    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
1092301361Sarybchik/* V3 format uses Huntington TLV format partition. See SF-108797-SW */
1093301361Sarybchik#define EFX_LICENSE_V3_KEY_LENGTH_MIN    (64)
1094301368Sarybchik#define EFX_LICENSE_V3_KEY_LENGTH_MAX    (160)
1095293901Sarybchik
1096301361Sarybchik	__checkReturn		efx_rc_t
1097301361Sarybchikefx_lic_v3_find_start(
1098301361Sarybchik	__in			efx_nic_t *enp,
1099301361Sarybchik	__in_bcount(buffer_size)
1100301361Sarybchik				caddr_t bufferp,
1101301361Sarybchik	__in			size_t buffer_size,
1102301361Sarybchik	__out			uint32_t *startp
1103301361Sarybchik	)
1104301361Sarybchik{
1105301361Sarybchik	_NOTE(ARGUNUSED(enp))
1106301361Sarybchik
1107301361Sarybchik	return ef10_nvram_buffer_find_item_start(bufferp, buffer_size, startp);
1108301361Sarybchik}
1109301361Sarybchik
1110301361Sarybchik	__checkReturn		efx_rc_t
1111301361Sarybchikefx_lic_v3_find_end(
1112301361Sarybchik	__in			efx_nic_t *enp,
1113301361Sarybchik	__in_bcount(buffer_size)
1114301361Sarybchik				caddr_t bufferp,
1115301361Sarybchik	__in			size_t buffer_size,
1116301361Sarybchik	__in			uint32_t offset,
1117301361Sarybchik	__out			uint32_t *endp
1118301361Sarybchik	)
1119301361Sarybchik{
1120301361Sarybchik	_NOTE(ARGUNUSED(enp))
1121301361Sarybchik
1122301361Sarybchik	return ef10_nvram_buffer_find_end(bufferp, buffer_size, offset, endp);
1123301361Sarybchik}
1124301361Sarybchik
1125301361Sarybchik	__checkReturn	__success(return != B_FALSE)	boolean_t
1126301361Sarybchikefx_lic_v3_find_key(
1127301361Sarybchik	__in			efx_nic_t *enp,
1128301361Sarybchik	__in_bcount(buffer_size)
1129301361Sarybchik				caddr_t bufferp,
1130301361Sarybchik	__in			size_t buffer_size,
1131301361Sarybchik	__in			uint32_t offset,
1132301361Sarybchik	__out			uint32_t *startp,
1133301361Sarybchik	__out			uint32_t *lengthp
1134301361Sarybchik	)
1135301361Sarybchik{
1136301361Sarybchik	_NOTE(ARGUNUSED(enp))
1137301361Sarybchik
1138301361Sarybchik	return ef10_nvram_buffer_find_item(bufferp, buffer_size,
1139301361Sarybchik	    offset, startp, lengthp);
1140301361Sarybchik}
1141301361Sarybchik
1142301361Sarybchik	__checkReturn	__success(return != B_FALSE)	boolean_t
1143301361Sarybchikefx_lic_v3_validate_key(
1144301361Sarybchik	__in			efx_nic_t *enp,
1145301361Sarybchik	__in_bcount(length)	caddr_t keyp,
1146301361Sarybchik	__in			uint32_t length
1147301361Sarybchik	)
1148301361Sarybchik{
1149311050Sarybchik	/* Check key is a valid V3 key */
1150301361Sarybchik	uint8_t key_type;
1151301361Sarybchik	uint8_t key_length;
1152301361Sarybchik
1153301361Sarybchik	_NOTE(ARGUNUSED(enp))
1154301361Sarybchik
1155301361Sarybchik	if (length < EFX_LICENSE_V3_KEY_LENGTH_MIN) {
1156301361Sarybchik		goto fail1;
1157301361Sarybchik	}
1158301361Sarybchik
1159301370Sarybchik	if (length > EFX_LICENSE_V3_KEY_LENGTH_MAX) {
1160301370Sarybchik		goto fail2;
1161301370Sarybchik	}
1162301370Sarybchik
1163311054Sarybchik	key_type = ((uint8_t *)keyp)[0];
1164311054Sarybchik	key_length = ((uint8_t *)keyp)[1];
1165301361Sarybchik
1166301361Sarybchik	if (key_type < 3) {
1167301361Sarybchik		goto fail3;
1168301361Sarybchik	}
1169301370Sarybchik	if (key_length > length) {
1170301361Sarybchik		goto fail4;
1171301361Sarybchik	}
1172301361Sarybchik	return (B_TRUE);
1173301361Sarybchik
1174301361Sarybchikfail4:
1175301361Sarybchik	EFSYS_PROBE(fail4);
1176301361Sarybchikfail3:
1177301361Sarybchik	EFSYS_PROBE(fail3);
1178301361Sarybchikfail2:
1179301361Sarybchik	EFSYS_PROBE(fail2);
1180301361Sarybchikfail1:
1181342497Sarybchik	EFSYS_PROBE1(fail1, boolean_t, B_FALSE);
1182301361Sarybchik
1183301361Sarybchik	return (B_FALSE);
1184301361Sarybchik}
1185301361Sarybchik
1186301361Sarybchik	__checkReturn		efx_rc_t
1187301361Sarybchikefx_lic_v3_read_key(
1188301361Sarybchik	__in			efx_nic_t *enp,
1189301361Sarybchik	__in_bcount(buffer_size)
1190301361Sarybchik				caddr_t bufferp,
1191301361Sarybchik	__in			size_t buffer_size,
1192301361Sarybchik	__in			uint32_t offset,
1193301361Sarybchik	__in			uint32_t length,
1194301361Sarybchik	__out_bcount_part(key_max_size, *lengthp)
1195301361Sarybchik				caddr_t keyp,
1196301361Sarybchik	__in			size_t key_max_size,
1197301361Sarybchik	__out			uint32_t *lengthp
1198301361Sarybchik	)
1199301361Sarybchik{
1200301361Sarybchik	_NOTE(ARGUNUSED(enp))
1201301361Sarybchik
1202301361Sarybchik	return ef10_nvram_buffer_get_item(bufferp, buffer_size,
1203301361Sarybchik		    offset, length, keyp, key_max_size, lengthp);
1204301361Sarybchik}
1205301361Sarybchik
1206301361Sarybchik	__checkReturn		efx_rc_t
1207301361Sarybchikefx_lic_v3_write_key(
1208301361Sarybchik	__in			efx_nic_t *enp,
1209301361Sarybchik	__in_bcount(buffer_size)
1210301361Sarybchik				caddr_t bufferp,
1211301361Sarybchik	__in			size_t buffer_size,
1212301361Sarybchik	__in			uint32_t offset,
1213301361Sarybchik	__in_bcount(length)	caddr_t keyp,
1214301361Sarybchik	__in			uint32_t length,
1215301361Sarybchik	__out			uint32_t *lengthp
1216301361Sarybchik	)
1217301361Sarybchik{
1218301361Sarybchik	_NOTE(ARGUNUSED(enp))
1219301361Sarybchik	EFSYS_ASSERT(length <= EFX_LICENSE_V3_KEY_LENGTH_MAX);
1220301361Sarybchik
1221301361Sarybchik	return ef10_nvram_buffer_insert_item(bufferp, buffer_size,
1222301361Sarybchik		    offset, keyp, length, lengthp);
1223301361Sarybchik}
1224301361Sarybchik
1225301361Sarybchik	__checkReturn		efx_rc_t
1226301361Sarybchikefx_lic_v3_delete_key(
1227301361Sarybchik	__in			efx_nic_t *enp,
1228301361Sarybchik	__in_bcount(buffer_size)
1229301361Sarybchik				caddr_t bufferp,
1230301361Sarybchik	__in			size_t buffer_size,
1231301361Sarybchik	__in			uint32_t offset,
1232301361Sarybchik	__in			uint32_t length,
1233301361Sarybchik	__in			uint32_t end,
1234301361Sarybchik	__out			uint32_t *deltap
1235301361Sarybchik	)
1236301361Sarybchik{
1237301361Sarybchik	efx_rc_t rc;
1238301361Sarybchik
1239301361Sarybchik	_NOTE(ARGUNUSED(enp))
1240301361Sarybchik
1241301361Sarybchik	if ((rc = ef10_nvram_buffer_delete_item(bufferp,
1242301361Sarybchik			buffer_size, offset, length, end)) != 0) {
1243301361Sarybchik		goto fail1;
1244301361Sarybchik	}
1245301361Sarybchik
1246301361Sarybchik	*deltap = length;
1247301361Sarybchik
1248301361Sarybchik	return (0);
1249301361Sarybchik
1250301361Sarybchikfail1:
1251301361Sarybchik	EFSYS_PROBE1(fail1, efx_rc_t, rc);
1252301361Sarybchik
1253301361Sarybchik	return (rc);
1254301361Sarybchik}
1255301361Sarybchik
1256301361Sarybchik	__checkReturn		efx_rc_t
1257301361Sarybchikefx_lic_v3_create_partition(
1258301361Sarybchik	__in			efx_nic_t *enp,
1259301361Sarybchik	__in_bcount(buffer_size)
1260301361Sarybchik				caddr_t bufferp,
1261301361Sarybchik	__in			size_t buffer_size
1262301361Sarybchik	)
1263301361Sarybchik{
1264301361Sarybchik	efx_rc_t rc;
1265301361Sarybchik
1266311050Sarybchik	/* Construct empty partition */
1267301361Sarybchik	if ((rc = ef10_nvram_buffer_create(enp,
1268301361Sarybchik	    NVRAM_PARTITION_TYPE_LICENSE,
1269301361Sarybchik	    bufferp, buffer_size)) != 0) {
1270301361Sarybchik		rc = EFAULT;
1271301361Sarybchik		goto fail1;
1272301361Sarybchik	}
1273301361Sarybchik
1274301361Sarybchik	return (0);
1275301361Sarybchik
1276301361Sarybchikfail1:
1277301361Sarybchik	EFSYS_PROBE1(fail1, efx_rc_t, rc);
1278301361Sarybchik
1279301361Sarybchik	return (rc);
1280301361Sarybchik}
1281301361Sarybchik
1282301361Sarybchik	__checkReturn		efx_rc_t
1283301361Sarybchikefx_lic_v3_finish_partition(
1284301361Sarybchik	__in			efx_nic_t *enp,
1285301361Sarybchik	__in_bcount(buffer_size)
1286301361Sarybchik				caddr_t bufferp,
1287301361Sarybchik	__in			size_t buffer_size
1288301361Sarybchik	)
1289301361Sarybchik{
1290301361Sarybchik	efx_rc_t rc;
1291301361Sarybchik
1292301361Sarybchik	if ((rc = ef10_nvram_buffer_finish(bufferp,
1293301361Sarybchik			buffer_size)) != 0) {
1294301361Sarybchik		goto fail1;
1295301361Sarybchik	}
1296301361Sarybchik
1297311050Sarybchik	/* Validate completed partition */
1298301361Sarybchik	if ((rc = ef10_nvram_buffer_validate(enp, NVRAM_PARTITION_TYPE_LICENSE,
1299301361Sarybchik					bufferp, buffer_size)) != 0) {
1300301361Sarybchik		goto fail2;
1301301361Sarybchik	}
1302301361Sarybchik
1303301361Sarybchik	return (0);
1304301361Sarybchik
1305301361Sarybchikfail2:
1306301361Sarybchik	EFSYS_PROBE(fail2);
1307301361Sarybchikfail1:
1308301361Sarybchik	EFSYS_PROBE1(fail1, efx_rc_t, rc);
1309301361Sarybchik
1310301361Sarybchik	return (rc);
1311301361Sarybchik}
1312301361Sarybchik
1313301361Sarybchik
1314293901Sarybchik#endif	/* EFSYS_OPT_MEDFORD */
1315293901Sarybchik
1316293901Sarybchik	__checkReturn		efx_rc_t
1317293901Sarybchikefx_lic_init(
1318293901Sarybchik	__in			efx_nic_t *enp)
1319293901Sarybchik{
1320301340Sarybchik	const efx_lic_ops_t *elop;
1321301379Sarybchik	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:
1332301340Sarybchik		elop = &__efx_lic_v1_ops;
1333293901Sarybchik		break;
1334293901Sarybchik#endif	/* EFSYS_OPT_SIENA */
1335293901Sarybchik
1336293901Sarybchik#if EFSYS_OPT_HUNTINGTON
1337293901Sarybchik	case EFX_FAMILY_HUNTINGTON:
1338301340Sarybchik		elop = &__efx_lic_v2_ops;
1339293901Sarybchik		break;
1340293901Sarybchik#endif	/* EFSYS_OPT_HUNTINGTON */
1341293901Sarybchik
1342293901Sarybchik#if EFSYS_OPT_MEDFORD
1343293901Sarybchik	case EFX_FAMILY_MEDFORD:
1344301340Sarybchik		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
1357301379Sarybchik	/* Probe for support */
1358301379Sarybchik	if (efx_lic_get_key_stats(enp, &eks) == 0) {
1359301379Sarybchik		enp->en_licensing_supported = B_TRUE;
1360301379Sarybchik	} else {
1361301379Sarybchik		enp->en_licensing_supported = B_FALSE;
1362301379Sarybchik	}
1363301379Sarybchik
1364293901Sarybchik	return (0);
1365293901Sarybchik
1366293901Sarybchikfail1:
1367293901Sarybchik	EFSYS_PROBE1(fail1, efx_rc_t, rc);
1368293901Sarybchik
1369293901Sarybchik	return (rc);
1370293901Sarybchik}
1371293901Sarybchik
1372301379Sarybchikextern	__checkReturn	boolean_t
1373301379Sarybchikefx_lic_check_support(
1374301379Sarybchik	__in			efx_nic_t *enp)
1375301379Sarybchik{
1376301379Sarybchik	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1377301379Sarybchik	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
1378301379Sarybchik	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1379301379Sarybchik
1380301379Sarybchik	return enp->en_licensing_supported;
1381301379Sarybchik}
1382301379Sarybchik
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{
1400301340Sarybchik	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{
1422301340Sarybchik	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{
1445301340Sarybchik	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
1451301362Sarybchik	if (elop->elo_app_state == NULL)
1452301362Sarybchik		return (ENOTSUP);
1453301362Sarybchik
1454301362Sarybchik	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{
1474301340Sarybchik	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
1480301362Sarybchik	if (elop->elo_get_id == NULL)
1481301362Sarybchik		return (ENOTSUP);
1482293901Sarybchik
1483293901Sarybchik	if ((rc = elop->elo_get_id(enp, buffer_size, typep,
1484293901Sarybchik				    lengthp, bufferp)) != 0)
1485301362Sarybchik		goto fail1;
1486293901Sarybchik
1487293901Sarybchik	return (0);
1488293901Sarybchik
1489293901Sarybchikfail1:
1490293901Sarybchik	EFSYS_PROBE1(fail1, efx_rc_t, rc);
1491293901Sarybchik
1492293901Sarybchik	return (rc);
1493293901Sarybchik}
1494293901Sarybchik
1495301361Sarybchik/* Buffer management API - abstracts varying TLV format used for License partition */
1496301361Sarybchik
1497301361Sarybchik	__checkReturn		efx_rc_t
1498301361Sarybchikefx_lic_find_start(
1499301361Sarybchik	__in			efx_nic_t *enp,
1500301361Sarybchik	__in_bcount(buffer_size)
1501301361Sarybchik				caddr_t bufferp,
1502301361Sarybchik	__in			size_t buffer_size,
1503301361Sarybchik	__out			uint32_t *startp
1504301361Sarybchik	)
1505301361Sarybchik{
1506301361Sarybchik	const efx_lic_ops_t *elop = enp->en_elop;
1507301361Sarybchik	efx_rc_t rc;
1508301361Sarybchik
1509301361Sarybchik	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1510301361Sarybchik	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1511301361Sarybchik
1512301361Sarybchik	if ((rc = elop->elo_find_start(enp, bufferp, buffer_size, startp)) != 0)
1513301361Sarybchik		goto fail1;
1514301361Sarybchik
1515301361Sarybchik	return (0);
1516301361Sarybchik
1517301361Sarybchikfail1:
1518301361Sarybchik	EFSYS_PROBE1(fail1, efx_rc_t, rc);
1519301361Sarybchik
1520301361Sarybchik	return (rc);
1521301361Sarybchik}
1522301361Sarybchik
1523301361Sarybchik	__checkReturn		efx_rc_t
1524301361Sarybchikefx_lic_find_end(
1525301361Sarybchik	__in			efx_nic_t *enp,
1526301361Sarybchik	__in_bcount(buffer_size)
1527301361Sarybchik				caddr_t bufferp,
1528301361Sarybchik	__in			size_t buffer_size,
1529301361Sarybchik	__in			uint32_t offset,
1530301361Sarybchik	__out			uint32_t *endp
1531301361Sarybchik	)
1532301361Sarybchik{
1533301361Sarybchik	const efx_lic_ops_t *elop = enp->en_elop;
1534301361Sarybchik	efx_rc_t rc;
1535301361Sarybchik
1536301361Sarybchik	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1537301361Sarybchik	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1538301361Sarybchik
1539301361Sarybchik	if ((rc = elop->elo_find_end(enp, bufferp, buffer_size, offset, endp)) != 0)
1540301361Sarybchik		goto fail1;
1541301361Sarybchik
1542301361Sarybchik	return (0);
1543301361Sarybchik
1544301361Sarybchikfail1:
1545301361Sarybchik	EFSYS_PROBE1(fail1, efx_rc_t, rc);
1546301361Sarybchik
1547301361Sarybchik	return (rc);
1548301361Sarybchik}
1549301361Sarybchik
1550301361Sarybchik	__checkReturn	__success(return != B_FALSE)	boolean_t
1551301361Sarybchikefx_lic_find_key(
1552301361Sarybchik	__in			efx_nic_t *enp,
1553301361Sarybchik	__in_bcount(buffer_size)
1554301361Sarybchik				caddr_t bufferp,
1555301361Sarybchik	__in			size_t buffer_size,
1556301361Sarybchik	__in			uint32_t offset,
1557301361Sarybchik	__out			uint32_t *startp,
1558301361Sarybchik	__out			uint32_t *lengthp
1559301361Sarybchik	)
1560301361Sarybchik{
1561301361Sarybchik	const efx_lic_ops_t *elop = enp->en_elop;
1562301361Sarybchik
1563301361Sarybchik	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1564301361Sarybchik	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1565301361Sarybchik
1566301361Sarybchik	EFSYS_ASSERT(bufferp);
1567301361Sarybchik	EFSYS_ASSERT(startp);
1568301361Sarybchik	EFSYS_ASSERT(lengthp);
1569301361Sarybchik
1570301361Sarybchik	return (elop->elo_find_key(enp, bufferp, buffer_size, offset,
1571301361Sarybchik				    startp, lengthp));
1572301361Sarybchik}
1573301361Sarybchik
1574301361Sarybchik
1575301361Sarybchik/* Validate that the buffer contains a single key in a recognised format.
1576301361Sarybchik** An empty or terminator buffer is not accepted as a valid key.
1577301361Sarybchik*/
1578301361Sarybchik	__checkReturn	__success(return != B_FALSE)	boolean_t
1579301361Sarybchikefx_lic_validate_key(
1580301361Sarybchik	__in			efx_nic_t *enp,
1581301361Sarybchik	__in_bcount(length)	caddr_t keyp,
1582301361Sarybchik	__in			uint32_t length
1583301361Sarybchik	)
1584301361Sarybchik{
1585301361Sarybchik	const efx_lic_ops_t *elop = enp->en_elop;
1586301361Sarybchik	boolean_t rc;
1587301361Sarybchik
1588301361Sarybchik	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1589301361Sarybchik	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1590301361Sarybchik
1591301361Sarybchik	if ((rc = elop->elo_validate_key(enp, keyp, length)) == B_FALSE)
1592301361Sarybchik		goto fail1;
1593301361Sarybchik
1594301361Sarybchik	return (B_TRUE);
1595301361Sarybchik
1596301361Sarybchikfail1:
1597301361Sarybchik	EFSYS_PROBE1(fail1, efx_rc_t, rc);
1598301361Sarybchik
1599301361Sarybchik	return (rc);
1600301361Sarybchik}
1601301361Sarybchik
1602301361Sarybchik	__checkReturn		efx_rc_t
1603301361Sarybchikefx_lic_read_key(
1604301361Sarybchik	__in			efx_nic_t *enp,
1605301361Sarybchik	__in_bcount(buffer_size)
1606301361Sarybchik				caddr_t bufferp,
1607301361Sarybchik	__in			size_t buffer_size,
1608301361Sarybchik	__in			uint32_t offset,
1609301361Sarybchik	__in			uint32_t length,
1610301361Sarybchik	__out_bcount_part(key_max_size, *lengthp)
1611301361Sarybchik				caddr_t keyp,
1612301361Sarybchik	__in			size_t key_max_size,
1613301361Sarybchik	__out			uint32_t *lengthp
1614301361Sarybchik	)
1615301361Sarybchik{
1616301361Sarybchik	const efx_lic_ops_t *elop = enp->en_elop;
1617301361Sarybchik	efx_rc_t rc;
1618301361Sarybchik
1619301361Sarybchik	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1620301361Sarybchik	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1621301361Sarybchik
1622301361Sarybchik	if ((rc = elop->elo_read_key(enp, bufferp, buffer_size, offset,
1623301361Sarybchik				    length, keyp, key_max_size, lengthp)) != 0)
1624301361Sarybchik		goto fail1;
1625301361Sarybchik
1626301361Sarybchik	return (0);
1627301361Sarybchik
1628301361Sarybchikfail1:
1629301361Sarybchik	EFSYS_PROBE1(fail1, efx_rc_t, rc);
1630301361Sarybchik
1631301361Sarybchik	return (rc);
1632301361Sarybchik}
1633301361Sarybchik
1634301361Sarybchik	__checkReturn		efx_rc_t
1635301361Sarybchikefx_lic_write_key(
1636301361Sarybchik	__in			efx_nic_t *enp,
1637301361Sarybchik	__in_bcount(buffer_size)
1638301361Sarybchik				caddr_t bufferp,
1639301361Sarybchik	__in			size_t buffer_size,
1640301361Sarybchik	__in			uint32_t offset,
1641301361Sarybchik	__in_bcount(length)	caddr_t keyp,
1642301361Sarybchik	__in			uint32_t length,
1643301361Sarybchik	__out			uint32_t *lengthp
1644301361Sarybchik	)
1645301361Sarybchik{
1646301361Sarybchik	const efx_lic_ops_t *elop = enp->en_elop;
1647301361Sarybchik	efx_rc_t rc;
1648301361Sarybchik
1649301361Sarybchik	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1650301361Sarybchik	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1651301361Sarybchik
1652301361Sarybchik	if ((rc = elop->elo_write_key(enp, bufferp, buffer_size, offset,
1653301361Sarybchik				    keyp, length, lengthp)) != 0)
1654301361Sarybchik		goto fail1;
1655301361Sarybchik
1656301361Sarybchik	return (0);
1657301361Sarybchik
1658301361Sarybchikfail1:
1659301361Sarybchik	EFSYS_PROBE1(fail1, efx_rc_t, rc);
1660301361Sarybchik
1661301361Sarybchik	return (rc);
1662301361Sarybchik}
1663301361Sarybchik
1664301361Sarybchik	__checkReturn		efx_rc_t
1665301361Sarybchikefx_lic_delete_key(
1666301361Sarybchik	__in			efx_nic_t *enp,
1667301361Sarybchik	__in_bcount(buffer_size)
1668301361Sarybchik				caddr_t bufferp,
1669301361Sarybchik	__in			size_t buffer_size,
1670301361Sarybchik	__in			uint32_t offset,
1671301361Sarybchik	__in			uint32_t length,
1672301361Sarybchik	__in			uint32_t end,
1673301361Sarybchik	__out			uint32_t *deltap
1674301361Sarybchik	)
1675301361Sarybchik{
1676301361Sarybchik	const efx_lic_ops_t *elop = enp->en_elop;
1677301361Sarybchik	efx_rc_t rc;
1678301361Sarybchik
1679301361Sarybchik	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1680301361Sarybchik	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1681301361Sarybchik
1682301361Sarybchik	if ((rc = elop->elo_delete_key(enp, bufferp, buffer_size, offset,
1683301361Sarybchik				    length, end, deltap)) != 0)
1684301361Sarybchik		goto fail1;
1685301361Sarybchik
1686301361Sarybchik	return (0);
1687301361Sarybchik
1688301361Sarybchikfail1:
1689301361Sarybchik	EFSYS_PROBE1(fail1, efx_rc_t, rc);
1690301361Sarybchik
1691301361Sarybchik	return (rc);
1692301361Sarybchik}
1693301361Sarybchik
1694301361Sarybchik	__checkReturn		efx_rc_t
1695301361Sarybchikefx_lic_create_partition(
1696301361Sarybchik	__in			efx_nic_t *enp,
1697301361Sarybchik	__in_bcount(buffer_size)
1698301361Sarybchik				caddr_t bufferp,
1699301361Sarybchik	__in			size_t buffer_size
1700301361Sarybchik	)
1701301361Sarybchik{
1702301361Sarybchik	const efx_lic_ops_t *elop = enp->en_elop;
1703301361Sarybchik	efx_rc_t rc;
1704301361Sarybchik
1705301361Sarybchik	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1706301361Sarybchik	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1707301361Sarybchik
1708301361Sarybchik	if ((rc = elop->elo_create_partition(enp, bufferp, buffer_size)) != 0)
1709301361Sarybchik		goto fail1;
1710301361Sarybchik
1711301361Sarybchik	return (0);
1712301361Sarybchik
1713301361Sarybchikfail1:
1714301361Sarybchik	EFSYS_PROBE1(fail1, efx_rc_t, rc);
1715301361Sarybchik
1716301361Sarybchik	return (rc);
1717301361Sarybchik}
1718301361Sarybchik
1719301361Sarybchik
1720301361Sarybchik	__checkReturn		efx_rc_t
1721301361Sarybchikefx_lic_finish_partition(
1722301361Sarybchik	__in			efx_nic_t *enp,
1723301361Sarybchik	__in_bcount(buffer_size)
1724301361Sarybchik				caddr_t bufferp,
1725301361Sarybchik	__in			size_t buffer_size
1726301361Sarybchik	)
1727301361Sarybchik{
1728301361Sarybchik	const efx_lic_ops_t *elop = enp->en_elop;
1729301361Sarybchik	efx_rc_t rc;
1730301361Sarybchik
1731301361Sarybchik	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1732301361Sarybchik	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1733301361Sarybchik
1734301361Sarybchik	if ((rc = elop->elo_finish_partition(enp, bufferp, buffer_size)) != 0)
1735301361Sarybchik		goto fail1;
1736301361Sarybchik
1737301361Sarybchik	return (0);
1738301361Sarybchik
1739301361Sarybchikfail1:
1740301361Sarybchik	EFSYS_PROBE1(fail1, efx_rc_t, rc);
1741301361Sarybchik
1742301361Sarybchik	return (rc);
1743301361Sarybchik}
1744301361Sarybchik
1745293901Sarybchik#endif	/* EFSYS_OPT_LICENSING */
1746