1 /* SPDX-License-Identifier: BSD-3-Clause
3 * Copyright (c) 2009-2018 Solarflare Communications Inc.
10 #if EFSYS_OPT_LICENSING
12 #include "ef10_tlv_layout.h"
14 #if EFSYS_OPT_SIENA | EFSYS_OPT_HUNTINGTON
16 __checkReturn efx_rc_t
17 efx_lic_v1v2_find_start(
19 __in_bcount(buffer_size)
21 __in size_t buffer_size,
22 __out uint32_t *startp);
24 __checkReturn efx_rc_t
25 efx_lic_v1v2_find_end(
27 __in_bcount(buffer_size)
29 __in size_t buffer_size,
31 __out uint32_t *endp);
33 __checkReturn __success(return != B_FALSE) boolean_t
34 efx_lic_v1v2_find_key(
36 __in_bcount(buffer_size)
38 __in size_t buffer_size,
40 __out uint32_t *startp,
41 __out uint32_t *lengthp);
43 __checkReturn __success(return != B_FALSE) boolean_t
44 efx_lic_v1v2_validate_key(
46 __in_bcount(length) caddr_t keyp,
47 __in uint32_t length);
49 __checkReturn efx_rc_t
50 efx_lic_v1v2_read_key(
52 __in_bcount(buffer_size)
54 __in size_t buffer_size,
57 __out_bcount_part(key_max_size, *lengthp)
59 __in size_t key_max_size,
60 __out uint32_t *lengthp);
62 __checkReturn efx_rc_t
63 efx_lic_v1v2_write_key(
65 __in_bcount(buffer_size)
67 __in size_t buffer_size,
69 __in_bcount(length) caddr_t keyp,
71 __out uint32_t *lengthp);
73 __checkReturn efx_rc_t
74 efx_lic_v1v2_delete_key(
76 __in_bcount(buffer_size)
78 __in size_t buffer_size,
82 __out uint32_t *deltap);
84 __checkReturn efx_rc_t
85 efx_lic_v1v2_create_partition(
87 __in_bcount(buffer_size)
89 __in size_t buffer_size);
91 __checkReturn efx_rc_t
92 efx_lic_v1v2_finish_partition(
94 __in_bcount(buffer_size)
96 __in size_t buffer_size);
98 #endif /* EFSYS_OPT_HUNTINGTON | EFSYS_OPT_SIENA */
103 static __checkReturn efx_rc_t
104 efx_mcdi_fc_license_update_license(
105 __in efx_nic_t *enp);
107 static __checkReturn efx_rc_t
108 efx_mcdi_fc_license_get_key_stats(
110 __out efx_key_stats_t *eksp);
112 static const efx_lic_ops_t __efx_lic_v1_ops = {
113 efx_mcdi_fc_license_update_license, /* elo_update_licenses */
114 efx_mcdi_fc_license_get_key_stats, /* elo_get_key_stats */
115 NULL, /* elo_app_state */
116 NULL, /* elo_get_id */
117 efx_lic_v1v2_find_start, /* elo_find_start */
118 efx_lic_v1v2_find_end, /* elo_find_end */
119 efx_lic_v1v2_find_key, /* elo_find_key */
120 efx_lic_v1v2_validate_key, /* elo_validate_key */
121 efx_lic_v1v2_read_key, /* elo_read_key */
122 efx_lic_v1v2_write_key, /* elo_write_key */
123 efx_lic_v1v2_delete_key, /* elo_delete_key */
124 efx_lic_v1v2_create_partition, /* elo_create_partition */
125 efx_lic_v1v2_finish_partition, /* elo_finish_partition */
128 #endif /* EFSYS_OPT_SIENA */
130 #if EFSYS_OPT_HUNTINGTON
132 static __checkReturn efx_rc_t
133 efx_mcdi_licensing_update_licenses(
134 __in efx_nic_t *enp);
136 static __checkReturn efx_rc_t
137 efx_mcdi_licensing_get_key_stats(
139 __out efx_key_stats_t *eksp);
141 static __checkReturn efx_rc_t
142 efx_mcdi_licensed_app_state(
144 __in uint64_t app_id,
145 __out boolean_t *licensedp);
147 static const efx_lic_ops_t __efx_lic_v2_ops = {
148 efx_mcdi_licensing_update_licenses, /* elo_update_licenses */
149 efx_mcdi_licensing_get_key_stats, /* elo_get_key_stats */
150 efx_mcdi_licensed_app_state, /* elo_app_state */
151 NULL, /* elo_get_id */
152 efx_lic_v1v2_find_start, /* elo_find_start */
153 efx_lic_v1v2_find_end, /* elo_find_end */
154 efx_lic_v1v2_find_key, /* elo_find_key */
155 efx_lic_v1v2_validate_key, /* elo_validate_key */
156 efx_lic_v1v2_read_key, /* elo_read_key */
157 efx_lic_v1v2_write_key, /* elo_write_key */
158 efx_lic_v1v2_delete_key, /* elo_delete_key */
159 efx_lic_v1v2_create_partition, /* elo_create_partition */
160 efx_lic_v1v2_finish_partition, /* elo_finish_partition */
163 #endif /* EFSYS_OPT_HUNTINGTON */
165 #if EFSYS_OPT_MEDFORD
167 static __checkReturn efx_rc_t
168 efx_mcdi_licensing_v3_update_licenses(
169 __in efx_nic_t *enp);
171 static __checkReturn efx_rc_t
172 efx_mcdi_licensing_v3_report_license(
174 __out efx_key_stats_t *eksp);
176 static __checkReturn efx_rc_t
177 efx_mcdi_licensing_v3_app_state(
179 __in uint64_t app_id,
180 __out boolean_t *licensedp);
182 static __checkReturn efx_rc_t
183 efx_mcdi_licensing_v3_get_id(
185 __in size_t buffer_size,
186 __out uint32_t *typep,
187 __out size_t *lengthp,
188 __out_bcount_part_opt(buffer_size, *lengthp)
191 __checkReturn efx_rc_t
192 efx_lic_v3_find_start(
194 __in_bcount(buffer_size)
196 __in size_t buffer_size,
197 __out uint32_t *startp);
199 __checkReturn efx_rc_t
202 __in_bcount(buffer_size)
204 __in size_t buffer_size,
205 __in uint32_t offset,
206 __out uint32_t *endp);
208 __checkReturn __success(return != B_FALSE) boolean_t
211 __in_bcount(buffer_size)
213 __in size_t buffer_size,
214 __in uint32_t offset,
215 __out uint32_t *startp,
216 __out uint32_t *lengthp);
218 __checkReturn __success(return != B_FALSE) boolean_t
219 efx_lic_v3_validate_key(
221 __in_bcount(length) caddr_t keyp,
222 __in uint32_t length);
224 __checkReturn efx_rc_t
227 __in_bcount(buffer_size)
229 __in size_t buffer_size,
230 __in uint32_t offset,
231 __in uint32_t length,
232 __out_bcount_part(key_max_size, *lengthp)
234 __in size_t key_max_size,
235 __out uint32_t *lengthp);
237 __checkReturn efx_rc_t
238 efx_lic_v3_write_key(
240 __in_bcount(buffer_size)
242 __in size_t buffer_size,
243 __in uint32_t offset,
244 __in_bcount(length) caddr_t keyp,
245 __in uint32_t length,
246 __out uint32_t *lengthp);
248 __checkReturn efx_rc_t
249 efx_lic_v3_delete_key(
251 __in_bcount(buffer_size)
253 __in size_t buffer_size,
254 __in uint32_t offset,
255 __in uint32_t length,
257 __out uint32_t *deltap);
259 __checkReturn efx_rc_t
260 efx_lic_v3_create_partition(
262 __in_bcount(buffer_size)
264 __in size_t buffer_size);
266 __checkReturn efx_rc_t
267 efx_lic_v3_finish_partition(
269 __in_bcount(buffer_size)
271 __in size_t buffer_size);
273 static const efx_lic_ops_t __efx_lic_v3_ops = {
274 efx_mcdi_licensing_v3_update_licenses, /* elo_update_licenses */
275 efx_mcdi_licensing_v3_report_license, /* elo_get_key_stats */
276 efx_mcdi_licensing_v3_app_state, /* elo_app_state */
277 efx_mcdi_licensing_v3_get_id, /* elo_get_id */
278 efx_lic_v3_find_start, /* elo_find_start */
279 efx_lic_v3_find_end, /* elo_find_end */
280 efx_lic_v3_find_key, /* elo_find_key */
281 efx_lic_v3_validate_key, /* elo_validate_key */
282 efx_lic_v3_read_key, /* elo_read_key */
283 efx_lic_v3_write_key, /* elo_write_key */
284 efx_lic_v3_delete_key, /* elo_delete_key */
285 efx_lic_v3_create_partition, /* elo_create_partition */
286 efx_lic_v3_finish_partition, /* elo_finish_partition */
289 #endif /* EFSYS_OPT_MEDFORD */
292 /* V1 Licensing - used in Siena Modena only */
296 static __checkReturn efx_rc_t
297 efx_mcdi_fc_license_update_license(
301 uint8_t payload[MC_CMD_FC_IN_LICENSE_LEN];
304 EFSYS_ASSERT(enp->en_family == EFX_FAMILY_SIENA);
306 (void) memset(payload, 0, sizeof (payload));
307 req.emr_cmd = MC_CMD_FC;
308 req.emr_in_buf = payload;
309 req.emr_in_length = MC_CMD_FC_IN_LICENSE_LEN;
310 req.emr_out_buf = payload;
311 req.emr_out_length = 0;
313 MCDI_IN_SET_DWORD(req, FC_IN_CMD,
314 MC_CMD_FC_OP_LICENSE);
316 MCDI_IN_SET_DWORD(req, FC_IN_LICENSE_OP,
317 MC_CMD_FC_IN_LICENSE_UPDATE_LICENSE);
319 efx_mcdi_execute(enp, &req);
321 if (req.emr_rc != 0) {
326 if (req.emr_out_length_used != 0) {
336 EFSYS_PROBE1(fail1, efx_rc_t, rc);
341 static __checkReturn efx_rc_t
342 efx_mcdi_fc_license_get_key_stats(
344 __out efx_key_stats_t *eksp)
347 uint8_t payload[MAX(MC_CMD_FC_IN_LICENSE_LEN,
348 MC_CMD_FC_OUT_LICENSE_LEN)];
351 EFSYS_ASSERT(enp->en_family == EFX_FAMILY_SIENA);
353 (void) memset(payload, 0, sizeof (payload));
354 req.emr_cmd = MC_CMD_FC;
355 req.emr_in_buf = payload;
356 req.emr_in_length = MC_CMD_FC_IN_LICENSE_LEN;
357 req.emr_out_buf = payload;
358 req.emr_out_length = MC_CMD_FC_OUT_LICENSE_LEN;
360 MCDI_IN_SET_DWORD(req, FC_IN_CMD,
361 MC_CMD_FC_OP_LICENSE);
363 MCDI_IN_SET_DWORD(req, FC_IN_LICENSE_OP,
364 MC_CMD_FC_IN_LICENSE_GET_KEY_STATS);
366 efx_mcdi_execute_quiet(enp, &req);
368 if (req.emr_rc != 0) {
373 if (req.emr_out_length_used < MC_CMD_FC_OUT_LICENSE_LEN) {
379 MCDI_OUT_DWORD(req, FC_OUT_LICENSE_VALID_KEYS);
381 MCDI_OUT_DWORD(req, FC_OUT_LICENSE_INVALID_KEYS);
382 eksp->eks_blacklisted =
383 MCDI_OUT_DWORD(req, FC_OUT_LICENSE_BLACKLISTED_KEYS);
384 eksp->eks_unverifiable = 0;
385 eksp->eks_wrong_node = 0;
386 eksp->eks_licensed_apps_lo = 0;
387 eksp->eks_licensed_apps_hi = 0;
388 eksp->eks_licensed_features_lo = 0;
389 eksp->eks_licensed_features_hi = 0;
396 EFSYS_PROBE1(fail1, efx_rc_t, rc);
401 #endif /* EFSYS_OPT_SIENA */
403 /* V1 and V2 Partition format - based on a 16-bit TLV format */
405 #if EFSYS_OPT_SIENA | EFSYS_OPT_HUNTINGTON
408 * V1/V2 format - defined in SF-108542-TC section 4.2:
409 * Type (T): 16bit - revision/HMAC algorithm
410 * Length (L): 16bit - value length in bytes
411 * Value (V): L bytes - payload
413 #define EFX_LICENSE_V1V2_PAYLOAD_LENGTH_MAX (256)
414 #define EFX_LICENSE_V1V2_HEADER_LENGTH (2 * sizeof (uint16_t))
416 __checkReturn efx_rc_t
417 efx_lic_v1v2_find_start(
419 __in_bcount(buffer_size)
421 __in size_t buffer_size,
422 __out uint32_t *startp)
424 _NOTE(ARGUNUSED(enp, bufferp, buffer_size))
430 __checkReturn efx_rc_t
431 efx_lic_v1v2_find_end(
433 __in_bcount(buffer_size)
435 __in size_t buffer_size,
436 __in uint32_t offset,
437 __out uint32_t *endp)
439 _NOTE(ARGUNUSED(enp, bufferp, buffer_size))
441 *endp = offset + EFX_LICENSE_V1V2_HEADER_LENGTH;
445 __checkReturn __success(return != B_FALSE) boolean_t
446 efx_lic_v1v2_find_key(
448 __in_bcount(buffer_size)
450 __in size_t buffer_size,
451 __in uint32_t offset,
452 __out uint32_t *startp,
453 __out uint32_t *lengthp)
459 _NOTE(ARGUNUSED(enp))
461 if ((size_t)buffer_size - offset < EFX_LICENSE_V1V2_HEADER_LENGTH)
464 tlv_type = __LE_TO_CPU_16(((uint16_t *)&bufferp[offset])[0]);
465 tlv_length = __LE_TO_CPU_16(((uint16_t *)&bufferp[offset])[1]);
466 if ((tlv_length > EFX_LICENSE_V1V2_PAYLOAD_LENGTH_MAX) ||
467 (tlv_type == 0 && tlv_length == 0)) {
471 *lengthp = tlv_length + EFX_LICENSE_V1V2_HEADER_LENGTH;
477 EFSYS_PROBE1(fail1, boolean_t, B_FALSE);
482 __checkReturn __success(return != B_FALSE) boolean_t
483 efx_lic_v1v2_validate_key(
485 __in_bcount(length) caddr_t keyp,
486 __in uint32_t length)
491 _NOTE(ARGUNUSED(enp))
493 if (length < EFX_LICENSE_V1V2_HEADER_LENGTH) {
497 tlv_type = __LE_TO_CPU_16(((uint16_t *)keyp)[0]);
498 tlv_length = __LE_TO_CPU_16(((uint16_t *)keyp)[1]);
500 if (tlv_length > EFX_LICENSE_V1V2_PAYLOAD_LENGTH_MAX) {
506 if ((tlv_length + EFX_LICENSE_V1V2_HEADER_LENGTH) != length) {
519 EFSYS_PROBE1(fail1, boolean_t, B_FALSE);
525 __checkReturn efx_rc_t
526 efx_lic_v1v2_read_key(
528 __in_bcount(buffer_size)
530 __in size_t buffer_size,
531 __in uint32_t offset,
532 __in uint32_t length,
533 __out_bcount_part(key_max_size, *lengthp)
535 __in size_t key_max_size,
536 __out uint32_t *lengthp)
540 _NOTE(ARGUNUSED(enp, buffer_size))
541 EFSYS_ASSERT(length <= (EFX_LICENSE_V1V2_PAYLOAD_LENGTH_MAX +
542 EFX_LICENSE_V1V2_HEADER_LENGTH));
544 if (key_max_size < length) {
548 memcpy(keyp, &bufferp[offset], length);
555 EFSYS_PROBE1(fail1, efx_rc_t, rc);
560 __checkReturn efx_rc_t
561 efx_lic_v1v2_write_key(
563 __in_bcount(buffer_size)
565 __in size_t buffer_size,
566 __in uint32_t offset,
567 __in_bcount(length) caddr_t keyp,
568 __in uint32_t length,
569 __out uint32_t *lengthp)
573 _NOTE(ARGUNUSED(enp))
574 EFSYS_ASSERT(length <= (EFX_LICENSE_V1V2_PAYLOAD_LENGTH_MAX +
575 EFX_LICENSE_V1V2_HEADER_LENGTH));
577 /* Ensure space for terminator remains */
578 if ((offset + length) >
579 (buffer_size - EFX_LICENSE_V1V2_HEADER_LENGTH)) {
584 memcpy(bufferp + offset, keyp, length);
591 EFSYS_PROBE1(fail1, efx_rc_t, rc);
596 __checkReturn efx_rc_t
597 efx_lic_v1v2_delete_key(
599 __in_bcount(buffer_size)
601 __in size_t buffer_size,
602 __in uint32_t offset,
603 __in uint32_t length,
605 __out uint32_t *deltap)
607 uint32_t move_start = offset + length;
608 uint32_t move_length = end - move_start;
610 _NOTE(ARGUNUSED(enp, buffer_size))
611 EFSYS_ASSERT(end <= buffer_size);
613 /* Shift everything after the key down */
614 memmove(bufferp + offset, bufferp + move_start, move_length);
621 __checkReturn efx_rc_t
622 efx_lic_v1v2_create_partition(
624 __in_bcount(buffer_size)
626 __in size_t buffer_size)
628 _NOTE(ARGUNUSED(enp, buffer_size))
629 EFSYS_ASSERT(EFX_LICENSE_V1V2_HEADER_LENGTH <= buffer_size);
631 /* Write terminator */
632 memset(bufferp, '\0', EFX_LICENSE_V1V2_HEADER_LENGTH);
637 __checkReturn efx_rc_t
638 efx_lic_v1v2_finish_partition(
640 __in_bcount(buffer_size)
642 __in size_t buffer_size)
644 _NOTE(ARGUNUSED(enp, bufferp, buffer_size))
649 #endif /* EFSYS_OPT_HUNTINGTON | EFSYS_OPT_SIENA */
652 /* V2 Licensing - used by Huntington family only. See SF-113611-TC */
654 #if EFSYS_OPT_HUNTINGTON
656 static __checkReturn efx_rc_t
657 efx_mcdi_licensed_app_state(
659 __in uint64_t app_id,
660 __out boolean_t *licensedp)
663 uint8_t payload[MAX(MC_CMD_GET_LICENSED_APP_STATE_IN_LEN,
664 MC_CMD_GET_LICENSED_APP_STATE_OUT_LEN)];
668 EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON);
670 /* V2 licensing supports 32bit app id only */
671 if ((app_id >> 32) != 0) {
676 (void) memset(payload, 0, sizeof (payload));
677 req.emr_cmd = MC_CMD_GET_LICENSED_APP_STATE;
678 req.emr_in_buf = payload;
679 req.emr_in_length = MC_CMD_GET_LICENSED_APP_STATE_IN_LEN;
680 req.emr_out_buf = payload;
681 req.emr_out_length = MC_CMD_GET_LICENSED_APP_STATE_OUT_LEN;
683 MCDI_IN_SET_DWORD(req, GET_LICENSED_APP_STATE_IN_APP_ID,
684 app_id & 0xffffffff);
686 efx_mcdi_execute(enp, &req);
688 if (req.emr_rc != 0) {
693 if (req.emr_out_length_used < MC_CMD_GET_LICENSED_APP_STATE_OUT_LEN) {
698 app_state = (MCDI_OUT_DWORD(req, GET_LICENSED_APP_STATE_OUT_STATE));
699 if (app_state != MC_CMD_GET_LICENSED_APP_STATE_OUT_NOT_LICENSED) {
702 *licensedp = B_FALSE;
712 EFSYS_PROBE1(fail1, efx_rc_t, rc);
717 static __checkReturn efx_rc_t
718 efx_mcdi_licensing_update_licenses(
722 uint8_t payload[MC_CMD_LICENSING_IN_LEN];
725 EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON);
727 (void) memset(payload, 0, sizeof (payload));
728 req.emr_cmd = MC_CMD_LICENSING;
729 req.emr_in_buf = payload;
730 req.emr_in_length = MC_CMD_LICENSING_IN_LEN;
731 req.emr_out_buf = payload;
732 req.emr_out_length = 0;
734 MCDI_IN_SET_DWORD(req, LICENSING_IN_OP,
735 MC_CMD_LICENSING_IN_OP_UPDATE_LICENSE);
737 efx_mcdi_execute(enp, &req);
739 if (req.emr_rc != 0) {
744 if (req.emr_out_length_used != 0) {
754 EFSYS_PROBE1(fail1, efx_rc_t, rc);
759 static __checkReturn efx_rc_t
760 efx_mcdi_licensing_get_key_stats(
762 __out efx_key_stats_t *eksp)
765 uint8_t payload[MAX(MC_CMD_LICENSING_IN_LEN,
766 MC_CMD_LICENSING_OUT_LEN)];
769 EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON);
771 (void) memset(payload, 0, sizeof (payload));
772 req.emr_cmd = MC_CMD_LICENSING;
773 req.emr_in_buf = payload;
774 req.emr_in_length = MC_CMD_LICENSING_IN_LEN;
775 req.emr_out_buf = payload;
776 req.emr_out_length = MC_CMD_LICENSING_OUT_LEN;
778 MCDI_IN_SET_DWORD(req, LICENSING_IN_OP,
779 MC_CMD_LICENSING_IN_OP_GET_KEY_STATS);
781 efx_mcdi_execute(enp, &req);
783 if (req.emr_rc != 0) {
788 if (req.emr_out_length_used < MC_CMD_LICENSING_OUT_LEN) {
794 MCDI_OUT_DWORD(req, LICENSING_OUT_VALID_APP_KEYS);
796 MCDI_OUT_DWORD(req, LICENSING_OUT_INVALID_APP_KEYS);
797 eksp->eks_blacklisted =
798 MCDI_OUT_DWORD(req, LICENSING_OUT_BLACKLISTED_APP_KEYS);
799 eksp->eks_unverifiable =
800 MCDI_OUT_DWORD(req, LICENSING_OUT_UNVERIFIABLE_APP_KEYS);
801 eksp->eks_wrong_node =
802 MCDI_OUT_DWORD(req, LICENSING_OUT_WRONG_NODE_APP_KEYS);
803 eksp->eks_licensed_apps_lo = 0;
804 eksp->eks_licensed_apps_hi = 0;
805 eksp->eks_licensed_features_lo = 0;
806 eksp->eks_licensed_features_hi = 0;
813 EFSYS_PROBE1(fail1, efx_rc_t, rc);
818 #endif /* EFSYS_OPT_HUNTINGTON */
820 /* V3 Licensing - used starting from Medford family. See SF-114884-SW */
822 #if EFSYS_OPT_MEDFORD
824 static __checkReturn efx_rc_t
825 efx_mcdi_licensing_v3_update_licenses(
829 uint8_t payload[MC_CMD_LICENSING_V3_IN_LEN];
832 EFSYS_ASSERT(enp->en_family == EFX_FAMILY_MEDFORD);
834 (void) memset(payload, 0, sizeof (payload));
835 req.emr_cmd = MC_CMD_LICENSING_V3;
836 req.emr_in_buf = payload;
837 req.emr_in_length = MC_CMD_LICENSING_V3_IN_LEN;
838 req.emr_out_buf = NULL;
839 req.emr_out_length = 0;
841 MCDI_IN_SET_DWORD(req, LICENSING_V3_IN_OP,
842 MC_CMD_LICENSING_V3_IN_OP_UPDATE_LICENSE);
844 efx_mcdi_execute(enp, &req);
846 if (req.emr_rc != 0) {
854 EFSYS_PROBE1(fail1, efx_rc_t, rc);
859 static __checkReturn efx_rc_t
860 efx_mcdi_licensing_v3_report_license(
862 __out efx_key_stats_t *eksp)
865 uint8_t payload[MAX(MC_CMD_LICENSING_V3_IN_LEN,
866 MC_CMD_LICENSING_V3_OUT_LEN)];
869 EFSYS_ASSERT(enp->en_family == EFX_FAMILY_MEDFORD);
871 (void) memset(payload, 0, sizeof (payload));
872 req.emr_cmd = MC_CMD_LICENSING_V3;
873 req.emr_in_buf = payload;
874 req.emr_in_length = MC_CMD_LICENSING_V3_IN_LEN;
875 req.emr_out_buf = payload;
876 req.emr_out_length = MC_CMD_LICENSING_V3_OUT_LEN;
878 MCDI_IN_SET_DWORD(req, LICENSING_V3_IN_OP,
879 MC_CMD_LICENSING_V3_IN_OP_REPORT_LICENSE);
881 efx_mcdi_execute_quiet(enp, &req);
883 if (req.emr_rc != 0) {
888 if (req.emr_out_length_used < MC_CMD_LICENSING_V3_OUT_LEN) {
894 MCDI_OUT_DWORD(req, LICENSING_V3_OUT_VALID_KEYS);
896 MCDI_OUT_DWORD(req, LICENSING_V3_OUT_INVALID_KEYS);
897 eksp->eks_blacklisted = 0;
898 eksp->eks_unverifiable =
899 MCDI_OUT_DWORD(req, LICENSING_V3_OUT_UNVERIFIABLE_KEYS);
900 eksp->eks_wrong_node =
901 MCDI_OUT_DWORD(req, LICENSING_V3_OUT_WRONG_NODE_KEYS);
902 eksp->eks_licensed_apps_lo =
903 MCDI_OUT_DWORD(req, LICENSING_V3_OUT_LICENSED_APPS_LO);
904 eksp->eks_licensed_apps_hi =
905 MCDI_OUT_DWORD(req, LICENSING_V3_OUT_LICENSED_APPS_HI);
906 eksp->eks_licensed_features_lo =
907 MCDI_OUT_DWORD(req, LICENSING_V3_OUT_LICENSED_FEATURES_LO);
908 eksp->eks_licensed_features_hi =
909 MCDI_OUT_DWORD(req, LICENSING_V3_OUT_LICENSED_FEATURES_HI);
916 EFSYS_PROBE1(fail1, efx_rc_t, rc);
921 static __checkReturn efx_rc_t
922 efx_mcdi_licensing_v3_app_state(
924 __in uint64_t app_id,
925 __out boolean_t *licensedp)
928 uint8_t payload[MAX(MC_CMD_GET_LICENSED_V3_APP_STATE_IN_LEN,
929 MC_CMD_GET_LICENSED_V3_APP_STATE_OUT_LEN)];
933 EFSYS_ASSERT(enp->en_family == EFX_FAMILY_MEDFORD);
935 (void) memset(payload, 0, sizeof (payload));
936 req.emr_cmd = MC_CMD_GET_LICENSED_V3_APP_STATE;
937 req.emr_in_buf = payload;
938 req.emr_in_length = MC_CMD_GET_LICENSED_V3_APP_STATE_IN_LEN;
939 req.emr_out_buf = payload;
940 req.emr_out_length = MC_CMD_GET_LICENSED_V3_APP_STATE_OUT_LEN;
942 MCDI_IN_SET_DWORD(req, GET_LICENSED_V3_APP_STATE_IN_APP_ID_LO,
943 app_id & 0xffffffff);
944 MCDI_IN_SET_DWORD(req, GET_LICENSED_V3_APP_STATE_IN_APP_ID_HI,
947 efx_mcdi_execute(enp, &req);
949 if (req.emr_rc != 0) {
954 if (req.emr_out_length_used <
955 MC_CMD_GET_LICENSED_V3_APP_STATE_OUT_LEN) {
960 app_state = (MCDI_OUT_DWORD(req, GET_LICENSED_V3_APP_STATE_OUT_STATE));
961 if (app_state != MC_CMD_GET_LICENSED_V3_APP_STATE_OUT_NOT_LICENSED) {
964 *licensedp = B_FALSE;
972 EFSYS_PROBE1(fail1, efx_rc_t, rc);
977 static __checkReturn efx_rc_t
978 efx_mcdi_licensing_v3_get_id(
980 __in size_t buffer_size,
981 __out uint32_t *typep,
982 __out size_t *lengthp,
983 __out_bcount_part_opt(buffer_size, *lengthp)
987 uint8_t payload[MAX(MC_CMD_LICENSING_GET_ID_V3_IN_LEN,
988 MC_CMD_LICENSING_GET_ID_V3_OUT_LENMIN)];
991 req.emr_cmd = MC_CMD_LICENSING_GET_ID_V3;
993 if (bufferp == NULL) {
994 /* Request id type and length only */
995 req.emr_in_buf = bufferp;
996 req.emr_in_length = MC_CMD_LICENSING_GET_ID_V3_IN_LEN;
997 req.emr_out_buf = bufferp;
998 req.emr_out_length = MC_CMD_LICENSING_GET_ID_V3_OUT_LENMIN;
999 (void) memset(payload, 0, sizeof (payload));
1001 /* Request full buffer */
1002 req.emr_in_buf = bufferp;
1003 req.emr_in_length = MC_CMD_LICENSING_GET_ID_V3_IN_LEN;
1004 req.emr_out_buf = bufferp;
1005 req.emr_out_length =
1006 MIN(buffer_size, MC_CMD_LICENSING_GET_ID_V3_OUT_LENMAX);
1007 (void) memset(bufferp, 0, req.emr_out_length);
1010 efx_mcdi_execute_quiet(enp, &req);
1012 if (req.emr_rc != 0) {
1017 if (req.emr_out_length_used < MC_CMD_LICENSING_GET_ID_V3_OUT_LENMIN) {
1022 *typep = MCDI_OUT_DWORD(req, LICENSING_GET_ID_V3_OUT_LICENSE_TYPE);
1024 MCDI_OUT_DWORD(req, LICENSING_GET_ID_V3_OUT_LICENSE_ID_LENGTH);
1026 if (bufferp == NULL) {
1028 * Modify length requirements to indicate to caller the extra
1029 * buffering needed to read the complete output.
1031 *lengthp += MC_CMD_LICENSING_GET_ID_V3_OUT_LENMIN;
1033 /* Shift ID down to start of buffer */
1035 bufferp + MC_CMD_LICENSING_GET_ID_V3_OUT_LICENSE_ID_OFST,
1037 memset(bufferp + (*lengthp), 0,
1038 MC_CMD_LICENSING_GET_ID_V3_OUT_LICENSE_ID_OFST);
1046 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1051 /* V3 format uses Huntington TLV format partition. See SF-108797-SW */
1052 #define EFX_LICENSE_V3_KEY_LENGTH_MIN (64)
1053 #define EFX_LICENSE_V3_KEY_LENGTH_MAX (160)
1055 __checkReturn efx_rc_t
1056 efx_lic_v3_find_start(
1057 __in efx_nic_t *enp,
1058 __in_bcount(buffer_size)
1060 __in size_t buffer_size,
1061 __out uint32_t *startp)
1063 _NOTE(ARGUNUSED(enp))
1065 return (ef10_nvram_buffer_find_item_start(bufferp, buffer_size,
1069 __checkReturn efx_rc_t
1070 efx_lic_v3_find_end(
1071 __in efx_nic_t *enp,
1072 __in_bcount(buffer_size)
1074 __in size_t buffer_size,
1075 __in uint32_t offset,
1076 __out uint32_t *endp)
1078 _NOTE(ARGUNUSED(enp))
1080 return (ef10_nvram_buffer_find_end(bufferp, buffer_size, offset, endp));
1083 __checkReturn __success(return != B_FALSE) boolean_t
1084 efx_lic_v3_find_key(
1085 __in efx_nic_t *enp,
1086 __in_bcount(buffer_size)
1088 __in size_t buffer_size,
1089 __in uint32_t offset,
1090 __out uint32_t *startp,
1091 __out uint32_t *lengthp)
1093 _NOTE(ARGUNUSED(enp))
1095 return ef10_nvram_buffer_find_item(bufferp, buffer_size,
1096 offset, startp, lengthp);
1099 __checkReturn __success(return != B_FALSE) boolean_t
1100 efx_lic_v3_validate_key(
1101 __in efx_nic_t *enp,
1102 __in_bcount(length) caddr_t keyp,
1103 __in uint32_t length)
1105 /* Check key is a valid V3 key */
1109 _NOTE(ARGUNUSED(enp))
1111 if (length < EFX_LICENSE_V3_KEY_LENGTH_MIN) {
1115 if (length > EFX_LICENSE_V3_KEY_LENGTH_MAX) {
1119 key_type = ((uint8_t *)keyp)[0];
1120 key_length = ((uint8_t *)keyp)[1];
1125 if (key_length > length) {
1137 EFSYS_PROBE1(fail1, boolean_t, B_FALSE);
1142 __checkReturn efx_rc_t
1143 efx_lic_v3_read_key(
1144 __in efx_nic_t *enp,
1145 __in_bcount(buffer_size)
1147 __in size_t buffer_size,
1148 __in uint32_t offset,
1149 __in uint32_t length,
1150 __out_bcount_part(key_max_size, *lengthp)
1152 __in size_t key_max_size,
1153 __out uint32_t *lengthp)
1155 _NOTE(ARGUNUSED(enp))
1157 return ef10_nvram_buffer_get_item(bufferp, buffer_size,
1158 offset, length, keyp, key_max_size, lengthp);
1161 __checkReturn efx_rc_t
1162 efx_lic_v3_write_key(
1163 __in efx_nic_t *enp,
1164 __in_bcount(buffer_size)
1166 __in size_t buffer_size,
1167 __in uint32_t offset,
1168 __in_bcount(length) caddr_t keyp,
1169 __in uint32_t length,
1170 __out uint32_t *lengthp)
1172 _NOTE(ARGUNUSED(enp))
1173 EFSYS_ASSERT(length <= EFX_LICENSE_V3_KEY_LENGTH_MAX);
1175 return ef10_nvram_buffer_insert_item(bufferp, buffer_size,
1176 offset, keyp, length, lengthp);
1179 __checkReturn efx_rc_t
1180 efx_lic_v3_delete_key(
1181 __in efx_nic_t *enp,
1182 __in_bcount(buffer_size)
1184 __in size_t buffer_size,
1185 __in uint32_t offset,
1186 __in uint32_t length,
1188 __out uint32_t *deltap)
1192 _NOTE(ARGUNUSED(enp))
1194 if ((rc = ef10_nvram_buffer_delete_item(bufferp,
1195 buffer_size, offset, length, end)) != 0) {
1204 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1209 __checkReturn efx_rc_t
1210 efx_lic_v3_create_partition(
1211 __in efx_nic_t *enp,
1212 __in_bcount(buffer_size)
1214 __in size_t buffer_size)
1218 /* Construct empty partition */
1219 if ((rc = ef10_nvram_buffer_create(enp,
1220 NVRAM_PARTITION_TYPE_LICENSE,
1221 bufferp, buffer_size)) != 0) {
1229 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1234 __checkReturn efx_rc_t
1235 efx_lic_v3_finish_partition(
1236 __in efx_nic_t *enp,
1237 __in_bcount(buffer_size)
1239 __in size_t buffer_size)
1243 if ((rc = ef10_nvram_buffer_finish(bufferp,
1244 buffer_size)) != 0) {
1248 /* Validate completed partition */
1249 if ((rc = ef10_nvram_buffer_validate(enp, NVRAM_PARTITION_TYPE_LICENSE,
1250 bufferp, buffer_size)) != 0) {
1259 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1265 #endif /* EFSYS_OPT_MEDFORD */
1267 __checkReturn efx_rc_t
1269 __in efx_nic_t *enp)
1271 const efx_lic_ops_t *elop;
1272 efx_key_stats_t eks;
1275 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1276 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
1277 EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_LIC));
1279 switch (enp->en_family) {
1282 case EFX_FAMILY_SIENA:
1283 elop = &__efx_lic_v1_ops;
1285 #endif /* EFSYS_OPT_SIENA */
1287 #if EFSYS_OPT_HUNTINGTON
1288 case EFX_FAMILY_HUNTINGTON:
1289 elop = &__efx_lic_v2_ops;
1291 #endif /* EFSYS_OPT_HUNTINGTON */
1293 #if EFSYS_OPT_MEDFORD
1294 case EFX_FAMILY_MEDFORD:
1295 elop = &__efx_lic_v3_ops;
1297 #endif /* EFSYS_OPT_MEDFORD */
1305 enp->en_elop = elop;
1306 enp->en_mod_flags |= EFX_MOD_LIC;
1308 /* Probe for support */
1309 if (efx_lic_get_key_stats(enp, &eks) == 0) {
1310 enp->en_licensing_supported = B_TRUE;
1312 enp->en_licensing_supported = B_FALSE;
1318 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1323 extern __checkReturn boolean_t
1324 efx_lic_check_support(
1325 __in efx_nic_t *enp)
1327 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1328 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
1329 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1331 return (enp->en_licensing_supported);
1336 __in efx_nic_t *enp)
1338 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1339 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
1340 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1342 enp->en_elop = NULL;
1343 enp->en_mod_flags &= ~EFX_MOD_LIC;
1347 __checkReturn efx_rc_t
1348 efx_lic_update_licenses(
1349 __in efx_nic_t *enp)
1351 const efx_lic_ops_t *elop = enp->en_elop;
1354 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1355 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1357 if ((rc = elop->elo_update_licenses(enp)) != 0)
1363 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1368 __checkReturn efx_rc_t
1369 efx_lic_get_key_stats(
1370 __in efx_nic_t *enp,
1371 __out efx_key_stats_t *eksp)
1373 const efx_lic_ops_t *elop = enp->en_elop;
1376 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1377 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1379 if ((rc = elop->elo_get_key_stats(enp, eksp)) != 0)
1385 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1390 __checkReturn efx_rc_t
1392 __in efx_nic_t *enp,
1393 __in uint64_t app_id,
1394 __out boolean_t *licensedp)
1396 const efx_lic_ops_t *elop = enp->en_elop;
1399 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1400 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1402 if (elop->elo_app_state == NULL)
1405 if ((rc = elop->elo_app_state(enp, app_id, licensedp)) != 0)
1411 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1416 __checkReturn efx_rc_t
1418 __in efx_nic_t *enp,
1419 __in size_t buffer_size,
1420 __out uint32_t *typep,
1421 __out size_t *lengthp,
1422 __out_opt uint8_t *bufferp)
1424 const efx_lic_ops_t *elop = enp->en_elop;
1427 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1428 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1430 if (elop->elo_get_id == NULL)
1433 if ((rc = elop->elo_get_id(enp, buffer_size, typep,
1434 lengthp, bufferp)) != 0)
1440 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1446 * Buffer management API - abstracts varying TLV format used for License
1450 __checkReturn efx_rc_t
1452 __in efx_nic_t *enp,
1453 __in_bcount(buffer_size)
1455 __in size_t buffer_size,
1456 __out uint32_t *startp)
1458 const efx_lic_ops_t *elop = enp->en_elop;
1461 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1462 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1464 if ((rc = elop->elo_find_start(enp, bufferp, buffer_size, startp)) != 0)
1470 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1475 __checkReturn efx_rc_t
1477 __in efx_nic_t *enp,
1478 __in_bcount(buffer_size)
1480 __in size_t buffer_size,
1481 __in uint32_t offset,
1482 __out uint32_t *endp)
1484 const efx_lic_ops_t *elop = enp->en_elop;
1487 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1488 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1490 rc = elop->elo_find_end(enp, bufferp, buffer_size, offset, endp);
1497 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1502 __checkReturn __success(return != B_FALSE) boolean_t
1504 __in efx_nic_t *enp,
1505 __in_bcount(buffer_size)
1507 __in size_t buffer_size,
1508 __in uint32_t offset,
1509 __out uint32_t *startp,
1510 __out uint32_t *lengthp)
1512 const efx_lic_ops_t *elop = enp->en_elop;
1514 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1515 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1517 EFSYS_ASSERT(bufferp);
1518 EFSYS_ASSERT(startp);
1519 EFSYS_ASSERT(lengthp);
1521 return (elop->elo_find_key(enp, bufferp, buffer_size, offset,
1527 * Validate that the buffer contains a single key in a recognised format.
1528 * An empty or terminator buffer is not accepted as a valid key.
1530 __checkReturn __success(return != B_FALSE) boolean_t
1531 efx_lic_validate_key(
1532 __in efx_nic_t *enp,
1533 __in_bcount(length) caddr_t keyp,
1534 __in uint32_t length)
1536 const efx_lic_ops_t *elop = enp->en_elop;
1539 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1540 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1542 if ((rc = elop->elo_validate_key(enp, keyp, length)) == B_FALSE)
1548 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1553 __checkReturn efx_rc_t
1555 __in efx_nic_t *enp,
1556 __in_bcount(buffer_size)
1558 __in size_t buffer_size,
1559 __in uint32_t offset,
1560 __in uint32_t length,
1561 __out_bcount_part(key_max_size, *lengthp)
1563 __in size_t key_max_size,
1564 __out uint32_t *lengthp)
1566 const efx_lic_ops_t *elop = enp->en_elop;
1569 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1570 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1572 if ((rc = elop->elo_read_key(enp, bufferp, buffer_size, offset,
1573 length, keyp, key_max_size, lengthp)) != 0)
1579 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1584 __checkReturn efx_rc_t
1586 __in efx_nic_t *enp,
1587 __in_bcount(buffer_size)
1589 __in size_t buffer_size,
1590 __in uint32_t offset,
1591 __in_bcount(length) caddr_t keyp,
1592 __in uint32_t length,
1593 __out uint32_t *lengthp)
1595 const efx_lic_ops_t *elop = enp->en_elop;
1598 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1599 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1601 if ((rc = elop->elo_write_key(enp, bufferp, buffer_size, offset,
1602 keyp, length, lengthp)) != 0)
1608 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1613 __checkReturn efx_rc_t
1615 __in efx_nic_t *enp,
1616 __in_bcount(buffer_size)
1618 __in size_t buffer_size,
1619 __in uint32_t offset,
1620 __in uint32_t length,
1622 __out uint32_t *deltap)
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_delete_key(enp, bufferp, buffer_size, offset,
1631 length, end, deltap)) != 0)
1637 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1642 __checkReturn efx_rc_t
1643 efx_lic_create_partition(
1644 __in efx_nic_t *enp,
1645 __in_bcount(buffer_size)
1647 __in size_t buffer_size)
1649 const efx_lic_ops_t *elop = enp->en_elop;
1652 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1653 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1655 if ((rc = elop->elo_create_partition(enp, bufferp, buffer_size)) != 0)
1661 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1667 __checkReturn efx_rc_t
1668 efx_lic_finish_partition(
1669 __in efx_nic_t *enp,
1670 __in_bcount(buffer_size)
1672 __in size_t buffer_size)
1674 const efx_lic_ops_t *elop = enp->en_elop;
1677 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1678 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1680 if ((rc = elop->elo_finish_partition(enp, bufferp, buffer_size)) != 0)
1686 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1691 #endif /* EFSYS_OPT_LICENSING */