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