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