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