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