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