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