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