2 * Copyright (c) 2009-2016 Solarflare Communications Inc.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
8 * 1. Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright notice,
11 * this list of conditions and the following disclaimer in the documentation
12 * and/or other materials provided with the distribution.
14 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
15 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
16 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
18 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
21 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
22 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
23 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
24 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 * The views and conclusions contained in the software and documentation are
27 * those of the authors and should not be interpreted as representing official
28 * policies, either expressed or implied, of the FreeBSD Project.
34 #if EFSYS_OPT_LICENSING
36 #include "ef10_tlv_layout.h"
38 #if EFSYS_OPT_SIENA | EFSYS_OPT_HUNTINGTON
40 __checkReturn efx_rc_t
41 efx_lic_v1v2_find_start(
43 __in_bcount(buffer_size)
45 __in size_t buffer_size,
46 __out uint32_t *startp
49 __checkReturn efx_rc_t
50 efx_lic_v1v2_find_end(
52 __in_bcount(buffer_size)
54 __in size_t buffer_size,
59 __checkReturn __success(return != B_FALSE) boolean_t
60 efx_lic_v1v2_find_key(
62 __in_bcount(buffer_size)
64 __in size_t buffer_size,
66 __out uint32_t *startp,
67 __out uint32_t *lengthp
70 __checkReturn __success(return != B_FALSE) boolean_t
71 efx_lic_v1v2_validate_key(
73 __in_bcount(length) caddr_t keyp,
77 __checkReturn efx_rc_t
78 efx_lic_v1v2_read_key(
80 __in_bcount(buffer_size)
82 __in size_t buffer_size,
85 __out_bcount_part(key_max_size, *lengthp)
87 __in size_t key_max_size,
88 __out uint32_t *lengthp
91 __checkReturn efx_rc_t
92 efx_lic_v1v2_write_key(
94 __in_bcount(buffer_size)
96 __in size_t buffer_size,
98 __in_bcount(length) caddr_t keyp,
100 __out uint32_t *lengthp
103 __checkReturn efx_rc_t
104 efx_lic_v1v2_delete_key(
106 __in_bcount(buffer_size)
108 __in size_t buffer_size,
109 __in uint32_t offset,
110 __in uint32_t length,
112 __out uint32_t *deltap
115 __checkReturn efx_rc_t
116 efx_lic_v1v2_create_partition(
118 __in_bcount(buffer_size)
120 __in size_t buffer_size
123 __checkReturn efx_rc_t
124 efx_lic_v1v2_finish_partition(
126 __in_bcount(buffer_size)
128 __in size_t buffer_size
131 #endif /* EFSYS_OPT_HUNTINGTON | EFSYS_OPT_SIENA */
136 static __checkReturn efx_rc_t
137 efx_mcdi_fc_license_update_license(
138 __in efx_nic_t *enp);
140 static __checkReturn efx_rc_t
141 efx_mcdi_fc_license_get_key_stats(
143 __out efx_key_stats_t *eksp);
145 static const efx_lic_ops_t __efx_lic_v1_ops = {
146 efx_mcdi_fc_license_update_license, /* elo_update_licenses */
147 efx_mcdi_fc_license_get_key_stats, /* elo_get_key_stats */
148 NULL, /* elo_app_state */
149 NULL, /* elo_get_id */
150 efx_lic_v1v2_find_start, /* elo_find_start */
151 efx_lic_v1v2_find_end, /* elo_find_end */
152 efx_lic_v1v2_find_key, /* elo_find_key */
153 efx_lic_v1v2_validate_key, /* elo_validate_key */
154 efx_lic_v1v2_read_key, /* elo_read_key */
155 efx_lic_v1v2_write_key, /* elo_write_key */
156 efx_lic_v1v2_delete_key, /* elo_delete_key */
157 efx_lic_v1v2_create_partition, /* elo_create_partition */
158 efx_lic_v1v2_finish_partition, /* elo_finish_partition */
161 #endif /* EFSYS_OPT_SIENA */
163 #if EFSYS_OPT_HUNTINGTON
165 static __checkReturn efx_rc_t
166 efx_mcdi_licensing_update_licenses(
167 __in efx_nic_t *enp);
169 static __checkReturn efx_rc_t
170 efx_mcdi_licensing_get_key_stats(
172 __out efx_key_stats_t *eksp);
174 static __checkReturn efx_rc_t
175 efx_mcdi_licensed_app_state(
177 __in uint64_t app_id,
178 __out boolean_t *licensedp);
180 static const efx_lic_ops_t __efx_lic_v2_ops = {
181 efx_mcdi_licensing_update_licenses, /* elo_update_licenses */
182 efx_mcdi_licensing_get_key_stats, /* elo_get_key_stats */
183 efx_mcdi_licensed_app_state, /* elo_app_state */
184 NULL, /* elo_get_id */
185 efx_lic_v1v2_find_start, /* elo_find_start */
186 efx_lic_v1v2_find_end, /* elo_find_end */
187 efx_lic_v1v2_find_key, /* elo_find_key */
188 efx_lic_v1v2_validate_key, /* elo_validate_key */
189 efx_lic_v1v2_read_key, /* elo_read_key */
190 efx_lic_v1v2_write_key, /* elo_write_key */
191 efx_lic_v1v2_delete_key, /* elo_delete_key */
192 efx_lic_v1v2_create_partition, /* elo_create_partition */
193 efx_lic_v1v2_finish_partition, /* elo_finish_partition */
196 #endif /* EFSYS_OPT_HUNTINGTON */
198 #if EFSYS_OPT_MEDFORD
200 static __checkReturn efx_rc_t
201 efx_mcdi_licensing_v3_update_licenses(
202 __in efx_nic_t *enp);
204 static __checkReturn efx_rc_t
205 efx_mcdi_licensing_v3_report_license(
207 __out efx_key_stats_t *eksp);
209 static __checkReturn efx_rc_t
210 efx_mcdi_licensing_v3_app_state(
212 __in uint64_t app_id,
213 __out boolean_t *licensedp);
215 static __checkReturn efx_rc_t
216 efx_mcdi_licensing_v3_get_id(
218 __in size_t buffer_size,
219 __out uint32_t *typep,
220 __out size_t *lengthp,
221 __out_bcount_part_opt(buffer_size, *lengthp)
224 __checkReturn efx_rc_t
225 efx_lic_v3_find_start(
227 __in_bcount(buffer_size)
229 __in size_t buffer_size,
230 __out uint32_t *startp
233 __checkReturn efx_rc_t
236 __in_bcount(buffer_size)
238 __in size_t buffer_size,
239 __in uint32_t offset,
243 __checkReturn __success(return != B_FALSE) boolean_t
246 __in_bcount(buffer_size)
248 __in size_t buffer_size,
249 __in uint32_t offset,
250 __out uint32_t *startp,
251 __out uint32_t *lengthp
254 __checkReturn __success(return != B_FALSE) boolean_t
255 efx_lic_v3_validate_key(
257 __in_bcount(length) caddr_t keyp,
261 __checkReturn efx_rc_t
264 __in_bcount(buffer_size)
266 __in size_t buffer_size,
267 __in uint32_t offset,
268 __in uint32_t length,
269 __out_bcount_part(key_max_size, *lengthp)
271 __in size_t key_max_size,
272 __out uint32_t *lengthp
275 __checkReturn efx_rc_t
276 efx_lic_v3_write_key(
278 __in_bcount(buffer_size)
280 __in size_t buffer_size,
281 __in uint32_t offset,
282 __in_bcount(length) caddr_t keyp,
283 __in uint32_t length,
284 __out uint32_t *lengthp
287 __checkReturn efx_rc_t
288 efx_lic_v3_delete_key(
290 __in_bcount(buffer_size)
292 __in size_t buffer_size,
293 __in uint32_t offset,
294 __in uint32_t length,
296 __out uint32_t *deltap
299 __checkReturn efx_rc_t
300 efx_lic_v3_create_partition(
302 __in_bcount(buffer_size)
304 __in size_t buffer_size
307 __checkReturn efx_rc_t
308 efx_lic_v3_finish_partition(
310 __in_bcount(buffer_size)
312 __in size_t buffer_size
315 static const efx_lic_ops_t __efx_lic_v3_ops = {
316 efx_mcdi_licensing_v3_update_licenses, /* elo_update_licenses */
317 efx_mcdi_licensing_v3_report_license, /* elo_get_key_stats */
318 efx_mcdi_licensing_v3_app_state, /* elo_app_state */
319 efx_mcdi_licensing_v3_get_id, /* elo_get_id */
320 efx_lic_v3_find_start, /* elo_find_start*/
321 efx_lic_v3_find_end, /* elo_find_end */
322 efx_lic_v3_find_key, /* elo_find_key */
323 efx_lic_v3_validate_key, /* elo_validate_key */
324 efx_lic_v3_read_key, /* elo_read_key */
325 efx_lic_v3_write_key, /* elo_write_key */
326 efx_lic_v3_delete_key, /* elo_delete_key */
327 efx_lic_v3_create_partition, /* elo_create_partition */
328 efx_lic_v3_finish_partition, /* elo_finish_partition */
331 #endif /* EFSYS_OPT_MEDFORD */
334 /* V1 Licensing - used in Siena Modena only */
338 static __checkReturn efx_rc_t
339 efx_mcdi_fc_license_update_license(
343 uint8_t payload[MC_CMD_FC_IN_LICENSE_LEN];
346 EFSYS_ASSERT(enp->en_family == EFX_FAMILY_SIENA);
348 (void) memset(payload, 0, sizeof (payload));
349 req.emr_cmd = MC_CMD_FC;
350 req.emr_in_buf = payload;
351 req.emr_in_length = MC_CMD_FC_IN_LICENSE_LEN;
352 req.emr_out_buf = payload;
353 req.emr_out_length = 0;
355 MCDI_IN_SET_DWORD(req, FC_IN_CMD,
356 MC_CMD_FC_OP_LICENSE);
358 MCDI_IN_SET_DWORD(req, FC_IN_LICENSE_OP,
359 MC_CMD_FC_IN_LICENSE_UPDATE_LICENSE);
361 efx_mcdi_execute(enp, &req);
363 if (req.emr_rc != 0) {
368 if (req.emr_out_length_used != 0) {
378 EFSYS_PROBE1(fail1, efx_rc_t, rc);
383 static __checkReturn efx_rc_t
384 efx_mcdi_fc_license_get_key_stats(
386 __out efx_key_stats_t *eksp)
389 uint8_t payload[MAX(MC_CMD_FC_IN_LICENSE_LEN,
390 MC_CMD_FC_OUT_LICENSE_LEN)];
393 EFSYS_ASSERT(enp->en_family == EFX_FAMILY_SIENA);
395 (void) memset(payload, 0, sizeof (payload));
396 req.emr_cmd = MC_CMD_FC;
397 req.emr_in_buf = payload;
398 req.emr_in_length = MC_CMD_FC_IN_LICENSE_LEN;
399 req.emr_out_buf = payload;
400 req.emr_out_length = MC_CMD_FC_OUT_LICENSE_LEN;
402 MCDI_IN_SET_DWORD(req, FC_IN_CMD,
403 MC_CMD_FC_OP_LICENSE);
405 MCDI_IN_SET_DWORD(req, FC_IN_LICENSE_OP,
406 MC_CMD_FC_IN_LICENSE_GET_KEY_STATS);
408 efx_mcdi_execute_quiet(enp, &req);
410 if (req.emr_rc != 0) {
415 if (req.emr_out_length_used < MC_CMD_FC_OUT_LICENSE_LEN) {
421 MCDI_OUT_DWORD(req, FC_OUT_LICENSE_VALID_KEYS);
423 MCDI_OUT_DWORD(req, FC_OUT_LICENSE_INVALID_KEYS);
424 eksp->eks_blacklisted =
425 MCDI_OUT_DWORD(req, FC_OUT_LICENSE_BLACKLISTED_KEYS);
426 eksp->eks_unverifiable = 0;
427 eksp->eks_wrong_node = 0;
428 eksp->eks_licensed_apps_lo = 0;
429 eksp->eks_licensed_apps_hi = 0;
430 eksp->eks_licensed_features_lo = 0;
431 eksp->eks_licensed_features_hi = 0;
438 EFSYS_PROBE1(fail1, efx_rc_t, rc);
443 #endif /* EFSYS_OPT_SIENA */
445 /* V1 and V2 Partition format - based on a 16-bit TLV format */
447 #if EFSYS_OPT_SIENA | EFSYS_OPT_HUNTINGTON
450 * V1/V2 format - defined in SF-108542-TC section 4.2:
451 * Type (T): 16bit - revision/HMAC algorithm
452 * Length (L): 16bit - value length in bytes
453 * Value (V): L bytes - payload
455 #define EFX_LICENSE_V1V2_PAYLOAD_LENGTH_MAX (256)
456 #define EFX_LICENSE_V1V2_HEADER_LENGTH (2 * sizeof(uint16_t))
458 __checkReturn efx_rc_t
459 efx_lic_v1v2_find_start(
461 __in_bcount(buffer_size)
463 __in size_t buffer_size,
464 __out uint32_t *startp
467 _NOTE(ARGUNUSED(enp, bufferp, buffer_size))
473 __checkReturn efx_rc_t
474 efx_lic_v1v2_find_end(
476 __in_bcount(buffer_size)
478 __in size_t buffer_size,
479 __in uint32_t offset,
483 _NOTE(ARGUNUSED(enp, bufferp, buffer_size))
485 *endp = offset + EFX_LICENSE_V1V2_HEADER_LENGTH;
489 __checkReturn __success(return != B_FALSE) boolean_t
490 efx_lic_v1v2_find_key(
492 __in_bcount(buffer_size)
494 __in size_t buffer_size,
495 __in uint32_t offset,
496 __out uint32_t *startp,
497 __out uint32_t *lengthp
504 _NOTE(ARGUNUSED(enp))
506 if ((size_t)buffer_size - offset < EFX_LICENSE_V1V2_HEADER_LENGTH)
509 tlv_type = __LE_TO_CPU_16(((uint16_t *)&bufferp[offset])[0]);
510 tlv_length = __LE_TO_CPU_16(((uint16_t *)&bufferp[offset])[1]);
511 if ((tlv_length > EFX_LICENSE_V1V2_PAYLOAD_LENGTH_MAX) ||
512 (tlv_type == 0 && tlv_length == 0)) {
516 *lengthp = tlv_length + EFX_LICENSE_V1V2_HEADER_LENGTH;
527 __checkReturn __success(return != B_FALSE) boolean_t
528 efx_lic_v1v2_validate_key(
530 __in_bcount(length) caddr_t keyp,
537 _NOTE(ARGUNUSED(enp))
539 if (length < EFX_LICENSE_V1V2_HEADER_LENGTH) {
543 tlv_type = __LE_TO_CPU_16(((uint16_t *)keyp)[0]);
544 tlv_length = __LE_TO_CPU_16(((uint16_t *)keyp)[1]);
546 if (tlv_length > EFX_LICENSE_V1V2_PAYLOAD_LENGTH_MAX) {
552 if ((tlv_length + EFX_LICENSE_V1V2_HEADER_LENGTH) != length) {
571 __checkReturn efx_rc_t
572 efx_lic_v1v2_read_key(
574 __in_bcount(buffer_size)
576 __in size_t buffer_size,
577 __in uint32_t offset,
578 __in uint32_t length,
579 __out_bcount_part(key_max_size, *lengthp)
581 __in size_t key_max_size,
582 __out uint32_t *lengthp
587 _NOTE(ARGUNUSED(enp))
588 EFSYS_ASSERT(length <= (EFX_LICENSE_V1V2_PAYLOAD_LENGTH_MAX +
589 EFX_LICENSE_V1V2_HEADER_LENGTH));
591 if (key_max_size < length) {
595 memcpy(keyp, &bufferp[offset], length);
602 EFSYS_PROBE1(fail1, efx_rc_t, rc);
607 __checkReturn efx_rc_t
608 efx_lic_v1v2_write_key(
610 __in_bcount(buffer_size)
612 __in size_t buffer_size,
613 __in uint32_t offset,
614 __in_bcount(length) caddr_t keyp,
615 __in uint32_t length,
616 __out uint32_t *lengthp
621 _NOTE(ARGUNUSED(enp))
622 EFSYS_ASSERT(length <= (EFX_LICENSE_V1V2_PAYLOAD_LENGTH_MAX +
623 EFX_LICENSE_V1V2_HEADER_LENGTH));
625 /* Ensure space for terminator remains */
626 if ((offset + length) >
627 (buffer_size - EFX_LICENSE_V1V2_HEADER_LENGTH)) {
632 memcpy(bufferp + offset, keyp, length);
639 EFSYS_PROBE1(fail1, efx_rc_t, rc);
644 __checkReturn efx_rc_t
645 efx_lic_v1v2_delete_key(
647 __in_bcount(buffer_size)
649 __in size_t buffer_size,
650 __in uint32_t offset,
651 __in uint32_t length,
653 __out uint32_t *deltap
656 uint32_t move_start = offset + length;
657 uint32_t move_length = end - move_start;
659 _NOTE(ARGUNUSED(enp))
660 EFSYS_ASSERT(end <= buffer_size);
662 /* Shift everything after the key down */
663 memmove(bufferp + offset, bufferp + move_start, move_length);
670 __checkReturn efx_rc_t
671 efx_lic_v1v2_create_partition(
673 __in_bcount(buffer_size)
675 __in size_t buffer_size
678 _NOTE(ARGUNUSED(enp))
679 EFSYS_ASSERT(EFX_LICENSE_V1V2_HEADER_LENGTH <= buffer_size);
681 /* Write terminator */
682 memset(bufferp, '\0', EFX_LICENSE_V1V2_HEADER_LENGTH);
687 __checkReturn efx_rc_t
688 efx_lic_v1v2_finish_partition(
690 __in_bcount(buffer_size)
692 __in size_t buffer_size
695 _NOTE(ARGUNUSED(enp, bufferp, buffer_size))
700 #endif /* EFSYS_OPT_HUNTINGTON | EFSYS_OPT_SIENA */
703 /* V2 Licensing - used by Huntington family only. See SF-113611-TC */
705 #if EFSYS_OPT_HUNTINGTON
707 static __checkReturn efx_rc_t
708 efx_mcdi_licensed_app_state(
710 __in uint64_t app_id,
711 __out boolean_t *licensedp)
714 uint8_t payload[MAX(MC_CMD_GET_LICENSED_APP_STATE_IN_LEN,
715 MC_CMD_GET_LICENSED_APP_STATE_OUT_LEN)];
719 EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON);
721 /* V2 licensing supports 32bit app id only */
722 if ((app_id >> 32) != 0) {
727 (void) memset(payload, 0, sizeof (payload));
728 req.emr_cmd = MC_CMD_GET_LICENSED_APP_STATE;
729 req.emr_in_buf = payload;
730 req.emr_in_length = MC_CMD_GET_LICENSED_APP_STATE_IN_LEN;
731 req.emr_out_buf = payload;
732 req.emr_out_length = MC_CMD_GET_LICENSED_APP_STATE_OUT_LEN;
734 MCDI_IN_SET_DWORD(req, GET_LICENSED_APP_STATE_IN_APP_ID,
735 app_id & 0xffffffff);
737 efx_mcdi_execute(enp, &req);
739 if (req.emr_rc != 0) {
744 if (req.emr_out_length_used < MC_CMD_GET_LICENSED_APP_STATE_OUT_LEN) {
749 app_state = (MCDI_OUT_DWORD(req, GET_LICENSED_APP_STATE_OUT_STATE));
750 if (app_state != MC_CMD_GET_LICENSED_APP_STATE_OUT_NOT_LICENSED) {
753 *licensedp = B_FALSE;
763 EFSYS_PROBE1(fail1, efx_rc_t, rc);
768 static __checkReturn efx_rc_t
769 efx_mcdi_licensing_update_licenses(
773 uint8_t payload[MC_CMD_LICENSING_IN_LEN];
776 EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON);
778 (void) memset(payload, 0, sizeof (payload));
779 req.emr_cmd = MC_CMD_LICENSING;
780 req.emr_in_buf = payload;
781 req.emr_in_length = MC_CMD_LICENSING_IN_LEN;
782 req.emr_out_buf = payload;
783 req.emr_out_length = 0;
785 MCDI_IN_SET_DWORD(req, LICENSING_IN_OP,
786 MC_CMD_LICENSING_IN_OP_UPDATE_LICENSE);
788 efx_mcdi_execute(enp, &req);
790 if (req.emr_rc != 0) {
795 if (req.emr_out_length_used != 0) {
805 EFSYS_PROBE1(fail1, efx_rc_t, rc);
810 static __checkReturn efx_rc_t
811 efx_mcdi_licensing_get_key_stats(
813 __out efx_key_stats_t *eksp)
816 uint8_t payload[MAX(MC_CMD_LICENSING_IN_LEN,
817 MC_CMD_LICENSING_OUT_LEN)];
820 EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON);
822 (void) memset(payload, 0, sizeof (payload));
823 req.emr_cmd = MC_CMD_LICENSING;
824 req.emr_in_buf = payload;
825 req.emr_in_length = MC_CMD_LICENSING_IN_LEN;
826 req.emr_out_buf = payload;
827 req.emr_out_length = MC_CMD_LICENSING_OUT_LEN;
829 MCDI_IN_SET_DWORD(req, LICENSING_IN_OP,
830 MC_CMD_LICENSING_IN_OP_GET_KEY_STATS);
832 efx_mcdi_execute(enp, &req);
834 if (req.emr_rc != 0) {
839 if (req.emr_out_length_used < MC_CMD_LICENSING_OUT_LEN) {
845 MCDI_OUT_DWORD(req, LICENSING_OUT_VALID_APP_KEYS);
847 MCDI_OUT_DWORD(req, LICENSING_OUT_INVALID_APP_KEYS);
848 eksp->eks_blacklisted =
849 MCDI_OUT_DWORD(req, LICENSING_OUT_BLACKLISTED_APP_KEYS);
850 eksp->eks_unverifiable =
851 MCDI_OUT_DWORD(req, LICENSING_OUT_UNVERIFIABLE_APP_KEYS);
852 eksp->eks_wrong_node =
853 MCDI_OUT_DWORD(req, LICENSING_OUT_WRONG_NODE_APP_KEYS);
854 eksp->eks_licensed_apps_lo = 0;
855 eksp->eks_licensed_apps_hi = 0;
856 eksp->eks_licensed_features_lo = 0;
857 eksp->eks_licensed_features_hi = 0;
864 EFSYS_PROBE1(fail1, efx_rc_t, rc);
869 #endif /* EFSYS_OPT_HUNTINGTON */
871 /* V3 Licensing - used starting from Medford family. See SF-114884-SW */
873 #if EFSYS_OPT_MEDFORD
875 static __checkReturn efx_rc_t
876 efx_mcdi_licensing_v3_update_licenses(
880 uint8_t payload[MC_CMD_LICENSING_V3_IN_LEN];
883 EFSYS_ASSERT(enp->en_family == EFX_FAMILY_MEDFORD);
885 (void) memset(payload, 0, sizeof (payload));
886 req.emr_cmd = MC_CMD_LICENSING_V3;
887 req.emr_in_buf = payload;
888 req.emr_in_length = MC_CMD_LICENSING_V3_IN_LEN;
889 req.emr_out_buf = NULL;
890 req.emr_out_length = 0;
892 MCDI_IN_SET_DWORD(req, LICENSING_V3_IN_OP,
893 MC_CMD_LICENSING_V3_IN_OP_UPDATE_LICENSE);
895 efx_mcdi_execute(enp, &req);
897 if (req.emr_rc != 0) {
905 EFSYS_PROBE1(fail1, efx_rc_t, rc);
910 static __checkReturn efx_rc_t
911 efx_mcdi_licensing_v3_report_license(
913 __out efx_key_stats_t *eksp)
916 uint8_t payload[MAX(MC_CMD_LICENSING_V3_IN_LEN,
917 MC_CMD_LICENSING_V3_OUT_LEN)];
920 EFSYS_ASSERT(enp->en_family == EFX_FAMILY_MEDFORD);
922 (void) memset(payload, 0, sizeof (payload));
923 req.emr_cmd = MC_CMD_LICENSING_V3;
924 req.emr_in_buf = payload;
925 req.emr_in_length = MC_CMD_LICENSING_V3_IN_LEN;
926 req.emr_out_buf = payload;
927 req.emr_out_length = MC_CMD_LICENSING_V3_OUT_LEN;
929 MCDI_IN_SET_DWORD(req, LICENSING_V3_IN_OP,
930 MC_CMD_LICENSING_V3_IN_OP_REPORT_LICENSE);
932 efx_mcdi_execute_quiet(enp, &req);
934 if (req.emr_rc != 0) {
939 if (req.emr_out_length_used < MC_CMD_LICENSING_V3_OUT_LEN) {
945 MCDI_OUT_DWORD(req, LICENSING_V3_OUT_VALID_KEYS);
947 MCDI_OUT_DWORD(req, LICENSING_V3_OUT_INVALID_KEYS);
948 eksp->eks_blacklisted = 0;
949 eksp->eks_unverifiable =
950 MCDI_OUT_DWORD(req, LICENSING_V3_OUT_UNVERIFIABLE_KEYS);
951 eksp->eks_wrong_node =
952 MCDI_OUT_DWORD(req, LICENSING_V3_OUT_WRONG_NODE_KEYS);
953 eksp->eks_licensed_apps_lo =
954 MCDI_OUT_DWORD(req, LICENSING_V3_OUT_LICENSED_APPS_LO);
955 eksp->eks_licensed_apps_hi =
956 MCDI_OUT_DWORD(req, LICENSING_V3_OUT_LICENSED_APPS_HI);
957 eksp->eks_licensed_features_lo =
958 MCDI_OUT_DWORD(req, LICENSING_V3_OUT_LICENSED_FEATURES_LO);
959 eksp->eks_licensed_features_hi =
960 MCDI_OUT_DWORD(req, LICENSING_V3_OUT_LICENSED_FEATURES_HI);
967 EFSYS_PROBE1(fail1, efx_rc_t, rc);
972 static __checkReturn efx_rc_t
973 efx_mcdi_licensing_v3_app_state(
975 __in uint64_t app_id,
976 __out boolean_t *licensedp)
979 uint8_t payload[MAX(MC_CMD_GET_LICENSED_V3_APP_STATE_IN_LEN,
980 MC_CMD_GET_LICENSED_V3_APP_STATE_OUT_LEN)];
984 EFSYS_ASSERT(enp->en_family == EFX_FAMILY_MEDFORD);
986 (void) memset(payload, 0, sizeof (payload));
987 req.emr_cmd = MC_CMD_GET_LICENSED_V3_APP_STATE;
988 req.emr_in_buf = payload;
989 req.emr_in_length = MC_CMD_GET_LICENSED_V3_APP_STATE_IN_LEN;
990 req.emr_out_buf = payload;
991 req.emr_out_length = MC_CMD_GET_LICENSED_V3_APP_STATE_OUT_LEN;
993 MCDI_IN_SET_DWORD(req, GET_LICENSED_V3_APP_STATE_IN_APP_ID_LO,
994 app_id & 0xffffffff);
995 MCDI_IN_SET_DWORD(req, GET_LICENSED_V3_APP_STATE_IN_APP_ID_HI,
998 efx_mcdi_execute(enp, &req);
1000 if (req.emr_rc != 0) {
1005 if (req.emr_out_length_used < MC_CMD_GET_LICENSED_V3_APP_STATE_OUT_LEN) {
1010 app_state = (MCDI_OUT_DWORD(req, GET_LICENSED_V3_APP_STATE_OUT_STATE));
1011 if (app_state != MC_CMD_GET_LICENSED_V3_APP_STATE_OUT_NOT_LICENSED) {
1012 *licensedp = B_TRUE;
1014 *licensedp = B_FALSE;
1022 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1027 static __checkReturn efx_rc_t
1028 efx_mcdi_licensing_v3_get_id(
1029 __in efx_nic_t *enp,
1030 __in size_t buffer_size,
1031 __out uint32_t *typep,
1032 __out size_t *lengthp,
1033 __out_bcount_part_opt(buffer_size, *lengthp)
1037 uint8_t payload[MAX(MC_CMD_LICENSING_GET_ID_V3_IN_LEN,
1038 MC_CMD_LICENSING_GET_ID_V3_OUT_LENMIN)];
1041 req.emr_cmd = MC_CMD_LICENSING_GET_ID_V3;
1043 if (bufferp == NULL) {
1044 /* Request id type and length only */
1045 req.emr_in_buf = bufferp;
1046 req.emr_in_length = MC_CMD_LICENSING_GET_ID_V3_IN_LEN;
1047 req.emr_out_buf = bufferp;
1048 req.emr_out_length = MC_CMD_LICENSING_GET_ID_V3_OUT_LENMIN;
1049 (void) memset(payload, 0, sizeof (payload));
1051 /* Request full buffer */
1052 req.emr_in_buf = bufferp;
1053 req.emr_in_length = MC_CMD_LICENSING_GET_ID_V3_IN_LEN;
1054 req.emr_out_buf = bufferp;
1055 req.emr_out_length = MIN(buffer_size, MC_CMD_LICENSING_GET_ID_V3_OUT_LENMAX);
1056 (void) memset(bufferp, 0, req.emr_out_length);
1059 efx_mcdi_execute_quiet(enp, &req);
1061 if (req.emr_rc != 0) {
1066 if (req.emr_out_length_used < MC_CMD_LICENSING_GET_ID_V3_OUT_LENMIN) {
1071 *typep = MCDI_OUT_DWORD(req, LICENSING_GET_ID_V3_OUT_LICENSE_TYPE);
1072 *lengthp = MCDI_OUT_DWORD(req, LICENSING_GET_ID_V3_OUT_LICENSE_ID_LENGTH);
1074 if (bufferp == NULL) {
1075 /* modify length requirements to indicate to caller the extra buffering
1076 ** needed to read the complete output.
1078 *lengthp += MC_CMD_LICENSING_GET_ID_V3_OUT_LENMIN;
1080 /* Shift ID down to start of buffer */
1082 bufferp + MC_CMD_LICENSING_GET_ID_V3_OUT_LICENSE_ID_OFST,
1084 memset(bufferp + (*lengthp), 0,
1085 MC_CMD_LICENSING_GET_ID_V3_OUT_LICENSE_ID_OFST);
1093 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1098 /* V3 format uses Huntington TLV format partition. See SF-108797-SW */
1099 #define EFX_LICENSE_V3_KEY_LENGTH_MIN (64)
1100 #define EFX_LICENSE_V3_KEY_LENGTH_MAX (160)
1102 __checkReturn efx_rc_t
1103 efx_lic_v3_find_start(
1104 __in efx_nic_t *enp,
1105 __in_bcount(buffer_size)
1107 __in size_t buffer_size,
1108 __out uint32_t *startp
1111 _NOTE(ARGUNUSED(enp))
1113 return ef10_nvram_buffer_find_item_start(bufferp, buffer_size, startp);
1116 __checkReturn efx_rc_t
1117 efx_lic_v3_find_end(
1118 __in efx_nic_t *enp,
1119 __in_bcount(buffer_size)
1121 __in size_t buffer_size,
1122 __in uint32_t offset,
1123 __out uint32_t *endp
1126 _NOTE(ARGUNUSED(enp))
1128 return ef10_nvram_buffer_find_end(bufferp, buffer_size, offset, endp);
1131 __checkReturn __success(return != B_FALSE) boolean_t
1132 efx_lic_v3_find_key(
1133 __in efx_nic_t *enp,
1134 __in_bcount(buffer_size)
1136 __in size_t buffer_size,
1137 __in uint32_t offset,
1138 __out uint32_t *startp,
1139 __out uint32_t *lengthp
1142 _NOTE(ARGUNUSED(enp))
1144 return ef10_nvram_buffer_find_item(bufferp, buffer_size,
1145 offset, startp, lengthp);
1148 __checkReturn __success(return != B_FALSE) boolean_t
1149 efx_lic_v3_validate_key(
1150 __in efx_nic_t *enp,
1151 __in_bcount(length) caddr_t keyp,
1152 __in uint32_t length
1155 /* Check key is a valid V3 key */
1159 _NOTE(ARGUNUSED(enp))
1161 if (length < EFX_LICENSE_V3_KEY_LENGTH_MIN) {
1165 if (length > EFX_LICENSE_V3_KEY_LENGTH_MAX) {
1169 key_type = ((uint8_t *)keyp)[0];
1170 key_length = ((uint8_t *)keyp)[1];
1175 if (key_length > length) {
1192 __checkReturn efx_rc_t
1193 efx_lic_v3_read_key(
1194 __in efx_nic_t *enp,
1195 __in_bcount(buffer_size)
1197 __in size_t buffer_size,
1198 __in uint32_t offset,
1199 __in uint32_t length,
1200 __out_bcount_part(key_max_size, *lengthp)
1202 __in size_t key_max_size,
1203 __out uint32_t *lengthp
1206 _NOTE(ARGUNUSED(enp))
1208 return ef10_nvram_buffer_get_item(bufferp, buffer_size,
1209 offset, length, keyp, key_max_size, lengthp);
1212 __checkReturn efx_rc_t
1213 efx_lic_v3_write_key(
1214 __in efx_nic_t *enp,
1215 __in_bcount(buffer_size)
1217 __in size_t buffer_size,
1218 __in uint32_t offset,
1219 __in_bcount(length) caddr_t keyp,
1220 __in uint32_t length,
1221 __out uint32_t *lengthp
1224 _NOTE(ARGUNUSED(enp))
1225 EFSYS_ASSERT(length <= EFX_LICENSE_V3_KEY_LENGTH_MAX);
1227 return ef10_nvram_buffer_insert_item(bufferp, buffer_size,
1228 offset, keyp, length, lengthp);
1231 __checkReturn efx_rc_t
1232 efx_lic_v3_delete_key(
1233 __in efx_nic_t *enp,
1234 __in_bcount(buffer_size)
1236 __in size_t buffer_size,
1237 __in uint32_t offset,
1238 __in uint32_t length,
1240 __out uint32_t *deltap
1245 _NOTE(ARGUNUSED(enp))
1247 if ((rc = ef10_nvram_buffer_delete_item(bufferp,
1248 buffer_size, offset, length, end)) != 0) {
1257 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1262 __checkReturn efx_rc_t
1263 efx_lic_v3_create_partition(
1264 __in efx_nic_t *enp,
1265 __in_bcount(buffer_size)
1267 __in size_t buffer_size
1272 /* Construct empty partition */
1273 if ((rc = ef10_nvram_buffer_create(enp,
1274 NVRAM_PARTITION_TYPE_LICENSE,
1275 bufferp, buffer_size)) != 0) {
1283 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1288 __checkReturn efx_rc_t
1289 efx_lic_v3_finish_partition(
1290 __in efx_nic_t *enp,
1291 __in_bcount(buffer_size)
1293 __in size_t buffer_size
1298 if ((rc = ef10_nvram_buffer_finish(bufferp,
1299 buffer_size)) != 0) {
1303 /* Validate completed partition */
1304 if ((rc = ef10_nvram_buffer_validate(enp, NVRAM_PARTITION_TYPE_LICENSE,
1305 bufferp, buffer_size)) != 0) {
1314 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1320 #endif /* EFSYS_OPT_MEDFORD */
1322 __checkReturn efx_rc_t
1324 __in efx_nic_t *enp)
1326 const efx_lic_ops_t *elop;
1327 efx_key_stats_t eks;
1330 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1331 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
1332 EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_LIC));
1334 switch (enp->en_family) {
1337 case EFX_FAMILY_SIENA:
1338 elop = &__efx_lic_v1_ops;
1340 #endif /* EFSYS_OPT_SIENA */
1342 #if EFSYS_OPT_HUNTINGTON
1343 case EFX_FAMILY_HUNTINGTON:
1344 elop = &__efx_lic_v2_ops;
1346 #endif /* EFSYS_OPT_HUNTINGTON */
1348 #if EFSYS_OPT_MEDFORD
1349 case EFX_FAMILY_MEDFORD:
1350 elop = &__efx_lic_v3_ops;
1352 #endif /* EFSYS_OPT_MEDFORD */
1360 enp->en_elop = elop;
1361 enp->en_mod_flags |= EFX_MOD_LIC;
1363 /* Probe for support */
1364 if (efx_lic_get_key_stats(enp, &eks) == 0) {
1365 enp->en_licensing_supported = B_TRUE;
1367 enp->en_licensing_supported = B_FALSE;
1373 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1378 extern __checkReturn boolean_t
1379 efx_lic_check_support(
1380 __in efx_nic_t *enp)
1382 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1383 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
1384 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1386 return enp->en_licensing_supported;
1391 __in efx_nic_t *enp)
1393 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1394 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
1395 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1397 enp->en_elop = NULL;
1398 enp->en_mod_flags &= ~EFX_MOD_LIC;
1402 __checkReturn efx_rc_t
1403 efx_lic_update_licenses(
1404 __in efx_nic_t *enp)
1406 const efx_lic_ops_t *elop = enp->en_elop;
1409 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1410 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1412 if ((rc = elop->elo_update_licenses(enp)) != 0)
1418 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1423 __checkReturn efx_rc_t
1424 efx_lic_get_key_stats(
1425 __in efx_nic_t *enp,
1426 __out efx_key_stats_t *eksp)
1428 const efx_lic_ops_t *elop = enp->en_elop;
1431 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1432 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1434 if ((rc = elop->elo_get_key_stats(enp, eksp)) != 0)
1440 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1445 __checkReturn efx_rc_t
1447 __in efx_nic_t *enp,
1448 __in uint64_t app_id,
1449 __out boolean_t *licensedp)
1451 const efx_lic_ops_t *elop = enp->en_elop;
1454 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1455 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1457 if (elop->elo_app_state == NULL)
1460 if ((rc = elop->elo_app_state(enp, app_id, licensedp)) != 0)
1466 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1471 __checkReturn efx_rc_t
1473 __in efx_nic_t *enp,
1474 __in size_t buffer_size,
1475 __out uint32_t *typep,
1476 __out size_t *lengthp,
1477 __out_opt uint8_t *bufferp
1480 const efx_lic_ops_t *elop = enp->en_elop;
1483 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1484 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1486 if (elop->elo_get_id == NULL)
1489 if ((rc = elop->elo_get_id(enp, buffer_size, typep,
1490 lengthp, bufferp)) != 0)
1496 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1501 /* Buffer management API - abstracts varying TLV format used for License partition */
1503 __checkReturn efx_rc_t
1505 __in efx_nic_t *enp,
1506 __in_bcount(buffer_size)
1508 __in size_t buffer_size,
1509 __out uint32_t *startp
1512 const efx_lic_ops_t *elop = enp->en_elop;
1515 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1516 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1518 if ((rc = elop->elo_find_start(enp, bufferp, buffer_size, startp)) != 0)
1524 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1529 __checkReturn efx_rc_t
1531 __in efx_nic_t *enp,
1532 __in_bcount(buffer_size)
1534 __in size_t buffer_size,
1535 __in uint32_t offset,
1536 __out uint32_t *endp
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_find_end(enp, bufferp, buffer_size, offset, endp)) != 0)
1551 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1556 __checkReturn __success(return != B_FALSE) boolean_t
1558 __in efx_nic_t *enp,
1559 __in_bcount(buffer_size)
1561 __in size_t buffer_size,
1562 __in uint32_t offset,
1563 __out uint32_t *startp,
1564 __out uint32_t *lengthp
1567 const efx_lic_ops_t *elop = enp->en_elop;
1569 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1570 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1572 EFSYS_ASSERT(bufferp);
1573 EFSYS_ASSERT(startp);
1574 EFSYS_ASSERT(lengthp);
1576 return (elop->elo_find_key(enp, bufferp, buffer_size, offset,
1581 /* Validate that the buffer contains a single key in a recognised format.
1582 ** An empty or terminator buffer is not accepted as a valid key.
1584 __checkReturn __success(return != B_FALSE) boolean_t
1585 efx_lic_validate_key(
1586 __in efx_nic_t *enp,
1587 __in_bcount(length) caddr_t keyp,
1588 __in uint32_t length
1591 const efx_lic_ops_t *elop = enp->en_elop;
1594 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1595 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1597 if ((rc = elop->elo_validate_key(enp, keyp, length)) == B_FALSE)
1603 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1608 __checkReturn efx_rc_t
1610 __in efx_nic_t *enp,
1611 __in_bcount(buffer_size)
1613 __in size_t buffer_size,
1614 __in uint32_t offset,
1615 __in uint32_t length,
1616 __out_bcount_part(key_max_size, *lengthp)
1618 __in size_t key_max_size,
1619 __out uint32_t *lengthp
1622 const efx_lic_ops_t *elop = enp->en_elop;
1625 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1626 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1628 if ((rc = elop->elo_read_key(enp, bufferp, buffer_size, offset,
1629 length, keyp, key_max_size, lengthp)) != 0)
1635 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1640 __checkReturn efx_rc_t
1642 __in efx_nic_t *enp,
1643 __in_bcount(buffer_size)
1645 __in size_t buffer_size,
1646 __in uint32_t offset,
1647 __in_bcount(length) caddr_t keyp,
1648 __in uint32_t length,
1649 __out uint32_t *lengthp
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_write_key(enp, bufferp, buffer_size, offset,
1659 keyp, length, lengthp)) != 0)
1665 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1670 __checkReturn efx_rc_t
1672 __in efx_nic_t *enp,
1673 __in_bcount(buffer_size)
1675 __in size_t buffer_size,
1676 __in uint32_t offset,
1677 __in uint32_t length,
1679 __out uint32_t *deltap
1682 const efx_lic_ops_t *elop = enp->en_elop;
1685 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1686 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1688 if ((rc = elop->elo_delete_key(enp, bufferp, buffer_size, offset,
1689 length, end, deltap)) != 0)
1695 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1700 __checkReturn efx_rc_t
1701 efx_lic_create_partition(
1702 __in efx_nic_t *enp,
1703 __in_bcount(buffer_size)
1705 __in size_t buffer_size
1708 const efx_lic_ops_t *elop = enp->en_elop;
1711 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1712 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1714 if ((rc = elop->elo_create_partition(enp, bufferp, buffer_size)) != 0)
1720 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1726 __checkReturn efx_rc_t
1727 efx_lic_finish_partition(
1728 __in efx_nic_t *enp,
1729 __in_bcount(buffer_size)
1731 __in size_t buffer_size
1734 const efx_lic_ops_t *elop = enp->en_elop;
1737 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1738 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1740 if ((rc = elop->elo_finish_partition(enp, bufferp, buffer_size)) != 0)
1746 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1751 #endif /* EFSYS_OPT_LICENSING */