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