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
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 */
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
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);
837 (void) memset(payload, 0, sizeof (payload));
838 req.emr_cmd = MC_CMD_LICENSING_V3;
839 req.emr_in_buf = payload;
840 req.emr_in_length = MC_CMD_LICENSING_V3_IN_LEN;
841 req.emr_out_buf = NULL;
842 req.emr_out_length = 0;
844 MCDI_IN_SET_DWORD(req, LICENSING_V3_IN_OP,
845 MC_CMD_LICENSING_V3_IN_OP_UPDATE_LICENSE);
847 efx_mcdi_execute(enp, &req);
849 if (req.emr_rc != 0) {
857 EFSYS_PROBE1(fail1, efx_rc_t, rc);
862 static __checkReturn efx_rc_t
863 efx_mcdi_licensing_v3_report_license(
865 __out efx_key_stats_t *eksp)
868 uint8_t payload[MAX(MC_CMD_LICENSING_V3_IN_LEN,
869 MC_CMD_LICENSING_V3_OUT_LEN)];
872 EFSYS_ASSERT(enp->en_family == EFX_FAMILY_MEDFORD);
874 (void) memset(payload, 0, sizeof (payload));
875 req.emr_cmd = MC_CMD_LICENSING_V3;
876 req.emr_in_buf = payload;
877 req.emr_in_length = MC_CMD_LICENSING_V3_IN_LEN;
878 req.emr_out_buf = payload;
879 req.emr_out_length = MC_CMD_LICENSING_V3_OUT_LEN;
881 MCDI_IN_SET_DWORD(req, LICENSING_V3_IN_OP,
882 MC_CMD_LICENSING_V3_IN_OP_REPORT_LICENSE);
884 efx_mcdi_execute_quiet(enp, &req);
886 if (req.emr_rc != 0) {
891 if (req.emr_out_length_used < MC_CMD_LICENSING_V3_OUT_LEN) {
897 MCDI_OUT_DWORD(req, LICENSING_V3_OUT_VALID_KEYS);
899 MCDI_OUT_DWORD(req, LICENSING_V3_OUT_INVALID_KEYS);
900 eksp->eks_blacklisted = 0;
901 eksp->eks_unverifiable =
902 MCDI_OUT_DWORD(req, LICENSING_V3_OUT_UNVERIFIABLE_KEYS);
903 eksp->eks_wrong_node =
904 MCDI_OUT_DWORD(req, LICENSING_V3_OUT_WRONG_NODE_KEYS);
905 eksp->eks_licensed_apps_lo =
906 MCDI_OUT_DWORD(req, LICENSING_V3_OUT_LICENSED_APPS_LO);
907 eksp->eks_licensed_apps_hi =
908 MCDI_OUT_DWORD(req, LICENSING_V3_OUT_LICENSED_APPS_HI);
909 eksp->eks_licensed_features_lo =
910 MCDI_OUT_DWORD(req, LICENSING_V3_OUT_LICENSED_FEATURES_LO);
911 eksp->eks_licensed_features_hi =
912 MCDI_OUT_DWORD(req, LICENSING_V3_OUT_LICENSED_FEATURES_HI);
919 EFSYS_PROBE1(fail1, efx_rc_t, rc);
924 static __checkReturn efx_rc_t
925 efx_mcdi_licensing_v3_app_state(
927 __in uint64_t app_id,
928 __out boolean_t *licensedp)
931 uint8_t payload[MAX(MC_CMD_GET_LICENSED_V3_APP_STATE_IN_LEN,
932 MC_CMD_GET_LICENSED_V3_APP_STATE_OUT_LEN)];
936 EFSYS_ASSERT(enp->en_family == EFX_FAMILY_MEDFORD);
938 (void) memset(payload, 0, sizeof (payload));
939 req.emr_cmd = MC_CMD_GET_LICENSED_V3_APP_STATE;
940 req.emr_in_buf = payload;
941 req.emr_in_length = MC_CMD_GET_LICENSED_V3_APP_STATE_IN_LEN;
942 req.emr_out_buf = payload;
943 req.emr_out_length = MC_CMD_GET_LICENSED_V3_APP_STATE_OUT_LEN;
945 MCDI_IN_SET_DWORD(req, GET_LICENSED_V3_APP_STATE_IN_APP_ID_LO,
946 app_id & 0xffffffff);
947 MCDI_IN_SET_DWORD(req, GET_LICENSED_V3_APP_STATE_IN_APP_ID_HI,
950 efx_mcdi_execute(enp, &req);
952 if (req.emr_rc != 0) {
957 if (req.emr_out_length_used <
958 MC_CMD_GET_LICENSED_V3_APP_STATE_OUT_LEN) {
963 app_state = (MCDI_OUT_DWORD(req, GET_LICENSED_V3_APP_STATE_OUT_STATE));
964 if (app_state != MC_CMD_GET_LICENSED_V3_APP_STATE_OUT_NOT_LICENSED) {
967 *licensedp = B_FALSE;
975 EFSYS_PROBE1(fail1, efx_rc_t, rc);
980 static __checkReturn efx_rc_t
981 efx_mcdi_licensing_v3_get_id(
983 __in size_t buffer_size,
984 __out uint32_t *typep,
985 __out size_t *lengthp,
986 __out_bcount_part_opt(buffer_size, *lengthp)
990 uint8_t payload[MAX(MC_CMD_LICENSING_GET_ID_V3_IN_LEN,
991 MC_CMD_LICENSING_GET_ID_V3_OUT_LENMIN)];
994 req.emr_cmd = MC_CMD_LICENSING_GET_ID_V3;
996 if (bufferp == NULL) {
997 /* Request id type and length only */
998 req.emr_in_buf = bufferp;
999 req.emr_in_length = MC_CMD_LICENSING_GET_ID_V3_IN_LEN;
1000 req.emr_out_buf = bufferp;
1001 req.emr_out_length = MC_CMD_LICENSING_GET_ID_V3_OUT_LENMIN;
1002 (void) memset(payload, 0, sizeof (payload));
1004 /* Request full buffer */
1005 req.emr_in_buf = bufferp;
1006 req.emr_in_length = MC_CMD_LICENSING_GET_ID_V3_IN_LEN;
1007 req.emr_out_buf = bufferp;
1008 req.emr_out_length =
1009 MIN(buffer_size, MC_CMD_LICENSING_GET_ID_V3_OUT_LENMAX);
1010 (void) memset(bufferp, 0, req.emr_out_length);
1013 efx_mcdi_execute_quiet(enp, &req);
1015 if (req.emr_rc != 0) {
1020 if (req.emr_out_length_used < MC_CMD_LICENSING_GET_ID_V3_OUT_LENMIN) {
1025 *typep = MCDI_OUT_DWORD(req, LICENSING_GET_ID_V3_OUT_LICENSE_TYPE);
1027 MCDI_OUT_DWORD(req, LICENSING_GET_ID_V3_OUT_LICENSE_ID_LENGTH);
1029 if (bufferp == NULL) {
1031 * Modify length requirements to indicate to caller the extra
1032 * buffering needed to read the complete output.
1034 *lengthp += MC_CMD_LICENSING_GET_ID_V3_OUT_LENMIN;
1036 /* Shift ID down to start of buffer */
1038 bufferp + MC_CMD_LICENSING_GET_ID_V3_OUT_LICENSE_ID_OFST,
1040 memset(bufferp + (*lengthp), 0,
1041 MC_CMD_LICENSING_GET_ID_V3_OUT_LICENSE_ID_OFST);
1049 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1054 /* V3 format uses Huntington TLV format partition. See SF-108797-SW */
1055 #define EFX_LICENSE_V3_KEY_LENGTH_MIN (64)
1056 #define EFX_LICENSE_V3_KEY_LENGTH_MAX (160)
1058 __checkReturn efx_rc_t
1059 efx_lic_v3_find_start(
1060 __in efx_nic_t *enp,
1061 __in_bcount(buffer_size)
1063 __in size_t buffer_size,
1064 __out uint32_t *startp)
1066 _NOTE(ARGUNUSED(enp))
1068 return (ef10_nvram_buffer_find_item_start(bufferp, buffer_size,
1072 __checkReturn efx_rc_t
1073 efx_lic_v3_find_end(
1074 __in efx_nic_t *enp,
1075 __in_bcount(buffer_size)
1077 __in size_t buffer_size,
1078 __in uint32_t offset,
1079 __out uint32_t *endp)
1081 _NOTE(ARGUNUSED(enp))
1083 return (ef10_nvram_buffer_find_end(bufferp, buffer_size, offset, endp));
1086 __checkReturn __success(return != B_FALSE) boolean_t
1087 efx_lic_v3_find_key(
1088 __in efx_nic_t *enp,
1089 __in_bcount(buffer_size)
1091 __in size_t buffer_size,
1092 __in uint32_t offset,
1093 __out uint32_t *startp,
1094 __out uint32_t *lengthp)
1096 _NOTE(ARGUNUSED(enp))
1098 return ef10_nvram_buffer_find_item(bufferp, buffer_size,
1099 offset, startp, lengthp);
1102 __checkReturn __success(return != B_FALSE) boolean_t
1103 efx_lic_v3_validate_key(
1104 __in efx_nic_t *enp,
1105 __in_bcount(length) caddr_t keyp,
1106 __in uint32_t length)
1108 /* Check key is a valid V3 key */
1112 _NOTE(ARGUNUSED(enp))
1114 if (length < EFX_LICENSE_V3_KEY_LENGTH_MIN) {
1118 if (length > EFX_LICENSE_V3_KEY_LENGTH_MAX) {
1122 key_type = ((uint8_t *)keyp)[0];
1123 key_length = ((uint8_t *)keyp)[1];
1128 if (key_length > length) {
1140 EFSYS_PROBE1(fail1, boolean_t, B_FALSE);
1145 __checkReturn efx_rc_t
1146 efx_lic_v3_read_key(
1147 __in efx_nic_t *enp,
1148 __in_bcount(buffer_size)
1150 __in size_t buffer_size,
1151 __in uint32_t offset,
1152 __in uint32_t length,
1153 __out_bcount_part(key_max_size, *lengthp)
1155 __in size_t key_max_size,
1156 __out uint32_t *lengthp)
1158 _NOTE(ARGUNUSED(enp))
1160 return ef10_nvram_buffer_get_item(bufferp, buffer_size,
1161 offset, length, keyp, key_max_size, lengthp);
1164 __checkReturn efx_rc_t
1165 efx_lic_v3_write_key(
1166 __in efx_nic_t *enp,
1167 __in_bcount(buffer_size)
1169 __in size_t buffer_size,
1170 __in uint32_t offset,
1171 __in_bcount(length) caddr_t keyp,
1172 __in uint32_t length,
1173 __out uint32_t *lengthp)
1175 _NOTE(ARGUNUSED(enp))
1176 EFSYS_ASSERT(length <= EFX_LICENSE_V3_KEY_LENGTH_MAX);
1178 return ef10_nvram_buffer_insert_item(bufferp, buffer_size,
1179 offset, keyp, length, lengthp);
1182 __checkReturn efx_rc_t
1183 efx_lic_v3_delete_key(
1184 __in efx_nic_t *enp,
1185 __in_bcount(buffer_size)
1187 __in size_t buffer_size,
1188 __in uint32_t offset,
1189 __in uint32_t length,
1191 __out uint32_t *deltap)
1195 _NOTE(ARGUNUSED(enp))
1197 if ((rc = ef10_nvram_buffer_delete_item(bufferp,
1198 buffer_size, offset, length, end)) != 0) {
1207 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1212 __checkReturn efx_rc_t
1213 efx_lic_v3_create_partition(
1214 __in efx_nic_t *enp,
1215 __in_bcount(buffer_size)
1217 __in size_t buffer_size)
1221 /* Construct empty partition */
1222 if ((rc = ef10_nvram_buffer_create(enp,
1223 NVRAM_PARTITION_TYPE_LICENSE,
1224 bufferp, buffer_size)) != 0) {
1232 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1237 __checkReturn efx_rc_t
1238 efx_lic_v3_finish_partition(
1239 __in efx_nic_t *enp,
1240 __in_bcount(buffer_size)
1242 __in size_t buffer_size)
1246 if ((rc = ef10_nvram_buffer_finish(bufferp,
1247 buffer_size)) != 0) {
1251 /* Validate completed partition */
1252 if ((rc = ef10_nvram_buffer_validate(enp, NVRAM_PARTITION_TYPE_LICENSE,
1253 bufferp, buffer_size)) != 0) {
1262 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1268 #endif /* EFSYS_OPT_MEDFORD */
1270 __checkReturn efx_rc_t
1272 __in efx_nic_t *enp)
1274 const efx_lic_ops_t *elop;
1275 efx_key_stats_t eks;
1278 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1279 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
1280 EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_LIC));
1282 switch (enp->en_family) {
1285 case EFX_FAMILY_SIENA:
1286 elop = &__efx_lic_v1_ops;
1288 #endif /* EFSYS_OPT_SIENA */
1290 #if EFSYS_OPT_HUNTINGTON
1291 case EFX_FAMILY_HUNTINGTON:
1292 elop = &__efx_lic_v2_ops;
1294 #endif /* EFSYS_OPT_HUNTINGTON */
1296 #if EFSYS_OPT_MEDFORD
1297 case EFX_FAMILY_MEDFORD:
1298 elop = &__efx_lic_v3_ops;
1300 #endif /* EFSYS_OPT_MEDFORD */
1308 enp->en_elop = elop;
1309 enp->en_mod_flags |= EFX_MOD_LIC;
1311 /* Probe for support */
1312 if (efx_lic_get_key_stats(enp, &eks) == 0) {
1313 enp->en_licensing_supported = B_TRUE;
1315 enp->en_licensing_supported = B_FALSE;
1321 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1326 extern __checkReturn boolean_t
1327 efx_lic_check_support(
1328 __in efx_nic_t *enp)
1330 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1331 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
1332 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1334 return (enp->en_licensing_supported);
1339 __in efx_nic_t *enp)
1341 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1342 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
1343 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1345 enp->en_elop = NULL;
1346 enp->en_mod_flags &= ~EFX_MOD_LIC;
1350 __checkReturn efx_rc_t
1351 efx_lic_update_licenses(
1352 __in efx_nic_t *enp)
1354 const efx_lic_ops_t *elop = enp->en_elop;
1357 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1358 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1360 if ((rc = elop->elo_update_licenses(enp)) != 0)
1366 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1371 __checkReturn efx_rc_t
1372 efx_lic_get_key_stats(
1373 __in efx_nic_t *enp,
1374 __out efx_key_stats_t *eksp)
1376 const efx_lic_ops_t *elop = enp->en_elop;
1379 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1380 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1382 if ((rc = elop->elo_get_key_stats(enp, eksp)) != 0)
1388 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1393 __checkReturn efx_rc_t
1395 __in efx_nic_t *enp,
1396 __in uint64_t app_id,
1397 __out boolean_t *licensedp)
1399 const efx_lic_ops_t *elop = enp->en_elop;
1402 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1403 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1405 if (elop->elo_app_state == NULL)
1408 if ((rc = elop->elo_app_state(enp, app_id, licensedp)) != 0)
1414 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1419 __checkReturn efx_rc_t
1421 __in efx_nic_t *enp,
1422 __in size_t buffer_size,
1423 __out uint32_t *typep,
1424 __out size_t *lengthp,
1425 __out_opt uint8_t *bufferp)
1427 const efx_lic_ops_t *elop = enp->en_elop;
1430 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1431 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1433 if (elop->elo_get_id == NULL)
1436 if ((rc = elop->elo_get_id(enp, buffer_size, typep,
1437 lengthp, bufferp)) != 0)
1443 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1449 * Buffer management API - abstracts varying TLV format used for License
1453 __checkReturn efx_rc_t
1455 __in efx_nic_t *enp,
1456 __in_bcount(buffer_size)
1458 __in size_t buffer_size,
1459 __out uint32_t *startp)
1461 const efx_lic_ops_t *elop = enp->en_elop;
1464 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1465 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1467 if ((rc = elop->elo_find_start(enp, bufferp, buffer_size, startp)) != 0)
1473 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1478 __checkReturn efx_rc_t
1480 __in efx_nic_t *enp,
1481 __in_bcount(buffer_size)
1483 __in size_t buffer_size,
1484 __in uint32_t offset,
1485 __out uint32_t *endp)
1487 const efx_lic_ops_t *elop = enp->en_elop;
1490 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1491 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1493 rc = elop->elo_find_end(enp, bufferp, buffer_size, offset, endp);
1500 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1505 __checkReturn __success(return != B_FALSE) boolean_t
1507 __in efx_nic_t *enp,
1508 __in_bcount(buffer_size)
1510 __in size_t buffer_size,
1511 __in uint32_t offset,
1512 __out uint32_t *startp,
1513 __out uint32_t *lengthp)
1515 const efx_lic_ops_t *elop = enp->en_elop;
1517 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1518 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1520 EFSYS_ASSERT(bufferp);
1521 EFSYS_ASSERT(startp);
1522 EFSYS_ASSERT(lengthp);
1524 return (elop->elo_find_key(enp, bufferp, buffer_size, offset,
1530 * Validate that the buffer contains a single key in a recognised format.
1531 * An empty or terminator buffer is not accepted as a valid key.
1533 __checkReturn __success(return != B_FALSE) boolean_t
1534 efx_lic_validate_key(
1535 __in efx_nic_t *enp,
1536 __in_bcount(length) caddr_t keyp,
1537 __in uint32_t length)
1539 const efx_lic_ops_t *elop = enp->en_elop;
1542 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1543 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1545 if ((rc = elop->elo_validate_key(enp, keyp, length)) == B_FALSE)
1551 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1556 __checkReturn efx_rc_t
1558 __in efx_nic_t *enp,
1559 __in_bcount(buffer_size)
1561 __in size_t buffer_size,
1562 __in uint32_t offset,
1563 __in uint32_t length,
1564 __out_bcount_part(key_max_size, *lengthp)
1566 __in size_t key_max_size,
1567 __out uint32_t *lengthp)
1569 const efx_lic_ops_t *elop = enp->en_elop;
1572 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1573 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1575 if ((rc = elop->elo_read_key(enp, bufferp, buffer_size, offset,
1576 length, keyp, key_max_size, lengthp)) != 0)
1582 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1587 __checkReturn efx_rc_t
1589 __in efx_nic_t *enp,
1590 __in_bcount(buffer_size)
1592 __in size_t buffer_size,
1593 __in uint32_t offset,
1594 __in_bcount(length) caddr_t keyp,
1595 __in uint32_t length,
1596 __out uint32_t *lengthp)
1598 const efx_lic_ops_t *elop = enp->en_elop;
1601 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1602 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1604 if ((rc = elop->elo_write_key(enp, bufferp, buffer_size, offset,
1605 keyp, length, lengthp)) != 0)
1611 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1616 __checkReturn efx_rc_t
1618 __in efx_nic_t *enp,
1619 __in_bcount(buffer_size)
1621 __in size_t buffer_size,
1622 __in uint32_t offset,
1623 __in uint32_t length,
1625 __out uint32_t *deltap)
1627 const efx_lic_ops_t *elop = enp->en_elop;
1630 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1631 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1633 if ((rc = elop->elo_delete_key(enp, bufferp, buffer_size, offset,
1634 length, end, deltap)) != 0)
1640 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1645 __checkReturn efx_rc_t
1646 efx_lic_create_partition(
1647 __in efx_nic_t *enp,
1648 __in_bcount(buffer_size)
1650 __in size_t buffer_size)
1652 const efx_lic_ops_t *elop = enp->en_elop;
1655 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1656 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1658 if ((rc = elop->elo_create_partition(enp, bufferp, buffer_size)) != 0)
1664 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1670 __checkReturn efx_rc_t
1671 efx_lic_finish_partition(
1672 __in efx_nic_t *enp,
1673 __in_bcount(buffer_size)
1675 __in size_t buffer_size)
1677 const efx_lic_ops_t *elop = enp->en_elop;
1680 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1681 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1683 if ((rc = elop->elo_finish_partition(enp, bufferp, buffer_size)) != 0)
1689 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1694 #endif /* EFSYS_OPT_LICENSING */