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