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