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