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