New upstream version 18.08
[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         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         _NOTE(ARGUNUSED(enp))
1162
1163         return ef10_nvram_buffer_get_item(bufferp, buffer_size,
1164                     offset, length, keyp, key_max_size, lengthp);
1165 }
1166
1167         __checkReturn           efx_rc_t
1168 efx_lic_v3_write_key(
1169         __in                    efx_nic_t *enp,
1170         __in_bcount(buffer_size)
1171                                 caddr_t bufferp,
1172         __in                    size_t buffer_size,
1173         __in                    uint32_t offset,
1174         __in_bcount(length)     caddr_t keyp,
1175         __in                    uint32_t length,
1176         __out                   uint32_t *lengthp)
1177 {
1178         _NOTE(ARGUNUSED(enp))
1179         EFSYS_ASSERT(length <= EFX_LICENSE_V3_KEY_LENGTH_MAX);
1180
1181         return ef10_nvram_buffer_insert_item(bufferp, buffer_size,
1182                     offset, keyp, length, lengthp);
1183 }
1184
1185         __checkReturn           efx_rc_t
1186 efx_lic_v3_delete_key(
1187         __in                    efx_nic_t *enp,
1188         __in_bcount(buffer_size)
1189                                 caddr_t bufferp,
1190         __in                    size_t buffer_size,
1191         __in                    uint32_t offset,
1192         __in                    uint32_t length,
1193         __in                    uint32_t end,
1194         __out                   uint32_t *deltap)
1195 {
1196         efx_rc_t rc;
1197
1198         _NOTE(ARGUNUSED(enp))
1199
1200         if ((rc = ef10_nvram_buffer_delete_item(bufferp,
1201                         buffer_size, offset, length, end)) != 0) {
1202                 goto fail1;
1203         }
1204
1205         *deltap = length;
1206
1207         return (0);
1208
1209 fail1:
1210         EFSYS_PROBE1(fail1, efx_rc_t, rc);
1211
1212         return (rc);
1213 }
1214
1215         __checkReturn           efx_rc_t
1216 efx_lic_v3_create_partition(
1217         __in                    efx_nic_t *enp,
1218         __in_bcount(buffer_size)
1219                                 caddr_t bufferp,
1220         __in                    size_t buffer_size)
1221 {
1222         efx_rc_t rc;
1223
1224         /* Construct empty partition */
1225         if ((rc = ef10_nvram_buffer_create(enp,
1226             NVRAM_PARTITION_TYPE_LICENSE,
1227             bufferp, buffer_size)) != 0) {
1228                 rc = EFAULT;
1229                 goto fail1;
1230         }
1231
1232         return (0);
1233
1234 fail1:
1235         EFSYS_PROBE1(fail1, efx_rc_t, rc);
1236
1237         return (rc);
1238 }
1239
1240         __checkReturn           efx_rc_t
1241 efx_lic_v3_finish_partition(
1242         __in                    efx_nic_t *enp,
1243         __in_bcount(buffer_size)
1244                                 caddr_t bufferp,
1245         __in                    size_t buffer_size)
1246 {
1247         efx_rc_t rc;
1248
1249         if ((rc = ef10_nvram_buffer_finish(bufferp,
1250                         buffer_size)) != 0) {
1251                 goto fail1;
1252         }
1253
1254         /* Validate completed partition */
1255         if ((rc = ef10_nvram_buffer_validate(enp, NVRAM_PARTITION_TYPE_LICENSE,
1256                                         bufferp, buffer_size)) != 0) {
1257                 goto fail2;
1258         }
1259
1260         return (0);
1261
1262 fail2:
1263         EFSYS_PROBE(fail2);
1264 fail1:
1265         EFSYS_PROBE1(fail1, efx_rc_t, rc);
1266
1267         return (rc);
1268 }
1269
1270
1271 #endif  /* EFSYS_OPT_MEDFORD || EFSYS_OPT_MEDFORD2 */
1272
1273         __checkReturn           efx_rc_t
1274 efx_lic_init(
1275         __in                    efx_nic_t *enp)
1276 {
1277         const efx_lic_ops_t *elop;
1278         efx_key_stats_t eks;
1279         efx_rc_t rc;
1280
1281         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1282         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
1283         EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_LIC));
1284
1285         switch (enp->en_family) {
1286
1287 #if EFSYS_OPT_SIENA
1288         case EFX_FAMILY_SIENA:
1289                 elop = &__efx_lic_v1_ops;
1290                 break;
1291 #endif  /* EFSYS_OPT_SIENA */
1292
1293 #if EFSYS_OPT_HUNTINGTON
1294         case EFX_FAMILY_HUNTINGTON:
1295                 elop = &__efx_lic_v2_ops;
1296                 break;
1297 #endif  /* EFSYS_OPT_HUNTINGTON */
1298
1299 #if EFSYS_OPT_MEDFORD
1300         case EFX_FAMILY_MEDFORD:
1301                 elop = &__efx_lic_v3_ops;
1302                 break;
1303 #endif  /* EFSYS_OPT_MEDFORD */
1304
1305 #if EFSYS_OPT_MEDFORD2
1306         case EFX_FAMILY_MEDFORD2:
1307                 elop = &__efx_lic_v3_ops;
1308                 break;
1309 #endif  /* EFSYS_OPT_MEDFORD2 */
1310
1311         default:
1312                 EFSYS_ASSERT(0);
1313                 rc = ENOTSUP;
1314                 goto fail1;
1315         }
1316
1317         enp->en_elop = elop;
1318         enp->en_mod_flags |= EFX_MOD_LIC;
1319
1320         /* Probe for support */
1321         if (efx_lic_get_key_stats(enp, &eks) == 0) {
1322                 enp->en_licensing_supported = B_TRUE;
1323         } else {
1324                 enp->en_licensing_supported = B_FALSE;
1325         }
1326
1327         return (0);
1328
1329 fail1:
1330         EFSYS_PROBE1(fail1, efx_rc_t, rc);
1331
1332         return (rc);
1333 }
1334
1335 extern  __checkReturn   boolean_t
1336 efx_lic_check_support(
1337         __in                    efx_nic_t *enp)
1338 {
1339         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1340         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
1341         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1342
1343         return (enp->en_licensing_supported);
1344 }
1345
1346                                 void
1347 efx_lic_fini(
1348         __in                    efx_nic_t *enp)
1349 {
1350         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1351         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
1352         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1353
1354         enp->en_elop = NULL;
1355         enp->en_mod_flags &= ~EFX_MOD_LIC;
1356 }
1357
1358
1359         __checkReturn   efx_rc_t
1360 efx_lic_update_licenses(
1361         __in            efx_nic_t *enp)
1362 {
1363         const efx_lic_ops_t *elop = enp->en_elop;
1364         efx_rc_t rc;
1365
1366         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1367         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1368
1369         if ((rc = elop->elo_update_licenses(enp)) != 0)
1370                 goto fail1;
1371
1372         return (0);
1373
1374 fail1:
1375         EFSYS_PROBE1(fail1, efx_rc_t, rc);
1376
1377         return (rc);
1378 }
1379
1380         __checkReturn   efx_rc_t
1381 efx_lic_get_key_stats(
1382         __in            efx_nic_t *enp,
1383         __out           efx_key_stats_t *eksp)
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 ((rc = elop->elo_get_key_stats(enp, eksp)) != 0)
1392                 goto fail1;
1393
1394         return (0);
1395
1396 fail1:
1397         EFSYS_PROBE1(fail1, efx_rc_t, rc);
1398
1399         return (rc);
1400 }
1401
1402         __checkReturn   efx_rc_t
1403 efx_lic_app_state(
1404         __in            efx_nic_t *enp,
1405         __in            uint64_t app_id,
1406         __out           boolean_t *licensedp)
1407 {
1408         const efx_lic_ops_t *elop = enp->en_elop;
1409         efx_rc_t rc;
1410
1411         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1412         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1413
1414         if (elop->elo_app_state == NULL)
1415                 return (ENOTSUP);
1416
1417         if ((rc = elop->elo_app_state(enp, app_id, licensedp)) != 0)
1418                 goto fail1;
1419
1420         return (0);
1421
1422 fail1:
1423         EFSYS_PROBE1(fail1, efx_rc_t, rc);
1424
1425         return (rc);
1426 }
1427
1428         __checkReturn   efx_rc_t
1429 efx_lic_get_id(
1430         __in            efx_nic_t *enp,
1431         __in            size_t buffer_size,
1432         __out           uint32_t *typep,
1433         __out           size_t *lengthp,
1434         __out_opt       uint8_t *bufferp)
1435 {
1436         const efx_lic_ops_t *elop = enp->en_elop;
1437         efx_rc_t rc;
1438
1439         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1440         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1441
1442         if (elop->elo_get_id == NULL)
1443                 return (ENOTSUP);
1444
1445         if ((rc = elop->elo_get_id(enp, buffer_size, typep,
1446                                     lengthp, bufferp)) != 0)
1447                 goto fail1;
1448
1449         return (0);
1450
1451 fail1:
1452         EFSYS_PROBE1(fail1, efx_rc_t, rc);
1453
1454         return (rc);
1455 }
1456
1457 /*
1458  * Buffer management API - abstracts varying TLV format used for License
1459  * partition.
1460  */
1461
1462         __checkReturn           efx_rc_t
1463 efx_lic_find_start(
1464         __in                    efx_nic_t *enp,
1465         __in_bcount(buffer_size)
1466                                 caddr_t bufferp,
1467         __in                    size_t buffer_size,
1468         __out                   uint32_t *startp)
1469 {
1470         const efx_lic_ops_t *elop = enp->en_elop;
1471         efx_rc_t rc;
1472
1473         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1474         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1475
1476         if ((rc = elop->elo_find_start(enp, bufferp, buffer_size, startp)) != 0)
1477                 goto fail1;
1478
1479         return (0);
1480
1481 fail1:
1482         EFSYS_PROBE1(fail1, efx_rc_t, rc);
1483
1484         return (rc);
1485 }
1486
1487         __checkReturn           efx_rc_t
1488 efx_lic_find_end(
1489         __in                    efx_nic_t *enp,
1490         __in_bcount(buffer_size)
1491                                 caddr_t bufferp,
1492         __in                    size_t buffer_size,
1493         __in                    uint32_t offset,
1494         __out                   uint32_t *endp)
1495 {
1496         const efx_lic_ops_t *elop = enp->en_elop;
1497         efx_rc_t rc;
1498
1499         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1500         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1501
1502         rc = elop->elo_find_end(enp, bufferp, buffer_size, offset, endp);
1503         if (rc != 0)
1504                 goto fail1;
1505
1506         return (0);
1507
1508 fail1:
1509         EFSYS_PROBE1(fail1, efx_rc_t, rc);
1510
1511         return (rc);
1512 }
1513
1514         __checkReturn   __success(return != B_FALSE)    boolean_t
1515 efx_lic_find_key(
1516         __in                    efx_nic_t *enp,
1517         __in_bcount(buffer_size)
1518                                 caddr_t bufferp,
1519         __in                    size_t buffer_size,
1520         __in                    uint32_t offset,
1521         __out                   uint32_t *startp,
1522         __out                   uint32_t *lengthp)
1523 {
1524         const efx_lic_ops_t *elop = enp->en_elop;
1525
1526         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1527         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1528
1529         EFSYS_ASSERT(bufferp);
1530         EFSYS_ASSERT(startp);
1531         EFSYS_ASSERT(lengthp);
1532
1533         return (elop->elo_find_key(enp, bufferp, buffer_size, offset,
1534                                     startp, lengthp));
1535 }
1536
1537
1538 /*
1539  * Validate that the buffer contains a single key in a recognised format.
1540  * An empty or terminator buffer is not accepted as a valid key.
1541  */
1542         __checkReturn   __success(return != B_FALSE)    boolean_t
1543 efx_lic_validate_key(
1544         __in                    efx_nic_t *enp,
1545         __in_bcount(length)     caddr_t keyp,
1546         __in                    uint32_t length)
1547 {
1548         const efx_lic_ops_t *elop = enp->en_elop;
1549         boolean_t rc;
1550
1551         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1552         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1553
1554         if ((rc = elop->elo_validate_key(enp, keyp, length)) == B_FALSE)
1555                 goto fail1;
1556
1557         return (B_TRUE);
1558
1559 fail1:
1560         EFSYS_PROBE1(fail1, efx_rc_t, rc);
1561
1562         return (rc);
1563 }
1564
1565         __checkReturn           efx_rc_t
1566 efx_lic_read_key(
1567         __in                    efx_nic_t *enp,
1568         __in_bcount(buffer_size)
1569                                 caddr_t bufferp,
1570         __in                    size_t buffer_size,
1571         __in                    uint32_t offset,
1572         __in                    uint32_t length,
1573         __out_bcount_part(key_max_size, *lengthp)
1574                                 caddr_t keyp,
1575         __in                    size_t key_max_size,
1576         __out                   uint32_t *lengthp)
1577 {
1578         const efx_lic_ops_t *elop = enp->en_elop;
1579         efx_rc_t rc;
1580
1581         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1582         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1583
1584         if ((rc = elop->elo_read_key(enp, bufferp, buffer_size, offset,
1585                                     length, keyp, key_max_size, lengthp)) != 0)
1586                 goto fail1;
1587
1588         return (0);
1589
1590 fail1:
1591         EFSYS_PROBE1(fail1, efx_rc_t, rc);
1592
1593         return (rc);
1594 }
1595
1596         __checkReturn           efx_rc_t
1597 efx_lic_write_key(
1598         __in                    efx_nic_t *enp,
1599         __in_bcount(buffer_size)
1600                                 caddr_t bufferp,
1601         __in                    size_t buffer_size,
1602         __in                    uint32_t offset,
1603         __in_bcount(length)     caddr_t keyp,
1604         __in                    uint32_t length,
1605         __out                   uint32_t *lengthp)
1606 {
1607         const efx_lic_ops_t *elop = enp->en_elop;
1608         efx_rc_t rc;
1609
1610         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1611         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1612
1613         if ((rc = elop->elo_write_key(enp, bufferp, buffer_size, offset,
1614                                     keyp, length, lengthp)) != 0)
1615                 goto fail1;
1616
1617         return (0);
1618
1619 fail1:
1620         EFSYS_PROBE1(fail1, efx_rc_t, rc);
1621
1622         return (rc);
1623 }
1624
1625         __checkReturn           efx_rc_t
1626 efx_lic_delete_key(
1627         __in                    efx_nic_t *enp,
1628         __in_bcount(buffer_size)
1629                                 caddr_t bufferp,
1630         __in                    size_t buffer_size,
1631         __in                    uint32_t offset,
1632         __in                    uint32_t length,
1633         __in                    uint32_t end,
1634         __out                   uint32_t *deltap)
1635 {
1636         const efx_lic_ops_t *elop = enp->en_elop;
1637         efx_rc_t rc;
1638
1639         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1640         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1641
1642         if ((rc = elop->elo_delete_key(enp, bufferp, buffer_size, offset,
1643                                     length, end, deltap)) != 0)
1644                 goto fail1;
1645
1646         return (0);
1647
1648 fail1:
1649         EFSYS_PROBE1(fail1, efx_rc_t, rc);
1650
1651         return (rc);
1652 }
1653
1654         __checkReturn           efx_rc_t
1655 efx_lic_create_partition(
1656         __in                    efx_nic_t *enp,
1657         __in_bcount(buffer_size)
1658                                 caddr_t bufferp,
1659         __in                    size_t buffer_size)
1660 {
1661         const efx_lic_ops_t *elop = enp->en_elop;
1662         efx_rc_t rc;
1663
1664         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1665         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1666
1667         if ((rc = elop->elo_create_partition(enp, bufferp, buffer_size)) != 0)
1668                 goto fail1;
1669
1670         return (0);
1671
1672 fail1:
1673         EFSYS_PROBE1(fail1, efx_rc_t, rc);
1674
1675         return (rc);
1676 }
1677
1678
1679         __checkReturn           efx_rc_t
1680 efx_lic_finish_partition(
1681         __in                    efx_nic_t *enp,
1682         __in_bcount(buffer_size)
1683                                 caddr_t bufferp,
1684         __in                    size_t buffer_size)
1685 {
1686         const efx_lic_ops_t *elop = enp->en_elop;
1687         efx_rc_t rc;
1688
1689         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1690         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1691
1692         if ((rc = elop->elo_finish_partition(enp, bufferp, buffer_size)) != 0)
1693                 goto fail1;
1694
1695         return (0);
1696
1697 fail1:
1698         EFSYS_PROBE1(fail1, efx_rc_t, rc);
1699
1700         return (rc);
1701 }
1702
1703 #endif  /* EFSYS_OPT_LICENSING */