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