]> CyberLeo.Net >> Repos - FreeBSD/stable/10.git/blob - sys/dev/sfxge/common/efx_lic.c
MFC r310680
[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         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,
1088                     MC_CMD_LICENSING_GET_ID_V3_OUT_LICENSE_ID_OFST);
1089         }
1090
1091         return (0);
1092
1093 fail2:
1094         EFSYS_PROBE(fail2);
1095 fail1:
1096         EFSYS_PROBE1(fail1, efx_rc_t, rc);
1097
1098         return (rc);
1099 }
1100
1101 /* V3 format uses Huntington TLV format partition. See SF-108797-SW */
1102 #define EFX_LICENSE_V3_KEY_LENGTH_MIN    (64)
1103 #define EFX_LICENSE_V3_KEY_LENGTH_MAX    (160)
1104
1105         __checkReturn           efx_rc_t
1106 efx_lic_v3_find_start(
1107         __in                    efx_nic_t *enp,
1108         __in_bcount(buffer_size)
1109                                 caddr_t bufferp,
1110         __in                    size_t buffer_size,
1111         __out                   uint32_t *startp
1112         )
1113 {
1114         _NOTE(ARGUNUSED(enp))
1115
1116         return ef10_nvram_buffer_find_item_start(bufferp, buffer_size, startp);
1117 }
1118
1119         __checkReturn           efx_rc_t
1120 efx_lic_v3_find_end(
1121         __in                    efx_nic_t *enp,
1122         __in_bcount(buffer_size)
1123                                 caddr_t bufferp,
1124         __in                    size_t buffer_size,
1125         __in                    uint32_t offset,
1126         __out                   uint32_t *endp
1127         )
1128 {
1129         _NOTE(ARGUNUSED(enp))
1130
1131         return ef10_nvram_buffer_find_end(bufferp, buffer_size, offset, endp);
1132 }
1133
1134         __checkReturn   __success(return != B_FALSE)    boolean_t
1135 efx_lic_v3_find_key(
1136         __in                    efx_nic_t *enp,
1137         __in_bcount(buffer_size)
1138                                 caddr_t bufferp,
1139         __in                    size_t buffer_size,
1140         __in                    uint32_t offset,
1141         __out                   uint32_t *startp,
1142         __out                   uint32_t *lengthp
1143         )
1144 {
1145         _NOTE(ARGUNUSED(enp))
1146
1147         return ef10_nvram_buffer_find_item(bufferp, buffer_size,
1148             offset, startp, lengthp);
1149 }
1150
1151         __checkReturn   __success(return != B_FALSE)    boolean_t
1152 efx_lic_v3_validate_key(
1153         __in                    efx_nic_t *enp,
1154         __in_bcount(length)     caddr_t keyp,
1155         __in                    uint32_t length
1156         )
1157 {
1158         // Check key is a valid V3 key
1159         uint8_t key_type;
1160         uint8_t key_length;
1161
1162         _NOTE(ARGUNUSED(enp))
1163
1164         if (length < EFX_LICENSE_V3_KEY_LENGTH_MIN) {
1165                 goto fail1;
1166         }
1167
1168         if (length > EFX_LICENSE_V3_KEY_LENGTH_MAX) {
1169                 goto fail2;
1170         }
1171
1172         key_type = ((uint8_t*)keyp)[0];
1173         key_length = ((uint8_t*)keyp)[1];
1174
1175         if (key_type < 3) {
1176                 goto fail3;
1177         }
1178         if (key_length > length) {
1179                 goto fail4;
1180         }
1181         return (B_TRUE);
1182
1183 fail4:
1184         EFSYS_PROBE(fail4);
1185 fail3:
1186         EFSYS_PROBE(fail3);
1187 fail2:
1188         EFSYS_PROBE(fail2);
1189 fail1:
1190         EFSYS_PROBE(fail1);
1191
1192         return (B_FALSE);
1193 }
1194
1195         __checkReturn           efx_rc_t
1196 efx_lic_v3_read_key(
1197         __in                    efx_nic_t *enp,
1198         __in_bcount(buffer_size)
1199                                 caddr_t bufferp,
1200         __in                    size_t buffer_size,
1201         __in                    uint32_t offset,
1202         __in                    uint32_t length,
1203         __out_bcount_part(key_max_size, *lengthp)
1204                                 caddr_t keyp,
1205         __in                    size_t key_max_size,
1206         __out                   uint32_t *lengthp
1207         )
1208 {
1209         _NOTE(ARGUNUSED(enp))
1210
1211         return ef10_nvram_buffer_get_item(bufferp, buffer_size,
1212                     offset, length, keyp, key_max_size, lengthp);
1213 }
1214
1215         __checkReturn           efx_rc_t
1216 efx_lic_v3_write_key(
1217         __in                    efx_nic_t *enp,
1218         __in_bcount(buffer_size)
1219                                 caddr_t bufferp,
1220         __in                    size_t buffer_size,
1221         __in                    uint32_t offset,
1222         __in_bcount(length)     caddr_t keyp,
1223         __in                    uint32_t length,
1224         __out                   uint32_t *lengthp
1225         )
1226 {
1227         _NOTE(ARGUNUSED(enp))
1228         EFSYS_ASSERT(length <= EFX_LICENSE_V3_KEY_LENGTH_MAX);
1229
1230         return ef10_nvram_buffer_insert_item(bufferp, buffer_size,
1231                     offset, keyp, length, lengthp);
1232 }
1233
1234         __checkReturn           efx_rc_t
1235 efx_lic_v3_delete_key(
1236         __in                    efx_nic_t *enp,
1237         __in_bcount(buffer_size)
1238                                 caddr_t bufferp,
1239         __in                    size_t buffer_size,
1240         __in                    uint32_t offset,
1241         __in                    uint32_t length,
1242         __in                    uint32_t end,
1243         __out                   uint32_t *deltap
1244         )
1245 {
1246         efx_rc_t rc;
1247
1248         _NOTE(ARGUNUSED(enp))
1249
1250         if ((rc = ef10_nvram_buffer_delete_item(bufferp,
1251                         buffer_size, offset, length, end)) != 0) {
1252                 goto fail1;
1253         }
1254
1255         *deltap = length;
1256
1257         return (0);
1258
1259 fail1:
1260         EFSYS_PROBE1(fail1, efx_rc_t, rc);
1261
1262         return (rc);
1263 }
1264
1265         __checkReturn           efx_rc_t
1266 efx_lic_v3_create_partition(
1267         __in                    efx_nic_t *enp,
1268         __in_bcount(buffer_size)
1269                                 caddr_t bufferp,
1270         __in                    size_t buffer_size
1271         )
1272 {
1273         efx_rc_t rc;
1274
1275         // Construct empty partition
1276         if ((rc = ef10_nvram_buffer_create(enp,
1277             NVRAM_PARTITION_TYPE_LICENSE,
1278             bufferp, buffer_size)) != 0) {
1279                 rc = EFAULT;
1280                 goto fail1;
1281         }
1282
1283         return (0);
1284
1285 fail1:
1286         EFSYS_PROBE1(fail1, efx_rc_t, rc);
1287
1288         return (rc);
1289 }
1290
1291         __checkReturn           efx_rc_t
1292 efx_lic_v3_finish_partition(
1293         __in                    efx_nic_t *enp,
1294         __in_bcount(buffer_size)
1295                                 caddr_t bufferp,
1296         __in                    size_t buffer_size
1297         )
1298 {
1299         efx_rc_t rc;
1300
1301         if ((rc = ef10_nvram_buffer_finish(bufferp,
1302                         buffer_size)) != 0) {
1303                 goto fail1;
1304         }
1305
1306         // Validate completed partition
1307         if ((rc = ef10_nvram_buffer_validate(enp, NVRAM_PARTITION_TYPE_LICENSE,
1308                                         bufferp, buffer_size)) != 0) {
1309                 goto fail2;
1310         }
1311
1312         return (0);
1313
1314 fail2:
1315         EFSYS_PROBE(fail2);
1316 fail1:
1317         EFSYS_PROBE1(fail1, efx_rc_t, rc);
1318
1319         return (rc);
1320 }
1321
1322
1323 #endif  /* EFSYS_OPT_MEDFORD */
1324
1325         __checkReturn           efx_rc_t
1326 efx_lic_init(
1327         __in                    efx_nic_t *enp)
1328 {
1329         const efx_lic_ops_t *elop;
1330         efx_key_stats_t eks;
1331         efx_rc_t rc;
1332
1333         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1334         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
1335         EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_LIC));
1336
1337         switch (enp->en_family) {
1338
1339 #if EFSYS_OPT_SIENA
1340         case EFX_FAMILY_SIENA:
1341                 elop = &__efx_lic_v1_ops;
1342                 break;
1343 #endif  /* EFSYS_OPT_SIENA */
1344
1345 #if EFSYS_OPT_HUNTINGTON
1346         case EFX_FAMILY_HUNTINGTON:
1347                 elop = &__efx_lic_v2_ops;
1348                 break;
1349 #endif  /* EFSYS_OPT_HUNTINGTON */
1350
1351 #if EFSYS_OPT_MEDFORD
1352         case EFX_FAMILY_MEDFORD:
1353                 elop = &__efx_lic_v3_ops;
1354                 break;
1355 #endif  /* EFSYS_OPT_MEDFORD */
1356
1357         default:
1358                 EFSYS_ASSERT(0);
1359                 rc = ENOTSUP;
1360                 goto fail1;
1361         }
1362
1363         enp->en_elop = elop;
1364         enp->en_mod_flags |= EFX_MOD_LIC;
1365
1366         /* Probe for support */
1367         if (efx_lic_get_key_stats(enp, &eks) == 0) {
1368                 enp->en_licensing_supported = B_TRUE;
1369         } else {
1370                 enp->en_licensing_supported = B_FALSE;
1371         }
1372
1373         return (0);
1374
1375 fail1:
1376         EFSYS_PROBE1(fail1, efx_rc_t, rc);
1377
1378         return (rc);
1379 }
1380
1381 extern  __checkReturn   boolean_t
1382 efx_lic_check_support(
1383         __in                    efx_nic_t *enp)
1384 {
1385         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1386         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
1387         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1388
1389         return enp->en_licensing_supported;
1390 }
1391
1392                                 void
1393 efx_lic_fini(
1394         __in                    efx_nic_t *enp)
1395 {
1396         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1397         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
1398         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1399
1400         enp->en_elop = NULL;
1401         enp->en_mod_flags &= ~EFX_MOD_LIC;
1402 }
1403
1404
1405         __checkReturn   efx_rc_t
1406 efx_lic_update_licenses(
1407         __in            efx_nic_t *enp)
1408 {
1409         const efx_lic_ops_t *elop = enp->en_elop;
1410         efx_rc_t rc;
1411
1412         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1413         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1414
1415         if ((rc = elop->elo_update_licenses(enp)) != 0)
1416                 goto fail1;
1417
1418         return (0);
1419
1420 fail1:
1421         EFSYS_PROBE1(fail1, efx_rc_t, rc);
1422
1423         return (rc);
1424 }
1425
1426         __checkReturn   efx_rc_t
1427 efx_lic_get_key_stats(
1428         __in            efx_nic_t *enp,
1429         __out           efx_key_stats_t *eksp)
1430 {
1431         const efx_lic_ops_t *elop = enp->en_elop;
1432         efx_rc_t rc;
1433
1434         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1435         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1436
1437         if ((rc = elop->elo_get_key_stats(enp, eksp)) != 0)
1438                 goto fail1;
1439
1440         return (0);
1441
1442 fail1:
1443         EFSYS_PROBE1(fail1, efx_rc_t, rc);
1444
1445         return (rc);
1446 }
1447
1448         __checkReturn   efx_rc_t
1449 efx_lic_app_state(
1450         __in            efx_nic_t *enp,
1451         __in            uint64_t app_id,
1452         __out           boolean_t *licensedp)
1453 {
1454         const efx_lic_ops_t *elop = enp->en_elop;
1455         efx_rc_t rc;
1456
1457         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1458         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1459
1460         if (elop->elo_app_state == NULL)
1461                 return (ENOTSUP);
1462
1463         if ((rc = elop->elo_app_state(enp, app_id, licensedp)) != 0)
1464                 goto fail1;
1465
1466         return (0);
1467
1468 fail1:
1469         EFSYS_PROBE1(fail1, efx_rc_t, rc);
1470
1471         return (rc);
1472 }
1473
1474         __checkReturn   efx_rc_t
1475 efx_lic_get_id(
1476         __in            efx_nic_t *enp,
1477         __in            size_t buffer_size,
1478         __out           uint32_t *typep,
1479         __out           size_t *lengthp,
1480         __out_opt       uint8_t *bufferp
1481         )
1482 {
1483         const efx_lic_ops_t *elop = enp->en_elop;
1484         efx_rc_t rc;
1485
1486         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1487         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1488
1489         if (elop->elo_get_id == NULL)
1490                 return (ENOTSUP);
1491
1492         if ((rc = elop->elo_get_id(enp, buffer_size, typep,
1493                                     lengthp, bufferp)) != 0)
1494                 goto fail1;
1495
1496         return (0);
1497
1498 fail1:
1499         EFSYS_PROBE1(fail1, efx_rc_t, rc);
1500
1501         return (rc);
1502 }
1503
1504 /* Buffer management API - abstracts varying TLV format used for License partition */
1505
1506         __checkReturn           efx_rc_t
1507 efx_lic_find_start(
1508         __in                    efx_nic_t *enp,
1509         __in_bcount(buffer_size)
1510                                 caddr_t bufferp,
1511         __in                    size_t buffer_size,
1512         __out                   uint32_t *startp
1513         )
1514 {
1515         const efx_lic_ops_t *elop = enp->en_elop;
1516         efx_rc_t rc;
1517
1518         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1519         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1520
1521         if ((rc = elop->elo_find_start(enp, bufferp, buffer_size, startp)) != 0)
1522                 goto fail1;
1523
1524         return (0);
1525
1526 fail1:
1527         EFSYS_PROBE1(fail1, efx_rc_t, rc);
1528
1529         return (rc);
1530 }
1531
1532         __checkReturn           efx_rc_t
1533 efx_lic_find_end(
1534         __in                    efx_nic_t *enp,
1535         __in_bcount(buffer_size)
1536                                 caddr_t bufferp,
1537         __in                    size_t buffer_size,
1538         __in                    uint32_t offset,
1539         __out                   uint32_t *endp
1540         )
1541 {
1542         const efx_lic_ops_t *elop = enp->en_elop;
1543         efx_rc_t rc;
1544
1545         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1546         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1547
1548         if ((rc = elop->elo_find_end(enp, bufferp, buffer_size, offset, endp)) != 0)
1549                 goto fail1;
1550
1551         return (0);
1552
1553 fail1:
1554         EFSYS_PROBE1(fail1, efx_rc_t, rc);
1555
1556         return (rc);
1557 }
1558
1559         __checkReturn   __success(return != B_FALSE)    boolean_t
1560 efx_lic_find_key(
1561         __in                    efx_nic_t *enp,
1562         __in_bcount(buffer_size)
1563                                 caddr_t bufferp,
1564         __in                    size_t buffer_size,
1565         __in                    uint32_t offset,
1566         __out                   uint32_t *startp,
1567         __out                   uint32_t *lengthp
1568         )
1569 {
1570         const efx_lic_ops_t *elop = enp->en_elop;
1571
1572         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1573         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1574
1575         EFSYS_ASSERT(bufferp);
1576         EFSYS_ASSERT(startp);
1577         EFSYS_ASSERT(lengthp);
1578
1579         return (elop->elo_find_key(enp, bufferp, buffer_size, offset,
1580                                     startp, lengthp));
1581 }
1582
1583
1584 /* Validate that the buffer contains a single key in a recognised format.
1585 ** An empty or terminator buffer is not accepted as a valid key.
1586 */
1587         __checkReturn   __success(return != B_FALSE)    boolean_t
1588 efx_lic_validate_key(
1589         __in                    efx_nic_t *enp,
1590         __in_bcount(length)     caddr_t keyp,
1591         __in                    uint32_t length
1592         )
1593 {
1594         const efx_lic_ops_t *elop = enp->en_elop;
1595         boolean_t rc;
1596
1597         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1598         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1599
1600         if ((rc = elop->elo_validate_key(enp, keyp, length)) == B_FALSE)
1601                 goto fail1;
1602
1603         return (B_TRUE);
1604
1605 fail1:
1606         EFSYS_PROBE1(fail1, efx_rc_t, rc);
1607
1608         return (rc);
1609 }
1610
1611         __checkReturn           efx_rc_t
1612 efx_lic_read_key(
1613         __in                    efx_nic_t *enp,
1614         __in_bcount(buffer_size)
1615                                 caddr_t bufferp,
1616         __in                    size_t buffer_size,
1617         __in                    uint32_t offset,
1618         __in                    uint32_t length,
1619         __out_bcount_part(key_max_size, *lengthp)
1620                                 caddr_t keyp,
1621         __in                    size_t key_max_size,
1622         __out                   uint32_t *lengthp
1623         )
1624 {
1625         const efx_lic_ops_t *elop = enp->en_elop;
1626         efx_rc_t rc;
1627
1628         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1629         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1630
1631         if ((rc = elop->elo_read_key(enp, bufferp, buffer_size, offset,
1632                                     length, keyp, key_max_size, lengthp)) != 0)
1633                 goto fail1;
1634
1635         return (0);
1636
1637 fail1:
1638         EFSYS_PROBE1(fail1, efx_rc_t, rc);
1639
1640         return (rc);
1641 }
1642
1643         __checkReturn           efx_rc_t
1644 efx_lic_write_key(
1645         __in                    efx_nic_t *enp,
1646         __in_bcount(buffer_size)
1647                                 caddr_t bufferp,
1648         __in                    size_t buffer_size,
1649         __in                    uint32_t offset,
1650         __in_bcount(length)     caddr_t keyp,
1651         __in                    uint32_t length,
1652         __out                   uint32_t *lengthp
1653         )
1654 {
1655         const efx_lic_ops_t *elop = enp->en_elop;
1656         efx_rc_t rc;
1657
1658         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1659         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1660
1661         if ((rc = elop->elo_write_key(enp, bufferp, buffer_size, offset,
1662                                     keyp, length, lengthp)) != 0)
1663                 goto fail1;
1664
1665         return (0);
1666
1667 fail1:
1668         EFSYS_PROBE1(fail1, efx_rc_t, rc);
1669
1670         return (rc);
1671 }
1672
1673         __checkReturn           efx_rc_t
1674 efx_lic_delete_key(
1675         __in                    efx_nic_t *enp,
1676         __in_bcount(buffer_size)
1677                                 caddr_t bufferp,
1678         __in                    size_t buffer_size,
1679         __in                    uint32_t offset,
1680         __in                    uint32_t length,
1681         __in                    uint32_t end,
1682         __out                   uint32_t *deltap
1683         )
1684 {
1685         const efx_lic_ops_t *elop = enp->en_elop;
1686         efx_rc_t rc;
1687
1688         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1689         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1690
1691         if ((rc = elop->elo_delete_key(enp, bufferp, buffer_size, offset,
1692                                     length, end, deltap)) != 0)
1693                 goto fail1;
1694
1695         return (0);
1696
1697 fail1:
1698         EFSYS_PROBE1(fail1, efx_rc_t, rc);
1699
1700         return (rc);
1701 }
1702
1703         __checkReturn           efx_rc_t
1704 efx_lic_create_partition(
1705         __in                    efx_nic_t *enp,
1706         __in_bcount(buffer_size)
1707                                 caddr_t bufferp,
1708         __in                    size_t buffer_size
1709         )
1710 {
1711         const efx_lic_ops_t *elop = enp->en_elop;
1712         efx_rc_t rc;
1713
1714         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1715         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1716
1717         if ((rc = elop->elo_create_partition(enp, bufferp, buffer_size)) != 0)
1718                 goto fail1;
1719
1720         return (0);
1721
1722 fail1:
1723         EFSYS_PROBE1(fail1, efx_rc_t, rc);
1724
1725         return (rc);
1726 }
1727
1728
1729         __checkReturn           efx_rc_t
1730 efx_lic_finish_partition(
1731         __in                    efx_nic_t *enp,
1732         __in_bcount(buffer_size)
1733                                 caddr_t bufferp,
1734         __in                    size_t buffer_size
1735         )
1736 {
1737         const efx_lic_ops_t *elop = enp->en_elop;
1738         efx_rc_t rc;
1739
1740         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1741         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1742
1743         if ((rc = elop->elo_finish_partition(enp, bufferp, buffer_size)) != 0)
1744                 goto fail1;
1745
1746         return (0);
1747
1748 fail1:
1749         EFSYS_PROBE1(fail1, efx_rc_t, rc);
1750
1751         return (rc);
1752 }
1753
1754 #endif  /* EFSYS_OPT_LICENSING */