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