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.
31 #include <sys/cdefs.h>
32 __FBSDID("$FreeBSD$");
37 #if EFSYS_OPT_LICENSING
39 #include "ef10_tlv_layout.h"
41 #if EFSYS_OPT_SIENA | EFSYS_OPT_HUNTINGTON
43 __checkReturn efx_rc_t
44 efx_lic_v1v2_find_start(
46 __in_bcount(buffer_size)
48 __in size_t buffer_size,
49 __out uint32_t *startp
52 __checkReturn efx_rc_t
53 efx_lic_v1v2_find_end(
55 __in_bcount(buffer_size)
57 __in size_t buffer_size,
62 __checkReturn __success(return != B_FALSE) boolean_t
63 efx_lic_v1v2_find_key(
65 __in_bcount(buffer_size)
67 __in size_t buffer_size,
69 __out uint32_t *startp,
70 __out uint32_t *lengthp
73 __checkReturn __success(return != B_FALSE) boolean_t
74 efx_lic_v1v2_validate_key(
76 __in_bcount(length) caddr_t keyp,
80 __checkReturn efx_rc_t
81 efx_lic_v1v2_read_key(
83 __in_bcount(buffer_size)
85 __in size_t buffer_size,
88 __out_bcount_part(key_max_size, *lengthp)
90 __in size_t key_max_size,
91 __out uint32_t *lengthp
94 __checkReturn efx_rc_t
95 efx_lic_v1v2_write_key(
97 __in_bcount(buffer_size)
99 __in size_t buffer_size,
100 __in uint32_t offset,
101 __in_bcount(length) caddr_t keyp,
102 __in uint32_t length,
103 __out uint32_t *lengthp
106 __checkReturn efx_rc_t
107 efx_lic_v1v2_delete_key(
109 __in_bcount(buffer_size)
111 __in size_t buffer_size,
112 __in uint32_t offset,
113 __in uint32_t length,
115 __out uint32_t *deltap
118 __checkReturn efx_rc_t
119 efx_lic_v1v2_create_partition(
121 __in_bcount(buffer_size)
123 __in size_t buffer_size
126 __checkReturn efx_rc_t
127 efx_lic_v1v2_finish_partition(
129 __in_bcount(buffer_size)
131 __in size_t buffer_size
134 #endif /* EFSYS_OPT_HUNTINGTON | EFSYS_OPT_SIENA */
139 static __checkReturn efx_rc_t
140 efx_mcdi_fc_license_update_license(
141 __in efx_nic_t *enp);
143 static __checkReturn efx_rc_t
144 efx_mcdi_fc_license_get_key_stats(
146 __out efx_key_stats_t *eksp);
148 static const efx_lic_ops_t __efx_lic_v1_ops = {
149 efx_mcdi_fc_license_update_license, /* elo_update_licenses */
150 efx_mcdi_fc_license_get_key_stats, /* elo_get_key_stats */
151 NULL, /* elo_app_state */
152 NULL, /* elo_get_id */
153 efx_lic_v1v2_find_start, /* elo_find_start */
154 efx_lic_v1v2_find_end, /* elo_find_end */
155 efx_lic_v1v2_find_key, /* elo_find_key */
156 efx_lic_v1v2_validate_key, /* elo_validate_key */
157 efx_lic_v1v2_read_key, /* elo_read_key */
158 efx_lic_v1v2_write_key, /* elo_write_key */
159 efx_lic_v1v2_delete_key, /* elo_delete_key */
160 efx_lic_v1v2_create_partition, /* elo_create_partition */
161 efx_lic_v1v2_finish_partition, /* elo_finish_partition */
164 #endif /* EFSYS_OPT_SIENA */
166 #if EFSYS_OPT_HUNTINGTON
168 static __checkReturn efx_rc_t
169 efx_mcdi_licensing_update_licenses(
170 __in efx_nic_t *enp);
172 static __checkReturn efx_rc_t
173 efx_mcdi_licensing_get_key_stats(
175 __out efx_key_stats_t *eksp);
177 static __checkReturn efx_rc_t
178 efx_mcdi_licensed_app_state(
180 __in uint64_t app_id,
181 __out boolean_t *licensedp);
183 static const efx_lic_ops_t __efx_lic_v2_ops = {
184 efx_mcdi_licensing_update_licenses, /* elo_update_licenses */
185 efx_mcdi_licensing_get_key_stats, /* elo_get_key_stats */
186 efx_mcdi_licensed_app_state, /* elo_app_state */
187 NULL, /* elo_get_id */
188 efx_lic_v1v2_find_start, /* elo_find_start */
189 efx_lic_v1v2_find_end, /* elo_find_end */
190 efx_lic_v1v2_find_key, /* elo_find_key */
191 efx_lic_v1v2_validate_key, /* elo_validate_key */
192 efx_lic_v1v2_read_key, /* elo_read_key */
193 efx_lic_v1v2_write_key, /* elo_write_key */
194 efx_lic_v1v2_delete_key, /* elo_delete_key */
195 efx_lic_v1v2_create_partition, /* elo_create_partition */
196 efx_lic_v1v2_finish_partition, /* elo_finish_partition */
199 #endif /* EFSYS_OPT_HUNTINGTON */
201 #if EFSYS_OPT_MEDFORD
203 static __checkReturn efx_rc_t
204 efx_mcdi_licensing_v3_update_licenses(
205 __in efx_nic_t *enp);
207 static __checkReturn efx_rc_t
208 efx_mcdi_licensing_v3_report_license(
210 __out efx_key_stats_t *eksp);
212 static __checkReturn efx_rc_t
213 efx_mcdi_licensing_v3_app_state(
215 __in uint64_t app_id,
216 __out boolean_t *licensedp);
218 static __checkReturn efx_rc_t
219 efx_mcdi_licensing_v3_get_id(
221 __in size_t buffer_size,
222 __out uint32_t *typep,
223 __out size_t *lengthp,
224 __out_bcount_part_opt(buffer_size, *lengthp)
227 __checkReturn efx_rc_t
228 efx_lic_v3_find_start(
230 __in_bcount(buffer_size)
232 __in size_t buffer_size,
233 __out uint32_t *startp
236 __checkReturn efx_rc_t
239 __in_bcount(buffer_size)
241 __in size_t buffer_size,
242 __in uint32_t offset,
246 __checkReturn __success(return != B_FALSE) boolean_t
249 __in_bcount(buffer_size)
251 __in size_t buffer_size,
252 __in uint32_t offset,
253 __out uint32_t *startp,
254 __out uint32_t *lengthp
257 __checkReturn __success(return != B_FALSE) boolean_t
258 efx_lic_v3_validate_key(
260 __in_bcount(length) caddr_t keyp,
264 __checkReturn efx_rc_t
267 __in_bcount(buffer_size)
269 __in size_t buffer_size,
270 __in uint32_t offset,
271 __in uint32_t length,
272 __out_bcount_part(key_max_size, *lengthp)
274 __in size_t key_max_size,
275 __out uint32_t *lengthp
278 __checkReturn efx_rc_t
279 efx_lic_v3_write_key(
281 __in_bcount(buffer_size)
283 __in size_t buffer_size,
284 __in uint32_t offset,
285 __in_bcount(length) caddr_t keyp,
286 __in uint32_t length,
287 __out uint32_t *lengthp
290 __checkReturn efx_rc_t
291 efx_lic_v3_delete_key(
293 __in_bcount(buffer_size)
295 __in size_t buffer_size,
296 __in uint32_t offset,
297 __in uint32_t length,
299 __out uint32_t *deltap
302 __checkReturn efx_rc_t
303 efx_lic_v3_create_partition(
305 __in_bcount(buffer_size)
307 __in size_t buffer_size
310 __checkReturn efx_rc_t
311 efx_lic_v3_finish_partition(
313 __in_bcount(buffer_size)
315 __in size_t buffer_size
318 static const efx_lic_ops_t __efx_lic_v3_ops = {
319 efx_mcdi_licensing_v3_update_licenses, /* elo_update_licenses */
320 efx_mcdi_licensing_v3_report_license, /* elo_get_key_stats */
321 efx_mcdi_licensing_v3_app_state, /* elo_app_state */
322 efx_mcdi_licensing_v3_get_id, /* elo_get_id */
323 efx_lic_v3_find_start, /* elo_find_start*/
324 efx_lic_v3_find_end, /* elo_find_end */
325 efx_lic_v3_find_key, /* elo_find_key */
326 efx_lic_v3_validate_key, /* elo_validate_key */
327 efx_lic_v3_read_key, /* elo_read_key */
328 efx_lic_v3_write_key, /* elo_write_key */
329 efx_lic_v3_delete_key, /* elo_delete_key */
330 efx_lic_v3_create_partition, /* elo_create_partition */
331 efx_lic_v3_finish_partition, /* elo_finish_partition */
334 #endif /* EFSYS_OPT_MEDFORD */
337 /* V1 Licensing - used in Siena Modena only */
341 static __checkReturn efx_rc_t
342 efx_mcdi_fc_license_update_license(
346 uint8_t payload[MC_CMD_FC_IN_LICENSE_LEN];
349 EFSYS_ASSERT(enp->en_family == EFX_FAMILY_SIENA);
351 (void) memset(payload, 0, sizeof (payload));
352 req.emr_cmd = MC_CMD_FC;
353 req.emr_in_buf = payload;
354 req.emr_in_length = MC_CMD_FC_IN_LICENSE_LEN;
355 req.emr_out_buf = payload;
356 req.emr_out_length = 0;
358 MCDI_IN_SET_DWORD(req, FC_IN_CMD,
359 MC_CMD_FC_OP_LICENSE);
361 MCDI_IN_SET_DWORD(req, FC_IN_LICENSE_OP,
362 MC_CMD_FC_IN_LICENSE_UPDATE_LICENSE);
364 efx_mcdi_execute(enp, &req);
366 if (req.emr_rc != 0) {
371 if (req.emr_out_length_used != 0) {
381 EFSYS_PROBE1(fail1, efx_rc_t, rc);
386 static __checkReturn efx_rc_t
387 efx_mcdi_fc_license_get_key_stats(
389 __out efx_key_stats_t *eksp)
392 uint8_t payload[MAX(MC_CMD_FC_IN_LICENSE_LEN,
393 MC_CMD_FC_OUT_LICENSE_LEN)];
396 EFSYS_ASSERT(enp->en_family == EFX_FAMILY_SIENA);
398 (void) memset(payload, 0, sizeof (payload));
399 req.emr_cmd = MC_CMD_FC;
400 req.emr_in_buf = payload;
401 req.emr_in_length = MC_CMD_FC_IN_LICENSE_LEN;
402 req.emr_out_buf = payload;
403 req.emr_out_length = MC_CMD_FC_OUT_LICENSE_LEN;
405 MCDI_IN_SET_DWORD(req, FC_IN_CMD,
406 MC_CMD_FC_OP_LICENSE);
408 MCDI_IN_SET_DWORD(req, FC_IN_LICENSE_OP,
409 MC_CMD_FC_IN_LICENSE_GET_KEY_STATS);
411 efx_mcdi_execute_quiet(enp, &req);
413 if (req.emr_rc != 0) {
418 if (req.emr_out_length_used < MC_CMD_FC_OUT_LICENSE_LEN) {
424 MCDI_OUT_DWORD(req, FC_OUT_LICENSE_VALID_KEYS);
426 MCDI_OUT_DWORD(req, FC_OUT_LICENSE_INVALID_KEYS);
427 eksp->eks_blacklisted =
428 MCDI_OUT_DWORD(req, FC_OUT_LICENSE_BLACKLISTED_KEYS);
429 eksp->eks_unverifiable = 0;
430 eksp->eks_wrong_node = 0;
431 eksp->eks_licensed_apps_lo = 0;
432 eksp->eks_licensed_apps_hi = 0;
433 eksp->eks_licensed_features_lo = 0;
434 eksp->eks_licensed_features_hi = 0;
441 EFSYS_PROBE1(fail1, efx_rc_t, rc);
446 #endif /* EFSYS_OPT_SIENA */
448 /* V1 and V2 Partition format - based on a 16-bit TLV format */
450 #if EFSYS_OPT_SIENA | EFSYS_OPT_HUNTINGTON
453 * V1/V2 format - defined in SF-108542-TC section 4.2:
454 * Type (T): 16bit - revision/HMAC algorithm
455 * Length (L): 16bit - value length in bytes
456 * Value (V): L bytes - payload
458 #define EFX_LICENSE_V1V2_PAYLOAD_LENGTH_MAX (256)
459 #define EFX_LICENSE_V1V2_HEADER_LENGTH (2*sizeof(uint16_t))
461 __checkReturn efx_rc_t
462 efx_lic_v1v2_find_start(
464 __in_bcount(buffer_size)
466 __in size_t buffer_size,
467 __out uint32_t *startp
470 _NOTE(ARGUNUSED(enp, bufferp, buffer_size))
476 __checkReturn efx_rc_t
477 efx_lic_v1v2_find_end(
479 __in_bcount(buffer_size)
481 __in size_t buffer_size,
482 __in uint32_t offset,
486 _NOTE(ARGUNUSED(enp, bufferp, buffer_size))
488 *endp = offset + EFX_LICENSE_V1V2_HEADER_LENGTH;
492 __checkReturn __success(return != B_FALSE) boolean_t
493 efx_lic_v1v2_find_key(
495 __in_bcount(buffer_size)
497 __in size_t buffer_size,
498 __in uint32_t offset,
499 __out uint32_t *startp,
500 __out uint32_t *lengthp
507 _NOTE(ARGUNUSED(enp))
509 if ((size_t)buffer_size - offset < EFX_LICENSE_V1V2_HEADER_LENGTH)
512 tlv_type = __LE_TO_CPU_16(((uint16_t*)&bufferp[offset])[0]);
513 tlv_length = __LE_TO_CPU_16(((uint16_t*)&bufferp[offset])[1]);
514 if ((tlv_length > EFX_LICENSE_V1V2_PAYLOAD_LENGTH_MAX) ||
515 (tlv_type == 0 && tlv_length == 0)) {
519 *lengthp = tlv_length + EFX_LICENSE_V1V2_HEADER_LENGTH;
530 __checkReturn __success(return != B_FALSE) boolean_t
531 efx_lic_v1v2_validate_key(
533 __in_bcount(length) caddr_t keyp,
537 const efx_lic_ops_t *elop = enp->en_elop;
542 _NOTE(ARGUNUSED(enp))
544 if (length < EFX_LICENSE_V1V2_HEADER_LENGTH) {
548 tlv_type = __LE_TO_CPU_16(((uint16_t*)keyp)[0]);
549 tlv_length = __LE_TO_CPU_16(((uint16_t*)keyp)[1]);
551 if (tlv_length > EFX_LICENSE_V1V2_PAYLOAD_LENGTH_MAX) {
557 if ((tlv_length + EFX_LICENSE_V1V2_HEADER_LENGTH) != length) {
576 __checkReturn efx_rc_t
577 efx_lic_v1v2_read_key(
579 __in_bcount(buffer_size)
581 __in size_t buffer_size,
582 __in uint32_t offset,
583 __in uint32_t length,
584 __out_bcount_part(key_max_size, *lengthp)
586 __in size_t key_max_size,
587 __out uint32_t *lengthp
592 _NOTE(ARGUNUSED(enp))
593 EFSYS_ASSERT(length <= (EFX_LICENSE_V1V2_PAYLOAD_LENGTH_MAX +
594 EFX_LICENSE_V1V2_HEADER_LENGTH));
596 if (key_max_size < length) {
600 memcpy(keyp, &bufferp[offset], length);
607 EFSYS_PROBE1(fail1, efx_rc_t, rc);
612 __checkReturn efx_rc_t
613 efx_lic_v1v2_write_key(
615 __in_bcount(buffer_size)
617 __in size_t buffer_size,
618 __in uint32_t offset,
619 __in_bcount(length) caddr_t keyp,
620 __in uint32_t length,
621 __out uint32_t *lengthp
626 _NOTE(ARGUNUSED(enp))
627 EFSYS_ASSERT(length <= (EFX_LICENSE_V1V2_PAYLOAD_LENGTH_MAX +
628 EFX_LICENSE_V1V2_HEADER_LENGTH));
630 // Ensure space for terminator remains
631 if ((offset + length) >
632 (buffer_size - EFX_LICENSE_V1V2_HEADER_LENGTH) ) {
637 memcpy(bufferp + offset, keyp, length);
644 EFSYS_PROBE1(fail1, efx_rc_t, rc);
649 __checkReturn efx_rc_t
650 efx_lic_v1v2_delete_key(
652 __in_bcount(buffer_size)
654 __in size_t buffer_size,
655 __in uint32_t offset,
656 __in uint32_t length,
658 __out uint32_t *deltap
662 uint32_t move_start = offset + length;
663 uint32_t move_length = end - move_start;
665 _NOTE(ARGUNUSED(enp))
666 EFSYS_ASSERT(end <= buffer_size);
668 // Shift everything after the key down
669 memmove(bufferp + offset, bufferp + move_start, move_length);
676 __checkReturn efx_rc_t
677 efx_lic_v1v2_create_partition(
679 __in_bcount(buffer_size)
681 __in size_t buffer_size
684 _NOTE(ARGUNUSED(enp))
685 EFSYS_ASSERT(EFX_LICENSE_V1V2_HEADER_LENGTH <= buffer_size);
688 memset(bufferp, '\0', EFX_LICENSE_V1V2_HEADER_LENGTH);
693 __checkReturn efx_rc_t
694 efx_lic_v1v2_finish_partition(
696 __in_bcount(buffer_size)
698 __in size_t buffer_size
701 _NOTE(ARGUNUSED(enp, bufferp, buffer_size))
706 #endif /* EFSYS_OPT_HUNTINGTON | EFSYS_OPT_SIENA */
709 /* V2 Licensing - used by Huntington family only. See SF-113611-TC */
711 #if EFSYS_OPT_HUNTINGTON
713 static __checkReturn efx_rc_t
714 efx_mcdi_licensed_app_state(
716 __in uint64_t app_id,
717 __out boolean_t *licensedp)
720 uint8_t payload[MAX(MC_CMD_GET_LICENSED_APP_STATE_IN_LEN,
721 MC_CMD_GET_LICENSED_APP_STATE_OUT_LEN)];
725 EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON);
727 /* V2 licensing supports 32bit app id only */
728 if ((app_id >> 32) != 0) {
733 (void) memset(payload, 0, sizeof (payload));
734 req.emr_cmd = MC_CMD_GET_LICENSED_APP_STATE;
735 req.emr_in_buf = payload;
736 req.emr_in_length = MC_CMD_GET_LICENSED_APP_STATE_IN_LEN;
737 req.emr_out_buf = payload;
738 req.emr_out_length = MC_CMD_GET_LICENSED_APP_STATE_OUT_LEN;
740 MCDI_IN_SET_DWORD(req, GET_LICENSED_APP_STATE_IN_APP_ID,
741 app_id & 0xffffffff);
743 efx_mcdi_execute(enp, &req);
745 if (req.emr_rc != 0) {
750 if (req.emr_out_length_used < MC_CMD_GET_LICENSED_APP_STATE_OUT_LEN) {
755 app_state = (MCDI_OUT_DWORD(req, GET_LICENSED_APP_STATE_OUT_STATE));
756 if (app_state != MC_CMD_GET_LICENSED_APP_STATE_OUT_NOT_LICENSED) {
759 *licensedp = B_FALSE;
769 EFSYS_PROBE1(fail1, efx_rc_t, rc);
774 static __checkReturn efx_rc_t
775 efx_mcdi_licensing_update_licenses(
779 uint8_t payload[MC_CMD_LICENSING_IN_LEN];
782 EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON);
784 (void) memset(payload, 0, sizeof (payload));
785 req.emr_cmd = MC_CMD_LICENSING;
786 req.emr_in_buf = payload;
787 req.emr_in_length = MC_CMD_LICENSING_IN_LEN;
788 req.emr_out_buf = payload;
789 req.emr_out_length = 0;
791 MCDI_IN_SET_DWORD(req, LICENSING_IN_OP,
792 MC_CMD_LICENSING_IN_OP_UPDATE_LICENSE);
794 efx_mcdi_execute(enp, &req);
796 if (req.emr_rc != 0) {
801 if (req.emr_out_length_used != 0) {
811 EFSYS_PROBE1(fail1, efx_rc_t, rc);
816 static __checkReturn efx_rc_t
817 efx_mcdi_licensing_get_key_stats(
819 __out efx_key_stats_t *eksp)
822 uint8_t payload[MAX(MC_CMD_LICENSING_IN_LEN,
823 MC_CMD_LICENSING_OUT_LEN)];
826 EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON);
828 (void) memset(payload, 0, sizeof (payload));
829 req.emr_cmd = MC_CMD_LICENSING;
830 req.emr_in_buf = payload;
831 req.emr_in_length = MC_CMD_LICENSING_IN_LEN;
832 req.emr_out_buf = payload;
833 req.emr_out_length = MC_CMD_LICENSING_OUT_LEN;
835 MCDI_IN_SET_DWORD(req, LICENSING_IN_OP,
836 MC_CMD_LICENSING_IN_OP_GET_KEY_STATS);
838 efx_mcdi_execute(enp, &req);
840 if (req.emr_rc != 0) {
845 if (req.emr_out_length_used < MC_CMD_LICENSING_OUT_LEN) {
851 MCDI_OUT_DWORD(req, LICENSING_OUT_VALID_APP_KEYS);
853 MCDI_OUT_DWORD(req, LICENSING_OUT_INVALID_APP_KEYS);
854 eksp->eks_blacklisted =
855 MCDI_OUT_DWORD(req, LICENSING_OUT_BLACKLISTED_APP_KEYS);
856 eksp->eks_unverifiable =
857 MCDI_OUT_DWORD(req, LICENSING_OUT_UNVERIFIABLE_APP_KEYS);
858 eksp->eks_wrong_node =
859 MCDI_OUT_DWORD(req, LICENSING_OUT_WRONG_NODE_APP_KEYS);
860 eksp->eks_licensed_apps_lo = 0;
861 eksp->eks_licensed_apps_hi = 0;
862 eksp->eks_licensed_features_lo = 0;
863 eksp->eks_licensed_features_hi = 0;
870 EFSYS_PROBE1(fail1, efx_rc_t, rc);
875 #endif /* EFSYS_OPT_HUNTINGTON */
877 /* V3 Licensing - used starting from Medford family. See SF-114884-SW */
879 #if EFSYS_OPT_MEDFORD
881 static __checkReturn efx_rc_t
882 efx_mcdi_licensing_v3_update_licenses(
886 uint8_t payload[MC_CMD_LICENSING_V3_IN_LEN];
889 EFSYS_ASSERT(enp->en_family == EFX_FAMILY_MEDFORD);
891 (void) memset(payload, 0, sizeof (payload));
892 req.emr_cmd = MC_CMD_LICENSING_V3;
893 req.emr_in_buf = payload;
894 req.emr_in_length = MC_CMD_LICENSING_V3_IN_LEN;
895 req.emr_out_buf = NULL;
896 req.emr_out_length = 0;
898 MCDI_IN_SET_DWORD(req, LICENSING_V3_IN_OP,
899 MC_CMD_LICENSING_V3_IN_OP_UPDATE_LICENSE);
901 efx_mcdi_execute(enp, &req);
903 if (req.emr_rc != 0) {
911 EFSYS_PROBE1(fail1, efx_rc_t, rc);
916 static __checkReturn efx_rc_t
917 efx_mcdi_licensing_v3_report_license(
919 __out efx_key_stats_t *eksp)
922 uint8_t payload[MAX(MC_CMD_LICENSING_V3_IN_LEN,
923 MC_CMD_LICENSING_V3_OUT_LEN)];
926 EFSYS_ASSERT(enp->en_family == EFX_FAMILY_MEDFORD);
928 (void) memset(payload, 0, sizeof (payload));
929 req.emr_cmd = MC_CMD_LICENSING_V3;
930 req.emr_in_buf = payload;
931 req.emr_in_length = MC_CMD_LICENSING_V3_IN_LEN;
932 req.emr_out_buf = payload;
933 req.emr_out_length = MC_CMD_LICENSING_V3_OUT_LEN;
935 MCDI_IN_SET_DWORD(req, LICENSING_V3_IN_OP,
936 MC_CMD_LICENSING_V3_IN_OP_REPORT_LICENSE);
938 efx_mcdi_execute_quiet(enp, &req);
940 if (req.emr_rc != 0) {
945 if (req.emr_out_length_used < MC_CMD_LICENSING_V3_OUT_LEN) {
951 MCDI_OUT_DWORD(req, LICENSING_V3_OUT_VALID_KEYS);
953 MCDI_OUT_DWORD(req, LICENSING_V3_OUT_INVALID_KEYS);
954 eksp->eks_blacklisted = 0;
955 eksp->eks_unverifiable =
956 MCDI_OUT_DWORD(req, LICENSING_V3_OUT_UNVERIFIABLE_KEYS);
957 eksp->eks_wrong_node =
958 MCDI_OUT_DWORD(req, LICENSING_V3_OUT_WRONG_NODE_KEYS);
959 eksp->eks_licensed_apps_lo =
960 MCDI_OUT_DWORD(req, LICENSING_V3_OUT_LICENSED_APPS_LO);
961 eksp->eks_licensed_apps_hi =
962 MCDI_OUT_DWORD(req, LICENSING_V3_OUT_LICENSED_APPS_HI);
963 eksp->eks_licensed_features_lo =
964 MCDI_OUT_DWORD(req, LICENSING_V3_OUT_LICENSED_FEATURES_LO);
965 eksp->eks_licensed_features_hi =
966 MCDI_OUT_DWORD(req, LICENSING_V3_OUT_LICENSED_FEATURES_HI);
973 EFSYS_PROBE1(fail1, efx_rc_t, rc);
978 static __checkReturn efx_rc_t
979 efx_mcdi_licensing_v3_app_state(
981 __in uint64_t app_id,
982 __out boolean_t *licensedp)
985 uint8_t payload[MAX(MC_CMD_GET_LICENSED_V3_APP_STATE_IN_LEN,
986 MC_CMD_GET_LICENSED_V3_APP_STATE_OUT_LEN)];
990 EFSYS_ASSERT(enp->en_family == EFX_FAMILY_MEDFORD);
992 (void) memset(payload, 0, sizeof (payload));
993 req.emr_cmd = MC_CMD_GET_LICENSED_V3_APP_STATE;
994 req.emr_in_buf = payload;
995 req.emr_in_length = MC_CMD_GET_LICENSED_V3_APP_STATE_IN_LEN;
996 req.emr_out_buf = payload;
997 req.emr_out_length = MC_CMD_GET_LICENSED_V3_APP_STATE_OUT_LEN;
999 MCDI_IN_SET_DWORD(req, GET_LICENSED_V3_APP_STATE_IN_APP_ID_LO,
1000 app_id & 0xffffffff);
1001 MCDI_IN_SET_DWORD(req, GET_LICENSED_V3_APP_STATE_IN_APP_ID_HI,
1004 efx_mcdi_execute(enp, &req);
1006 if (req.emr_rc != 0) {
1011 if (req.emr_out_length_used < MC_CMD_GET_LICENSED_V3_APP_STATE_OUT_LEN) {
1016 app_state = (MCDI_OUT_DWORD(req, GET_LICENSED_V3_APP_STATE_OUT_STATE));
1017 if (app_state != MC_CMD_GET_LICENSED_V3_APP_STATE_OUT_NOT_LICENSED) {
1018 *licensedp = B_TRUE;
1020 *licensedp = B_FALSE;
1028 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1033 static __checkReturn efx_rc_t
1034 efx_mcdi_licensing_v3_get_id(
1035 __in efx_nic_t *enp,
1036 __in size_t buffer_size,
1037 __out uint32_t *typep,
1038 __out size_t *lengthp,
1039 __out_bcount_part_opt(buffer_size, *lengthp)
1043 uint8_t payload[MAX(MC_CMD_LICENSING_GET_ID_V3_IN_LEN,
1044 MC_CMD_LICENSING_GET_ID_V3_OUT_LENMIN)];
1047 req.emr_cmd = MC_CMD_LICENSING_GET_ID_V3;
1049 if (bufferp == NULL) {
1050 /* Request id type and length only */
1051 req.emr_in_buf = bufferp;
1052 req.emr_in_length = MC_CMD_LICENSING_GET_ID_V3_IN_LEN;
1053 req.emr_out_buf = bufferp;
1054 req.emr_out_length = MC_CMD_LICENSING_GET_ID_V3_OUT_LENMIN;
1055 (void) memset(payload, 0, sizeof (payload));
1057 /* Request full buffer */
1058 req.emr_in_buf = bufferp;
1059 req.emr_in_length = MC_CMD_LICENSING_GET_ID_V3_IN_LEN;
1060 req.emr_out_buf = bufferp;
1061 req.emr_out_length = MIN(buffer_size, MC_CMD_LICENSING_GET_ID_V3_OUT_LENMAX);
1062 (void) memset(bufferp, 0, req.emr_out_length);
1065 efx_mcdi_execute_quiet(enp, &req);
1067 if (req.emr_rc != 0) {
1072 if (req.emr_out_length_used < MC_CMD_LICENSING_GET_ID_V3_OUT_LENMIN) {
1077 *typep = MCDI_OUT_DWORD(req, LICENSING_GET_ID_V3_OUT_LICENSE_TYPE);
1078 *lengthp = MCDI_OUT_DWORD(req, LICENSING_GET_ID_V3_OUT_LICENSE_ID_LENGTH);
1080 if (bufferp == NULL) {
1081 /* modify length requirements to indicate to caller the extra buffering
1082 ** needed to read the complete output.
1084 *lengthp += MC_CMD_LICENSING_GET_ID_V3_OUT_LENMIN;
1086 /* Shift ID down to start of buffer */
1088 bufferp+MC_CMD_LICENSING_GET_ID_V3_OUT_LICENSE_ID_OFST,
1090 memset(bufferp+(*lengthp), 0, MC_CMD_LICENSING_GET_ID_V3_OUT_LICENSE_ID_OFST);
1098 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1103 /* V3 format uses Huntington TLV format partition. See SF-108797-SW */
1104 #define EFX_LICENSE_V3_KEY_LENGTH_MIN (64)
1105 #define EFX_LICENSE_V3_KEY_LENGTH_MAX (160)
1107 __checkReturn efx_rc_t
1108 efx_lic_v3_find_start(
1109 __in efx_nic_t *enp,
1110 __in_bcount(buffer_size)
1112 __in size_t buffer_size,
1113 __out uint32_t *startp
1116 _NOTE(ARGUNUSED(enp))
1118 return ef10_nvram_buffer_find_item_start(bufferp, buffer_size, startp);
1121 __checkReturn efx_rc_t
1122 efx_lic_v3_find_end(
1123 __in efx_nic_t *enp,
1124 __in_bcount(buffer_size)
1126 __in size_t buffer_size,
1127 __in uint32_t offset,
1128 __out uint32_t *endp
1131 _NOTE(ARGUNUSED(enp))
1133 return ef10_nvram_buffer_find_end(bufferp, buffer_size, offset, endp);
1136 __checkReturn __success(return != B_FALSE) boolean_t
1137 efx_lic_v3_find_key(
1138 __in efx_nic_t *enp,
1139 __in_bcount(buffer_size)
1141 __in size_t buffer_size,
1142 __in uint32_t offset,
1143 __out uint32_t *startp,
1144 __out uint32_t *lengthp
1147 _NOTE(ARGUNUSED(enp))
1149 return ef10_nvram_buffer_find_item(bufferp, buffer_size,
1150 offset, startp, lengthp);
1153 __checkReturn __success(return != B_FALSE) boolean_t
1154 efx_lic_v3_validate_key(
1155 __in efx_nic_t *enp,
1156 __in_bcount(length) caddr_t keyp,
1157 __in uint32_t length
1160 // Check key is a valid V3 key
1165 _NOTE(ARGUNUSED(enp))
1167 if (length < EFX_LICENSE_V3_KEY_LENGTH_MIN) {
1171 if (length > EFX_LICENSE_V3_KEY_LENGTH_MAX) {
1175 key_type = ((uint8_t*)keyp)[0];
1176 key_length = ((uint8_t*)keyp)[1];
1181 if (key_length > length) {
1198 __checkReturn efx_rc_t
1199 efx_lic_v3_read_key(
1200 __in efx_nic_t *enp,
1201 __in_bcount(buffer_size)
1203 __in size_t buffer_size,
1204 __in uint32_t offset,
1205 __in uint32_t length,
1206 __out_bcount_part(key_max_size, *lengthp)
1208 __in size_t key_max_size,
1209 __out uint32_t *lengthp
1212 _NOTE(ARGUNUSED(enp))
1214 return ef10_nvram_buffer_get_item(bufferp, buffer_size,
1215 offset, length, keyp, key_max_size, lengthp);
1218 __checkReturn efx_rc_t
1219 efx_lic_v3_write_key(
1220 __in efx_nic_t *enp,
1221 __in_bcount(buffer_size)
1223 __in size_t buffer_size,
1224 __in uint32_t offset,
1225 __in_bcount(length) caddr_t keyp,
1226 __in uint32_t length,
1227 __out uint32_t *lengthp
1230 _NOTE(ARGUNUSED(enp))
1231 EFSYS_ASSERT(length <= EFX_LICENSE_V3_KEY_LENGTH_MAX);
1233 return ef10_nvram_buffer_insert_item(bufferp, buffer_size,
1234 offset, keyp, length, lengthp);
1237 __checkReturn efx_rc_t
1238 efx_lic_v3_delete_key(
1239 __in efx_nic_t *enp,
1240 __in_bcount(buffer_size)
1242 __in size_t buffer_size,
1243 __in uint32_t offset,
1244 __in uint32_t length,
1246 __out uint32_t *deltap
1251 _NOTE(ARGUNUSED(enp))
1253 if ((rc = ef10_nvram_buffer_delete_item(bufferp,
1254 buffer_size, offset, length, end)) != 0) {
1263 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1268 __checkReturn efx_rc_t
1269 efx_lic_v3_create_partition(
1270 __in efx_nic_t *enp,
1271 __in_bcount(buffer_size)
1273 __in size_t buffer_size
1278 // Construct empty partition
1279 if ((rc = ef10_nvram_buffer_create(enp,
1280 NVRAM_PARTITION_TYPE_LICENSE,
1281 bufferp, buffer_size)) != 0) {
1289 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1294 __checkReturn efx_rc_t
1295 efx_lic_v3_finish_partition(
1296 __in efx_nic_t *enp,
1297 __in_bcount(buffer_size)
1299 __in size_t buffer_size
1304 if ((rc = ef10_nvram_buffer_finish(bufferp,
1305 buffer_size)) != 0) {
1309 // Validate completed partition
1310 if ((rc = ef10_nvram_buffer_validate(enp, NVRAM_PARTITION_TYPE_LICENSE,
1311 bufferp, buffer_size)) != 0) {
1320 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1326 #endif /* EFSYS_OPT_MEDFORD */
1328 __checkReturn efx_rc_t
1330 __in efx_nic_t *enp)
1332 const efx_lic_ops_t *elop;
1333 efx_key_stats_t eks;
1336 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1337 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
1338 EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_LIC));
1340 switch (enp->en_family) {
1343 case EFX_FAMILY_SIENA:
1344 elop = &__efx_lic_v1_ops;
1346 #endif /* EFSYS_OPT_SIENA */
1348 #if EFSYS_OPT_HUNTINGTON
1349 case EFX_FAMILY_HUNTINGTON:
1350 elop = &__efx_lic_v2_ops;
1352 #endif /* EFSYS_OPT_HUNTINGTON */
1354 #if EFSYS_OPT_MEDFORD
1355 case EFX_FAMILY_MEDFORD:
1356 elop = &__efx_lic_v3_ops;
1358 #endif /* EFSYS_OPT_MEDFORD */
1366 enp->en_elop = elop;
1367 enp->en_mod_flags |= EFX_MOD_LIC;
1369 /* Probe for support */
1370 if (efx_lic_get_key_stats(enp, &eks) == 0) {
1371 enp->en_licensing_supported = B_TRUE;
1373 enp->en_licensing_supported = B_FALSE;
1379 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1384 extern __checkReturn boolean_t
1385 efx_lic_check_support(
1386 __in efx_nic_t *enp)
1388 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1389 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
1390 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1392 return enp->en_licensing_supported;
1397 __in efx_nic_t *enp)
1399 const efx_lic_ops_t *elop = enp->en_elop;
1401 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1402 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
1403 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1405 enp->en_elop = NULL;
1406 enp->en_mod_flags &= ~EFX_MOD_LIC;
1410 __checkReturn efx_rc_t
1411 efx_lic_update_licenses(
1412 __in efx_nic_t *enp)
1414 const efx_lic_ops_t *elop = enp->en_elop;
1417 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1418 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1420 if ((rc = elop->elo_update_licenses(enp)) != 0)
1426 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1431 __checkReturn efx_rc_t
1432 efx_lic_get_key_stats(
1433 __in efx_nic_t *enp,
1434 __out efx_key_stats_t *eksp)
1436 const efx_lic_ops_t *elop = enp->en_elop;
1439 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1440 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1442 if ((rc = elop->elo_get_key_stats(enp, eksp)) != 0)
1448 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1453 __checkReturn efx_rc_t
1455 __in efx_nic_t *enp,
1456 __in uint64_t app_id,
1457 __out boolean_t *licensedp)
1459 const efx_lic_ops_t *elop = enp->en_elop;
1462 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1463 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1465 if (elop->elo_app_state == NULL)
1468 if ((rc = elop->elo_app_state(enp, app_id, licensedp)) != 0)
1474 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1479 __checkReturn efx_rc_t
1481 __in efx_nic_t *enp,
1482 __in size_t buffer_size,
1483 __out uint32_t *typep,
1484 __out size_t *lengthp,
1485 __out_opt uint8_t *bufferp
1488 const efx_lic_ops_t *elop = enp->en_elop;
1491 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1492 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1494 if (elop->elo_get_id == NULL)
1497 if ((rc = elop->elo_get_id(enp, buffer_size, typep,
1498 lengthp, bufferp)) != 0)
1504 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1509 /* Buffer management API - abstracts varying TLV format used for License partition */
1511 __checkReturn efx_rc_t
1513 __in efx_nic_t *enp,
1514 __in_bcount(buffer_size)
1516 __in size_t buffer_size,
1517 __out uint32_t *startp
1520 const efx_lic_ops_t *elop = enp->en_elop;
1523 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1524 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1526 if ((rc = elop->elo_find_start(enp, bufferp, buffer_size, startp)) != 0)
1532 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1537 __checkReturn efx_rc_t
1539 __in efx_nic_t *enp,
1540 __in_bcount(buffer_size)
1542 __in size_t buffer_size,
1543 __in uint32_t offset,
1544 __out uint32_t *endp
1547 const efx_lic_ops_t *elop = enp->en_elop;
1550 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1551 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1553 if ((rc = elop->elo_find_end(enp, bufferp, buffer_size, offset, endp)) != 0)
1559 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1564 __checkReturn __success(return != B_FALSE) boolean_t
1566 __in efx_nic_t *enp,
1567 __in_bcount(buffer_size)
1569 __in size_t buffer_size,
1570 __in uint32_t offset,
1571 __out uint32_t *startp,
1572 __out uint32_t *lengthp
1575 const efx_lic_ops_t *elop = enp->en_elop;
1578 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1579 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1581 EFSYS_ASSERT(bufferp);
1582 EFSYS_ASSERT(startp);
1583 EFSYS_ASSERT(lengthp);
1585 return (elop->elo_find_key(enp, bufferp, buffer_size, offset,
1590 /* Validate that the buffer contains a single key in a recognised format.
1591 ** An empty or terminator buffer is not accepted as a valid key.
1593 __checkReturn __success(return != B_FALSE) boolean_t
1594 efx_lic_validate_key(
1595 __in efx_nic_t *enp,
1596 __in_bcount(length) caddr_t keyp,
1597 __in uint32_t length
1600 const efx_lic_ops_t *elop = enp->en_elop;
1603 uint16_t tlv_length;
1605 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1606 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1608 if ((rc = elop->elo_validate_key(enp, keyp, length)) == B_FALSE)
1614 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1619 __checkReturn efx_rc_t
1621 __in efx_nic_t *enp,
1622 __in_bcount(buffer_size)
1624 __in size_t buffer_size,
1625 __in uint32_t offset,
1626 __in uint32_t length,
1627 __out_bcount_part(key_max_size, *lengthp)
1629 __in size_t key_max_size,
1630 __out uint32_t *lengthp
1633 const efx_lic_ops_t *elop = enp->en_elop;
1636 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1637 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1639 if ((rc = elop->elo_read_key(enp, bufferp, buffer_size, offset,
1640 length, keyp, key_max_size, lengthp)) != 0)
1646 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1651 __checkReturn efx_rc_t
1653 __in efx_nic_t *enp,
1654 __in_bcount(buffer_size)
1656 __in size_t buffer_size,
1657 __in uint32_t offset,
1658 __in_bcount(length) caddr_t keyp,
1659 __in uint32_t length,
1660 __out uint32_t *lengthp
1663 const efx_lic_ops_t *elop = enp->en_elop;
1666 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1667 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1669 if ((rc = elop->elo_write_key(enp, bufferp, buffer_size, offset,
1670 keyp, length, lengthp)) != 0)
1676 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1681 __checkReturn efx_rc_t
1683 __in efx_nic_t *enp,
1684 __in_bcount(buffer_size)
1686 __in size_t buffer_size,
1687 __in uint32_t offset,
1688 __in uint32_t length,
1690 __out uint32_t *deltap
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_delete_key(enp, bufferp, buffer_size, offset,
1700 length, end, deltap)) != 0)
1706 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1711 __checkReturn efx_rc_t
1712 efx_lic_create_partition(
1713 __in efx_nic_t *enp,
1714 __in_bcount(buffer_size)
1716 __in size_t buffer_size
1719 const efx_lic_ops_t *elop = enp->en_elop;
1722 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1723 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1725 if ((rc = elop->elo_create_partition(enp, bufferp, buffer_size)) != 0)
1731 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1737 __checkReturn efx_rc_t
1738 efx_lic_finish_partition(
1739 __in efx_nic_t *enp,
1740 __in_bcount(buffer_size)
1742 __in size_t buffer_size
1745 const efx_lic_ops_t *elop = enp->en_elop;
1748 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1749 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1751 if ((rc = elop->elo_finish_partition(enp, bufferp, buffer_size)) != 0)
1757 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1762 #endif /* EFSYS_OPT_LICENSING */