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 #include "efx_regs_mcdi_aoe.h"
17 #if EFSYS_OPT_SIENA | EFSYS_OPT_HUNTINGTON
19 __checkReturn efx_rc_t
20 efx_lic_v1v2_find_start(
22 __in_bcount(buffer_size)
24 __in size_t buffer_size,
25 __out uint32_t *startp);
27 __checkReturn efx_rc_t
28 efx_lic_v1v2_find_end(
30 __in_bcount(buffer_size)
32 __in size_t buffer_size,
34 __out uint32_t *endp);
36 __checkReturn __success(return != B_FALSE) boolean_t
37 efx_lic_v1v2_find_key(
39 __in_bcount(buffer_size)
41 __in size_t buffer_size,
43 __out uint32_t *startp,
44 __out uint32_t *lengthp);
46 __checkReturn __success(return != B_FALSE) boolean_t
47 efx_lic_v1v2_validate_key(
49 __in_bcount(length) caddr_t keyp,
50 __in uint32_t length);
52 __checkReturn efx_rc_t
53 efx_lic_v1v2_read_key(
55 __in_bcount(buffer_size)
57 __in size_t buffer_size,
60 __out_bcount_part(key_max_size, *lengthp)
62 __in size_t key_max_size,
63 __out uint32_t *lengthp);
65 __checkReturn efx_rc_t
66 efx_lic_v1v2_write_key(
68 __in_bcount(buffer_size)
70 __in size_t buffer_size,
72 __in_bcount(length) caddr_t keyp,
74 __out uint32_t *lengthp);
76 __checkReturn efx_rc_t
77 efx_lic_v1v2_delete_key(
79 __in_bcount(buffer_size)
81 __in size_t buffer_size,
85 __out uint32_t *deltap);
87 __checkReturn efx_rc_t
88 efx_lic_v1v2_create_partition(
90 __in_bcount(buffer_size)
92 __in size_t buffer_size);
94 __checkReturn efx_rc_t
95 efx_lic_v1v2_finish_partition(
97 __in_bcount(buffer_size)
99 __in size_t buffer_size);
101 #endif /* EFSYS_OPT_HUNTINGTON | EFSYS_OPT_SIENA */
106 static __checkReturn efx_rc_t
107 efx_mcdi_fc_license_update_license(
108 __in efx_nic_t *enp);
110 static __checkReturn efx_rc_t
111 efx_mcdi_fc_license_get_key_stats(
113 __out efx_key_stats_t *eksp);
115 static const efx_lic_ops_t __efx_lic_v1_ops = {
116 efx_mcdi_fc_license_update_license, /* elo_update_licenses */
117 efx_mcdi_fc_license_get_key_stats, /* elo_get_key_stats */
118 NULL, /* elo_app_state */
119 NULL, /* elo_get_id */
120 efx_lic_v1v2_find_start, /* elo_find_start */
121 efx_lic_v1v2_find_end, /* elo_find_end */
122 efx_lic_v1v2_find_key, /* elo_find_key */
123 efx_lic_v1v2_validate_key, /* elo_validate_key */
124 efx_lic_v1v2_read_key, /* elo_read_key */
125 efx_lic_v1v2_write_key, /* elo_write_key */
126 efx_lic_v1v2_delete_key, /* elo_delete_key */
127 efx_lic_v1v2_create_partition, /* elo_create_partition */
128 efx_lic_v1v2_finish_partition, /* elo_finish_partition */
131 #endif /* EFSYS_OPT_SIENA */
133 #if EFSYS_OPT_HUNTINGTON
135 static __checkReturn efx_rc_t
136 efx_mcdi_licensing_update_licenses(
137 __in efx_nic_t *enp);
139 static __checkReturn efx_rc_t
140 efx_mcdi_licensing_get_key_stats(
142 __out efx_key_stats_t *eksp);
144 static __checkReturn efx_rc_t
145 efx_mcdi_licensed_app_state(
147 __in uint64_t app_id,
148 __out boolean_t *licensedp);
150 static const efx_lic_ops_t __efx_lic_v2_ops = {
151 efx_mcdi_licensing_update_licenses, /* elo_update_licenses */
152 efx_mcdi_licensing_get_key_stats, /* elo_get_key_stats */
153 efx_mcdi_licensed_app_state, /* elo_app_state */
154 NULL, /* elo_get_id */
155 efx_lic_v1v2_find_start, /* elo_find_start */
156 efx_lic_v1v2_find_end, /* elo_find_end */
157 efx_lic_v1v2_find_key, /* elo_find_key */
158 efx_lic_v1v2_validate_key, /* elo_validate_key */
159 efx_lic_v1v2_read_key, /* elo_read_key */
160 efx_lic_v1v2_write_key, /* elo_write_key */
161 efx_lic_v1v2_delete_key, /* elo_delete_key */
162 efx_lic_v1v2_create_partition, /* elo_create_partition */
163 efx_lic_v1v2_finish_partition, /* elo_finish_partition */
166 #endif /* EFSYS_OPT_HUNTINGTON */
168 #if EFSYS_OPT_MEDFORD || EFSYS_OPT_MEDFORD2
170 static __checkReturn efx_rc_t
171 efx_mcdi_licensing_v3_update_licenses(
172 __in efx_nic_t *enp);
174 static __checkReturn efx_rc_t
175 efx_mcdi_licensing_v3_report_license(
177 __out efx_key_stats_t *eksp);
179 static __checkReturn efx_rc_t
180 efx_mcdi_licensing_v3_app_state(
182 __in uint64_t app_id,
183 __out boolean_t *licensedp);
185 static __checkReturn efx_rc_t
186 efx_mcdi_licensing_v3_get_id(
188 __in size_t buffer_size,
189 __out uint32_t *typep,
190 __out size_t *lengthp,
191 __out_bcount_part_opt(buffer_size, *lengthp)
194 __checkReturn efx_rc_t
195 efx_lic_v3_find_start(
197 __in_bcount(buffer_size)
199 __in size_t buffer_size,
200 __out uint32_t *startp);
202 __checkReturn efx_rc_t
205 __in_bcount(buffer_size)
207 __in size_t buffer_size,
208 __in uint32_t offset,
209 __out uint32_t *endp);
211 __checkReturn __success(return != B_FALSE) boolean_t
214 __in_bcount(buffer_size)
216 __in size_t buffer_size,
217 __in uint32_t offset,
218 __out uint32_t *startp,
219 __out uint32_t *lengthp);
221 __checkReturn __success(return != B_FALSE) boolean_t
222 efx_lic_v3_validate_key(
224 __in_bcount(length) caddr_t keyp,
225 __in uint32_t length);
227 __checkReturn efx_rc_t
230 __in_bcount(buffer_size)
232 __in size_t buffer_size,
233 __in uint32_t offset,
234 __in uint32_t length,
235 __out_bcount_part(key_max_size, *lengthp)
237 __in size_t key_max_size,
238 __out uint32_t *lengthp);
240 __checkReturn efx_rc_t
241 efx_lic_v3_write_key(
243 __in_bcount(buffer_size)
245 __in size_t buffer_size,
246 __in uint32_t offset,
247 __in_bcount(length) caddr_t keyp,
248 __in uint32_t length,
249 __out uint32_t *lengthp);
251 __checkReturn efx_rc_t
252 efx_lic_v3_delete_key(
254 __in_bcount(buffer_size)
256 __in size_t buffer_size,
257 __in uint32_t offset,
258 __in uint32_t length,
260 __out uint32_t *deltap);
262 __checkReturn efx_rc_t
263 efx_lic_v3_create_partition(
265 __in_bcount(buffer_size)
267 __in size_t buffer_size);
269 __checkReturn efx_rc_t
270 efx_lic_v3_finish_partition(
272 __in_bcount(buffer_size)
274 __in size_t buffer_size);
276 static const efx_lic_ops_t __efx_lic_v3_ops = {
277 efx_mcdi_licensing_v3_update_licenses, /* elo_update_licenses */
278 efx_mcdi_licensing_v3_report_license, /* elo_get_key_stats */
279 efx_mcdi_licensing_v3_app_state, /* elo_app_state */
280 efx_mcdi_licensing_v3_get_id, /* elo_get_id */
281 efx_lic_v3_find_start, /* elo_find_start */
282 efx_lic_v3_find_end, /* elo_find_end */
283 efx_lic_v3_find_key, /* elo_find_key */
284 efx_lic_v3_validate_key, /* elo_validate_key */
285 efx_lic_v3_read_key, /* elo_read_key */
286 efx_lic_v3_write_key, /* elo_write_key */
287 efx_lic_v3_delete_key, /* elo_delete_key */
288 efx_lic_v3_create_partition, /* elo_create_partition */
289 efx_lic_v3_finish_partition, /* elo_finish_partition */
292 #endif /* EFSYS_OPT_MEDFORD || EFSYS_OPT_MEDFORD2 */
295 /* V1 Licensing - used in Siena Modena only */
299 static __checkReturn efx_rc_t
300 efx_mcdi_fc_license_update_license(
304 uint8_t payload[MC_CMD_FC_IN_LICENSE_LEN];
307 EFSYS_ASSERT(enp->en_family == EFX_FAMILY_SIENA);
309 (void) memset(payload, 0, sizeof (payload));
310 req.emr_cmd = MC_CMD_FC;
311 req.emr_in_buf = payload;
312 req.emr_in_length = MC_CMD_FC_IN_LICENSE_LEN;
313 req.emr_out_buf = payload;
314 req.emr_out_length = 0;
316 MCDI_IN_SET_DWORD(req, FC_IN_CMD,
317 MC_CMD_FC_OP_LICENSE);
319 MCDI_IN_SET_DWORD(req, FC_IN_LICENSE_OP,
320 MC_CMD_FC_IN_LICENSE_UPDATE_LICENSE);
322 efx_mcdi_execute(enp, &req);
324 if (req.emr_rc != 0) {
329 if (req.emr_out_length_used != 0) {
339 EFSYS_PROBE1(fail1, efx_rc_t, rc);
344 static __checkReturn efx_rc_t
345 efx_mcdi_fc_license_get_key_stats(
347 __out efx_key_stats_t *eksp)
350 uint8_t payload[MAX(MC_CMD_FC_IN_LICENSE_LEN,
351 MC_CMD_FC_OUT_LICENSE_LEN)];
354 EFSYS_ASSERT(enp->en_family == EFX_FAMILY_SIENA);
356 (void) memset(payload, 0, sizeof (payload));
357 req.emr_cmd = MC_CMD_FC;
358 req.emr_in_buf = payload;
359 req.emr_in_length = MC_CMD_FC_IN_LICENSE_LEN;
360 req.emr_out_buf = payload;
361 req.emr_out_length = MC_CMD_FC_OUT_LICENSE_LEN;
363 MCDI_IN_SET_DWORD(req, FC_IN_CMD,
364 MC_CMD_FC_OP_LICENSE);
366 MCDI_IN_SET_DWORD(req, FC_IN_LICENSE_OP,
367 MC_CMD_FC_IN_LICENSE_GET_KEY_STATS);
369 efx_mcdi_execute_quiet(enp, &req);
371 if (req.emr_rc != 0) {
376 if (req.emr_out_length_used < MC_CMD_FC_OUT_LICENSE_LEN) {
382 MCDI_OUT_DWORD(req, FC_OUT_LICENSE_VALID_KEYS);
384 MCDI_OUT_DWORD(req, FC_OUT_LICENSE_INVALID_KEYS);
385 eksp->eks_blacklisted =
386 MCDI_OUT_DWORD(req, FC_OUT_LICENSE_BLACKLISTED_KEYS);
387 eksp->eks_unverifiable = 0;
388 eksp->eks_wrong_node = 0;
389 eksp->eks_licensed_apps_lo = 0;
390 eksp->eks_licensed_apps_hi = 0;
391 eksp->eks_licensed_features_lo = 0;
392 eksp->eks_licensed_features_hi = 0;
399 EFSYS_PROBE1(fail1, efx_rc_t, rc);
404 #endif /* EFSYS_OPT_SIENA */
406 /* V1 and V2 Partition format - based on a 16-bit TLV format */
408 #if EFSYS_OPT_SIENA | EFSYS_OPT_HUNTINGTON
411 * V1/V2 format - defined in SF-108542-TC section 4.2:
412 * Type (T): 16bit - revision/HMAC algorithm
413 * Length (L): 16bit - value length in bytes
414 * Value (V): L bytes - payload
416 #define EFX_LICENSE_V1V2_PAYLOAD_LENGTH_MAX (256)
417 #define EFX_LICENSE_V1V2_HEADER_LENGTH (2 * sizeof (uint16_t))
419 __checkReturn efx_rc_t
420 efx_lic_v1v2_find_start(
422 __in_bcount(buffer_size)
424 __in size_t buffer_size,
425 __out uint32_t *startp)
427 _NOTE(ARGUNUSED(enp, bufferp, buffer_size))
433 __checkReturn efx_rc_t
434 efx_lic_v1v2_find_end(
436 __in_bcount(buffer_size)
438 __in size_t buffer_size,
439 __in uint32_t offset,
440 __out uint32_t *endp)
442 _NOTE(ARGUNUSED(enp, bufferp, buffer_size))
444 *endp = offset + EFX_LICENSE_V1V2_HEADER_LENGTH;
448 __checkReturn __success(return != B_FALSE) boolean_t
449 efx_lic_v1v2_find_key(
451 __in_bcount(buffer_size)
453 __in size_t buffer_size,
454 __in uint32_t offset,
455 __out uint32_t *startp,
456 __out uint32_t *lengthp)
462 _NOTE(ARGUNUSED(enp))
464 if ((size_t)buffer_size - offset < EFX_LICENSE_V1V2_HEADER_LENGTH)
467 tlv_type = __LE_TO_CPU_16(((uint16_t *)&bufferp[offset])[0]);
468 tlv_length = __LE_TO_CPU_16(((uint16_t *)&bufferp[offset])[1]);
469 if ((tlv_length > EFX_LICENSE_V1V2_PAYLOAD_LENGTH_MAX) ||
470 (tlv_type == 0 && tlv_length == 0)) {
474 *lengthp = tlv_length + EFX_LICENSE_V1V2_HEADER_LENGTH;
480 EFSYS_PROBE1(fail1, boolean_t, B_FALSE);
485 __checkReturn __success(return != B_FALSE) boolean_t
486 efx_lic_v1v2_validate_key(
488 __in_bcount(length) caddr_t keyp,
489 __in uint32_t length)
494 _NOTE(ARGUNUSED(enp))
496 if (length < EFX_LICENSE_V1V2_HEADER_LENGTH) {
500 tlv_type = __LE_TO_CPU_16(((uint16_t *)keyp)[0]);
501 tlv_length = __LE_TO_CPU_16(((uint16_t *)keyp)[1]);
503 if (tlv_length > EFX_LICENSE_V1V2_PAYLOAD_LENGTH_MAX) {
509 if ((tlv_length + EFX_LICENSE_V1V2_HEADER_LENGTH) != length) {
522 EFSYS_PROBE1(fail1, boolean_t, B_FALSE);
528 __checkReturn efx_rc_t
529 efx_lic_v1v2_read_key(
531 __in_bcount(buffer_size)
533 __in size_t buffer_size,
534 __in uint32_t offset,
535 __in uint32_t length,
536 __out_bcount_part(key_max_size, *lengthp)
538 __in size_t key_max_size,
539 __out uint32_t *lengthp)
543 _NOTE(ARGUNUSED(enp, buffer_size))
544 EFSYS_ASSERT(length <= (EFX_LICENSE_V1V2_PAYLOAD_LENGTH_MAX +
545 EFX_LICENSE_V1V2_HEADER_LENGTH));
547 if (key_max_size < length) {
551 memcpy(keyp, &bufferp[offset], length);
558 EFSYS_PROBE1(fail1, efx_rc_t, rc);
563 __checkReturn efx_rc_t
564 efx_lic_v1v2_write_key(
566 __in_bcount(buffer_size)
568 __in size_t buffer_size,
569 __in uint32_t offset,
570 __in_bcount(length) caddr_t keyp,
571 __in uint32_t length,
572 __out uint32_t *lengthp)
576 _NOTE(ARGUNUSED(enp))
577 EFSYS_ASSERT(length <= (EFX_LICENSE_V1V2_PAYLOAD_LENGTH_MAX +
578 EFX_LICENSE_V1V2_HEADER_LENGTH));
580 /* Ensure space for terminator remains */
581 if ((offset + length) >
582 (buffer_size - EFX_LICENSE_V1V2_HEADER_LENGTH)) {
587 memcpy(bufferp + offset, keyp, length);
594 EFSYS_PROBE1(fail1, efx_rc_t, rc);
599 __checkReturn efx_rc_t
600 efx_lic_v1v2_delete_key(
602 __in_bcount(buffer_size)
604 __in size_t buffer_size,
605 __in uint32_t offset,
606 __in uint32_t length,
608 __out uint32_t *deltap)
610 uint32_t move_start = offset + length;
611 uint32_t move_length = end - move_start;
613 _NOTE(ARGUNUSED(enp, buffer_size))
614 EFSYS_ASSERT(end <= buffer_size);
616 /* Shift everything after the key down */
617 memmove(bufferp + offset, bufferp + move_start, move_length);
624 __checkReturn efx_rc_t
625 efx_lic_v1v2_create_partition(
627 __in_bcount(buffer_size)
629 __in size_t buffer_size)
631 _NOTE(ARGUNUSED(enp, buffer_size))
632 EFSYS_ASSERT(EFX_LICENSE_V1V2_HEADER_LENGTH <= buffer_size);
634 /* Write terminator */
635 memset(bufferp, '\0', EFX_LICENSE_V1V2_HEADER_LENGTH);
640 __checkReturn efx_rc_t
641 efx_lic_v1v2_finish_partition(
643 __in_bcount(buffer_size)
645 __in size_t buffer_size)
647 _NOTE(ARGUNUSED(enp, bufferp, buffer_size))
652 #endif /* EFSYS_OPT_HUNTINGTON | EFSYS_OPT_SIENA */
655 /* V2 Licensing - used by Huntington family only. See SF-113611-TC */
657 #if EFSYS_OPT_HUNTINGTON
659 static __checkReturn efx_rc_t
660 efx_mcdi_licensed_app_state(
662 __in uint64_t app_id,
663 __out boolean_t *licensedp)
666 uint8_t payload[MAX(MC_CMD_GET_LICENSED_APP_STATE_IN_LEN,
667 MC_CMD_GET_LICENSED_APP_STATE_OUT_LEN)];
671 EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON);
673 /* V2 licensing supports 32bit app id only */
674 if ((app_id >> 32) != 0) {
679 (void) memset(payload, 0, sizeof (payload));
680 req.emr_cmd = MC_CMD_GET_LICENSED_APP_STATE;
681 req.emr_in_buf = payload;
682 req.emr_in_length = MC_CMD_GET_LICENSED_APP_STATE_IN_LEN;
683 req.emr_out_buf = payload;
684 req.emr_out_length = MC_CMD_GET_LICENSED_APP_STATE_OUT_LEN;
686 MCDI_IN_SET_DWORD(req, GET_LICENSED_APP_STATE_IN_APP_ID,
687 app_id & 0xffffffff);
689 efx_mcdi_execute(enp, &req);
691 if (req.emr_rc != 0) {
696 if (req.emr_out_length_used < MC_CMD_GET_LICENSED_APP_STATE_OUT_LEN) {
701 app_state = (MCDI_OUT_DWORD(req, GET_LICENSED_APP_STATE_OUT_STATE));
702 if (app_state != MC_CMD_GET_LICENSED_APP_STATE_OUT_NOT_LICENSED) {
705 *licensedp = B_FALSE;
715 EFSYS_PROBE1(fail1, efx_rc_t, rc);
720 static __checkReturn efx_rc_t
721 efx_mcdi_licensing_update_licenses(
725 uint8_t payload[MC_CMD_LICENSING_IN_LEN];
728 EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON);
730 (void) memset(payload, 0, sizeof (payload));
731 req.emr_cmd = MC_CMD_LICENSING;
732 req.emr_in_buf = payload;
733 req.emr_in_length = MC_CMD_LICENSING_IN_LEN;
734 req.emr_out_buf = payload;
735 req.emr_out_length = 0;
737 MCDI_IN_SET_DWORD(req, LICENSING_IN_OP,
738 MC_CMD_LICENSING_IN_OP_UPDATE_LICENSE);
740 efx_mcdi_execute(enp, &req);
742 if (req.emr_rc != 0) {
747 if (req.emr_out_length_used != 0) {
757 EFSYS_PROBE1(fail1, efx_rc_t, rc);
762 static __checkReturn efx_rc_t
763 efx_mcdi_licensing_get_key_stats(
765 __out efx_key_stats_t *eksp)
768 uint8_t payload[MAX(MC_CMD_LICENSING_IN_LEN,
769 MC_CMD_LICENSING_OUT_LEN)];
772 EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON);
774 (void) memset(payload, 0, sizeof (payload));
775 req.emr_cmd = MC_CMD_LICENSING;
776 req.emr_in_buf = payload;
777 req.emr_in_length = MC_CMD_LICENSING_IN_LEN;
778 req.emr_out_buf = payload;
779 req.emr_out_length = MC_CMD_LICENSING_OUT_LEN;
781 MCDI_IN_SET_DWORD(req, LICENSING_IN_OP,
782 MC_CMD_LICENSING_IN_OP_GET_KEY_STATS);
784 efx_mcdi_execute(enp, &req);
786 if (req.emr_rc != 0) {
791 if (req.emr_out_length_used < MC_CMD_LICENSING_OUT_LEN) {
797 MCDI_OUT_DWORD(req, LICENSING_OUT_VALID_APP_KEYS);
799 MCDI_OUT_DWORD(req, LICENSING_OUT_INVALID_APP_KEYS);
800 eksp->eks_blacklisted =
801 MCDI_OUT_DWORD(req, LICENSING_OUT_BLACKLISTED_APP_KEYS);
802 eksp->eks_unverifiable =
803 MCDI_OUT_DWORD(req, LICENSING_OUT_UNVERIFIABLE_APP_KEYS);
804 eksp->eks_wrong_node =
805 MCDI_OUT_DWORD(req, LICENSING_OUT_WRONG_NODE_APP_KEYS);
806 eksp->eks_licensed_apps_lo = 0;
807 eksp->eks_licensed_apps_hi = 0;
808 eksp->eks_licensed_features_lo = 0;
809 eksp->eks_licensed_features_hi = 0;
816 EFSYS_PROBE1(fail1, efx_rc_t, rc);
821 #endif /* EFSYS_OPT_HUNTINGTON */
823 /* V3 Licensing - used starting from Medford family. See SF-114884-SW */
825 #if EFSYS_OPT_MEDFORD || EFSYS_OPT_MEDFORD2
827 static __checkReturn efx_rc_t
828 efx_mcdi_licensing_v3_update_licenses(
832 uint8_t payload[MC_CMD_LICENSING_V3_IN_LEN];
835 EFSYS_ASSERT((enp->en_family == EFX_FAMILY_MEDFORD) ||
836 (enp->en_family == EFX_FAMILY_MEDFORD2));
838 (void) memset(payload, 0, sizeof (payload));
839 req.emr_cmd = MC_CMD_LICENSING_V3;
840 req.emr_in_buf = payload;
841 req.emr_in_length = MC_CMD_LICENSING_V3_IN_LEN;
842 req.emr_out_buf = NULL;
843 req.emr_out_length = 0;
845 MCDI_IN_SET_DWORD(req, LICENSING_V3_IN_OP,
846 MC_CMD_LICENSING_V3_IN_OP_UPDATE_LICENSE);
848 efx_mcdi_execute(enp, &req);
850 if (req.emr_rc != 0) {
858 EFSYS_PROBE1(fail1, efx_rc_t, rc);
863 static __checkReturn efx_rc_t
864 efx_mcdi_licensing_v3_report_license(
866 __out efx_key_stats_t *eksp)
869 uint8_t payload[MAX(MC_CMD_LICENSING_V3_IN_LEN,
870 MC_CMD_LICENSING_V3_OUT_LEN)];
873 EFSYS_ASSERT((enp->en_family == EFX_FAMILY_MEDFORD) ||
874 (enp->en_family == EFX_FAMILY_MEDFORD2));
876 (void) memset(payload, 0, sizeof (payload));
877 req.emr_cmd = MC_CMD_LICENSING_V3;
878 req.emr_in_buf = payload;
879 req.emr_in_length = MC_CMD_LICENSING_V3_IN_LEN;
880 req.emr_out_buf = payload;
881 req.emr_out_length = MC_CMD_LICENSING_V3_OUT_LEN;
883 MCDI_IN_SET_DWORD(req, LICENSING_V3_IN_OP,
884 MC_CMD_LICENSING_V3_IN_OP_REPORT_LICENSE);
886 efx_mcdi_execute_quiet(enp, &req);
888 if (req.emr_rc != 0) {
893 if (req.emr_out_length_used < MC_CMD_LICENSING_V3_OUT_LEN) {
899 MCDI_OUT_DWORD(req, LICENSING_V3_OUT_VALID_KEYS);
901 MCDI_OUT_DWORD(req, LICENSING_V3_OUT_INVALID_KEYS);
902 eksp->eks_blacklisted = 0;
903 eksp->eks_unverifiable =
904 MCDI_OUT_DWORD(req, LICENSING_V3_OUT_UNVERIFIABLE_KEYS);
905 eksp->eks_wrong_node =
906 MCDI_OUT_DWORD(req, LICENSING_V3_OUT_WRONG_NODE_KEYS);
907 eksp->eks_licensed_apps_lo =
908 MCDI_OUT_DWORD(req, LICENSING_V3_OUT_LICENSED_APPS_LO);
909 eksp->eks_licensed_apps_hi =
910 MCDI_OUT_DWORD(req, LICENSING_V3_OUT_LICENSED_APPS_HI);
911 eksp->eks_licensed_features_lo =
912 MCDI_OUT_DWORD(req, LICENSING_V3_OUT_LICENSED_FEATURES_LO);
913 eksp->eks_licensed_features_hi =
914 MCDI_OUT_DWORD(req, LICENSING_V3_OUT_LICENSED_FEATURES_HI);
921 EFSYS_PROBE1(fail1, efx_rc_t, rc);
926 static __checkReturn efx_rc_t
927 efx_mcdi_licensing_v3_app_state(
929 __in uint64_t app_id,
930 __out boolean_t *licensedp)
933 uint8_t payload[MAX(MC_CMD_GET_LICENSED_V3_APP_STATE_IN_LEN,
934 MC_CMD_GET_LICENSED_V3_APP_STATE_OUT_LEN)];
938 EFSYS_ASSERT((enp->en_family == EFX_FAMILY_MEDFORD) ||
939 (enp->en_family == EFX_FAMILY_MEDFORD2));
941 (void) memset(payload, 0, sizeof (payload));
942 req.emr_cmd = MC_CMD_GET_LICENSED_V3_APP_STATE;
943 req.emr_in_buf = payload;
944 req.emr_in_length = MC_CMD_GET_LICENSED_V3_APP_STATE_IN_LEN;
945 req.emr_out_buf = payload;
946 req.emr_out_length = MC_CMD_GET_LICENSED_V3_APP_STATE_OUT_LEN;
948 MCDI_IN_SET_DWORD(req, GET_LICENSED_V3_APP_STATE_IN_APP_ID_LO,
949 app_id & 0xffffffff);
950 MCDI_IN_SET_DWORD(req, GET_LICENSED_V3_APP_STATE_IN_APP_ID_HI,
953 efx_mcdi_execute(enp, &req);
955 if (req.emr_rc != 0) {
960 if (req.emr_out_length_used <
961 MC_CMD_GET_LICENSED_V3_APP_STATE_OUT_LEN) {
966 app_state = (MCDI_OUT_DWORD(req, GET_LICENSED_V3_APP_STATE_OUT_STATE));
967 if (app_state != MC_CMD_GET_LICENSED_V3_APP_STATE_OUT_NOT_LICENSED) {
970 *licensedp = B_FALSE;
978 EFSYS_PROBE1(fail1, efx_rc_t, rc);
983 static __checkReturn efx_rc_t
984 efx_mcdi_licensing_v3_get_id(
986 __in size_t buffer_size,
987 __out uint32_t *typep,
988 __out size_t *lengthp,
989 __out_bcount_part_opt(buffer_size, *lengthp)
993 uint8_t payload[MAX(MC_CMD_LICENSING_GET_ID_V3_IN_LEN,
994 MC_CMD_LICENSING_GET_ID_V3_OUT_LENMIN)];
997 req.emr_cmd = MC_CMD_LICENSING_GET_ID_V3;
999 if (bufferp == NULL) {
1000 /* Request id type and length only */
1001 req.emr_in_buf = bufferp;
1002 req.emr_in_length = MC_CMD_LICENSING_GET_ID_V3_IN_LEN;
1003 req.emr_out_buf = bufferp;
1004 req.emr_out_length = MC_CMD_LICENSING_GET_ID_V3_OUT_LENMIN;
1005 (void) memset(payload, 0, sizeof (payload));
1007 /* Request full buffer */
1008 req.emr_in_buf = bufferp;
1009 req.emr_in_length = MC_CMD_LICENSING_GET_ID_V3_IN_LEN;
1010 req.emr_out_buf = bufferp;
1011 req.emr_out_length =
1012 MIN(buffer_size, MC_CMD_LICENSING_GET_ID_V3_OUT_LENMAX);
1013 (void) memset(bufferp, 0, req.emr_out_length);
1016 efx_mcdi_execute_quiet(enp, &req);
1018 if (req.emr_rc != 0) {
1023 if (req.emr_out_length_used < MC_CMD_LICENSING_GET_ID_V3_OUT_LENMIN) {
1028 *typep = MCDI_OUT_DWORD(req, LICENSING_GET_ID_V3_OUT_LICENSE_TYPE);
1030 MCDI_OUT_DWORD(req, LICENSING_GET_ID_V3_OUT_LICENSE_ID_LENGTH);
1032 if (bufferp == NULL) {
1034 * Modify length requirements to indicate to caller the extra
1035 * buffering needed to read the complete output.
1037 *lengthp += MC_CMD_LICENSING_GET_ID_V3_OUT_LENMIN;
1039 /* Shift ID down to start of buffer */
1041 bufferp + MC_CMD_LICENSING_GET_ID_V3_OUT_LICENSE_ID_OFST,
1043 memset(bufferp + (*lengthp), 0,
1044 MC_CMD_LICENSING_GET_ID_V3_OUT_LICENSE_ID_OFST);
1052 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1057 /* V3 format uses Huntington TLV format partition. See SF-108797-SW */
1058 #define EFX_LICENSE_V3_KEY_LENGTH_MIN (64)
1059 #define EFX_LICENSE_V3_KEY_LENGTH_MAX (160)
1061 __checkReturn efx_rc_t
1062 efx_lic_v3_find_start(
1063 __in efx_nic_t *enp,
1064 __in_bcount(buffer_size)
1066 __in size_t buffer_size,
1067 __out uint32_t *startp)
1069 _NOTE(ARGUNUSED(enp))
1071 return (ef10_nvram_buffer_find_item_start(bufferp, buffer_size,
1075 __checkReturn efx_rc_t
1076 efx_lic_v3_find_end(
1077 __in efx_nic_t *enp,
1078 __in_bcount(buffer_size)
1080 __in size_t buffer_size,
1081 __in uint32_t offset,
1082 __out uint32_t *endp)
1084 _NOTE(ARGUNUSED(enp))
1086 return (ef10_nvram_buffer_find_end(bufferp, buffer_size, offset, endp));
1089 __checkReturn __success(return != B_FALSE) boolean_t
1090 efx_lic_v3_find_key(
1091 __in efx_nic_t *enp,
1092 __in_bcount(buffer_size)
1094 __in size_t buffer_size,
1095 __in uint32_t offset,
1096 __out uint32_t *startp,
1097 __out uint32_t *lengthp)
1099 _NOTE(ARGUNUSED(enp))
1101 return ef10_nvram_buffer_find_item(bufferp, buffer_size,
1102 offset, startp, lengthp);
1105 __checkReturn __success(return != B_FALSE) boolean_t
1106 efx_lic_v3_validate_key(
1107 __in efx_nic_t *enp,
1108 __in_bcount(length) caddr_t keyp,
1109 __in uint32_t length)
1111 /* Check key is a valid V3 key */
1115 _NOTE(ARGUNUSED(enp))
1117 if (length < EFX_LICENSE_V3_KEY_LENGTH_MIN) {
1121 if (length > EFX_LICENSE_V3_KEY_LENGTH_MAX) {
1125 key_type = ((uint8_t *)keyp)[0];
1126 key_length = ((uint8_t *)keyp)[1];
1131 if (key_length > length) {
1143 EFSYS_PROBE1(fail1, boolean_t, B_FALSE);
1148 __checkReturn efx_rc_t
1149 efx_lic_v3_read_key(
1150 __in efx_nic_t *enp,
1151 __in_bcount(buffer_size)
1153 __in size_t buffer_size,
1154 __in uint32_t offset,
1155 __in uint32_t length,
1156 __out_bcount_part(key_max_size, *lengthp)
1158 __in size_t key_max_size,
1159 __out uint32_t *lengthp)
1161 _NOTE(ARGUNUSED(enp))
1163 return ef10_nvram_buffer_get_item(bufferp, buffer_size,
1164 offset, length, keyp, key_max_size, lengthp);
1167 __checkReturn efx_rc_t
1168 efx_lic_v3_write_key(
1169 __in efx_nic_t *enp,
1170 __in_bcount(buffer_size)
1172 __in size_t buffer_size,
1173 __in uint32_t offset,
1174 __in_bcount(length) caddr_t keyp,
1175 __in uint32_t length,
1176 __out uint32_t *lengthp)
1178 _NOTE(ARGUNUSED(enp))
1179 EFSYS_ASSERT(length <= EFX_LICENSE_V3_KEY_LENGTH_MAX);
1181 return ef10_nvram_buffer_insert_item(bufferp, buffer_size,
1182 offset, keyp, length, lengthp);
1185 __checkReturn efx_rc_t
1186 efx_lic_v3_delete_key(
1187 __in efx_nic_t *enp,
1188 __in_bcount(buffer_size)
1190 __in size_t buffer_size,
1191 __in uint32_t offset,
1192 __in uint32_t length,
1194 __out uint32_t *deltap)
1198 _NOTE(ARGUNUSED(enp))
1200 if ((rc = ef10_nvram_buffer_delete_item(bufferp,
1201 buffer_size, offset, length, end)) != 0) {
1210 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1215 __checkReturn efx_rc_t
1216 efx_lic_v3_create_partition(
1217 __in efx_nic_t *enp,
1218 __in_bcount(buffer_size)
1220 __in size_t buffer_size)
1224 /* Construct empty partition */
1225 if ((rc = ef10_nvram_buffer_create(enp,
1226 NVRAM_PARTITION_TYPE_LICENSE,
1227 bufferp, buffer_size)) != 0) {
1235 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1240 __checkReturn efx_rc_t
1241 efx_lic_v3_finish_partition(
1242 __in efx_nic_t *enp,
1243 __in_bcount(buffer_size)
1245 __in size_t buffer_size)
1249 if ((rc = ef10_nvram_buffer_finish(bufferp,
1250 buffer_size)) != 0) {
1254 /* Validate completed partition */
1255 if ((rc = ef10_nvram_buffer_validate(enp, NVRAM_PARTITION_TYPE_LICENSE,
1256 bufferp, buffer_size)) != 0) {
1265 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1271 #endif /* EFSYS_OPT_MEDFORD || EFSYS_OPT_MEDFORD2 */
1273 __checkReturn efx_rc_t
1275 __in efx_nic_t *enp)
1277 const efx_lic_ops_t *elop;
1278 efx_key_stats_t eks;
1281 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1282 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
1283 EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_LIC));
1285 switch (enp->en_family) {
1288 case EFX_FAMILY_SIENA:
1289 elop = &__efx_lic_v1_ops;
1291 #endif /* EFSYS_OPT_SIENA */
1293 #if EFSYS_OPT_HUNTINGTON
1294 case EFX_FAMILY_HUNTINGTON:
1295 elop = &__efx_lic_v2_ops;
1297 #endif /* EFSYS_OPT_HUNTINGTON */
1299 #if EFSYS_OPT_MEDFORD
1300 case EFX_FAMILY_MEDFORD:
1301 elop = &__efx_lic_v3_ops;
1303 #endif /* EFSYS_OPT_MEDFORD */
1305 #if EFSYS_OPT_MEDFORD2
1306 case EFX_FAMILY_MEDFORD2:
1307 elop = &__efx_lic_v3_ops;
1309 #endif /* EFSYS_OPT_MEDFORD2 */
1317 enp->en_elop = elop;
1318 enp->en_mod_flags |= EFX_MOD_LIC;
1320 /* Probe for support */
1321 if (efx_lic_get_key_stats(enp, &eks) == 0) {
1322 enp->en_licensing_supported = B_TRUE;
1324 enp->en_licensing_supported = B_FALSE;
1330 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1335 extern __checkReturn boolean_t
1336 efx_lic_check_support(
1337 __in efx_nic_t *enp)
1339 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1340 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
1341 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1343 return (enp->en_licensing_supported);
1348 __in efx_nic_t *enp)
1350 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1351 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
1352 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1354 enp->en_elop = NULL;
1355 enp->en_mod_flags &= ~EFX_MOD_LIC;
1359 __checkReturn efx_rc_t
1360 efx_lic_update_licenses(
1361 __in efx_nic_t *enp)
1363 const efx_lic_ops_t *elop = enp->en_elop;
1366 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1367 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1369 if ((rc = elop->elo_update_licenses(enp)) != 0)
1375 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1380 __checkReturn efx_rc_t
1381 efx_lic_get_key_stats(
1382 __in efx_nic_t *enp,
1383 __out efx_key_stats_t *eksp)
1385 const efx_lic_ops_t *elop = enp->en_elop;
1388 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1389 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1391 if ((rc = elop->elo_get_key_stats(enp, eksp)) != 0)
1397 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1402 __checkReturn efx_rc_t
1404 __in efx_nic_t *enp,
1405 __in uint64_t app_id,
1406 __out boolean_t *licensedp)
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 (elop->elo_app_state == NULL)
1417 if ((rc = elop->elo_app_state(enp, app_id, licensedp)) != 0)
1423 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1428 __checkReturn efx_rc_t
1430 __in efx_nic_t *enp,
1431 __in size_t buffer_size,
1432 __out uint32_t *typep,
1433 __out size_t *lengthp,
1434 __out_opt uint8_t *bufferp)
1436 const efx_lic_ops_t *elop = enp->en_elop;
1439 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1440 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1442 if (elop->elo_get_id == NULL)
1445 if ((rc = elop->elo_get_id(enp, buffer_size, typep,
1446 lengthp, bufferp)) != 0)
1452 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1458 * Buffer management API - abstracts varying TLV format used for License
1462 __checkReturn efx_rc_t
1464 __in efx_nic_t *enp,
1465 __in_bcount(buffer_size)
1467 __in size_t buffer_size,
1468 __out uint32_t *startp)
1470 const efx_lic_ops_t *elop = enp->en_elop;
1473 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1474 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1476 if ((rc = elop->elo_find_start(enp, bufferp, buffer_size, startp)) != 0)
1482 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1487 __checkReturn efx_rc_t
1489 __in efx_nic_t *enp,
1490 __in_bcount(buffer_size)
1492 __in size_t buffer_size,
1493 __in uint32_t offset,
1494 __out uint32_t *endp)
1496 const efx_lic_ops_t *elop = enp->en_elop;
1499 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1500 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1502 rc = elop->elo_find_end(enp, bufferp, buffer_size, offset, endp);
1509 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1514 __checkReturn __success(return != B_FALSE) boolean_t
1516 __in efx_nic_t *enp,
1517 __in_bcount(buffer_size)
1519 __in size_t buffer_size,
1520 __in uint32_t offset,
1521 __out uint32_t *startp,
1522 __out uint32_t *lengthp)
1524 const efx_lic_ops_t *elop = enp->en_elop;
1526 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1527 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1529 EFSYS_ASSERT(bufferp);
1530 EFSYS_ASSERT(startp);
1531 EFSYS_ASSERT(lengthp);
1533 return (elop->elo_find_key(enp, bufferp, buffer_size, offset,
1539 * Validate that the buffer contains a single key in a recognised format.
1540 * An empty or terminator buffer is not accepted as a valid key.
1542 __checkReturn __success(return != B_FALSE) boolean_t
1543 efx_lic_validate_key(
1544 __in efx_nic_t *enp,
1545 __in_bcount(length) caddr_t keyp,
1546 __in uint32_t length)
1548 const efx_lic_ops_t *elop = enp->en_elop;
1551 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1552 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1554 if ((rc = elop->elo_validate_key(enp, keyp, length)) == B_FALSE)
1560 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1565 __checkReturn efx_rc_t
1567 __in efx_nic_t *enp,
1568 __in_bcount(buffer_size)
1570 __in size_t buffer_size,
1571 __in uint32_t offset,
1572 __in uint32_t length,
1573 __out_bcount_part(key_max_size, *lengthp)
1575 __in size_t key_max_size,
1576 __out uint32_t *lengthp)
1578 const efx_lic_ops_t *elop = enp->en_elop;
1581 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1582 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1584 if ((rc = elop->elo_read_key(enp, bufferp, buffer_size, offset,
1585 length, keyp, key_max_size, lengthp)) != 0)
1591 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1596 __checkReturn efx_rc_t
1598 __in efx_nic_t *enp,
1599 __in_bcount(buffer_size)
1601 __in size_t buffer_size,
1602 __in uint32_t offset,
1603 __in_bcount(length) caddr_t keyp,
1604 __in uint32_t length,
1605 __out uint32_t *lengthp)
1607 const efx_lic_ops_t *elop = enp->en_elop;
1610 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1611 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1613 if ((rc = elop->elo_write_key(enp, bufferp, buffer_size, offset,
1614 keyp, length, lengthp)) != 0)
1620 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1625 __checkReturn efx_rc_t
1627 __in efx_nic_t *enp,
1628 __in_bcount(buffer_size)
1630 __in size_t buffer_size,
1631 __in uint32_t offset,
1632 __in uint32_t length,
1634 __out uint32_t *deltap)
1636 const efx_lic_ops_t *elop = enp->en_elop;
1639 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1640 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1642 if ((rc = elop->elo_delete_key(enp, bufferp, buffer_size, offset,
1643 length, end, deltap)) != 0)
1649 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1654 __checkReturn efx_rc_t
1655 efx_lic_create_partition(
1656 __in efx_nic_t *enp,
1657 __in_bcount(buffer_size)
1659 __in size_t buffer_size)
1661 const efx_lic_ops_t *elop = enp->en_elop;
1664 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1665 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1667 if ((rc = elop->elo_create_partition(enp, bufferp, buffer_size)) != 0)
1673 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1679 __checkReturn efx_rc_t
1680 efx_lic_finish_partition(
1681 __in efx_nic_t *enp,
1682 __in_bcount(buffer_size)
1684 __in size_t buffer_size)
1686 const efx_lic_ops_t *elop = enp->en_elop;
1689 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1690 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1692 if ((rc = elop->elo_finish_partition(enp, bufferp, buffer_size)) != 0)
1698 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1703 #endif /* EFSYS_OPT_LICENSING */