2 * Copyright (c) 2009-2016 Solarflare Communications Inc.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
8 * 1. Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright notice,
11 * this list of conditions and the following disclaimer in the documentation
12 * and/or other materials provided with the distribution.
14 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
15 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
16 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
18 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
21 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
22 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
23 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
24 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 * The views and conclusions contained in the software and documentation are
27 * those of the authors and should not be interpreted as representing official
28 * policies, either expressed or implied, of the FreeBSD Project.
31 #include <sys/cdefs.h>
32 __FBSDID("$FreeBSD$");
37 #if EFSYS_OPT_LICENSING
39 #include "ef10_tlv_layout.h"
41 #if EFSYS_OPT_SIENA | EFSYS_OPT_HUNTINGTON
43 __checkReturn efx_rc_t
44 efx_lic_v1v2_find_start(
46 __in_bcount(buffer_size)
48 __in size_t buffer_size,
49 __out uint32_t *startp
52 __checkReturn efx_rc_t
53 efx_lic_v1v2_find_end(
55 __in_bcount(buffer_size)
57 __in size_t buffer_size,
62 __checkReturn __success(return != B_FALSE) boolean_t
63 efx_lic_v1v2_find_key(
65 __in_bcount(buffer_size)
67 __in size_t buffer_size,
69 __out uint32_t *startp,
70 __out uint32_t *lengthp
73 __checkReturn __success(return != B_FALSE) boolean_t
74 efx_lic_v1v2_validate_key(
76 __in_bcount(length) caddr_t keyp,
80 __checkReturn efx_rc_t
81 efx_lic_v1v2_read_key(
83 __in_bcount(buffer_size)
85 __in size_t buffer_size,
88 __out_bcount_part(key_max_size, *lengthp)
90 __in size_t key_max_size,
91 __out uint32_t *lengthp
94 __checkReturn efx_rc_t
95 efx_lic_v1v2_write_key(
97 __in_bcount(buffer_size)
99 __in size_t buffer_size,
100 __in uint32_t offset,
101 __in_bcount(length) caddr_t keyp,
102 __in uint32_t length,
103 __out uint32_t *lengthp
106 __checkReturn efx_rc_t
107 efx_lic_v1v2_delete_key(
109 __in_bcount(buffer_size)
111 __in size_t buffer_size,
112 __in uint32_t offset,
113 __in uint32_t length,
115 __out uint32_t *deltap
118 __checkReturn efx_rc_t
119 efx_lic_v1v2_create_partition(
121 __in_bcount(buffer_size)
123 __in size_t buffer_size
126 __checkReturn efx_rc_t
127 efx_lic_v1v2_finish_partition(
129 __in_bcount(buffer_size)
131 __in size_t buffer_size
134 #endif /* EFSYS_OPT_HUNTINGTON | EFSYS_OPT_SIENA */
139 static __checkReturn efx_rc_t
140 efx_mcdi_fc_license_update_license(
141 __in efx_nic_t *enp);
143 static __checkReturn efx_rc_t
144 efx_mcdi_fc_license_get_key_stats(
146 __out efx_key_stats_t *eksp);
148 static const efx_lic_ops_t __efx_lic_v1_ops = {
149 efx_mcdi_fc_license_update_license, /* elo_update_licenses */
150 efx_mcdi_fc_license_get_key_stats, /* elo_get_key_stats */
151 NULL, /* elo_app_state */
152 NULL, /* elo_get_id */
153 efx_lic_v1v2_find_start, /* elo_find_start */
154 efx_lic_v1v2_find_end, /* elo_find_end */
155 efx_lic_v1v2_find_key, /* elo_find_key */
156 efx_lic_v1v2_validate_key, /* elo_validate_key */
157 efx_lic_v1v2_read_key, /* elo_read_key */
158 efx_lic_v1v2_write_key, /* elo_write_key */
159 efx_lic_v1v2_delete_key, /* elo_delete_key */
160 efx_lic_v1v2_create_partition, /* elo_create_partition */
161 efx_lic_v1v2_finish_partition, /* elo_finish_partition */
164 #endif /* EFSYS_OPT_SIENA */
166 #if EFSYS_OPT_HUNTINGTON
168 static __checkReturn efx_rc_t
169 efx_mcdi_licensing_update_licenses(
170 __in efx_nic_t *enp);
172 static __checkReturn efx_rc_t
173 efx_mcdi_licensing_get_key_stats(
175 __out efx_key_stats_t *eksp);
177 static __checkReturn efx_rc_t
178 efx_mcdi_licensed_app_state(
180 __in uint64_t app_id,
181 __out boolean_t *licensedp);
183 static const efx_lic_ops_t __efx_lic_v2_ops = {
184 efx_mcdi_licensing_update_licenses, /* elo_update_licenses */
185 efx_mcdi_licensing_get_key_stats, /* elo_get_key_stats */
186 efx_mcdi_licensed_app_state, /* elo_app_state */
187 NULL, /* elo_get_id */
188 efx_lic_v1v2_find_start, /* elo_find_start */
189 efx_lic_v1v2_find_end, /* elo_find_end */
190 efx_lic_v1v2_find_key, /* elo_find_key */
191 efx_lic_v1v2_validate_key, /* elo_validate_key */
192 efx_lic_v1v2_read_key, /* elo_read_key */
193 efx_lic_v1v2_write_key, /* elo_write_key */
194 efx_lic_v1v2_delete_key, /* elo_delete_key */
195 efx_lic_v1v2_create_partition, /* elo_create_partition */
196 efx_lic_v1v2_finish_partition, /* elo_finish_partition */
199 #endif /* EFSYS_OPT_HUNTINGTON */
201 #if EFSYS_OPT_MEDFORD
203 static __checkReturn efx_rc_t
204 efx_mcdi_licensing_v3_update_licenses(
205 __in efx_nic_t *enp);
207 static __checkReturn efx_rc_t
208 efx_mcdi_licensing_v3_report_license(
210 __out efx_key_stats_t *eksp);
212 static __checkReturn efx_rc_t
213 efx_mcdi_licensing_v3_app_state(
215 __in uint64_t app_id,
216 __out boolean_t *licensedp);
218 static __checkReturn efx_rc_t
219 efx_mcdi_licensing_v3_get_id(
221 __in size_t buffer_size,
222 __out uint32_t *typep,
223 __out size_t *lengthp,
224 __out_bcount_part_opt(buffer_size, *lengthp)
227 __checkReturn efx_rc_t
228 efx_lic_v3_find_start(
230 __in_bcount(buffer_size)
232 __in size_t buffer_size,
233 __out uint32_t *startp
236 __checkReturn efx_rc_t
239 __in_bcount(buffer_size)
241 __in size_t buffer_size,
242 __in uint32_t offset,
246 __checkReturn __success(return != B_FALSE) boolean_t
249 __in_bcount(buffer_size)
251 __in size_t buffer_size,
252 __in uint32_t offset,
253 __out uint32_t *startp,
254 __out uint32_t *lengthp
257 __checkReturn __success(return != B_FALSE) boolean_t
258 efx_lic_v3_validate_key(
260 __in_bcount(length) caddr_t keyp,
264 __checkReturn efx_rc_t
267 __in_bcount(buffer_size)
269 __in size_t buffer_size,
270 __in uint32_t offset,
271 __in uint32_t length,
272 __out_bcount_part(key_max_size, *lengthp)
274 __in size_t key_max_size,
275 __out uint32_t *lengthp
278 __checkReturn efx_rc_t
279 efx_lic_v3_write_key(
281 __in_bcount(buffer_size)
283 __in size_t buffer_size,
284 __in uint32_t offset,
285 __in_bcount(length) caddr_t keyp,
286 __in uint32_t length,
287 __out uint32_t *lengthp
290 __checkReturn efx_rc_t
291 efx_lic_v3_delete_key(
293 __in_bcount(buffer_size)
295 __in size_t buffer_size,
296 __in uint32_t offset,
297 __in uint32_t length,
299 __out uint32_t *deltap
302 __checkReturn efx_rc_t
303 efx_lic_v3_create_partition(
305 __in_bcount(buffer_size)
307 __in size_t buffer_size
310 __checkReturn efx_rc_t
311 efx_lic_v3_finish_partition(
313 __in_bcount(buffer_size)
315 __in size_t buffer_size
318 static const efx_lic_ops_t __efx_lic_v3_ops = {
319 efx_mcdi_licensing_v3_update_licenses, /* elo_update_licenses */
320 efx_mcdi_licensing_v3_report_license, /* elo_get_key_stats */
321 efx_mcdi_licensing_v3_app_state, /* elo_app_state */
322 efx_mcdi_licensing_v3_get_id, /* elo_get_id */
323 efx_lic_v3_find_start, /* elo_find_start*/
324 efx_lic_v3_find_end, /* elo_find_end */
325 efx_lic_v3_find_key, /* elo_find_key */
326 efx_lic_v3_validate_key, /* elo_validate_key */
327 efx_lic_v3_read_key, /* elo_read_key */
328 efx_lic_v3_write_key, /* elo_write_key */
329 efx_lic_v3_delete_key, /* elo_delete_key */
330 efx_lic_v3_create_partition, /* elo_create_partition */
331 efx_lic_v3_finish_partition, /* elo_finish_partition */
334 #endif /* EFSYS_OPT_MEDFORD */
337 /* V1 Licensing - used in Siena Modena only */
341 static __checkReturn efx_rc_t
342 efx_mcdi_fc_license_update_license(
346 uint8_t payload[MC_CMD_FC_IN_LICENSE_LEN];
349 EFSYS_ASSERT(enp->en_family == EFX_FAMILY_SIENA);
351 (void) memset(payload, 0, sizeof (payload));
352 req.emr_cmd = MC_CMD_FC;
353 req.emr_in_buf = payload;
354 req.emr_in_length = MC_CMD_FC_IN_LICENSE_LEN;
355 req.emr_out_buf = payload;
356 req.emr_out_length = 0;
358 MCDI_IN_SET_DWORD(req, FC_IN_CMD,
359 MC_CMD_FC_OP_LICENSE);
361 MCDI_IN_SET_DWORD(req, FC_IN_LICENSE_OP,
362 MC_CMD_FC_IN_LICENSE_UPDATE_LICENSE);
364 efx_mcdi_execute(enp, &req);
366 if (req.emr_rc != 0) {
371 if (req.emr_out_length_used != 0) {
381 EFSYS_PROBE1(fail1, efx_rc_t, rc);
386 static __checkReturn efx_rc_t
387 efx_mcdi_fc_license_get_key_stats(
389 __out efx_key_stats_t *eksp)
392 uint8_t payload[MAX(MC_CMD_FC_IN_LICENSE_LEN,
393 MC_CMD_FC_OUT_LICENSE_LEN)];
396 EFSYS_ASSERT(enp->en_family == EFX_FAMILY_SIENA);
398 (void) memset(payload, 0, sizeof (payload));
399 req.emr_cmd = MC_CMD_FC;
400 req.emr_in_buf = payload;
401 req.emr_in_length = MC_CMD_FC_IN_LICENSE_LEN;
402 req.emr_out_buf = payload;
403 req.emr_out_length = MC_CMD_FC_OUT_LICENSE_LEN;
405 MCDI_IN_SET_DWORD(req, FC_IN_CMD,
406 MC_CMD_FC_OP_LICENSE);
408 MCDI_IN_SET_DWORD(req, FC_IN_LICENSE_OP,
409 MC_CMD_FC_IN_LICENSE_GET_KEY_STATS);
411 efx_mcdi_execute_quiet(enp, &req);
413 if (req.emr_rc != 0) {
418 if (req.emr_out_length_used < MC_CMD_FC_OUT_LICENSE_LEN) {
424 MCDI_OUT_DWORD(req, FC_OUT_LICENSE_VALID_KEYS);
426 MCDI_OUT_DWORD(req, FC_OUT_LICENSE_INVALID_KEYS);
427 eksp->eks_blacklisted =
428 MCDI_OUT_DWORD(req, FC_OUT_LICENSE_BLACKLISTED_KEYS);
429 eksp->eks_unverifiable = 0;
430 eksp->eks_wrong_node = 0;
431 eksp->eks_licensed_apps_lo = 0;
432 eksp->eks_licensed_apps_hi = 0;
433 eksp->eks_licensed_features_lo = 0;
434 eksp->eks_licensed_features_hi = 0;
441 EFSYS_PROBE1(fail1, efx_rc_t, rc);
446 #endif /* EFSYS_OPT_SIENA */
448 /* V1 and V2 Partition format - based on a 16-bit TLV format */
450 #if EFSYS_OPT_SIENA | EFSYS_OPT_HUNTINGTON
453 * V1/V2 format - defined in SF-108542-TC section 4.2:
454 * Type (T): 16bit - revision/HMAC algorithm
455 * Length (L): 16bit - value length in bytes
456 * Value (V): L bytes - payload
458 #define EFX_LICENSE_V1V2_PAYLOAD_LENGTH_MAX (256)
459 #define EFX_LICENSE_V1V2_HEADER_LENGTH (2 * sizeof(uint16_t))
461 __checkReturn efx_rc_t
462 efx_lic_v1v2_find_start(
464 __in_bcount(buffer_size)
466 __in size_t buffer_size,
467 __out uint32_t *startp
470 _NOTE(ARGUNUSED(enp, bufferp, buffer_size))
476 __checkReturn efx_rc_t
477 efx_lic_v1v2_find_end(
479 __in_bcount(buffer_size)
481 __in size_t buffer_size,
482 __in uint32_t offset,
486 _NOTE(ARGUNUSED(enp, bufferp, buffer_size))
488 *endp = offset + EFX_LICENSE_V1V2_HEADER_LENGTH;
492 __checkReturn __success(return != B_FALSE) boolean_t
493 efx_lic_v1v2_find_key(
495 __in_bcount(buffer_size)
497 __in size_t buffer_size,
498 __in uint32_t offset,
499 __out uint32_t *startp,
500 __out uint32_t *lengthp
507 _NOTE(ARGUNUSED(enp))
509 if ((size_t)buffer_size - offset < EFX_LICENSE_V1V2_HEADER_LENGTH)
512 tlv_type = __LE_TO_CPU_16(((uint16_t *)&bufferp[offset])[0]);
513 tlv_length = __LE_TO_CPU_16(((uint16_t *)&bufferp[offset])[1]);
514 if ((tlv_length > EFX_LICENSE_V1V2_PAYLOAD_LENGTH_MAX) ||
515 (tlv_type == 0 && tlv_length == 0)) {
519 *lengthp = tlv_length + EFX_LICENSE_V1V2_HEADER_LENGTH;
530 __checkReturn __success(return != B_FALSE) boolean_t
531 efx_lic_v1v2_validate_key(
533 __in_bcount(length) caddr_t keyp,
540 _NOTE(ARGUNUSED(enp))
542 if (length < EFX_LICENSE_V1V2_HEADER_LENGTH) {
546 tlv_type = __LE_TO_CPU_16(((uint16_t *)keyp)[0]);
547 tlv_length = __LE_TO_CPU_16(((uint16_t *)keyp)[1]);
549 if (tlv_length > EFX_LICENSE_V1V2_PAYLOAD_LENGTH_MAX) {
555 if ((tlv_length + EFX_LICENSE_V1V2_HEADER_LENGTH) != length) {
574 __checkReturn efx_rc_t
575 efx_lic_v1v2_read_key(
577 __in_bcount(buffer_size)
579 __in size_t buffer_size,
580 __in uint32_t offset,
581 __in uint32_t length,
582 __out_bcount_part(key_max_size, *lengthp)
584 __in size_t key_max_size,
585 __out uint32_t *lengthp
590 _NOTE(ARGUNUSED(enp))
591 EFSYS_ASSERT(length <= (EFX_LICENSE_V1V2_PAYLOAD_LENGTH_MAX +
592 EFX_LICENSE_V1V2_HEADER_LENGTH));
594 if (key_max_size < length) {
598 memcpy(keyp, &bufferp[offset], length);
605 EFSYS_PROBE1(fail1, efx_rc_t, rc);
610 __checkReturn efx_rc_t
611 efx_lic_v1v2_write_key(
613 __in_bcount(buffer_size)
615 __in size_t buffer_size,
616 __in uint32_t offset,
617 __in_bcount(length) caddr_t keyp,
618 __in uint32_t length,
619 __out uint32_t *lengthp
624 _NOTE(ARGUNUSED(enp))
625 EFSYS_ASSERT(length <= (EFX_LICENSE_V1V2_PAYLOAD_LENGTH_MAX +
626 EFX_LICENSE_V1V2_HEADER_LENGTH));
628 /* Ensure space for terminator remains */
629 if ((offset + length) >
630 (buffer_size - EFX_LICENSE_V1V2_HEADER_LENGTH)) {
635 memcpy(bufferp + offset, keyp, length);
642 EFSYS_PROBE1(fail1, efx_rc_t, rc);
647 __checkReturn efx_rc_t
648 efx_lic_v1v2_delete_key(
650 __in_bcount(buffer_size)
652 __in size_t buffer_size,
653 __in uint32_t offset,
654 __in uint32_t length,
656 __out uint32_t *deltap
659 uint32_t move_start = offset + length;
660 uint32_t move_length = end - move_start;
662 _NOTE(ARGUNUSED(enp))
663 EFSYS_ASSERT(end <= buffer_size);
665 /* Shift everything after the key down */
666 memmove(bufferp + offset, bufferp + move_start, move_length);
673 __checkReturn efx_rc_t
674 efx_lic_v1v2_create_partition(
676 __in_bcount(buffer_size)
678 __in size_t buffer_size
681 _NOTE(ARGUNUSED(enp))
682 EFSYS_ASSERT(EFX_LICENSE_V1V2_HEADER_LENGTH <= buffer_size);
684 /* Write terminator */
685 memset(bufferp, '\0', EFX_LICENSE_V1V2_HEADER_LENGTH);
690 __checkReturn efx_rc_t
691 efx_lic_v1v2_finish_partition(
693 __in_bcount(buffer_size)
695 __in size_t buffer_size
698 _NOTE(ARGUNUSED(enp, bufferp, buffer_size))
703 #endif /* EFSYS_OPT_HUNTINGTON | EFSYS_OPT_SIENA */
706 /* V2 Licensing - used by Huntington family only. See SF-113611-TC */
708 #if EFSYS_OPT_HUNTINGTON
710 static __checkReturn efx_rc_t
711 efx_mcdi_licensed_app_state(
713 __in uint64_t app_id,
714 __out boolean_t *licensedp)
717 uint8_t payload[MAX(MC_CMD_GET_LICENSED_APP_STATE_IN_LEN,
718 MC_CMD_GET_LICENSED_APP_STATE_OUT_LEN)];
722 EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON);
724 /* V2 licensing supports 32bit app id only */
725 if ((app_id >> 32) != 0) {
730 (void) memset(payload, 0, sizeof (payload));
731 req.emr_cmd = MC_CMD_GET_LICENSED_APP_STATE;
732 req.emr_in_buf = payload;
733 req.emr_in_length = MC_CMD_GET_LICENSED_APP_STATE_IN_LEN;
734 req.emr_out_buf = payload;
735 req.emr_out_length = MC_CMD_GET_LICENSED_APP_STATE_OUT_LEN;
737 MCDI_IN_SET_DWORD(req, GET_LICENSED_APP_STATE_IN_APP_ID,
738 app_id & 0xffffffff);
740 efx_mcdi_execute(enp, &req);
742 if (req.emr_rc != 0) {
747 if (req.emr_out_length_used < MC_CMD_GET_LICENSED_APP_STATE_OUT_LEN) {
752 app_state = (MCDI_OUT_DWORD(req, GET_LICENSED_APP_STATE_OUT_STATE));
753 if (app_state != MC_CMD_GET_LICENSED_APP_STATE_OUT_NOT_LICENSED) {
756 *licensedp = B_FALSE;
766 EFSYS_PROBE1(fail1, efx_rc_t, rc);
771 static __checkReturn efx_rc_t
772 efx_mcdi_licensing_update_licenses(
776 uint8_t payload[MC_CMD_LICENSING_IN_LEN];
779 EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON);
781 (void) memset(payload, 0, sizeof (payload));
782 req.emr_cmd = MC_CMD_LICENSING;
783 req.emr_in_buf = payload;
784 req.emr_in_length = MC_CMD_LICENSING_IN_LEN;
785 req.emr_out_buf = payload;
786 req.emr_out_length = 0;
788 MCDI_IN_SET_DWORD(req, LICENSING_IN_OP,
789 MC_CMD_LICENSING_IN_OP_UPDATE_LICENSE);
791 efx_mcdi_execute(enp, &req);
793 if (req.emr_rc != 0) {
798 if (req.emr_out_length_used != 0) {
808 EFSYS_PROBE1(fail1, efx_rc_t, rc);
813 static __checkReturn efx_rc_t
814 efx_mcdi_licensing_get_key_stats(
816 __out efx_key_stats_t *eksp)
819 uint8_t payload[MAX(MC_CMD_LICENSING_IN_LEN,
820 MC_CMD_LICENSING_OUT_LEN)];
823 EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON);
825 (void) memset(payload, 0, sizeof (payload));
826 req.emr_cmd = MC_CMD_LICENSING;
827 req.emr_in_buf = payload;
828 req.emr_in_length = MC_CMD_LICENSING_IN_LEN;
829 req.emr_out_buf = payload;
830 req.emr_out_length = MC_CMD_LICENSING_OUT_LEN;
832 MCDI_IN_SET_DWORD(req, LICENSING_IN_OP,
833 MC_CMD_LICENSING_IN_OP_GET_KEY_STATS);
835 efx_mcdi_execute(enp, &req);
837 if (req.emr_rc != 0) {
842 if (req.emr_out_length_used < MC_CMD_LICENSING_OUT_LEN) {
848 MCDI_OUT_DWORD(req, LICENSING_OUT_VALID_APP_KEYS);
850 MCDI_OUT_DWORD(req, LICENSING_OUT_INVALID_APP_KEYS);
851 eksp->eks_blacklisted =
852 MCDI_OUT_DWORD(req, LICENSING_OUT_BLACKLISTED_APP_KEYS);
853 eksp->eks_unverifiable =
854 MCDI_OUT_DWORD(req, LICENSING_OUT_UNVERIFIABLE_APP_KEYS);
855 eksp->eks_wrong_node =
856 MCDI_OUT_DWORD(req, LICENSING_OUT_WRONG_NODE_APP_KEYS);
857 eksp->eks_licensed_apps_lo = 0;
858 eksp->eks_licensed_apps_hi = 0;
859 eksp->eks_licensed_features_lo = 0;
860 eksp->eks_licensed_features_hi = 0;
867 EFSYS_PROBE1(fail1, efx_rc_t, rc);
872 #endif /* EFSYS_OPT_HUNTINGTON */
874 /* V3 Licensing - used starting from Medford family. See SF-114884-SW */
876 #if EFSYS_OPT_MEDFORD
878 static __checkReturn efx_rc_t
879 efx_mcdi_licensing_v3_update_licenses(
883 uint8_t payload[MC_CMD_LICENSING_V3_IN_LEN];
886 EFSYS_ASSERT(enp->en_family == EFX_FAMILY_MEDFORD);
888 (void) memset(payload, 0, sizeof (payload));
889 req.emr_cmd = MC_CMD_LICENSING_V3;
890 req.emr_in_buf = payload;
891 req.emr_in_length = MC_CMD_LICENSING_V3_IN_LEN;
892 req.emr_out_buf = NULL;
893 req.emr_out_length = 0;
895 MCDI_IN_SET_DWORD(req, LICENSING_V3_IN_OP,
896 MC_CMD_LICENSING_V3_IN_OP_UPDATE_LICENSE);
898 efx_mcdi_execute(enp, &req);
900 if (req.emr_rc != 0) {
908 EFSYS_PROBE1(fail1, efx_rc_t, rc);
913 static __checkReturn efx_rc_t
914 efx_mcdi_licensing_v3_report_license(
916 __out efx_key_stats_t *eksp)
919 uint8_t payload[MAX(MC_CMD_LICENSING_V3_IN_LEN,
920 MC_CMD_LICENSING_V3_OUT_LEN)];
923 EFSYS_ASSERT(enp->en_family == EFX_FAMILY_MEDFORD);
925 (void) memset(payload, 0, sizeof (payload));
926 req.emr_cmd = MC_CMD_LICENSING_V3;
927 req.emr_in_buf = payload;
928 req.emr_in_length = MC_CMD_LICENSING_V3_IN_LEN;
929 req.emr_out_buf = payload;
930 req.emr_out_length = MC_CMD_LICENSING_V3_OUT_LEN;
932 MCDI_IN_SET_DWORD(req, LICENSING_V3_IN_OP,
933 MC_CMD_LICENSING_V3_IN_OP_REPORT_LICENSE);
935 efx_mcdi_execute_quiet(enp, &req);
937 if (req.emr_rc != 0) {
942 if (req.emr_out_length_used < MC_CMD_LICENSING_V3_OUT_LEN) {
948 MCDI_OUT_DWORD(req, LICENSING_V3_OUT_VALID_KEYS);
950 MCDI_OUT_DWORD(req, LICENSING_V3_OUT_INVALID_KEYS);
951 eksp->eks_blacklisted = 0;
952 eksp->eks_unverifiable =
953 MCDI_OUT_DWORD(req, LICENSING_V3_OUT_UNVERIFIABLE_KEYS);
954 eksp->eks_wrong_node =
955 MCDI_OUT_DWORD(req, LICENSING_V3_OUT_WRONG_NODE_KEYS);
956 eksp->eks_licensed_apps_lo =
957 MCDI_OUT_DWORD(req, LICENSING_V3_OUT_LICENSED_APPS_LO);
958 eksp->eks_licensed_apps_hi =
959 MCDI_OUT_DWORD(req, LICENSING_V3_OUT_LICENSED_APPS_HI);
960 eksp->eks_licensed_features_lo =
961 MCDI_OUT_DWORD(req, LICENSING_V3_OUT_LICENSED_FEATURES_LO);
962 eksp->eks_licensed_features_hi =
963 MCDI_OUT_DWORD(req, LICENSING_V3_OUT_LICENSED_FEATURES_HI);
970 EFSYS_PROBE1(fail1, efx_rc_t, rc);
975 static __checkReturn efx_rc_t
976 efx_mcdi_licensing_v3_app_state(
978 __in uint64_t app_id,
979 __out boolean_t *licensedp)
982 uint8_t payload[MAX(MC_CMD_GET_LICENSED_V3_APP_STATE_IN_LEN,
983 MC_CMD_GET_LICENSED_V3_APP_STATE_OUT_LEN)];
987 EFSYS_ASSERT(enp->en_family == EFX_FAMILY_MEDFORD);
989 (void) memset(payload, 0, sizeof (payload));
990 req.emr_cmd = MC_CMD_GET_LICENSED_V3_APP_STATE;
991 req.emr_in_buf = payload;
992 req.emr_in_length = MC_CMD_GET_LICENSED_V3_APP_STATE_IN_LEN;
993 req.emr_out_buf = payload;
994 req.emr_out_length = MC_CMD_GET_LICENSED_V3_APP_STATE_OUT_LEN;
996 MCDI_IN_SET_DWORD(req, GET_LICENSED_V3_APP_STATE_IN_APP_ID_LO,
997 app_id & 0xffffffff);
998 MCDI_IN_SET_DWORD(req, GET_LICENSED_V3_APP_STATE_IN_APP_ID_HI,
1001 efx_mcdi_execute(enp, &req);
1003 if (req.emr_rc != 0) {
1008 if (req.emr_out_length_used < MC_CMD_GET_LICENSED_V3_APP_STATE_OUT_LEN) {
1013 app_state = (MCDI_OUT_DWORD(req, GET_LICENSED_V3_APP_STATE_OUT_STATE));
1014 if (app_state != MC_CMD_GET_LICENSED_V3_APP_STATE_OUT_NOT_LICENSED) {
1015 *licensedp = B_TRUE;
1017 *licensedp = B_FALSE;
1025 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1030 static __checkReturn efx_rc_t
1031 efx_mcdi_licensing_v3_get_id(
1032 __in efx_nic_t *enp,
1033 __in size_t buffer_size,
1034 __out uint32_t *typep,
1035 __out size_t *lengthp,
1036 __out_bcount_part_opt(buffer_size, *lengthp)
1040 uint8_t payload[MAX(MC_CMD_LICENSING_GET_ID_V3_IN_LEN,
1041 MC_CMD_LICENSING_GET_ID_V3_OUT_LENMIN)];
1044 req.emr_cmd = MC_CMD_LICENSING_GET_ID_V3;
1046 if (bufferp == NULL) {
1047 /* Request id type and length only */
1048 req.emr_in_buf = bufferp;
1049 req.emr_in_length = MC_CMD_LICENSING_GET_ID_V3_IN_LEN;
1050 req.emr_out_buf = bufferp;
1051 req.emr_out_length = MC_CMD_LICENSING_GET_ID_V3_OUT_LENMIN;
1052 (void) memset(payload, 0, sizeof (payload));
1054 /* Request full buffer */
1055 req.emr_in_buf = bufferp;
1056 req.emr_in_length = MC_CMD_LICENSING_GET_ID_V3_IN_LEN;
1057 req.emr_out_buf = bufferp;
1058 req.emr_out_length = MIN(buffer_size, MC_CMD_LICENSING_GET_ID_V3_OUT_LENMAX);
1059 (void) memset(bufferp, 0, req.emr_out_length);
1062 efx_mcdi_execute_quiet(enp, &req);
1064 if (req.emr_rc != 0) {
1069 if (req.emr_out_length_used < MC_CMD_LICENSING_GET_ID_V3_OUT_LENMIN) {
1074 *typep = MCDI_OUT_DWORD(req, LICENSING_GET_ID_V3_OUT_LICENSE_TYPE);
1075 *lengthp = MCDI_OUT_DWORD(req, LICENSING_GET_ID_V3_OUT_LICENSE_ID_LENGTH);
1077 if (bufferp == NULL) {
1078 /* modify length requirements to indicate to caller the extra buffering
1079 ** needed to read the complete output.
1081 *lengthp += MC_CMD_LICENSING_GET_ID_V3_OUT_LENMIN;
1083 /* Shift ID down to start of buffer */
1085 bufferp + MC_CMD_LICENSING_GET_ID_V3_OUT_LICENSE_ID_OFST,
1087 memset(bufferp + (*lengthp), 0,
1088 MC_CMD_LICENSING_GET_ID_V3_OUT_LICENSE_ID_OFST);
1096 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1101 /* V3 format uses Huntington TLV format partition. See SF-108797-SW */
1102 #define EFX_LICENSE_V3_KEY_LENGTH_MIN (64)
1103 #define EFX_LICENSE_V3_KEY_LENGTH_MAX (160)
1105 __checkReturn efx_rc_t
1106 efx_lic_v3_find_start(
1107 __in efx_nic_t *enp,
1108 __in_bcount(buffer_size)
1110 __in size_t buffer_size,
1111 __out uint32_t *startp
1114 _NOTE(ARGUNUSED(enp))
1116 return ef10_nvram_buffer_find_item_start(bufferp, buffer_size, startp);
1119 __checkReturn efx_rc_t
1120 efx_lic_v3_find_end(
1121 __in efx_nic_t *enp,
1122 __in_bcount(buffer_size)
1124 __in size_t buffer_size,
1125 __in uint32_t offset,
1126 __out uint32_t *endp
1129 _NOTE(ARGUNUSED(enp))
1131 return ef10_nvram_buffer_find_end(bufferp, buffer_size, offset, endp);
1134 __checkReturn __success(return != B_FALSE) boolean_t
1135 efx_lic_v3_find_key(
1136 __in efx_nic_t *enp,
1137 __in_bcount(buffer_size)
1139 __in size_t buffer_size,
1140 __in uint32_t offset,
1141 __out uint32_t *startp,
1142 __out uint32_t *lengthp
1145 _NOTE(ARGUNUSED(enp))
1147 return ef10_nvram_buffer_find_item(bufferp, buffer_size,
1148 offset, startp, lengthp);
1151 __checkReturn __success(return != B_FALSE) boolean_t
1152 efx_lic_v3_validate_key(
1153 __in efx_nic_t *enp,
1154 __in_bcount(length) caddr_t keyp,
1155 __in uint32_t length
1158 /* Check key is a valid V3 key */
1162 _NOTE(ARGUNUSED(enp))
1164 if (length < EFX_LICENSE_V3_KEY_LENGTH_MIN) {
1168 if (length > EFX_LICENSE_V3_KEY_LENGTH_MAX) {
1172 key_type = ((uint8_t *)keyp)[0];
1173 key_length = ((uint8_t *)keyp)[1];
1178 if (key_length > length) {
1195 __checkReturn efx_rc_t
1196 efx_lic_v3_read_key(
1197 __in efx_nic_t *enp,
1198 __in_bcount(buffer_size)
1200 __in size_t buffer_size,
1201 __in uint32_t offset,
1202 __in uint32_t length,
1203 __out_bcount_part(key_max_size, *lengthp)
1205 __in size_t key_max_size,
1206 __out uint32_t *lengthp
1209 _NOTE(ARGUNUSED(enp))
1211 return ef10_nvram_buffer_get_item(bufferp, buffer_size,
1212 offset, length, keyp, key_max_size, lengthp);
1215 __checkReturn efx_rc_t
1216 efx_lic_v3_write_key(
1217 __in efx_nic_t *enp,
1218 __in_bcount(buffer_size)
1220 __in size_t buffer_size,
1221 __in uint32_t offset,
1222 __in_bcount(length) caddr_t keyp,
1223 __in uint32_t length,
1224 __out uint32_t *lengthp
1227 _NOTE(ARGUNUSED(enp))
1228 EFSYS_ASSERT(length <= EFX_LICENSE_V3_KEY_LENGTH_MAX);
1230 return ef10_nvram_buffer_insert_item(bufferp, buffer_size,
1231 offset, keyp, length, lengthp);
1234 __checkReturn efx_rc_t
1235 efx_lic_v3_delete_key(
1236 __in efx_nic_t *enp,
1237 __in_bcount(buffer_size)
1239 __in size_t buffer_size,
1240 __in uint32_t offset,
1241 __in uint32_t length,
1243 __out uint32_t *deltap
1248 _NOTE(ARGUNUSED(enp))
1250 if ((rc = ef10_nvram_buffer_delete_item(bufferp,
1251 buffer_size, offset, length, end)) != 0) {
1260 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1265 __checkReturn efx_rc_t
1266 efx_lic_v3_create_partition(
1267 __in efx_nic_t *enp,
1268 __in_bcount(buffer_size)
1270 __in size_t buffer_size
1275 /* Construct empty partition */
1276 if ((rc = ef10_nvram_buffer_create(enp,
1277 NVRAM_PARTITION_TYPE_LICENSE,
1278 bufferp, buffer_size)) != 0) {
1286 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1291 __checkReturn efx_rc_t
1292 efx_lic_v3_finish_partition(
1293 __in efx_nic_t *enp,
1294 __in_bcount(buffer_size)
1296 __in size_t buffer_size
1301 if ((rc = ef10_nvram_buffer_finish(bufferp,
1302 buffer_size)) != 0) {
1306 /* Validate completed partition */
1307 if ((rc = ef10_nvram_buffer_validate(enp, NVRAM_PARTITION_TYPE_LICENSE,
1308 bufferp, buffer_size)) != 0) {
1317 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1323 #endif /* EFSYS_OPT_MEDFORD */
1325 __checkReturn efx_rc_t
1327 __in efx_nic_t *enp)
1329 const efx_lic_ops_t *elop;
1330 efx_key_stats_t eks;
1333 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1334 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
1335 EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_LIC));
1337 switch (enp->en_family) {
1340 case EFX_FAMILY_SIENA:
1341 elop = &__efx_lic_v1_ops;
1343 #endif /* EFSYS_OPT_SIENA */
1345 #if EFSYS_OPT_HUNTINGTON
1346 case EFX_FAMILY_HUNTINGTON:
1347 elop = &__efx_lic_v2_ops;
1349 #endif /* EFSYS_OPT_HUNTINGTON */
1351 #if EFSYS_OPT_MEDFORD
1352 case EFX_FAMILY_MEDFORD:
1353 elop = &__efx_lic_v3_ops;
1355 #endif /* EFSYS_OPT_MEDFORD */
1363 enp->en_elop = elop;
1364 enp->en_mod_flags |= EFX_MOD_LIC;
1366 /* Probe for support */
1367 if (efx_lic_get_key_stats(enp, &eks) == 0) {
1368 enp->en_licensing_supported = B_TRUE;
1370 enp->en_licensing_supported = B_FALSE;
1376 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1381 extern __checkReturn boolean_t
1382 efx_lic_check_support(
1383 __in efx_nic_t *enp)
1385 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1386 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
1387 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1389 return enp->en_licensing_supported;
1394 __in efx_nic_t *enp)
1396 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1397 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
1398 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1400 enp->en_elop = NULL;
1401 enp->en_mod_flags &= ~EFX_MOD_LIC;
1405 __checkReturn efx_rc_t
1406 efx_lic_update_licenses(
1407 __in efx_nic_t *enp)
1409 const efx_lic_ops_t *elop = enp->en_elop;
1412 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1413 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1415 if ((rc = elop->elo_update_licenses(enp)) != 0)
1421 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1426 __checkReturn efx_rc_t
1427 efx_lic_get_key_stats(
1428 __in efx_nic_t *enp,
1429 __out efx_key_stats_t *eksp)
1431 const efx_lic_ops_t *elop = enp->en_elop;
1434 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1435 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1437 if ((rc = elop->elo_get_key_stats(enp, eksp)) != 0)
1443 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1448 __checkReturn efx_rc_t
1450 __in efx_nic_t *enp,
1451 __in uint64_t app_id,
1452 __out boolean_t *licensedp)
1454 const efx_lic_ops_t *elop = enp->en_elop;
1457 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1458 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1460 if (elop->elo_app_state == NULL)
1463 if ((rc = elop->elo_app_state(enp, app_id, licensedp)) != 0)
1469 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1474 __checkReturn efx_rc_t
1476 __in efx_nic_t *enp,
1477 __in size_t buffer_size,
1478 __out uint32_t *typep,
1479 __out size_t *lengthp,
1480 __out_opt uint8_t *bufferp
1483 const efx_lic_ops_t *elop = enp->en_elop;
1486 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1487 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1489 if (elop->elo_get_id == NULL)
1492 if ((rc = elop->elo_get_id(enp, buffer_size, typep,
1493 lengthp, bufferp)) != 0)
1499 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1504 /* Buffer management API - abstracts varying TLV format used for License partition */
1506 __checkReturn efx_rc_t
1508 __in efx_nic_t *enp,
1509 __in_bcount(buffer_size)
1511 __in size_t buffer_size,
1512 __out uint32_t *startp
1515 const efx_lic_ops_t *elop = enp->en_elop;
1518 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1519 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1521 if ((rc = elop->elo_find_start(enp, bufferp, buffer_size, startp)) != 0)
1527 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1532 __checkReturn efx_rc_t
1534 __in efx_nic_t *enp,
1535 __in_bcount(buffer_size)
1537 __in size_t buffer_size,
1538 __in uint32_t offset,
1539 __out uint32_t *endp
1542 const efx_lic_ops_t *elop = enp->en_elop;
1545 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1546 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1548 if ((rc = elop->elo_find_end(enp, bufferp, buffer_size, offset, endp)) != 0)
1554 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1559 __checkReturn __success(return != B_FALSE) boolean_t
1561 __in efx_nic_t *enp,
1562 __in_bcount(buffer_size)
1564 __in size_t buffer_size,
1565 __in uint32_t offset,
1566 __out uint32_t *startp,
1567 __out uint32_t *lengthp
1570 const efx_lic_ops_t *elop = enp->en_elop;
1572 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1573 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1575 EFSYS_ASSERT(bufferp);
1576 EFSYS_ASSERT(startp);
1577 EFSYS_ASSERT(lengthp);
1579 return (elop->elo_find_key(enp, bufferp, buffer_size, offset,
1584 /* Validate that the buffer contains a single key in a recognised format.
1585 ** An empty or terminator buffer is not accepted as a valid key.
1587 __checkReturn __success(return != B_FALSE) boolean_t
1588 efx_lic_validate_key(
1589 __in efx_nic_t *enp,
1590 __in_bcount(length) caddr_t keyp,
1591 __in uint32_t length
1594 const efx_lic_ops_t *elop = enp->en_elop;
1597 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1598 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1600 if ((rc = elop->elo_validate_key(enp, keyp, length)) == B_FALSE)
1606 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1611 __checkReturn efx_rc_t
1613 __in efx_nic_t *enp,
1614 __in_bcount(buffer_size)
1616 __in size_t buffer_size,
1617 __in uint32_t offset,
1618 __in uint32_t length,
1619 __out_bcount_part(key_max_size, *lengthp)
1621 __in size_t key_max_size,
1622 __out uint32_t *lengthp
1625 const efx_lic_ops_t *elop = enp->en_elop;
1628 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1629 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1631 if ((rc = elop->elo_read_key(enp, bufferp, buffer_size, offset,
1632 length, keyp, key_max_size, lengthp)) != 0)
1638 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1643 __checkReturn efx_rc_t
1645 __in efx_nic_t *enp,
1646 __in_bcount(buffer_size)
1648 __in size_t buffer_size,
1649 __in uint32_t offset,
1650 __in_bcount(length) caddr_t keyp,
1651 __in uint32_t length,
1652 __out uint32_t *lengthp
1655 const efx_lic_ops_t *elop = enp->en_elop;
1658 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1659 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1661 if ((rc = elop->elo_write_key(enp, bufferp, buffer_size, offset,
1662 keyp, length, lengthp)) != 0)
1668 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1673 __checkReturn efx_rc_t
1675 __in efx_nic_t *enp,
1676 __in_bcount(buffer_size)
1678 __in size_t buffer_size,
1679 __in uint32_t offset,
1680 __in uint32_t length,
1682 __out uint32_t *deltap
1685 const efx_lic_ops_t *elop = enp->en_elop;
1688 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1689 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1691 if ((rc = elop->elo_delete_key(enp, bufferp, buffer_size, offset,
1692 length, end, deltap)) != 0)
1698 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1703 __checkReturn efx_rc_t
1704 efx_lic_create_partition(
1705 __in efx_nic_t *enp,
1706 __in_bcount(buffer_size)
1708 __in size_t buffer_size
1711 const efx_lic_ops_t *elop = enp->en_elop;
1714 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1715 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1717 if ((rc = elop->elo_create_partition(enp, bufferp, buffer_size)) != 0)
1723 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1729 __checkReturn efx_rc_t
1730 efx_lic_finish_partition(
1731 __in efx_nic_t *enp,
1732 __in_bcount(buffer_size)
1734 __in size_t buffer_size
1737 const efx_lic_ops_t *elop = enp->en_elop;
1740 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1741 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1743 if ((rc = elop->elo_finish_partition(enp, bufferp, buffer_size)) != 0)
1749 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1754 #endif /* EFSYS_OPT_LICENSING */