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