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