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)
1163 _NOTE(ARGUNUSED(enp))
1165 return ef10_nvram_buffer_get_item(bufferp, buffer_size,
1166 offset, length, &tag, keyp, key_max_size, lengthp);
1169 __checkReturn efx_rc_t
1170 efx_lic_v3_write_key(
1171 __in efx_nic_t *enp,
1172 __in_bcount(buffer_size)
1174 __in size_t buffer_size,
1175 __in uint32_t offset,
1176 __in_bcount(length) caddr_t keyp,
1177 __in uint32_t length,
1178 __out uint32_t *lengthp)
1180 _NOTE(ARGUNUSED(enp))
1181 EFSYS_ASSERT(length <= EFX_LICENSE_V3_KEY_LENGTH_MAX);
1183 return ef10_nvram_buffer_insert_item(bufferp, buffer_size,
1184 offset, TLV_TAG_LICENSE, keyp, length, lengthp);
1187 __checkReturn efx_rc_t
1188 efx_lic_v3_delete_key(
1189 __in efx_nic_t *enp,
1190 __in_bcount(buffer_size)
1192 __in size_t buffer_size,
1193 __in uint32_t offset,
1194 __in uint32_t length,
1196 __out uint32_t *deltap)
1200 _NOTE(ARGUNUSED(enp))
1202 if ((rc = ef10_nvram_buffer_delete_item(bufferp,
1203 buffer_size, offset, length, end)) != 0) {
1212 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1217 __checkReturn efx_rc_t
1218 efx_lic_v3_create_partition(
1219 __in efx_nic_t *enp,
1220 __in_bcount(buffer_size)
1222 __in size_t buffer_size)
1226 _NOTE(ARGUNUSED(enp))
1228 /* Construct empty partition */
1229 if ((rc = ef10_nvram_buffer_create(
1230 NVRAM_PARTITION_TYPE_LICENSE,
1231 bufferp, buffer_size)) != 0) {
1239 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1244 __checkReturn efx_rc_t
1245 efx_lic_v3_finish_partition(
1246 __in efx_nic_t *enp,
1247 __in_bcount(buffer_size)
1249 __in size_t buffer_size)
1253 _NOTE(ARGUNUSED(enp))
1255 if ((rc = ef10_nvram_buffer_finish(bufferp,
1256 buffer_size)) != 0) {
1260 /* Validate completed partition */
1261 if ((rc = ef10_nvram_buffer_validate(
1262 NVRAM_PARTITION_TYPE_LICENSE,
1263 bufferp, buffer_size)) != 0) {
1272 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1278 #endif /* EFSYS_OPT_MEDFORD || EFSYS_OPT_MEDFORD2 */
1280 __checkReturn efx_rc_t
1282 __in efx_nic_t *enp)
1284 const efx_lic_ops_t *elop;
1285 efx_key_stats_t eks;
1288 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1289 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
1290 EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_LIC));
1292 switch (enp->en_family) {
1295 case EFX_FAMILY_SIENA:
1296 elop = &__efx_lic_v1_ops;
1298 #endif /* EFSYS_OPT_SIENA */
1300 #if EFSYS_OPT_HUNTINGTON
1301 case EFX_FAMILY_HUNTINGTON:
1302 elop = &__efx_lic_v2_ops;
1304 #endif /* EFSYS_OPT_HUNTINGTON */
1306 #if EFSYS_OPT_MEDFORD
1307 case EFX_FAMILY_MEDFORD:
1308 elop = &__efx_lic_v3_ops;
1310 #endif /* EFSYS_OPT_MEDFORD */
1312 #if EFSYS_OPT_MEDFORD2
1313 case EFX_FAMILY_MEDFORD2:
1314 elop = &__efx_lic_v3_ops;
1316 #endif /* EFSYS_OPT_MEDFORD2 */
1324 enp->en_elop = elop;
1325 enp->en_mod_flags |= EFX_MOD_LIC;
1327 /* Probe for support */
1328 if (efx_lic_get_key_stats(enp, &eks) == 0) {
1329 enp->en_licensing_supported = B_TRUE;
1331 enp->en_licensing_supported = B_FALSE;
1337 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1342 extern __checkReturn boolean_t
1343 efx_lic_check_support(
1344 __in efx_nic_t *enp)
1346 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1347 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
1348 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1350 return (enp->en_licensing_supported);
1355 __in efx_nic_t *enp)
1357 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1358 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
1359 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1361 enp->en_elop = NULL;
1362 enp->en_mod_flags &= ~EFX_MOD_LIC;
1366 __checkReturn efx_rc_t
1367 efx_lic_update_licenses(
1368 __in efx_nic_t *enp)
1370 const efx_lic_ops_t *elop = enp->en_elop;
1373 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1374 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1376 if ((rc = elop->elo_update_licenses(enp)) != 0)
1382 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1387 __checkReturn efx_rc_t
1388 efx_lic_get_key_stats(
1389 __in efx_nic_t *enp,
1390 __out efx_key_stats_t *eksp)
1392 const efx_lic_ops_t *elop = enp->en_elop;
1395 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1396 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1398 if ((rc = elop->elo_get_key_stats(enp, eksp)) != 0)
1404 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1409 __checkReturn efx_rc_t
1411 __in efx_nic_t *enp,
1412 __in uint64_t app_id,
1413 __out boolean_t *licensedp)
1415 const efx_lic_ops_t *elop = enp->en_elop;
1418 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1419 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1421 if (elop->elo_app_state == NULL)
1424 if ((rc = elop->elo_app_state(enp, app_id, licensedp)) != 0)
1430 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1435 __checkReturn efx_rc_t
1437 __in efx_nic_t *enp,
1438 __in size_t buffer_size,
1439 __out uint32_t *typep,
1440 __out size_t *lengthp,
1441 __out_opt uint8_t *bufferp)
1443 const efx_lic_ops_t *elop = enp->en_elop;
1446 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1447 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1449 if (elop->elo_get_id == NULL)
1452 if ((rc = elop->elo_get_id(enp, buffer_size, typep,
1453 lengthp, bufferp)) != 0)
1459 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1465 * Buffer management API - abstracts varying TLV format used for License
1469 __checkReturn efx_rc_t
1471 __in efx_nic_t *enp,
1472 __in_bcount(buffer_size)
1474 __in size_t buffer_size,
1475 __out uint32_t *startp)
1477 const efx_lic_ops_t *elop = enp->en_elop;
1480 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1481 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1483 if ((rc = elop->elo_find_start(enp, bufferp, buffer_size, startp)) != 0)
1489 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1494 __checkReturn efx_rc_t
1496 __in efx_nic_t *enp,
1497 __in_bcount(buffer_size)
1499 __in size_t buffer_size,
1500 __in uint32_t offset,
1501 __out uint32_t *endp)
1503 const efx_lic_ops_t *elop = enp->en_elop;
1506 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1507 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1509 rc = elop->elo_find_end(enp, bufferp, buffer_size, offset, endp);
1516 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1521 __checkReturn __success(return != B_FALSE) boolean_t
1523 __in efx_nic_t *enp,
1524 __in_bcount(buffer_size)
1526 __in size_t buffer_size,
1527 __in uint32_t offset,
1528 __out uint32_t *startp,
1529 __out uint32_t *lengthp)
1531 const efx_lic_ops_t *elop = enp->en_elop;
1533 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1534 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1536 EFSYS_ASSERT(bufferp);
1537 EFSYS_ASSERT(startp);
1538 EFSYS_ASSERT(lengthp);
1540 return (elop->elo_find_key(enp, bufferp, buffer_size, offset,
1546 * Validate that the buffer contains a single key in a recognised format.
1547 * An empty or terminator buffer is not accepted as a valid key.
1549 __checkReturn __success(return != B_FALSE) boolean_t
1550 efx_lic_validate_key(
1551 __in efx_nic_t *enp,
1552 __in_bcount(length) caddr_t keyp,
1553 __in uint32_t length)
1555 const efx_lic_ops_t *elop = enp->en_elop;
1558 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1559 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1561 if ((rc = elop->elo_validate_key(enp, keyp, length)) == B_FALSE)
1567 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1572 __checkReturn efx_rc_t
1574 __in efx_nic_t *enp,
1575 __in_bcount(buffer_size)
1577 __in size_t buffer_size,
1578 __in uint32_t offset,
1579 __in uint32_t length,
1580 __out_bcount_part(key_max_size, *lengthp)
1582 __in size_t key_max_size,
1583 __out uint32_t *lengthp)
1585 const efx_lic_ops_t *elop = enp->en_elop;
1588 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1589 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1591 if ((rc = elop->elo_read_key(enp, bufferp, buffer_size, offset,
1592 length, keyp, key_max_size, lengthp)) != 0)
1598 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1603 __checkReturn efx_rc_t
1605 __in efx_nic_t *enp,
1606 __in_bcount(buffer_size)
1608 __in size_t buffer_size,
1609 __in uint32_t offset,
1610 __in_bcount(length) caddr_t keyp,
1611 __in uint32_t length,
1612 __out uint32_t *lengthp)
1614 const efx_lic_ops_t *elop = enp->en_elop;
1617 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1618 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1620 if ((rc = elop->elo_write_key(enp, bufferp, buffer_size, offset,
1621 keyp, length, lengthp)) != 0)
1627 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1632 __checkReturn efx_rc_t
1634 __in efx_nic_t *enp,
1635 __in_bcount(buffer_size)
1637 __in size_t buffer_size,
1638 __in uint32_t offset,
1639 __in uint32_t length,
1641 __out uint32_t *deltap)
1643 const efx_lic_ops_t *elop = enp->en_elop;
1646 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1647 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1649 if ((rc = elop->elo_delete_key(enp, bufferp, buffer_size, offset,
1650 length, end, deltap)) != 0)
1656 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1661 __checkReturn efx_rc_t
1662 efx_lic_create_partition(
1663 __in efx_nic_t *enp,
1664 __in_bcount(buffer_size)
1666 __in size_t buffer_size)
1668 const efx_lic_ops_t *elop = enp->en_elop;
1671 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1672 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1674 if ((rc = elop->elo_create_partition(enp, bufferp, buffer_size)) != 0)
1680 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1686 __checkReturn efx_rc_t
1687 efx_lic_finish_partition(
1688 __in efx_nic_t *enp,
1689 __in_bcount(buffer_size)
1691 __in size_t buffer_size)
1693 const efx_lic_ops_t *elop = enp->en_elop;
1696 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1697 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1699 if ((rc = elop->elo_finish_partition(enp, bufferp, buffer_size)) != 0)
1705 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1710 #endif /* EFSYS_OPT_LICENSING */