efx_lic.c revision 299898
1293901Sarybchik/*-
2293901Sarybchik * Copyright (c) 2009-2015 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: head/sys/dev/sfxge/common/efx_lic.c 299898 2016-05-16 06:17:56Z 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;
346293901Sarybchik	uint8_t payload[MC_CMD_FC_IN_LICENSE_LEN];
347293901Sarybchik	efx_rc_t rc;
348293901Sarybchik
349293901Sarybchik	EFSYS_ASSERT(enp->en_family == EFX_FAMILY_SIENA);
350293901Sarybchik
351293901Sarybchik	(void) memset(payload, 0, sizeof (payload));
352293901Sarybchik	req.emr_cmd = MC_CMD_FC_OP_LICENSE;
353293901Sarybchik	req.emr_in_buf = payload;
354293901Sarybchik	req.emr_in_length = MC_CMD_FC_IN_LICENSE_LEN;
355293901Sarybchik	req.emr_out_buf = payload;
356293901Sarybchik	req.emr_out_length = 0;
357293901Sarybchik
358293901Sarybchik	MCDI_IN_SET_DWORD(req, FC_IN_LICENSE_OP,
359293901Sarybchik	    MC_CMD_FC_IN_LICENSE_UPDATE_LICENSE);
360293901Sarybchik
361293901Sarybchik	efx_mcdi_execute(enp, &req);
362293901Sarybchik
363293901Sarybchik	if (req.emr_rc != 0) {
364293901Sarybchik		rc = req.emr_rc;
365293901Sarybchik		goto fail1;
366293901Sarybchik	}
367293901Sarybchik
368293901Sarybchik	if (req.emr_out_length_used != 0) {
369293901Sarybchik		rc = EIO;
370293901Sarybchik		goto fail2;
371293901Sarybchik	}
372293901Sarybchik
373293901Sarybchik	return (0);
374293901Sarybchik
375293901Sarybchikfail2:
376293901Sarybchik	EFSYS_PROBE(fail2);
377293901Sarybchikfail1:
378293901Sarybchik	EFSYS_PROBE1(fail1, efx_rc_t, rc);
379293901Sarybchik
380293901Sarybchik	return (rc);
381293901Sarybchik}
382293901Sarybchik
383293901Sarybchikstatic	__checkReturn	efx_rc_t
384293901Sarybchikefx_mcdi_fc_license_get_key_stats(
385293901Sarybchik	__in		efx_nic_t *enp,
386293901Sarybchik	__out		efx_key_stats_t *eksp)
387293901Sarybchik{
388293901Sarybchik	efx_mcdi_req_t req;
389293901Sarybchik	uint8_t payload[MAX(MC_CMD_FC_IN_LICENSE_LEN,
390293901Sarybchik			    MC_CMD_FC_OUT_LICENSE_LEN)];
391293901Sarybchik	efx_rc_t rc;
392293901Sarybchik
393293901Sarybchik	EFSYS_ASSERT(enp->en_family == EFX_FAMILY_SIENA);
394293901Sarybchik
395293901Sarybchik	(void) memset(payload, 0, sizeof (payload));
396293901Sarybchik	req.emr_cmd = MC_CMD_FC_OP_LICENSE;
397293901Sarybchik	req.emr_in_buf = payload;
398293901Sarybchik	req.emr_in_length = MC_CMD_FC_IN_LICENSE_LEN;
399293901Sarybchik	req.emr_out_buf = payload;
400293901Sarybchik	req.emr_out_length = MC_CMD_FC_OUT_LICENSE_LEN;
401293901Sarybchik
402293901Sarybchik	MCDI_IN_SET_DWORD(req, FC_IN_LICENSE_OP,
403293901Sarybchik	    MC_CMD_FC_IN_LICENSE_GET_KEY_STATS);
404293901Sarybchik
405293901Sarybchik	efx_mcdi_execute(enp, &req);
406293901Sarybchik
407293901Sarybchik	if (req.emr_rc != 0) {
408293901Sarybchik		rc = req.emr_rc;
409293901Sarybchik		goto fail1;
410293901Sarybchik	}
411293901Sarybchik
412293901Sarybchik	if (req.emr_out_length_used < MC_CMD_FC_OUT_LICENSE_LEN) {
413293901Sarybchik		rc = EMSGSIZE;
414293901Sarybchik		goto fail2;
415293901Sarybchik	}
416293901Sarybchik
417293901Sarybchik	eksp->eks_valid =
418293901Sarybchik		MCDI_OUT_DWORD(req, FC_OUT_LICENSE_VALID_KEYS);
419293901Sarybchik	eksp->eks_invalid =
420293901Sarybchik		MCDI_OUT_DWORD(req, FC_OUT_LICENSE_INVALID_KEYS);
421293901Sarybchik	eksp->eks_blacklisted =
422293901Sarybchik		MCDI_OUT_DWORD(req, FC_OUT_LICENSE_BLACKLISTED_KEYS);
423293901Sarybchik	eksp->eks_unverifiable = 0;
424293901Sarybchik	eksp->eks_wrong_node = 0;
425293901Sarybchik	eksp->eks_licensed_apps_lo = 0;
426293901Sarybchik	eksp->eks_licensed_apps_hi = 0;
427293901Sarybchik	eksp->eks_licensed_features_lo = 0;
428293901Sarybchik	eksp->eks_licensed_features_hi = 0;
429293901Sarybchik
430293901Sarybchik	return (0);
431293901Sarybchik
432293901Sarybchikfail2:
433293901Sarybchik	EFSYS_PROBE(fail2);
434293901Sarybchikfail1:
435293901Sarybchik	EFSYS_PROBE1(fail1, efx_rc_t, rc);
436293901Sarybchik
437293901Sarybchik	return (rc);
438293901Sarybchik}
439293901Sarybchik
440293901Sarybchik#endif	/* EFSYS_OPT_SIENA */
441293901Sarybchik
442299898Sarybchik/* V1 and V2 Partition format - based on a 16-bit TLV format */
443299898Sarybchik
444299898Sarybchik#if EFSYS_OPT_SIENA | EFSYS_OPT_HUNTINGTON
445299898Sarybchik
446299898Sarybchik/*
447299898Sarybchik * V1/V2 format - defined in SF-108542-TC section 4.2:
448299898Sarybchik *  Type (T):   16bit - revision/HMAC algorithm
449299898Sarybchik *  Length (L): 16bit - value length in bytes
450299898Sarybchik *  Value (V):  L bytes - payload
451299898Sarybchik */
452299898Sarybchik#define EFX_LICENSE_V1V2_PAYLOAD_LENGTH_MAX    (256)
453299898Sarybchik#define EFX_LICENSE_V1V2_HEADER_LENGTH         (2*sizeof(uint16_t))
454299898Sarybchik
455299898Sarybchik	__checkReturn		efx_rc_t
456299898Sarybchikefx_lic_v1v2_find_start(
457299898Sarybchik	__in			efx_nic_t *enp,
458299898Sarybchik	__in_bcount(buffer_size)
459299898Sarybchik				caddr_t bufferp,
460299898Sarybchik	__in			size_t buffer_size,
461299898Sarybchik	__out			uint32_t *startp
462299898Sarybchik	)
463299898Sarybchik{
464299898Sarybchik	_NOTE(ARGUNUSED(enp, bufferp, buffer_size))
465299898Sarybchik
466299898Sarybchik	*startp = 0;
467299898Sarybchik	return (0);
468299898Sarybchik}
469299898Sarybchik
470299898Sarybchik	__checkReturn		efx_rc_t
471299898Sarybchikefx_lic_v1v2_find_end(
472299898Sarybchik	__in			efx_nic_t *enp,
473299898Sarybchik	__in_bcount(buffer_size)
474299898Sarybchik				caddr_t bufferp,
475299898Sarybchik	__in			size_t buffer_size,
476299898Sarybchik	__in			uint32_t offset,
477299898Sarybchik	__out			uint32_t *endp
478299898Sarybchik	)
479299898Sarybchik{
480299898Sarybchik	_NOTE(ARGUNUSED(enp, bufferp, buffer_size))
481299898Sarybchik
482299898Sarybchik	*endp = offset + EFX_LICENSE_V1V2_HEADER_LENGTH;
483299898Sarybchik	return (0);
484299898Sarybchik}
485299898Sarybchik
486299898Sarybchik	__checkReturn	__success(return != B_FALSE)	boolean_t
487299898Sarybchikefx_lic_v1v2_find_key(
488299898Sarybchik	__in			efx_nic_t *enp,
489299898Sarybchik	__in_bcount(buffer_size)
490299898Sarybchik				caddr_t bufferp,
491299898Sarybchik	__in			size_t buffer_size,
492299898Sarybchik	__in			uint32_t offset,
493299898Sarybchik	__out			uint32_t *startp,
494299898Sarybchik	__out			uint32_t *lengthp
495299898Sarybchik	)
496299898Sarybchik{
497299898Sarybchik	boolean_t found;
498299898Sarybchik	uint16_t tlv_type;
499299898Sarybchik	uint16_t tlv_length;
500299898Sarybchik
501299898Sarybchik	_NOTE(ARGUNUSED(enp))
502299898Sarybchik
503299898Sarybchik	if((size_t)buffer_size - offset < EFX_LICENSE_V1V2_HEADER_LENGTH)
504299898Sarybchik		goto fail1;
505299898Sarybchik
506299898Sarybchik	tlv_type = __LE_TO_CPU_16(((uint16_t*)&bufferp[offset])[0]);
507299898Sarybchik	tlv_length = __LE_TO_CPU_16(((uint16_t*)&bufferp[offset])[1]);
508299898Sarybchik	if ((tlv_length > EFX_LICENSE_V1V2_PAYLOAD_LENGTH_MAX) ||
509299898Sarybchik	    (tlv_type == 0 && tlv_length == 0)) {
510299898Sarybchik		found = B_FALSE;
511299898Sarybchik	} else {
512299898Sarybchik		*startp = offset;
513299898Sarybchik		*lengthp = tlv_length + EFX_LICENSE_V1V2_HEADER_LENGTH;
514299898Sarybchik		found = B_TRUE;
515299898Sarybchik	}
516299898Sarybchik	return (found);
517299898Sarybchik
518299898Sarybchikfail1:
519299898Sarybchik	EFSYS_PROBE(fail1);
520299898Sarybchik
521299898Sarybchik	return (B_FALSE);
522299898Sarybchik}
523299898Sarybchik
524299898Sarybchik	__checkReturn	__success(return != B_FALSE)	boolean_t
525299898Sarybchikefx_lic_v1v2_validate_key(
526299898Sarybchik	__in			efx_nic_t *enp,
527299898Sarybchik	__in_bcount(length)	caddr_t keyp,
528299898Sarybchik	__in			uint32_t length
529299898Sarybchik	)
530299898Sarybchik{
531299898Sarybchik	const efx_lic_ops_t *elop = enp->en_elop;
532299898Sarybchik	efx_rc_t rc;
533299898Sarybchik	uint16_t tlv_type;
534299898Sarybchik	uint16_t tlv_length;
535299898Sarybchik
536299898Sarybchik	_NOTE(ARGUNUSED(enp))
537299898Sarybchik
538299898Sarybchik	if (length < EFX_LICENSE_V1V2_HEADER_LENGTH) {
539299898Sarybchik		goto fail1;
540299898Sarybchik	}
541299898Sarybchik
542299898Sarybchik	tlv_type = __LE_TO_CPU_16(((uint16_t*)keyp)[0]);
543299898Sarybchik	tlv_length = __LE_TO_CPU_16(((uint16_t*)keyp)[1]);
544299898Sarybchik
545299898Sarybchik	if(tlv_length > EFX_LICENSE_V1V2_PAYLOAD_LENGTH_MAX) {
546299898Sarybchik		goto fail2;
547299898Sarybchik	}
548299898Sarybchik	if (tlv_type == 0) {
549299898Sarybchik		goto fail3;
550299898Sarybchik	}
551299898Sarybchik	if ((tlv_length + EFX_LICENSE_V1V2_HEADER_LENGTH) != length) {
552299898Sarybchik		goto fail4;
553299898Sarybchik	}
554299898Sarybchik
555299898Sarybchik	return (B_TRUE);
556299898Sarybchik
557299898Sarybchikfail4:
558299898Sarybchik	EFSYS_PROBE(fail4);
559299898Sarybchikfail3:
560299898Sarybchik	EFSYS_PROBE(fail3);
561299898Sarybchikfail2:
562299898Sarybchik	EFSYS_PROBE(fail2);
563299898Sarybchikfail1:
564299898Sarybchik	EFSYS_PROBE(fail1);
565299898Sarybchik
566299898Sarybchik	return (B_FALSE);
567299898Sarybchik}
568299898Sarybchik
569299898Sarybchik
570299898Sarybchik	__checkReturn		efx_rc_t
571299898Sarybchikefx_lic_v1v2_read_key(
572299898Sarybchik	__in			efx_nic_t *enp,
573299898Sarybchik	__in_bcount(buffer_size)
574299898Sarybchik				caddr_t bufferp,
575299898Sarybchik	__in			size_t buffer_size,
576299898Sarybchik	__in			uint32_t offset,
577299898Sarybchik	__in			uint32_t length,
578299898Sarybchik	__out_bcount_part(key_max_size, *lengthp)
579299898Sarybchik				caddr_t keyp,
580299898Sarybchik	__in			size_t key_max_size,
581299898Sarybchik	__out			uint32_t *lengthp
582299898Sarybchik	)
583299898Sarybchik{
584299898Sarybchik	efx_rc_t rc;
585299898Sarybchik
586299898Sarybchik	_NOTE(ARGUNUSED(enp))
587299898Sarybchik	EFSYS_ASSERT(length <= (EFX_LICENSE_V1V2_PAYLOAD_LENGTH_MAX +
588299898Sarybchik	    EFX_LICENSE_V1V2_HEADER_LENGTH));
589299898Sarybchik
590299898Sarybchik	if (key_max_size < length) {
591299898Sarybchik		rc = ENOSPC;
592299898Sarybchik		goto fail1;
593299898Sarybchik	}
594299898Sarybchik	memcpy(keyp, &bufferp[offset], length);
595299898Sarybchik
596299898Sarybchik	*lengthp = length;
597299898Sarybchik
598299898Sarybchik	return (0);
599299898Sarybchik
600299898Sarybchikfail1:
601299898Sarybchik	EFSYS_PROBE1(fail1, efx_rc_t, rc);
602299898Sarybchik
603299898Sarybchik	return (rc);
604299898Sarybchik}
605299898Sarybchik
606299898Sarybchik	__checkReturn		efx_rc_t
607299898Sarybchikefx_lic_v1v2_write_key(
608299898Sarybchik	__in			efx_nic_t *enp,
609299898Sarybchik	__in_bcount(buffer_size)
610299898Sarybchik				caddr_t bufferp,
611299898Sarybchik	__in			size_t buffer_size,
612299898Sarybchik	__in			uint32_t offset,
613299898Sarybchik	__in_bcount(length)	caddr_t keyp,
614299898Sarybchik	__in			uint32_t length,
615299898Sarybchik	__out			uint32_t *lengthp
616299898Sarybchik	)
617299898Sarybchik{
618299898Sarybchik	efx_rc_t rc;
619299898Sarybchik
620299898Sarybchik	_NOTE(ARGUNUSED(enp))
621299898Sarybchik	EFSYS_ASSERT(length <= (EFX_LICENSE_V1V2_PAYLOAD_LENGTH_MAX +
622299898Sarybchik	    EFX_LICENSE_V1V2_HEADER_LENGTH));
623299898Sarybchik
624299898Sarybchik	// Ensure space for terminator remains
625299898Sarybchik	if ((offset + length) >
626299898Sarybchik	    (buffer_size - EFX_LICENSE_V1V2_HEADER_LENGTH) ) {
627299898Sarybchik		rc = ENOSPC;
628299898Sarybchik		goto fail1;
629299898Sarybchik	}
630299898Sarybchik
631299898Sarybchik	memcpy(bufferp + offset, keyp, length);
632299898Sarybchik
633299898Sarybchik	*lengthp = length;
634299898Sarybchik
635299898Sarybchik	return (0);
636299898Sarybchik
637299898Sarybchikfail1:
638299898Sarybchik	EFSYS_PROBE1(fail1, efx_rc_t, rc);
639299898Sarybchik
640299898Sarybchik	return (rc);
641299898Sarybchik}
642299898Sarybchik
643299898Sarybchik	__checkReturn		efx_rc_t
644299898Sarybchikefx_lic_v1v2_delete_key(
645299898Sarybchik	__in			efx_nic_t *enp,
646299898Sarybchik	__in_bcount(buffer_size)
647299898Sarybchik				caddr_t bufferp,
648299898Sarybchik	__in			size_t buffer_size,
649299898Sarybchik	__in			uint32_t offset,
650299898Sarybchik	__in			uint32_t length,
651299898Sarybchik	__in			uint32_t end,
652299898Sarybchik	__out			uint32_t *deltap
653299898Sarybchik	)
654299898Sarybchik{
655299898Sarybchik	efx_rc_t rc;
656299898Sarybchik	uint32_t move_start = offset + length;
657299898Sarybchik	uint32_t move_length = end - move_start;
658299898Sarybchik
659299898Sarybchik	_NOTE(ARGUNUSED(enp))
660299898Sarybchik	EFSYS_ASSERT(end <= buffer_size);
661299898Sarybchik
662299898Sarybchik	// Shift everything after the key down
663299898Sarybchik	memmove(bufferp + offset, bufferp + move_start, move_length);
664299898Sarybchik
665299898Sarybchik	*deltap = length;
666299898Sarybchik
667299898Sarybchik	return (0);
668299898Sarybchik}
669299898Sarybchik
670299898Sarybchik	__checkReturn		efx_rc_t
671299898Sarybchikefx_lic_v1v2_create_partition(
672299898Sarybchik	__in			efx_nic_t *enp,
673299898Sarybchik	__in_bcount(buffer_size)
674299898Sarybchik				caddr_t bufferp,
675299898Sarybchik	__in			size_t buffer_size
676299898Sarybchik	)
677299898Sarybchik{
678299898Sarybchik	_NOTE(ARGUNUSED(enp))
679299898Sarybchik	EFSYS_ASSERT(EFX_LICENSE_V1V2_HEADER_LENGTH <= buffer_size);
680299898Sarybchik
681299898Sarybchik	// Write terminator
682299898Sarybchik	memset(bufferp, '\0', EFX_LICENSE_V1V2_HEADER_LENGTH);
683299898Sarybchik	return (0);
684299898Sarybchik}
685299898Sarybchik
686299898Sarybchik
687299898Sarybchik	__checkReturn		efx_rc_t
688299898Sarybchikefx_lic_v1v2_finish_partition(
689299898Sarybchik	__in			efx_nic_t *enp,
690299898Sarybchik	__in_bcount(buffer_size)
691299898Sarybchik				caddr_t bufferp,
692299898Sarybchik	__in			size_t buffer_size
693299898Sarybchik	)
694299898Sarybchik{
695299898Sarybchik	_NOTE(ARGUNUSED(enp, bufferp, buffer_size))
696299898Sarybchik
697299898Sarybchik	return (0);
698299898Sarybchik}
699299898Sarybchik
700299898Sarybchik#endif	/* EFSYS_OPT_HUNTINGTON | EFSYS_OPT_SIENA */
701299898Sarybchik
702299898Sarybchik
703293901Sarybchik/* V2 Licensing - used by Huntington family only. See SF-113611-TC */
704293901Sarybchik
705293901Sarybchik#if EFSYS_OPT_HUNTINGTON
706293901Sarybchik
707293901Sarybchikstatic	__checkReturn	efx_rc_t
708293901Sarybchikefx_mcdi_licensed_app_state(
709293901Sarybchik	__in		efx_nic_t *enp,
710293901Sarybchik	__in		uint64_t app_id,
711293901Sarybchik	__out		boolean_t *licensedp)
712293901Sarybchik{
713293901Sarybchik	efx_mcdi_req_t req;
714293901Sarybchik	uint8_t payload[MAX(MC_CMD_GET_LICENSED_APP_STATE_IN_LEN,
715293901Sarybchik			    MC_CMD_GET_LICENSED_APP_STATE_OUT_LEN)];
716293901Sarybchik	uint32_t app_state;
717293901Sarybchik	efx_rc_t rc;
718293901Sarybchik
719293901Sarybchik	EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON);
720293901Sarybchik
721293901Sarybchik	/* V2 licensing supports 32bit app id only */
722293901Sarybchik	if ((app_id >> 32) != 0) {
723293901Sarybchik		rc = EINVAL;
724293901Sarybchik		goto fail1;
725293901Sarybchik	}
726293901Sarybchik
727293901Sarybchik	(void) memset(payload, 0, sizeof (payload));
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;
773293901Sarybchik	uint8_t payload[MC_CMD_LICENSING_IN_LEN];
774293901Sarybchik	efx_rc_t rc;
775293901Sarybchik
776293901Sarybchik	EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON);
777293901Sarybchik
778293901Sarybchik	(void) memset(payload, 0, sizeof (payload));
779293901Sarybchik	req.emr_cmd = MC_CMD_LICENSING;
780293901Sarybchik	req.emr_in_buf = payload;
781293901Sarybchik	req.emr_in_length = MC_CMD_LICENSING_IN_LEN;
782293901Sarybchik	req.emr_out_buf = payload;
783293901Sarybchik	req.emr_out_length = 0;
784293901Sarybchik
785293901Sarybchik	MCDI_IN_SET_DWORD(req, LICENSING_IN_OP,
786293901Sarybchik	    MC_CMD_LICENSING_IN_OP_UPDATE_LICENSE);
787293901Sarybchik
788293901Sarybchik	efx_mcdi_execute(enp, &req);
789293901Sarybchik
790293901Sarybchik	if (req.emr_rc != 0) {
791293901Sarybchik		rc = req.emr_rc;
792293901Sarybchik		goto fail1;
793293901Sarybchik	}
794293901Sarybchik
795293901Sarybchik	if (req.emr_out_length_used != 0) {
796293901Sarybchik		rc = EIO;
797293901Sarybchik		goto fail2;
798293901Sarybchik	}
799293901Sarybchik
800293901Sarybchik	return (0);
801293901Sarybchik
802293901Sarybchikfail2:
803293901Sarybchik	EFSYS_PROBE(fail2);
804293901Sarybchikfail1:
805293901Sarybchik	EFSYS_PROBE1(fail1, efx_rc_t, rc);
806293901Sarybchik
807293901Sarybchik	return (rc);
808293901Sarybchik}
809293901Sarybchik
810293901Sarybchikstatic	__checkReturn	efx_rc_t
811293901Sarybchikefx_mcdi_licensing_get_key_stats(
812293901Sarybchik	__in		efx_nic_t *enp,
813293901Sarybchik	__out		efx_key_stats_t *eksp)
814293901Sarybchik{
815293901Sarybchik	efx_mcdi_req_t req;
816293901Sarybchik	uint8_t payload[MAX(MC_CMD_LICENSING_IN_LEN,
817293901Sarybchik			    MC_CMD_LICENSING_OUT_LEN)];
818293901Sarybchik	efx_rc_t rc;
819293901Sarybchik
820293901Sarybchik	EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON);
821293901Sarybchik
822293901Sarybchik	(void) memset(payload, 0, sizeof (payload));
823293901Sarybchik	req.emr_cmd = MC_CMD_LICENSING;
824293901Sarybchik	req.emr_in_buf = payload;
825293901Sarybchik	req.emr_in_length = MC_CMD_LICENSING_IN_LEN;
826293901Sarybchik	req.emr_out_buf = payload;
827293901Sarybchik	req.emr_out_length = MC_CMD_LICENSING_OUT_LEN;
828293901Sarybchik
829293901Sarybchik	MCDI_IN_SET_DWORD(req, LICENSING_IN_OP,
830293901Sarybchik	    MC_CMD_LICENSING_IN_OP_GET_KEY_STATS);
831293901Sarybchik
832293901Sarybchik	efx_mcdi_execute(enp, &req);
833293901Sarybchik
834293901Sarybchik	if (req.emr_rc != 0) {
835293901Sarybchik		rc = req.emr_rc;
836293901Sarybchik		goto fail1;
837293901Sarybchik	}
838293901Sarybchik
839293901Sarybchik	if (req.emr_out_length_used < MC_CMD_LICENSING_OUT_LEN) {
840293901Sarybchik		rc = EMSGSIZE;
841293901Sarybchik		goto fail2;
842293901Sarybchik	}
843293901Sarybchik
844293901Sarybchik	eksp->eks_valid =
845293901Sarybchik		MCDI_OUT_DWORD(req, LICENSING_OUT_VALID_APP_KEYS);
846293901Sarybchik	eksp->eks_invalid =
847293901Sarybchik		MCDI_OUT_DWORD(req, LICENSING_OUT_INVALID_APP_KEYS);
848293901Sarybchik	eksp->eks_blacklisted =
849293901Sarybchik		MCDI_OUT_DWORD(req, LICENSING_OUT_BLACKLISTED_APP_KEYS);
850293901Sarybchik	eksp->eks_unverifiable =
851293901Sarybchik		MCDI_OUT_DWORD(req, LICENSING_OUT_UNVERIFIABLE_APP_KEYS);
852293901Sarybchik	eksp->eks_wrong_node =
853293901Sarybchik		MCDI_OUT_DWORD(req, LICENSING_OUT_WRONG_NODE_APP_KEYS);
854293901Sarybchik	eksp->eks_licensed_apps_lo = 0;
855293901Sarybchik	eksp->eks_licensed_apps_hi = 0;
856293901Sarybchik	eksp->eks_licensed_features_lo = 0;
857293901Sarybchik	eksp->eks_licensed_features_hi = 0;
858293901Sarybchik
859293901Sarybchik	return (0);
860293901Sarybchik
861293901Sarybchikfail2:
862293901Sarybchik	EFSYS_PROBE(fail2);
863293901Sarybchikfail1:
864293901Sarybchik	EFSYS_PROBE1(fail1, efx_rc_t, rc);
865293901Sarybchik
866293901Sarybchik	return (rc);
867293901Sarybchik}
868293901Sarybchik
869293901Sarybchik#endif	/* EFSYS_OPT_HUNTINGTON */
870293901Sarybchik
871293901Sarybchik/* V3 Licensing - used starting from Medford family. See SF-114884-SW */
872293901Sarybchik
873293901Sarybchik#if EFSYS_OPT_MEDFORD
874293901Sarybchik
875293901Sarybchikstatic	__checkReturn	efx_rc_t
876293901Sarybchikefx_mcdi_licensing_v3_update_licenses(
877293901Sarybchik	__in		efx_nic_t *enp)
878293901Sarybchik{
879293901Sarybchik	efx_mcdi_req_t req;
880293901Sarybchik	uint8_t payload[MC_CMD_LICENSING_V3_IN_LEN];
881293901Sarybchik	efx_rc_t rc;
882293901Sarybchik
883293901Sarybchik	EFSYS_ASSERT(enp->en_family == EFX_FAMILY_MEDFORD);
884293901Sarybchik
885293901Sarybchik	(void) memset(payload, 0, sizeof (payload));
886293901Sarybchik	req.emr_cmd = MC_CMD_LICENSING_V3;
887293901Sarybchik	req.emr_in_buf = payload;
888293901Sarybchik	req.emr_in_length = MC_CMD_LICENSING_V3_IN_LEN;
889293901Sarybchik	req.emr_out_buf = NULL;
890293901Sarybchik	req.emr_out_length = 0;
891293901Sarybchik
892293901Sarybchik	MCDI_IN_SET_DWORD(req, LICENSING_V3_IN_OP,
893293901Sarybchik	    MC_CMD_LICENSING_V3_IN_OP_UPDATE_LICENSE);
894293901Sarybchik
895293901Sarybchik	efx_mcdi_execute(enp, &req);
896293901Sarybchik
897293901Sarybchik	if (req.emr_rc != 0) {
898293901Sarybchik		rc = req.emr_rc;
899293901Sarybchik		goto fail1;
900293901Sarybchik	}
901293901Sarybchik
902293901Sarybchik	return (0);
903293901Sarybchik
904293901Sarybchikfail1:
905293901Sarybchik	EFSYS_PROBE1(fail1, efx_rc_t, rc);
906293901Sarybchik
907293901Sarybchik	return (rc);
908293901Sarybchik}
909293901Sarybchik
910293901Sarybchikstatic	__checkReturn	efx_rc_t
911293901Sarybchikefx_mcdi_licensing_v3_report_license(
912293901Sarybchik	__in		efx_nic_t *enp,
913293901Sarybchik	__out		efx_key_stats_t *eksp)
914293901Sarybchik{
915293901Sarybchik	efx_mcdi_req_t req;
916293901Sarybchik	uint8_t payload[MAX(MC_CMD_LICENSING_V3_IN_LEN,
917293901Sarybchik			    MC_CMD_LICENSING_V3_OUT_LEN)];
918293901Sarybchik	efx_rc_t rc;
919293901Sarybchik
920293901Sarybchik	EFSYS_ASSERT(enp->en_family == EFX_FAMILY_MEDFORD);
921293901Sarybchik
922293901Sarybchik	(void) memset(payload, 0, sizeof (payload));
923293901Sarybchik	req.emr_cmd = MC_CMD_LICENSING_V3;
924293901Sarybchik	req.emr_in_buf = payload;
925293901Sarybchik	req.emr_in_length = MC_CMD_LICENSING_V3_IN_LEN;
926293901Sarybchik	req.emr_out_buf = payload;
927293901Sarybchik	req.emr_out_length = MC_CMD_LICENSING_V3_OUT_LEN;
928293901Sarybchik
929293901Sarybchik	MCDI_IN_SET_DWORD(req, LICENSING_V3_IN_OP,
930293901Sarybchik	    MC_CMD_LICENSING_V3_IN_OP_REPORT_LICENSE);
931293901Sarybchik
932293901Sarybchik	efx_mcdi_execute(enp, &req);
933293901Sarybchik
934293901Sarybchik	if (req.emr_rc != 0) {
935293901Sarybchik		rc = req.emr_rc;
936293901Sarybchik		goto fail1;
937293901Sarybchik	}
938293901Sarybchik
939293901Sarybchik	if (req.emr_out_length_used < MC_CMD_LICENSING_V3_OUT_LEN) {
940293901Sarybchik		rc = EMSGSIZE;
941293901Sarybchik		goto fail2;
942293901Sarybchik	}
943293901Sarybchik
944293901Sarybchik	eksp->eks_valid =
945293901Sarybchik		MCDI_OUT_DWORD(req, LICENSING_V3_OUT_VALID_KEYS);
946293901Sarybchik	eksp->eks_invalid =
947293901Sarybchik		MCDI_OUT_DWORD(req, LICENSING_V3_OUT_INVALID_KEYS);
948293901Sarybchik	eksp->eks_blacklisted = 0;
949293901Sarybchik	eksp->eks_unverifiable =
950293901Sarybchik		MCDI_OUT_DWORD(req, LICENSING_V3_OUT_UNVERIFIABLE_KEYS);
951293901Sarybchik	eksp->eks_wrong_node =
952293901Sarybchik		MCDI_OUT_DWORD(req, LICENSING_V3_OUT_WRONG_NODE_KEYS);
953293901Sarybchik	eksp->eks_licensed_apps_lo =
954293901Sarybchik		MCDI_OUT_DWORD(req, LICENSING_V3_OUT_LICENSED_APPS_LO);
955293901Sarybchik	eksp->eks_licensed_apps_hi =
956293901Sarybchik		MCDI_OUT_DWORD(req, LICENSING_V3_OUT_LICENSED_APPS_HI);
957293901Sarybchik	eksp->eks_licensed_features_lo =
958293901Sarybchik		MCDI_OUT_DWORD(req, LICENSING_V3_OUT_LICENSED_FEATURES_LO);
959293901Sarybchik	eksp->eks_licensed_features_hi =
960293901Sarybchik		MCDI_OUT_DWORD(req, LICENSING_V3_OUT_LICENSED_FEATURES_HI);
961293901Sarybchik
962293901Sarybchik	return (0);
963293901Sarybchik
964293901Sarybchikfail2:
965293901Sarybchik	EFSYS_PROBE(fail2);
966293901Sarybchikfail1:
967293901Sarybchik	EFSYS_PROBE1(fail1, efx_rc_t, rc);
968293901Sarybchik
969293901Sarybchik	return (rc);
970293901Sarybchik}
971293901Sarybchik
972293901Sarybchikstatic	__checkReturn	efx_rc_t
973293901Sarybchikefx_mcdi_licensing_v3_app_state(
974293901Sarybchik	__in		efx_nic_t *enp,
975293901Sarybchik	__in		uint64_t app_id,
976293901Sarybchik	__out		boolean_t *licensedp)
977293901Sarybchik{
978293901Sarybchik	efx_mcdi_req_t req;
979293901Sarybchik	uint8_t payload[MAX(MC_CMD_GET_LICENSED_V3_APP_STATE_IN_LEN,
980293901Sarybchik			    MC_CMD_GET_LICENSED_V3_APP_STATE_OUT_LEN)];
981293901Sarybchik	uint32_t app_state;
982293901Sarybchik	efx_rc_t rc;
983293901Sarybchik
984293901Sarybchik	EFSYS_ASSERT(enp->en_family == EFX_FAMILY_MEDFORD);
985293901Sarybchik
986293901Sarybchik	(void) memset(payload, 0, sizeof (payload));
987293901Sarybchik	req.emr_cmd = MC_CMD_GET_LICENSED_V3_APP_STATE;
988293901Sarybchik	req.emr_in_buf = payload;
989293901Sarybchik	req.emr_in_length = MC_CMD_GET_LICENSED_V3_APP_STATE_IN_LEN;
990293901Sarybchik	req.emr_out_buf = payload;
991293901Sarybchik	req.emr_out_length = MC_CMD_GET_LICENSED_V3_APP_STATE_OUT_LEN;
992293901Sarybchik
993293901Sarybchik	MCDI_IN_SET_DWORD(req, GET_LICENSED_V3_APP_STATE_IN_APP_ID_LO,
994293901Sarybchik		    app_id & 0xffffffff);
995293901Sarybchik	MCDI_IN_SET_DWORD(req, GET_LICENSED_V3_APP_STATE_IN_APP_ID_HI,
996293901Sarybchik		    app_id >> 32);
997293901Sarybchik
998293901Sarybchik	efx_mcdi_execute(enp, &req);
999293901Sarybchik
1000293901Sarybchik	if (req.emr_rc != 0) {
1001293901Sarybchik		rc = req.emr_rc;
1002293901Sarybchik		goto fail1;
1003293901Sarybchik	}
1004293901Sarybchik
1005293901Sarybchik	if (req.emr_out_length_used < MC_CMD_GET_LICENSED_V3_APP_STATE_OUT_LEN) {
1006293901Sarybchik		rc = EMSGSIZE;
1007293901Sarybchik		goto fail2;
1008293901Sarybchik	}
1009293901Sarybchik
1010293901Sarybchik	app_state = (MCDI_OUT_DWORD(req, GET_LICENSED_V3_APP_STATE_OUT_STATE));
1011293901Sarybchik	if (app_state != MC_CMD_GET_LICENSED_V3_APP_STATE_OUT_NOT_LICENSED) {
1012293901Sarybchik		*licensedp = B_TRUE;
1013293901Sarybchik	} else {
1014293901Sarybchik		*licensedp = B_FALSE;
1015293901Sarybchik	}
1016293901Sarybchik
1017293901Sarybchik	return (0);
1018293901Sarybchik
1019293901Sarybchikfail2:
1020293901Sarybchik	EFSYS_PROBE(fail2);
1021293901Sarybchikfail1:
1022293901Sarybchik	EFSYS_PROBE1(fail1, efx_rc_t, rc);
1023293901Sarybchik
1024293901Sarybchik	return (rc);
1025293901Sarybchik}
1026293901Sarybchik
1027293901Sarybchikstatic	__checkReturn	efx_rc_t
1028293901Sarybchikefx_mcdi_licensing_v3_get_id(
1029293901Sarybchik	__in		efx_nic_t *enp,
1030293901Sarybchik	__in		size_t buffer_size,
1031293901Sarybchik	__out		uint32_t *typep,
1032293901Sarybchik	__out		size_t *lengthp,
1033293901Sarybchik	__out_bcount_part_opt(buffer_size, *lengthp)
1034293901Sarybchik			uint8_t *bufferp)
1035293901Sarybchik{
1036293901Sarybchik	efx_mcdi_req_t req;
1037293901Sarybchik	uint8_t payload[MAX(MC_CMD_LICENSING_GET_ID_V3_IN_LEN,
1038293901Sarybchik			    MC_CMD_LICENSING_GET_ID_V3_OUT_LENMIN)];
1039293901Sarybchik	efx_rc_t rc;
1040293901Sarybchik
1041293901Sarybchik	req.emr_cmd = MC_CMD_LICENSING_GET_ID_V3;
1042293901Sarybchik
1043293901Sarybchik	if (bufferp == NULL) {
1044293901Sarybchik		/* Request id type and length only */
1045293901Sarybchik		req.emr_in_buf = bufferp;
1046293901Sarybchik		req.emr_in_length = MC_CMD_LICENSING_GET_ID_V3_IN_LEN;
1047293901Sarybchik		req.emr_out_buf = bufferp;
1048293901Sarybchik		req.emr_out_length = MC_CMD_LICENSING_GET_ID_V3_OUT_LENMIN;
1049293901Sarybchik		(void) memset(payload, 0, sizeof (payload));
1050293901Sarybchik	} else {
1051293901Sarybchik		/* Request full buffer */
1052293901Sarybchik		req.emr_in_buf = bufferp;
1053293901Sarybchik		req.emr_in_length = MC_CMD_LICENSING_GET_ID_V3_IN_LEN;
1054293901Sarybchik		req.emr_out_buf = bufferp;
1055299898Sarybchik		req.emr_out_length = MIN(buffer_size, MC_CMD_LICENSING_GET_ID_V3_OUT_LENMAX);
1056293901Sarybchik		(void) memset(bufferp, 0, req.emr_out_length);
1057293901Sarybchik	}
1058293901Sarybchik
1059293901Sarybchik	efx_mcdi_execute(enp, &req);
1060293901Sarybchik
1061293901Sarybchik	if (req.emr_rc != 0) {
1062293901Sarybchik		rc = req.emr_rc;
1063293901Sarybchik		goto fail1;
1064293901Sarybchik	}
1065293901Sarybchik
1066293901Sarybchik	if (req.emr_out_length_used < MC_CMD_LICENSING_GET_ID_V3_OUT_LENMIN) {
1067293901Sarybchik		rc = EMSGSIZE;
1068293901Sarybchik		goto fail2;
1069293901Sarybchik	}
1070293901Sarybchik
1071293901Sarybchik	*typep = MCDI_OUT_DWORD(req, LICENSING_GET_ID_V3_OUT_LICENSE_TYPE);
1072293901Sarybchik	*lengthp = MCDI_OUT_DWORD(req, LICENSING_GET_ID_V3_OUT_LICENSE_ID_LENGTH);
1073293901Sarybchik
1074293901Sarybchik	if (bufferp == NULL) {
1075293901Sarybchik		/* modify length requirements to indicate to caller the extra buffering
1076293901Sarybchik		** needed to read the complete output.
1077293901Sarybchik		*/
1078293901Sarybchik		*lengthp += MC_CMD_LICENSING_GET_ID_V3_OUT_LENMIN;
1079293901Sarybchik	} else {
1080293901Sarybchik		/* Shift ID down to start of buffer */
1081293901Sarybchik		memmove(bufferp,
1082293901Sarybchik		  bufferp+MC_CMD_LICENSING_GET_ID_V3_OUT_LICENSE_ID_OFST,
1083293901Sarybchik		  *lengthp);
1084293901Sarybchik		memset(bufferp+(*lengthp), 0, MC_CMD_LICENSING_GET_ID_V3_OUT_LICENSE_ID_OFST);
1085293901Sarybchik	}
1086293901Sarybchik
1087293901Sarybchik	return (0);
1088293901Sarybchik
1089293901Sarybchikfail2:
1090293901Sarybchik	EFSYS_PROBE(fail2);
1091293901Sarybchikfail1:
1092293901Sarybchik	EFSYS_PROBE1(fail1, efx_rc_t, rc);
1093293901Sarybchik
1094293901Sarybchik	return (rc);
1095293901Sarybchik}
1096293901Sarybchik
1097299898Sarybchik/* V3 format uses Huntington TLV format partition. See SF-108797-SW */
1098299898Sarybchik#define EFX_LICENSE_V3_KEY_LENGTH_MIN    (64)
1099299898Sarybchik#define EFX_LICENSE_V3_KEY_LENGTH_MAX    (128)
1100299898Sarybchik#define EFX_LICENSE_V3_HASH_LENGTH       (64)
1101293901Sarybchik
1102299898Sarybchik	__checkReturn		efx_rc_t
1103299898Sarybchikefx_lic_v3_find_start(
1104299898Sarybchik	__in			efx_nic_t *enp,
1105299898Sarybchik	__in_bcount(buffer_size)
1106299898Sarybchik				caddr_t bufferp,
1107299898Sarybchik	__in			size_t buffer_size,
1108299898Sarybchik	__out			uint32_t *startp
1109299898Sarybchik	)
1110299898Sarybchik{
1111299898Sarybchik	_NOTE(ARGUNUSED(enp))
1112299898Sarybchik
1113299898Sarybchik	return ef10_nvram_buffer_find_item_start(bufferp, buffer_size, startp);
1114299898Sarybchik}
1115299898Sarybchik
1116299898Sarybchik	__checkReturn		efx_rc_t
1117299898Sarybchikefx_lic_v3_find_end(
1118299898Sarybchik	__in			efx_nic_t *enp,
1119299898Sarybchik	__in_bcount(buffer_size)
1120299898Sarybchik				caddr_t bufferp,
1121299898Sarybchik	__in			size_t buffer_size,
1122299898Sarybchik	__in			uint32_t offset,
1123299898Sarybchik	__out			uint32_t *endp
1124299898Sarybchik	)
1125299898Sarybchik{
1126299898Sarybchik	_NOTE(ARGUNUSED(enp))
1127299898Sarybchik
1128299898Sarybchik	return ef10_nvram_buffer_find_end(bufferp, buffer_size, offset, endp);
1129299898Sarybchik}
1130299898Sarybchik
1131299898Sarybchik	__checkReturn	__success(return != B_FALSE)	boolean_t
1132299898Sarybchikefx_lic_v3_find_key(
1133299898Sarybchik	__in			efx_nic_t *enp,
1134299898Sarybchik	__in_bcount(buffer_size)
1135299898Sarybchik				caddr_t bufferp,
1136299898Sarybchik	__in			size_t buffer_size,
1137299898Sarybchik	__in			uint32_t offset,
1138299898Sarybchik	__out			uint32_t *startp,
1139299898Sarybchik	__out			uint32_t *lengthp
1140299898Sarybchik	)
1141299898Sarybchik{
1142299898Sarybchik	_NOTE(ARGUNUSED(enp))
1143299898Sarybchik
1144299898Sarybchik	return ef10_nvram_buffer_find_item(bufferp, buffer_size,
1145299898Sarybchik	    offset, startp, lengthp);
1146299898Sarybchik}
1147299898Sarybchik
1148299898Sarybchik	__checkReturn	__success(return != B_FALSE)	boolean_t
1149299898Sarybchikefx_lic_v3_validate_key(
1150299898Sarybchik	__in			efx_nic_t *enp,
1151299898Sarybchik	__in_bcount(length)	caddr_t keyp,
1152299898Sarybchik	__in			uint32_t length
1153299898Sarybchik	)
1154299898Sarybchik{
1155299898Sarybchik	// Check key is a valid V3 key
1156299898Sarybchik	efx_rc_t rc;
1157299898Sarybchik	uint8_t key_type;
1158299898Sarybchik	uint8_t key_length;
1159299898Sarybchik
1160299898Sarybchik	_NOTE(ARGUNUSED(enp))
1161299898Sarybchik
1162299898Sarybchik	if (length < EFX_LICENSE_V3_KEY_LENGTH_MIN) {
1163299898Sarybchik		goto fail1;
1164299898Sarybchik	}
1165299898Sarybchik
1166299898Sarybchik	key_type = ((uint8_t*)keyp)[0];
1167299898Sarybchik	key_length = ((uint8_t*)keyp)[1] + EFX_LICENSE_V3_HASH_LENGTH;
1168299898Sarybchik
1169299898Sarybchik	if(key_length > EFX_LICENSE_V3_KEY_LENGTH_MAX) {
1170299898Sarybchik		goto fail2;
1171299898Sarybchik	}
1172299898Sarybchik	if (key_type < 3) {
1173299898Sarybchik		goto fail3;
1174299898Sarybchik	}
1175299898Sarybchik	if (key_length != length) {
1176299898Sarybchik		goto fail4;
1177299898Sarybchik	}
1178299898Sarybchik	return (B_TRUE);
1179299898Sarybchik
1180299898Sarybchikfail4:
1181299898Sarybchik	EFSYS_PROBE(fail4);
1182299898Sarybchikfail3:
1183299898Sarybchik	EFSYS_PROBE(fail3);
1184299898Sarybchikfail2:
1185299898Sarybchik	EFSYS_PROBE(fail2);
1186299898Sarybchikfail1:
1187299898Sarybchik	EFSYS_PROBE(fail1);
1188299898Sarybchik
1189299898Sarybchik	return (B_FALSE);
1190299898Sarybchik}
1191299898Sarybchik
1192299898Sarybchik	__checkReturn		efx_rc_t
1193299898Sarybchikefx_lic_v3_read_key(
1194299898Sarybchik	__in			efx_nic_t *enp,
1195299898Sarybchik	__in_bcount(buffer_size)
1196299898Sarybchik				caddr_t bufferp,
1197299898Sarybchik	__in			size_t buffer_size,
1198299898Sarybchik	__in			uint32_t offset,
1199299898Sarybchik	__in			uint32_t length,
1200299898Sarybchik	__out_bcount_part(key_max_size, *lengthp)
1201299898Sarybchik				caddr_t keyp,
1202299898Sarybchik	__in			size_t key_max_size,
1203299898Sarybchik	__out			uint32_t *lengthp
1204299898Sarybchik	)
1205299898Sarybchik{
1206299898Sarybchik	_NOTE(ARGUNUSED(enp))
1207299898Sarybchik
1208299898Sarybchik	return ef10_nvram_buffer_get_item(bufferp, buffer_size,
1209299898Sarybchik		    offset, length, keyp, key_max_size, lengthp);
1210299898Sarybchik}
1211299898Sarybchik
1212299898Sarybchik	__checkReturn		efx_rc_t
1213299898Sarybchikefx_lic_v3_write_key(
1214299898Sarybchik	__in			efx_nic_t *enp,
1215299898Sarybchik	__in_bcount(buffer_size)
1216299898Sarybchik				caddr_t bufferp,
1217299898Sarybchik	__in			size_t buffer_size,
1218299898Sarybchik	__in			uint32_t offset,
1219299898Sarybchik	__in_bcount(length)	caddr_t keyp,
1220299898Sarybchik	__in			uint32_t length,
1221299898Sarybchik	__out			uint32_t *lengthp
1222299898Sarybchik	)
1223299898Sarybchik{
1224299898Sarybchik	_NOTE(ARGUNUSED(enp))
1225299898Sarybchik	EFSYS_ASSERT(length <= EFX_LICENSE_V3_KEY_LENGTH_MAX);
1226299898Sarybchik
1227299898Sarybchik	return ef10_nvram_buffer_insert_item(bufferp, buffer_size,
1228299898Sarybchik		    offset, keyp, length, lengthp);
1229299898Sarybchik}
1230299898Sarybchik
1231299898Sarybchik	__checkReturn		efx_rc_t
1232299898Sarybchikefx_lic_v3_delete_key(
1233299898Sarybchik	__in			efx_nic_t *enp,
1234299898Sarybchik	__in_bcount(buffer_size)
1235299898Sarybchik				caddr_t bufferp,
1236299898Sarybchik	__in			size_t buffer_size,
1237299898Sarybchik	__in			uint32_t offset,
1238299898Sarybchik	__in			uint32_t length,
1239299898Sarybchik	__in			uint32_t end,
1240299898Sarybchik	__out			uint32_t *deltap
1241299898Sarybchik	)
1242299898Sarybchik{
1243299898Sarybchik	efx_rc_t rc;
1244299898Sarybchik
1245299898Sarybchik	_NOTE(ARGUNUSED(enp))
1246299898Sarybchik
1247299898Sarybchik	if ((rc = ef10_nvram_buffer_delete_item(bufferp,
1248299898Sarybchik			buffer_size, offset, length, end)) != 0) {
1249299898Sarybchik		goto fail1;
1250299898Sarybchik	}
1251299898Sarybchik
1252299898Sarybchik	*deltap = length;
1253299898Sarybchik
1254299898Sarybchik	return (0);
1255299898Sarybchik
1256299898Sarybchikfail1:
1257299898Sarybchik	EFSYS_PROBE1(fail1, efx_rc_t, rc);
1258299898Sarybchik
1259299898Sarybchik	return (rc);
1260299898Sarybchik}
1261299898Sarybchik
1262299898Sarybchik	__checkReturn		efx_rc_t
1263299898Sarybchikefx_lic_v3_create_partition(
1264299898Sarybchik	__in			efx_nic_t *enp,
1265299898Sarybchik	__in_bcount(buffer_size)
1266299898Sarybchik				caddr_t bufferp,
1267299898Sarybchik	__in			size_t buffer_size
1268299898Sarybchik	)
1269299898Sarybchik{
1270299898Sarybchik	efx_rc_t rc;
1271299898Sarybchik
1272299898Sarybchik	// Construct empty partition
1273299898Sarybchik	if ((rc = ef10_nvram_buffer_create(enp,
1274299898Sarybchik	    NVRAM_PARTITION_TYPE_LICENSE,
1275299898Sarybchik	    bufferp, buffer_size)) != 0) {
1276299898Sarybchik		rc = EFAULT;
1277299898Sarybchik		goto fail1;
1278299898Sarybchik	}
1279299898Sarybchik
1280299898Sarybchik	return (0);
1281299898Sarybchik
1282299898Sarybchikfail1:
1283299898Sarybchik	EFSYS_PROBE1(fail1, efx_rc_t, rc);
1284299898Sarybchik
1285299898Sarybchik	return (rc);
1286299898Sarybchik}
1287299898Sarybchik
1288299898Sarybchik	__checkReturn		efx_rc_t
1289299898Sarybchikefx_lic_v3_finish_partition(
1290299898Sarybchik	__in			efx_nic_t *enp,
1291299898Sarybchik	__in_bcount(buffer_size)
1292299898Sarybchik				caddr_t bufferp,
1293299898Sarybchik	__in			size_t buffer_size
1294299898Sarybchik	)
1295299898Sarybchik{
1296299898Sarybchik	efx_rc_t rc;
1297299898Sarybchik
1298299898Sarybchik	if ((rc = ef10_nvram_buffer_finish(bufferp,
1299299898Sarybchik			buffer_size)) != 0) {
1300299898Sarybchik		goto fail1;
1301299898Sarybchik	}
1302299898Sarybchik
1303299898Sarybchik	// Validate completed partition
1304299898Sarybchik	if ((rc = ef10_nvram_buffer_validate(enp, NVRAM_PARTITION_TYPE_LICENSE,
1305299898Sarybchik					bufferp, buffer_size)) != 0) {
1306299898Sarybchik		goto fail2;
1307299898Sarybchik	}
1308299898Sarybchik
1309299898Sarybchik	return (0);
1310299898Sarybchik
1311299898Sarybchikfail2:
1312299898Sarybchik	EFSYS_PROBE(fail2);
1313299898Sarybchikfail1:
1314299898Sarybchik	EFSYS_PROBE1(fail1, efx_rc_t, rc);
1315299898Sarybchik
1316299898Sarybchik	return (rc);
1317299898Sarybchik}
1318299898Sarybchik
1319299898Sarybchik
1320293901Sarybchik#endif	/* EFSYS_OPT_MEDFORD */
1321293901Sarybchik
1322293901Sarybchik	__checkReturn		efx_rc_t
1323293901Sarybchikefx_lic_init(
1324293901Sarybchik	__in			efx_nic_t *enp)
1325293901Sarybchik{
1326299517Sarybchik	const efx_lic_ops_t *elop;
1327293901Sarybchik	efx_rc_t rc;
1328293901Sarybchik
1329293901Sarybchik	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1330293901Sarybchik	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
1331293901Sarybchik	EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_LIC));
1332293901Sarybchik
1333293901Sarybchik	switch (enp->en_family) {
1334293901Sarybchik
1335293901Sarybchik#if EFSYS_OPT_SIENA
1336293901Sarybchik	case EFX_FAMILY_SIENA:
1337299517Sarybchik		elop = &__efx_lic_v1_ops;
1338293901Sarybchik		break;
1339293901Sarybchik#endif	/* EFSYS_OPT_SIENA */
1340293901Sarybchik
1341293901Sarybchik#if EFSYS_OPT_HUNTINGTON
1342293901Sarybchik	case EFX_FAMILY_HUNTINGTON:
1343299517Sarybchik		elop = &__efx_lic_v2_ops;
1344293901Sarybchik		break;
1345293901Sarybchik#endif	/* EFSYS_OPT_HUNTINGTON */
1346293901Sarybchik
1347293901Sarybchik#if EFSYS_OPT_MEDFORD
1348293901Sarybchik	case EFX_FAMILY_MEDFORD:
1349299517Sarybchik		elop = &__efx_lic_v3_ops;
1350293901Sarybchik		break;
1351293901Sarybchik#endif	/* EFSYS_OPT_MEDFORD */
1352293901Sarybchik
1353293901Sarybchik	default:
1354293901Sarybchik		EFSYS_ASSERT(0);
1355293901Sarybchik		rc = ENOTSUP;
1356293901Sarybchik		goto fail1;
1357293901Sarybchik	}
1358293901Sarybchik
1359293901Sarybchik	enp->en_elop = elop;
1360293901Sarybchik	enp->en_mod_flags |= EFX_MOD_LIC;
1361293901Sarybchik
1362293901Sarybchik	return (0);
1363293901Sarybchik
1364293901Sarybchikfail1:
1365293901Sarybchik	EFSYS_PROBE1(fail1, efx_rc_t, rc);
1366293901Sarybchik
1367293901Sarybchik	return (rc);
1368293901Sarybchik}
1369293901Sarybchik
1370293901Sarybchik				void
1371293901Sarybchikefx_lic_fini(
1372293901Sarybchik	__in			efx_nic_t *enp)
1373293901Sarybchik{
1374299517Sarybchik	const efx_lic_ops_t *elop = enp->en_elop;
1375293901Sarybchik
1376293901Sarybchik	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1377293901Sarybchik	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
1378293901Sarybchik	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1379293901Sarybchik
1380293901Sarybchik	enp->en_elop = NULL;
1381293901Sarybchik	enp->en_mod_flags &= ~EFX_MOD_LIC;
1382293901Sarybchik}
1383293901Sarybchik
1384293901Sarybchik
1385293901Sarybchik	__checkReturn	efx_rc_t
1386293901Sarybchikefx_lic_update_licenses(
1387293901Sarybchik	__in		efx_nic_t *enp)
1388293901Sarybchik{
1389299517Sarybchik	const efx_lic_ops_t *elop = enp->en_elop;
1390293901Sarybchik	efx_rc_t rc;
1391293901Sarybchik
1392293901Sarybchik	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1393293901Sarybchik	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1394293901Sarybchik
1395293901Sarybchik	if ((rc = elop->elo_update_licenses(enp)) != 0)
1396293901Sarybchik		goto fail1;
1397293901Sarybchik
1398293901Sarybchik	return (0);
1399293901Sarybchik
1400293901Sarybchikfail1:
1401293901Sarybchik	EFSYS_PROBE1(fail1, efx_rc_t, rc);
1402293901Sarybchik
1403293901Sarybchik	return (rc);
1404293901Sarybchik}
1405293901Sarybchik
1406293901Sarybchik	__checkReturn	efx_rc_t
1407293901Sarybchikefx_lic_get_key_stats(
1408293901Sarybchik	__in		efx_nic_t *enp,
1409293901Sarybchik	__out		efx_key_stats_t *eksp)
1410293901Sarybchik{
1411299517Sarybchik	const efx_lic_ops_t *elop = enp->en_elop;
1412293901Sarybchik	efx_rc_t rc;
1413293901Sarybchik
1414293901Sarybchik	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1415293901Sarybchik	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1416293901Sarybchik
1417293901Sarybchik	if ((rc = elop->elo_get_key_stats(enp, eksp)) != 0)
1418293901Sarybchik		goto fail1;
1419293901Sarybchik
1420293901Sarybchik	return (0);
1421293901Sarybchik
1422293901Sarybchikfail1:
1423293901Sarybchik	EFSYS_PROBE1(fail1, efx_rc_t, rc);
1424293901Sarybchik
1425293901Sarybchik	return (rc);
1426293901Sarybchik}
1427293901Sarybchik
1428293901Sarybchik	__checkReturn	efx_rc_t
1429293901Sarybchikefx_lic_app_state(
1430293901Sarybchik	__in		efx_nic_t *enp,
1431293901Sarybchik	__in		uint64_t app_id,
1432293901Sarybchik	__out		boolean_t *licensedp)
1433293901Sarybchik{
1434299517Sarybchik	const efx_lic_ops_t *elop = enp->en_elop;
1435293901Sarybchik	efx_rc_t rc;
1436293901Sarybchik
1437293901Sarybchik	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1438293901Sarybchik	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1439293901Sarybchik
1440293901Sarybchik	if (elop->elo_app_state == NULL) {
1441293901Sarybchik		rc = ENOTSUP;
1442293901Sarybchik		goto fail1;
1443293901Sarybchik	}
1444293901Sarybchik	if ((rc = elop->elo_app_state(enp, app_id, licensedp)) != 0)
1445293901Sarybchik		goto fail2;
1446293901Sarybchik
1447293901Sarybchik	return (0);
1448293901Sarybchik
1449293901Sarybchikfail2:
1450293901Sarybchik	EFSYS_PROBE(fail2);
1451293901Sarybchikfail1:
1452293901Sarybchik	EFSYS_PROBE1(fail1, efx_rc_t, rc);
1453293901Sarybchik
1454293901Sarybchik	return (rc);
1455293901Sarybchik}
1456293901Sarybchik
1457293901Sarybchik	__checkReturn	efx_rc_t
1458293901Sarybchikefx_lic_get_id(
1459293901Sarybchik	__in		efx_nic_t *enp,
1460293901Sarybchik	__in		size_t buffer_size,
1461293901Sarybchik	__out		uint32_t *typep,
1462293901Sarybchik	__out		size_t *lengthp,
1463293901Sarybchik	__out_opt	uint8_t *bufferp
1464293901Sarybchik	)
1465293901Sarybchik{
1466299517Sarybchik	const efx_lic_ops_t *elop = enp->en_elop;
1467293901Sarybchik	efx_rc_t rc;
1468293901Sarybchik
1469293901Sarybchik	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1470293901Sarybchik	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1471293901Sarybchik
1472293901Sarybchik	if (elop->elo_get_id == NULL) {
1473293901Sarybchik		rc = ENOTSUP;
1474293901Sarybchik		goto fail1;
1475293901Sarybchik	}
1476293901Sarybchik
1477293901Sarybchik	if ((rc = elop->elo_get_id(enp, buffer_size, typep,
1478293901Sarybchik				    lengthp, bufferp)) != 0)
1479293901Sarybchik		goto fail2;
1480293901Sarybchik
1481293901Sarybchik	return (0);
1482293901Sarybchik
1483293901Sarybchikfail2:
1484293901Sarybchik	EFSYS_PROBE(fail2);
1485293901Sarybchikfail1:
1486293901Sarybchik	EFSYS_PROBE1(fail1, efx_rc_t, rc);
1487293901Sarybchik
1488293901Sarybchik	return (rc);
1489293901Sarybchik}
1490293901Sarybchik
1491299898Sarybchik/* Buffer management API - abstracts varying TLV format used for License partition */
1492299898Sarybchik
1493299898Sarybchik	__checkReturn		efx_rc_t
1494299898Sarybchikefx_lic_find_start(
1495299898Sarybchik	__in			efx_nic_t *enp,
1496299898Sarybchik	__in_bcount(buffer_size)
1497299898Sarybchik				caddr_t bufferp,
1498299898Sarybchik	__in			size_t buffer_size,
1499299898Sarybchik	__out			uint32_t *startp
1500299898Sarybchik	)
1501299898Sarybchik{
1502299898Sarybchik	const efx_lic_ops_t *elop = enp->en_elop;
1503299898Sarybchik	efx_rc_t rc;
1504299898Sarybchik
1505299898Sarybchik	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1506299898Sarybchik	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1507299898Sarybchik
1508299898Sarybchik	if ((rc = elop->elo_find_start(enp, bufferp, buffer_size, startp)) != 0)
1509299898Sarybchik		goto fail1;
1510299898Sarybchik
1511299898Sarybchik	return (0);
1512299898Sarybchik
1513299898Sarybchikfail1:
1514299898Sarybchik	EFSYS_PROBE1(fail1, efx_rc_t, rc);
1515299898Sarybchik
1516299898Sarybchik	return (rc);
1517299898Sarybchik}
1518299898Sarybchik
1519299898Sarybchik	__checkReturn		efx_rc_t
1520299898Sarybchikefx_lic_find_end(
1521299898Sarybchik	__in			efx_nic_t *enp,
1522299898Sarybchik	__in_bcount(buffer_size)
1523299898Sarybchik				caddr_t bufferp,
1524299898Sarybchik	__in			size_t buffer_size,
1525299898Sarybchik	__in			uint32_t offset,
1526299898Sarybchik	__out			uint32_t *endp
1527299898Sarybchik	)
1528299898Sarybchik{
1529299898Sarybchik	const efx_lic_ops_t *elop = enp->en_elop;
1530299898Sarybchik	efx_rc_t rc;
1531299898Sarybchik
1532299898Sarybchik	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1533299898Sarybchik	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1534299898Sarybchik
1535299898Sarybchik	if ((rc = elop->elo_find_end(enp, bufferp, buffer_size, offset, endp)) != 0)
1536299898Sarybchik		goto fail1;
1537299898Sarybchik
1538299898Sarybchik	return (0);
1539299898Sarybchik
1540299898Sarybchikfail1:
1541299898Sarybchik	EFSYS_PROBE1(fail1, efx_rc_t, rc);
1542299898Sarybchik
1543299898Sarybchik	return (rc);
1544299898Sarybchik}
1545299898Sarybchik
1546299898Sarybchik	__checkReturn	__success(return != B_FALSE)	boolean_t
1547299898Sarybchikefx_lic_find_key(
1548299898Sarybchik	__in			efx_nic_t *enp,
1549299898Sarybchik	__in_bcount(buffer_size)
1550299898Sarybchik				caddr_t bufferp,
1551299898Sarybchik	__in			size_t buffer_size,
1552299898Sarybchik	__in			uint32_t offset,
1553299898Sarybchik	__out			uint32_t *startp,
1554299898Sarybchik	__out			uint32_t *lengthp
1555299898Sarybchik	)
1556299898Sarybchik{
1557299898Sarybchik	const efx_lic_ops_t *elop = enp->en_elop;
1558299898Sarybchik	boolean_t rc;
1559299898Sarybchik
1560299898Sarybchik	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1561299898Sarybchik	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1562299898Sarybchik
1563299898Sarybchik	EFSYS_ASSERT(bufferp);
1564299898Sarybchik	EFSYS_ASSERT(startp);
1565299898Sarybchik	EFSYS_ASSERT(lengthp);
1566299898Sarybchik
1567299898Sarybchik	return (elop->elo_find_key(enp, bufferp, buffer_size, offset,
1568299898Sarybchik				    startp, lengthp));
1569299898Sarybchik}
1570299898Sarybchik
1571299898Sarybchik
1572299898Sarybchik/* Validate that the buffer contains a single key in a recognised format.
1573299898Sarybchik** An empty or terminator buffer is not accepted as a valid key.
1574299898Sarybchik*/
1575299898Sarybchik	__checkReturn	__success(return != B_FALSE)	boolean_t
1576299898Sarybchikefx_lic_validate_key(
1577299898Sarybchik	__in			efx_nic_t *enp,
1578299898Sarybchik	__in_bcount(length)	caddr_t keyp,
1579299898Sarybchik	__in			uint32_t length
1580299898Sarybchik	)
1581299898Sarybchik{
1582299898Sarybchik	const efx_lic_ops_t *elop = enp->en_elop;
1583299898Sarybchik	boolean_t rc;
1584299898Sarybchik	uint16_t tlv_type;
1585299898Sarybchik	uint16_t tlv_length;
1586299898Sarybchik
1587299898Sarybchik	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1588299898Sarybchik	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1589299898Sarybchik
1590299898Sarybchik	if ((rc = elop->elo_validate_key(enp, keyp, length)) == B_FALSE)
1591299898Sarybchik		goto fail1;
1592299898Sarybchik
1593299898Sarybchik	return (B_TRUE);
1594299898Sarybchik
1595299898Sarybchikfail1:
1596299898Sarybchik	EFSYS_PROBE1(fail1, efx_rc_t, rc);
1597299898Sarybchik
1598299898Sarybchik	return (rc);
1599299898Sarybchik}
1600299898Sarybchik
1601299898Sarybchik	__checkReturn		efx_rc_t
1602299898Sarybchikefx_lic_read_key(
1603299898Sarybchik	__in			efx_nic_t *enp,
1604299898Sarybchik	__in_bcount(buffer_size)
1605299898Sarybchik				caddr_t bufferp,
1606299898Sarybchik	__in			size_t buffer_size,
1607299898Sarybchik	__in			uint32_t offset,
1608299898Sarybchik	__in			uint32_t length,
1609299898Sarybchik	__out_bcount_part(key_max_size, *lengthp)
1610299898Sarybchik				caddr_t keyp,
1611299898Sarybchik	__in			size_t key_max_size,
1612299898Sarybchik	__out			uint32_t *lengthp
1613299898Sarybchik	)
1614299898Sarybchik{
1615299898Sarybchik	const efx_lic_ops_t *elop = enp->en_elop;
1616299898Sarybchik	efx_rc_t rc;
1617299898Sarybchik
1618299898Sarybchik	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1619299898Sarybchik	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1620299898Sarybchik
1621299898Sarybchik	if ((rc = elop->elo_read_key(enp, bufferp, buffer_size, offset,
1622299898Sarybchik				    length, keyp, key_max_size, lengthp)) != 0)
1623299898Sarybchik		goto fail1;
1624299898Sarybchik
1625299898Sarybchik	return (0);
1626299898Sarybchik
1627299898Sarybchikfail1:
1628299898Sarybchik	EFSYS_PROBE1(fail1, efx_rc_t, rc);
1629299898Sarybchik
1630299898Sarybchik	return (rc);
1631299898Sarybchik}
1632299898Sarybchik
1633299898Sarybchik	__checkReturn		efx_rc_t
1634299898Sarybchikefx_lic_write_key(
1635299898Sarybchik	__in			efx_nic_t *enp,
1636299898Sarybchik	__in_bcount(buffer_size)
1637299898Sarybchik				caddr_t bufferp,
1638299898Sarybchik	__in			size_t buffer_size,
1639299898Sarybchik	__in			uint32_t offset,
1640299898Sarybchik	__in_bcount(length)	caddr_t keyp,
1641299898Sarybchik	__in			uint32_t length,
1642299898Sarybchik	__out			uint32_t *lengthp
1643299898Sarybchik	)
1644299898Sarybchik{
1645299898Sarybchik	const efx_lic_ops_t *elop = enp->en_elop;
1646299898Sarybchik	efx_rc_t rc;
1647299898Sarybchik
1648299898Sarybchik	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1649299898Sarybchik	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1650299898Sarybchik
1651299898Sarybchik	if ((rc = elop->elo_write_key(enp, bufferp, buffer_size, offset,
1652299898Sarybchik				    keyp, length, lengthp)) != 0)
1653299898Sarybchik		goto fail1;
1654299898Sarybchik
1655299898Sarybchik	return (0);
1656299898Sarybchik
1657299898Sarybchikfail1:
1658299898Sarybchik	EFSYS_PROBE1(fail1, efx_rc_t, rc);
1659299898Sarybchik
1660299898Sarybchik	return (rc);
1661299898Sarybchik}
1662299898Sarybchik
1663299898Sarybchik	__checkReturn		efx_rc_t
1664299898Sarybchikefx_lic_delete_key(
1665299898Sarybchik	__in			efx_nic_t *enp,
1666299898Sarybchik	__in_bcount(buffer_size)
1667299898Sarybchik				caddr_t bufferp,
1668299898Sarybchik	__in			size_t buffer_size,
1669299898Sarybchik	__in			uint32_t offset,
1670299898Sarybchik	__in			uint32_t length,
1671299898Sarybchik	__in			uint32_t end,
1672299898Sarybchik	__out			uint32_t *deltap
1673299898Sarybchik	)
1674299898Sarybchik{
1675299898Sarybchik	const efx_lic_ops_t *elop = enp->en_elop;
1676299898Sarybchik	efx_rc_t rc;
1677299898Sarybchik
1678299898Sarybchik	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1679299898Sarybchik	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1680299898Sarybchik
1681299898Sarybchik	if ((rc = elop->elo_delete_key(enp, bufferp, buffer_size, offset,
1682299898Sarybchik				    length, end, deltap)) != 0)
1683299898Sarybchik		goto fail1;
1684299898Sarybchik
1685299898Sarybchik	return (0);
1686299898Sarybchik
1687299898Sarybchikfail1:
1688299898Sarybchik	EFSYS_PROBE1(fail1, efx_rc_t, rc);
1689299898Sarybchik
1690299898Sarybchik	return (rc);
1691299898Sarybchik}
1692299898Sarybchik
1693299898Sarybchik	__checkReturn		efx_rc_t
1694299898Sarybchikefx_lic_create_partition(
1695299898Sarybchik	__in			efx_nic_t *enp,
1696299898Sarybchik	__in_bcount(buffer_size)
1697299898Sarybchik				caddr_t bufferp,
1698299898Sarybchik	__in			size_t buffer_size
1699299898Sarybchik	)
1700299898Sarybchik{
1701299898Sarybchik	const efx_lic_ops_t *elop = enp->en_elop;
1702299898Sarybchik	efx_rc_t rc;
1703299898Sarybchik
1704299898Sarybchik	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1705299898Sarybchik	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1706299898Sarybchik
1707299898Sarybchik	if ((rc = elop->elo_create_partition(enp, bufferp, buffer_size)) != 0)
1708299898Sarybchik		goto fail1;
1709299898Sarybchik
1710299898Sarybchik	return (0);
1711299898Sarybchik
1712299898Sarybchikfail1:
1713299898Sarybchik	EFSYS_PROBE1(fail1, efx_rc_t, rc);
1714299898Sarybchik
1715299898Sarybchik	return (rc);
1716299898Sarybchik}
1717299898Sarybchik
1718299898Sarybchik
1719299898Sarybchik	__checkReturn		efx_rc_t
1720299898Sarybchikefx_lic_finish_partition(
1721299898Sarybchik	__in			efx_nic_t *enp,
1722299898Sarybchik	__in_bcount(buffer_size)
1723299898Sarybchik				caddr_t bufferp,
1724299898Sarybchik	__in			size_t buffer_size
1725299898Sarybchik	)
1726299898Sarybchik{
1727299898Sarybchik	const efx_lic_ops_t *elop = enp->en_elop;
1728299898Sarybchik	efx_rc_t rc;
1729299898Sarybchik
1730299898Sarybchik	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1731299898Sarybchik	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1732299898Sarybchik
1733299898Sarybchik	if ((rc = elop->elo_finish_partition(enp, bufferp, buffer_size)) != 0)
1734299898Sarybchik		goto fail1;
1735299898Sarybchik
1736299898Sarybchik	return (0);
1737299898Sarybchik
1738299898Sarybchikfail1:
1739299898Sarybchik	EFSYS_PROBE1(fail1, efx_rc_t, rc);
1740299898Sarybchik
1741299898Sarybchik	return (rc);
1742299898Sarybchik}
1743299898Sarybchik
1744293901Sarybchik#endif	/* EFSYS_OPT_LICENSING */
1745