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);
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, MC_CMD_LICENSING_GET_ID_V3_OUT_LICENSE_ID_OFST);
1095 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1100 /* V3 format uses Huntington TLV format partition. See SF-108797-SW */
1101 #define EFX_LICENSE_V3_KEY_LENGTH_MIN (64)
1102 #define EFX_LICENSE_V3_KEY_LENGTH_MAX (160)
1104 __checkReturn efx_rc_t
1105 efx_lic_v3_find_start(
1106 __in efx_nic_t *enp,
1107 __in_bcount(buffer_size)
1109 __in size_t buffer_size,
1110 __out uint32_t *startp
1113 _NOTE(ARGUNUSED(enp))
1115 return ef10_nvram_buffer_find_item_start(bufferp, buffer_size, startp);
1118 __checkReturn efx_rc_t
1119 efx_lic_v3_find_end(
1120 __in efx_nic_t *enp,
1121 __in_bcount(buffer_size)
1123 __in size_t buffer_size,
1124 __in uint32_t offset,
1125 __out uint32_t *endp
1128 _NOTE(ARGUNUSED(enp))
1130 return ef10_nvram_buffer_find_end(bufferp, buffer_size, offset, endp);
1133 __checkReturn __success(return != B_FALSE) boolean_t
1134 efx_lic_v3_find_key(
1135 __in efx_nic_t *enp,
1136 __in_bcount(buffer_size)
1138 __in size_t buffer_size,
1139 __in uint32_t offset,
1140 __out uint32_t *startp,
1141 __out uint32_t *lengthp
1144 _NOTE(ARGUNUSED(enp))
1146 return ef10_nvram_buffer_find_item(bufferp, buffer_size,
1147 offset, startp, lengthp);
1150 __checkReturn __success(return != B_FALSE) boolean_t
1151 efx_lic_v3_validate_key(
1152 __in efx_nic_t *enp,
1153 __in_bcount(length) caddr_t keyp,
1154 __in uint32_t length
1157 // Check key is a valid V3 key
1161 _NOTE(ARGUNUSED(enp))
1163 if (length < EFX_LICENSE_V3_KEY_LENGTH_MIN) {
1167 if (length > EFX_LICENSE_V3_KEY_LENGTH_MAX) {
1171 key_type = ((uint8_t*)keyp)[0];
1172 key_length = ((uint8_t*)keyp)[1];
1177 if (key_length > length) {
1194 __checkReturn efx_rc_t
1195 efx_lic_v3_read_key(
1196 __in efx_nic_t *enp,
1197 __in_bcount(buffer_size)
1199 __in size_t buffer_size,
1200 __in uint32_t offset,
1201 __in uint32_t length,
1202 __out_bcount_part(key_max_size, *lengthp)
1204 __in size_t key_max_size,
1205 __out uint32_t *lengthp
1208 _NOTE(ARGUNUSED(enp))
1210 return ef10_nvram_buffer_get_item(bufferp, buffer_size,
1211 offset, length, keyp, key_max_size, lengthp);
1214 __checkReturn efx_rc_t
1215 efx_lic_v3_write_key(
1216 __in efx_nic_t *enp,
1217 __in_bcount(buffer_size)
1219 __in size_t buffer_size,
1220 __in uint32_t offset,
1221 __in_bcount(length) caddr_t keyp,
1222 __in uint32_t length,
1223 __out uint32_t *lengthp
1226 _NOTE(ARGUNUSED(enp))
1227 EFSYS_ASSERT(length <= EFX_LICENSE_V3_KEY_LENGTH_MAX);
1229 return ef10_nvram_buffer_insert_item(bufferp, buffer_size,
1230 offset, keyp, length, lengthp);
1233 __checkReturn efx_rc_t
1234 efx_lic_v3_delete_key(
1235 __in efx_nic_t *enp,
1236 __in_bcount(buffer_size)
1238 __in size_t buffer_size,
1239 __in uint32_t offset,
1240 __in uint32_t length,
1242 __out uint32_t *deltap
1247 _NOTE(ARGUNUSED(enp))
1249 if ((rc = ef10_nvram_buffer_delete_item(bufferp,
1250 buffer_size, offset, length, end)) != 0) {
1259 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1264 __checkReturn efx_rc_t
1265 efx_lic_v3_create_partition(
1266 __in efx_nic_t *enp,
1267 __in_bcount(buffer_size)
1269 __in size_t buffer_size
1274 // Construct empty partition
1275 if ((rc = ef10_nvram_buffer_create(enp,
1276 NVRAM_PARTITION_TYPE_LICENSE,
1277 bufferp, buffer_size)) != 0) {
1285 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1290 __checkReturn efx_rc_t
1291 efx_lic_v3_finish_partition(
1292 __in efx_nic_t *enp,
1293 __in_bcount(buffer_size)
1295 __in size_t buffer_size
1300 if ((rc = ef10_nvram_buffer_finish(bufferp,
1301 buffer_size)) != 0) {
1305 // Validate completed partition
1306 if ((rc = ef10_nvram_buffer_validate(enp, NVRAM_PARTITION_TYPE_LICENSE,
1307 bufferp, buffer_size)) != 0) {
1316 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1322 #endif /* EFSYS_OPT_MEDFORD */
1324 __checkReturn efx_rc_t
1326 __in efx_nic_t *enp)
1328 const efx_lic_ops_t *elop;
1329 efx_key_stats_t eks;
1332 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1333 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
1334 EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_LIC));
1336 switch (enp->en_family) {
1339 case EFX_FAMILY_SIENA:
1340 elop = &__efx_lic_v1_ops;
1342 #endif /* EFSYS_OPT_SIENA */
1344 #if EFSYS_OPT_HUNTINGTON
1345 case EFX_FAMILY_HUNTINGTON:
1346 elop = &__efx_lic_v2_ops;
1348 #endif /* EFSYS_OPT_HUNTINGTON */
1350 #if EFSYS_OPT_MEDFORD
1351 case EFX_FAMILY_MEDFORD:
1352 elop = &__efx_lic_v3_ops;
1354 #endif /* EFSYS_OPT_MEDFORD */
1362 enp->en_elop = elop;
1363 enp->en_mod_flags |= EFX_MOD_LIC;
1365 /* Probe for support */
1366 if (efx_lic_get_key_stats(enp, &eks) == 0) {
1367 enp->en_licensing_supported = B_TRUE;
1369 enp->en_licensing_supported = B_FALSE;
1375 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1380 extern __checkReturn boolean_t
1381 efx_lic_check_support(
1382 __in efx_nic_t *enp)
1384 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1385 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
1386 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1388 return enp->en_licensing_supported;
1393 __in efx_nic_t *enp)
1395 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1396 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
1397 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1399 enp->en_elop = NULL;
1400 enp->en_mod_flags &= ~EFX_MOD_LIC;
1404 __checkReturn efx_rc_t
1405 efx_lic_update_licenses(
1406 __in efx_nic_t *enp)
1408 const efx_lic_ops_t *elop = enp->en_elop;
1411 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1412 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1414 if ((rc = elop->elo_update_licenses(enp)) != 0)
1420 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1425 __checkReturn efx_rc_t
1426 efx_lic_get_key_stats(
1427 __in efx_nic_t *enp,
1428 __out efx_key_stats_t *eksp)
1430 const efx_lic_ops_t *elop = enp->en_elop;
1433 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1434 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1436 if ((rc = elop->elo_get_key_stats(enp, eksp)) != 0)
1442 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1447 __checkReturn efx_rc_t
1449 __in efx_nic_t *enp,
1450 __in uint64_t app_id,
1451 __out boolean_t *licensedp)
1453 const efx_lic_ops_t *elop = enp->en_elop;
1456 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1457 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1459 if (elop->elo_app_state == NULL)
1462 if ((rc = elop->elo_app_state(enp, app_id, licensedp)) != 0)
1468 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1473 __checkReturn efx_rc_t
1475 __in efx_nic_t *enp,
1476 __in size_t buffer_size,
1477 __out uint32_t *typep,
1478 __out size_t *lengthp,
1479 __out_opt uint8_t *bufferp
1482 const efx_lic_ops_t *elop = enp->en_elop;
1485 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1486 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1488 if (elop->elo_get_id == NULL)
1491 if ((rc = elop->elo_get_id(enp, buffer_size, typep,
1492 lengthp, bufferp)) != 0)
1498 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1503 /* Buffer management API - abstracts varying TLV format used for License partition */
1505 __checkReturn efx_rc_t
1507 __in efx_nic_t *enp,
1508 __in_bcount(buffer_size)
1510 __in size_t buffer_size,
1511 __out uint32_t *startp
1514 const efx_lic_ops_t *elop = enp->en_elop;
1517 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1518 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1520 if ((rc = elop->elo_find_start(enp, bufferp, buffer_size, startp)) != 0)
1526 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1531 __checkReturn efx_rc_t
1533 __in efx_nic_t *enp,
1534 __in_bcount(buffer_size)
1536 __in size_t buffer_size,
1537 __in uint32_t offset,
1538 __out uint32_t *endp
1541 const efx_lic_ops_t *elop = enp->en_elop;
1544 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1545 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1547 if ((rc = elop->elo_find_end(enp, bufferp, buffer_size, offset, endp)) != 0)
1553 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1558 __checkReturn __success(return != B_FALSE) boolean_t
1560 __in efx_nic_t *enp,
1561 __in_bcount(buffer_size)
1563 __in size_t buffer_size,
1564 __in uint32_t offset,
1565 __out uint32_t *startp,
1566 __out uint32_t *lengthp
1569 const efx_lic_ops_t *elop = enp->en_elop;
1571 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1572 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1574 EFSYS_ASSERT(bufferp);
1575 EFSYS_ASSERT(startp);
1576 EFSYS_ASSERT(lengthp);
1578 return (elop->elo_find_key(enp, bufferp, buffer_size, offset,
1583 /* Validate that the buffer contains a single key in a recognised format.
1584 ** An empty or terminator buffer is not accepted as a valid key.
1586 __checkReturn __success(return != B_FALSE) boolean_t
1587 efx_lic_validate_key(
1588 __in efx_nic_t *enp,
1589 __in_bcount(length) caddr_t keyp,
1590 __in uint32_t length
1593 const efx_lic_ops_t *elop = enp->en_elop;
1596 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1597 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1599 if ((rc = elop->elo_validate_key(enp, keyp, length)) == B_FALSE)
1605 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1610 __checkReturn efx_rc_t
1612 __in efx_nic_t *enp,
1613 __in_bcount(buffer_size)
1615 __in size_t buffer_size,
1616 __in uint32_t offset,
1617 __in uint32_t length,
1618 __out_bcount_part(key_max_size, *lengthp)
1620 __in size_t key_max_size,
1621 __out uint32_t *lengthp
1624 const efx_lic_ops_t *elop = enp->en_elop;
1627 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1628 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1630 if ((rc = elop->elo_read_key(enp, bufferp, buffer_size, offset,
1631 length, keyp, key_max_size, lengthp)) != 0)
1637 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1642 __checkReturn efx_rc_t
1644 __in efx_nic_t *enp,
1645 __in_bcount(buffer_size)
1647 __in size_t buffer_size,
1648 __in uint32_t offset,
1649 __in_bcount(length) caddr_t keyp,
1650 __in uint32_t length,
1651 __out uint32_t *lengthp
1654 const efx_lic_ops_t *elop = enp->en_elop;
1657 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1658 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1660 if ((rc = elop->elo_write_key(enp, bufferp, buffer_size, offset,
1661 keyp, length, lengthp)) != 0)
1667 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1672 __checkReturn efx_rc_t
1674 __in efx_nic_t *enp,
1675 __in_bcount(buffer_size)
1677 __in size_t buffer_size,
1678 __in uint32_t offset,
1679 __in uint32_t length,
1681 __out uint32_t *deltap
1684 const efx_lic_ops_t *elop = enp->en_elop;
1687 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1688 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1690 if ((rc = elop->elo_delete_key(enp, bufferp, buffer_size, offset,
1691 length, end, deltap)) != 0)
1697 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1702 __checkReturn efx_rc_t
1703 efx_lic_create_partition(
1704 __in efx_nic_t *enp,
1705 __in_bcount(buffer_size)
1707 __in size_t buffer_size
1710 const efx_lic_ops_t *elop = enp->en_elop;
1713 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1714 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1716 if ((rc = elop->elo_create_partition(enp, bufferp, buffer_size)) != 0)
1722 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1728 __checkReturn efx_rc_t
1729 efx_lic_finish_partition(
1730 __in efx_nic_t *enp,
1731 __in_bcount(buffer_size)
1733 __in size_t buffer_size
1736 const efx_lic_ops_t *elop = enp->en_elop;
1739 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1740 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1742 if ((rc = elop->elo_finish_partition(enp, bufferp, buffer_size)) != 0)
1748 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1753 #endif /* EFSYS_OPT_LICENSING */