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 EFX_MCDI_DECLARE_BUF(payload, MC_CMD_FC_IN_LICENSE_LEN, 0);
349 EFSYS_ASSERT(enp->en_family == EFX_FAMILY_SIENA);
351 req.emr_cmd = MC_CMD_FC;
352 req.emr_in_buf = payload;
353 req.emr_in_length = MC_CMD_FC_IN_LICENSE_LEN;
354 req.emr_out_buf = payload;
355 req.emr_out_length = 0;
357 MCDI_IN_SET_DWORD(req, FC_IN_CMD,
358 MC_CMD_FC_OP_LICENSE);
360 MCDI_IN_SET_DWORD(req, FC_IN_LICENSE_OP,
361 MC_CMD_FC_IN_LICENSE_UPDATE_LICENSE);
363 efx_mcdi_execute(enp, &req);
365 if (req.emr_rc != 0) {
370 if (req.emr_out_length_used != 0) {
380 EFSYS_PROBE1(fail1, efx_rc_t, rc);
385 static __checkReturn efx_rc_t
386 efx_mcdi_fc_license_get_key_stats(
388 __out efx_key_stats_t *eksp)
391 EFX_MCDI_DECLARE_BUF(payload, MC_CMD_FC_IN_LICENSE_LEN,
392 MC_CMD_FC_OUT_LICENSE_LEN);
395 EFSYS_ASSERT(enp->en_family == EFX_FAMILY_SIENA);
397 req.emr_cmd = MC_CMD_FC;
398 req.emr_in_buf = payload;
399 req.emr_in_length = MC_CMD_FC_IN_LICENSE_LEN;
400 req.emr_out_buf = payload;
401 req.emr_out_length = MC_CMD_FC_OUT_LICENSE_LEN;
403 MCDI_IN_SET_DWORD(req, FC_IN_CMD,
404 MC_CMD_FC_OP_LICENSE);
406 MCDI_IN_SET_DWORD(req, FC_IN_LICENSE_OP,
407 MC_CMD_FC_IN_LICENSE_GET_KEY_STATS);
409 efx_mcdi_execute_quiet(enp, &req);
411 if (req.emr_rc != 0) {
416 if (req.emr_out_length_used < MC_CMD_FC_OUT_LICENSE_LEN) {
422 MCDI_OUT_DWORD(req, FC_OUT_LICENSE_VALID_KEYS);
424 MCDI_OUT_DWORD(req, FC_OUT_LICENSE_INVALID_KEYS);
425 eksp->eks_blacklisted =
426 MCDI_OUT_DWORD(req, FC_OUT_LICENSE_BLACKLISTED_KEYS);
427 eksp->eks_unverifiable = 0;
428 eksp->eks_wrong_node = 0;
429 eksp->eks_licensed_apps_lo = 0;
430 eksp->eks_licensed_apps_hi = 0;
431 eksp->eks_licensed_features_lo = 0;
432 eksp->eks_licensed_features_hi = 0;
439 EFSYS_PROBE1(fail1, efx_rc_t, rc);
444 #endif /* EFSYS_OPT_SIENA */
446 /* V1 and V2 Partition format - based on a 16-bit TLV format */
448 #if EFSYS_OPT_SIENA | EFSYS_OPT_HUNTINGTON
451 * V1/V2 format - defined in SF-108542-TC section 4.2:
452 * Type (T): 16bit - revision/HMAC algorithm
453 * Length (L): 16bit - value length in bytes
454 * Value (V): L bytes - payload
456 #define EFX_LICENSE_V1V2_PAYLOAD_LENGTH_MAX (256)
457 #define EFX_LICENSE_V1V2_HEADER_LENGTH (2 * sizeof(uint16_t))
459 __checkReturn efx_rc_t
460 efx_lic_v1v2_find_start(
462 __in_bcount(buffer_size)
464 __in size_t buffer_size,
465 __out uint32_t *startp
468 _NOTE(ARGUNUSED(enp, bufferp, buffer_size))
474 __checkReturn efx_rc_t
475 efx_lic_v1v2_find_end(
477 __in_bcount(buffer_size)
479 __in size_t buffer_size,
480 __in uint32_t offset,
484 _NOTE(ARGUNUSED(enp, bufferp, buffer_size))
486 *endp = offset + EFX_LICENSE_V1V2_HEADER_LENGTH;
490 __checkReturn __success(return != B_FALSE) boolean_t
491 efx_lic_v1v2_find_key(
493 __in_bcount(buffer_size)
495 __in size_t buffer_size,
496 __in uint32_t offset,
497 __out uint32_t *startp,
498 __out uint32_t *lengthp
505 _NOTE(ARGUNUSED(enp))
507 if ((size_t)buffer_size - offset < EFX_LICENSE_V1V2_HEADER_LENGTH)
510 tlv_type = __LE_TO_CPU_16(((uint16_t *)&bufferp[offset])[0]);
511 tlv_length = __LE_TO_CPU_16(((uint16_t *)&bufferp[offset])[1]);
512 if ((tlv_length > EFX_LICENSE_V1V2_PAYLOAD_LENGTH_MAX) ||
513 (tlv_type == 0 && tlv_length == 0)) {
517 *lengthp = tlv_length + EFX_LICENSE_V1V2_HEADER_LENGTH;
523 EFSYS_PROBE1(fail1, boolean_t, B_FALSE);
528 __checkReturn __success(return != B_FALSE) boolean_t
529 efx_lic_v1v2_validate_key(
531 __in_bcount(length) caddr_t keyp,
538 _NOTE(ARGUNUSED(enp))
540 if (length < EFX_LICENSE_V1V2_HEADER_LENGTH) {
544 tlv_type = __LE_TO_CPU_16(((uint16_t *)keyp)[0]);
545 tlv_length = __LE_TO_CPU_16(((uint16_t *)keyp)[1]);
547 if (tlv_length > EFX_LICENSE_V1V2_PAYLOAD_LENGTH_MAX) {
553 if ((tlv_length + EFX_LICENSE_V1V2_HEADER_LENGTH) != length) {
566 EFSYS_PROBE1(fail1, boolean_t, B_FALSE);
572 __checkReturn efx_rc_t
573 efx_lic_v1v2_read_key(
575 __in_bcount(buffer_size)
577 __in size_t buffer_size,
578 __in uint32_t offset,
579 __in uint32_t length,
580 __out_bcount_part(key_max_size, *lengthp)
582 __in size_t key_max_size,
583 __out uint32_t *lengthp
588 _NOTE(ARGUNUSED(enp, buffer_size))
589 EFSYS_ASSERT(length <= (EFX_LICENSE_V1V2_PAYLOAD_LENGTH_MAX +
590 EFX_LICENSE_V1V2_HEADER_LENGTH));
592 if (key_max_size < length) {
596 memcpy(keyp, &bufferp[offset], length);
603 EFSYS_PROBE1(fail1, efx_rc_t, rc);
608 __checkReturn efx_rc_t
609 efx_lic_v1v2_write_key(
611 __in_bcount(buffer_size)
613 __in size_t buffer_size,
614 __in uint32_t offset,
615 __in_bcount(length) caddr_t keyp,
616 __in uint32_t length,
617 __out uint32_t *lengthp
622 _NOTE(ARGUNUSED(enp))
623 EFSYS_ASSERT(length <= (EFX_LICENSE_V1V2_PAYLOAD_LENGTH_MAX +
624 EFX_LICENSE_V1V2_HEADER_LENGTH));
626 /* Ensure space for terminator remains */
627 if ((offset + length) >
628 (buffer_size - EFX_LICENSE_V1V2_HEADER_LENGTH)) {
633 memcpy(bufferp + offset, keyp, length);
640 EFSYS_PROBE1(fail1, efx_rc_t, rc);
645 __checkReturn efx_rc_t
646 efx_lic_v1v2_delete_key(
648 __in_bcount(buffer_size)
650 __in size_t buffer_size,
651 __in uint32_t offset,
652 __in uint32_t length,
654 __out uint32_t *deltap
657 uint32_t move_start = offset + length;
658 uint32_t move_length = end - move_start;
660 _NOTE(ARGUNUSED(enp, buffer_size))
661 EFSYS_ASSERT(end <= buffer_size);
663 /* Shift everything after the key down */
664 memmove(bufferp + offset, bufferp + move_start, move_length);
671 __checkReturn efx_rc_t
672 efx_lic_v1v2_create_partition(
674 __in_bcount(buffer_size)
676 __in size_t buffer_size
679 _NOTE(ARGUNUSED(enp, buffer_size))
680 EFSYS_ASSERT(EFX_LICENSE_V1V2_HEADER_LENGTH <= buffer_size);
682 /* Write terminator */
683 memset(bufferp, '\0', EFX_LICENSE_V1V2_HEADER_LENGTH);
688 __checkReturn efx_rc_t
689 efx_lic_v1v2_finish_partition(
691 __in_bcount(buffer_size)
693 __in size_t buffer_size
696 _NOTE(ARGUNUSED(enp, bufferp, buffer_size))
701 #endif /* EFSYS_OPT_HUNTINGTON | EFSYS_OPT_SIENA */
704 /* V2 Licensing - used by Huntington family only. See SF-113611-TC */
706 #if EFSYS_OPT_HUNTINGTON
708 static __checkReturn efx_rc_t
709 efx_mcdi_licensed_app_state(
711 __in uint64_t app_id,
712 __out boolean_t *licensedp)
715 EFX_MCDI_DECLARE_BUF(payload, MC_CMD_GET_LICENSED_APP_STATE_IN_LEN,
716 MC_CMD_GET_LICENSED_APP_STATE_OUT_LEN);
720 EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON);
722 /* V2 licensing supports 32bit app id only */
723 if ((app_id >> 32) != 0) {
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 EFX_MCDI_DECLARE_BUF(payload, MC_CMD_LICENSING_IN_LEN, 0);
776 EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON);
778 req.emr_cmd = MC_CMD_LICENSING;
779 req.emr_in_buf = payload;
780 req.emr_in_length = MC_CMD_LICENSING_IN_LEN;
781 req.emr_out_buf = payload;
782 req.emr_out_length = 0;
784 MCDI_IN_SET_DWORD(req, LICENSING_IN_OP,
785 MC_CMD_LICENSING_IN_OP_UPDATE_LICENSE);
787 efx_mcdi_execute(enp, &req);
789 if (req.emr_rc != 0) {
794 if (req.emr_out_length_used != 0) {
804 EFSYS_PROBE1(fail1, efx_rc_t, rc);
809 static __checkReturn efx_rc_t
810 efx_mcdi_licensing_get_key_stats(
812 __out efx_key_stats_t *eksp)
815 EFX_MCDI_DECLARE_BUF(payload, MC_CMD_LICENSING_IN_LEN,
816 MC_CMD_LICENSING_OUT_LEN);
819 EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON);
821 req.emr_cmd = MC_CMD_LICENSING;
822 req.emr_in_buf = payload;
823 req.emr_in_length = MC_CMD_LICENSING_IN_LEN;
824 req.emr_out_buf = payload;
825 req.emr_out_length = MC_CMD_LICENSING_OUT_LEN;
827 MCDI_IN_SET_DWORD(req, LICENSING_IN_OP,
828 MC_CMD_LICENSING_IN_OP_GET_KEY_STATS);
830 efx_mcdi_execute(enp, &req);
832 if (req.emr_rc != 0) {
837 if (req.emr_out_length_used < MC_CMD_LICENSING_OUT_LEN) {
843 MCDI_OUT_DWORD(req, LICENSING_OUT_VALID_APP_KEYS);
845 MCDI_OUT_DWORD(req, LICENSING_OUT_INVALID_APP_KEYS);
846 eksp->eks_blacklisted =
847 MCDI_OUT_DWORD(req, LICENSING_OUT_BLACKLISTED_APP_KEYS);
848 eksp->eks_unverifiable =
849 MCDI_OUT_DWORD(req, LICENSING_OUT_UNVERIFIABLE_APP_KEYS);
850 eksp->eks_wrong_node =
851 MCDI_OUT_DWORD(req, LICENSING_OUT_WRONG_NODE_APP_KEYS);
852 eksp->eks_licensed_apps_lo = 0;
853 eksp->eks_licensed_apps_hi = 0;
854 eksp->eks_licensed_features_lo = 0;
855 eksp->eks_licensed_features_hi = 0;
862 EFSYS_PROBE1(fail1, efx_rc_t, rc);
867 #endif /* EFSYS_OPT_HUNTINGTON */
869 /* V3 Licensing - used starting from Medford family. See SF-114884-SW */
871 #if EFSYS_OPT_MEDFORD
873 static __checkReturn efx_rc_t
874 efx_mcdi_licensing_v3_update_licenses(
878 EFX_MCDI_DECLARE_BUF(payload, MC_CMD_LICENSING_V3_IN_LEN, 0);
881 EFSYS_ASSERT(enp->en_family == EFX_FAMILY_MEDFORD);
883 req.emr_cmd = MC_CMD_LICENSING_V3;
884 req.emr_in_buf = payload;
885 req.emr_in_length = MC_CMD_LICENSING_V3_IN_LEN;
886 req.emr_out_buf = NULL;
887 req.emr_out_length = 0;
889 MCDI_IN_SET_DWORD(req, LICENSING_V3_IN_OP,
890 MC_CMD_LICENSING_V3_IN_OP_UPDATE_LICENSE);
892 efx_mcdi_execute(enp, &req);
894 if (req.emr_rc != 0) {
902 EFSYS_PROBE1(fail1, efx_rc_t, rc);
907 static __checkReturn efx_rc_t
908 efx_mcdi_licensing_v3_report_license(
910 __out efx_key_stats_t *eksp)
913 EFX_MCDI_DECLARE_BUF(payload, MC_CMD_LICENSING_V3_IN_LEN,
914 MC_CMD_LICENSING_V3_OUT_LEN);
917 EFSYS_ASSERT(enp->en_family == EFX_FAMILY_MEDFORD);
919 req.emr_cmd = MC_CMD_LICENSING_V3;
920 req.emr_in_buf = payload;
921 req.emr_in_length = MC_CMD_LICENSING_V3_IN_LEN;
922 req.emr_out_buf = payload;
923 req.emr_out_length = MC_CMD_LICENSING_V3_OUT_LEN;
925 MCDI_IN_SET_DWORD(req, LICENSING_V3_IN_OP,
926 MC_CMD_LICENSING_V3_IN_OP_REPORT_LICENSE);
928 efx_mcdi_execute_quiet(enp, &req);
930 if (req.emr_rc != 0) {
935 if (req.emr_out_length_used < MC_CMD_LICENSING_V3_OUT_LEN) {
941 MCDI_OUT_DWORD(req, LICENSING_V3_OUT_VALID_KEYS);
943 MCDI_OUT_DWORD(req, LICENSING_V3_OUT_INVALID_KEYS);
944 eksp->eks_blacklisted = 0;
945 eksp->eks_unverifiable =
946 MCDI_OUT_DWORD(req, LICENSING_V3_OUT_UNVERIFIABLE_KEYS);
947 eksp->eks_wrong_node =
948 MCDI_OUT_DWORD(req, LICENSING_V3_OUT_WRONG_NODE_KEYS);
949 eksp->eks_licensed_apps_lo =
950 MCDI_OUT_DWORD(req, LICENSING_V3_OUT_LICENSED_APPS_LO);
951 eksp->eks_licensed_apps_hi =
952 MCDI_OUT_DWORD(req, LICENSING_V3_OUT_LICENSED_APPS_HI);
953 eksp->eks_licensed_features_lo =
954 MCDI_OUT_DWORD(req, LICENSING_V3_OUT_LICENSED_FEATURES_LO);
955 eksp->eks_licensed_features_hi =
956 MCDI_OUT_DWORD(req, LICENSING_V3_OUT_LICENSED_FEATURES_HI);
963 EFSYS_PROBE1(fail1, efx_rc_t, rc);
968 static __checkReturn efx_rc_t
969 efx_mcdi_licensing_v3_app_state(
971 __in uint64_t app_id,
972 __out boolean_t *licensedp)
975 EFX_MCDI_DECLARE_BUF(payload, MC_CMD_GET_LICENSED_V3_APP_STATE_IN_LEN,
976 MC_CMD_GET_LICENSED_V3_APP_STATE_OUT_LEN);
980 EFSYS_ASSERT(enp->en_family == EFX_FAMILY_MEDFORD);
982 req.emr_cmd = MC_CMD_GET_LICENSED_V3_APP_STATE;
983 req.emr_in_buf = payload;
984 req.emr_in_length = MC_CMD_GET_LICENSED_V3_APP_STATE_IN_LEN;
985 req.emr_out_buf = payload;
986 req.emr_out_length = MC_CMD_GET_LICENSED_V3_APP_STATE_OUT_LEN;
988 MCDI_IN_SET_DWORD(req, GET_LICENSED_V3_APP_STATE_IN_APP_ID_LO,
989 app_id & 0xffffffff);
990 MCDI_IN_SET_DWORD(req, GET_LICENSED_V3_APP_STATE_IN_APP_ID_HI,
993 efx_mcdi_execute(enp, &req);
995 if (req.emr_rc != 0) {
1000 if (req.emr_out_length_used < MC_CMD_GET_LICENSED_V3_APP_STATE_OUT_LEN) {
1005 app_state = (MCDI_OUT_DWORD(req, GET_LICENSED_V3_APP_STATE_OUT_STATE));
1006 if (app_state != MC_CMD_GET_LICENSED_V3_APP_STATE_OUT_NOT_LICENSED) {
1007 *licensedp = B_TRUE;
1009 *licensedp = B_FALSE;
1017 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1022 static __checkReturn efx_rc_t
1023 efx_mcdi_licensing_v3_get_id(
1024 __in efx_nic_t *enp,
1025 __in size_t buffer_size,
1026 __out uint32_t *typep,
1027 __out size_t *lengthp,
1028 __out_bcount_part_opt(buffer_size, *lengthp)
1032 EFX_MCDI_DECLARE_BUF(payload, MC_CMD_LICENSING_GET_ID_V3_IN_LEN,
1033 MC_CMD_LICENSING_GET_ID_V3_OUT_LENMIN);
1036 req.emr_cmd = MC_CMD_LICENSING_GET_ID_V3;
1038 if (bufferp == NULL) {
1039 /* Request id type and length only */
1040 req.emr_in_buf = bufferp;
1041 req.emr_in_length = MC_CMD_LICENSING_GET_ID_V3_IN_LEN;
1042 req.emr_out_buf = bufferp;
1043 req.emr_out_length = MC_CMD_LICENSING_GET_ID_V3_OUT_LENMIN;
1045 /* Request full buffer */
1046 req.emr_in_buf = bufferp;
1047 req.emr_in_length = MC_CMD_LICENSING_GET_ID_V3_IN_LEN;
1048 req.emr_out_buf = bufferp;
1049 req.emr_out_length = MIN(buffer_size, MC_CMD_LICENSING_GET_ID_V3_OUT_LENMAX);
1050 (void) memset(bufferp, 0, req.emr_out_length);
1053 efx_mcdi_execute_quiet(enp, &req);
1055 if (req.emr_rc != 0) {
1060 if (req.emr_out_length_used < MC_CMD_LICENSING_GET_ID_V3_OUT_LENMIN) {
1065 *typep = MCDI_OUT_DWORD(req, LICENSING_GET_ID_V3_OUT_LICENSE_TYPE);
1066 *lengthp = MCDI_OUT_DWORD(req, LICENSING_GET_ID_V3_OUT_LICENSE_ID_LENGTH);
1068 if (bufferp == NULL) {
1069 /* modify length requirements to indicate to caller the extra buffering
1070 ** needed to read the complete output.
1072 *lengthp += MC_CMD_LICENSING_GET_ID_V3_OUT_LENMIN;
1074 /* Shift ID down to start of buffer */
1076 bufferp + MC_CMD_LICENSING_GET_ID_V3_OUT_LICENSE_ID_OFST,
1078 memset(bufferp + (*lengthp), 0,
1079 MC_CMD_LICENSING_GET_ID_V3_OUT_LICENSE_ID_OFST);
1087 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1092 /* V3 format uses Huntington TLV format partition. See SF-108797-SW */
1093 #define EFX_LICENSE_V3_KEY_LENGTH_MIN (64)
1094 #define EFX_LICENSE_V3_KEY_LENGTH_MAX (160)
1096 __checkReturn efx_rc_t
1097 efx_lic_v3_find_start(
1098 __in efx_nic_t *enp,
1099 __in_bcount(buffer_size)
1101 __in size_t buffer_size,
1102 __out uint32_t *startp
1105 _NOTE(ARGUNUSED(enp))
1107 return ef10_nvram_buffer_find_item_start(bufferp, buffer_size, startp);
1110 __checkReturn efx_rc_t
1111 efx_lic_v3_find_end(
1112 __in efx_nic_t *enp,
1113 __in_bcount(buffer_size)
1115 __in size_t buffer_size,
1116 __in uint32_t offset,
1117 __out uint32_t *endp
1120 _NOTE(ARGUNUSED(enp))
1122 return ef10_nvram_buffer_find_end(bufferp, buffer_size, offset, endp);
1125 __checkReturn __success(return != B_FALSE) boolean_t
1126 efx_lic_v3_find_key(
1127 __in efx_nic_t *enp,
1128 __in_bcount(buffer_size)
1130 __in size_t buffer_size,
1131 __in uint32_t offset,
1132 __out uint32_t *startp,
1133 __out uint32_t *lengthp
1136 _NOTE(ARGUNUSED(enp))
1138 return ef10_nvram_buffer_find_item(bufferp, buffer_size,
1139 offset, startp, lengthp);
1142 __checkReturn __success(return != B_FALSE) boolean_t
1143 efx_lic_v3_validate_key(
1144 __in efx_nic_t *enp,
1145 __in_bcount(length) caddr_t keyp,
1146 __in uint32_t length
1149 /* Check key is a valid V3 key */
1153 _NOTE(ARGUNUSED(enp))
1155 if (length < EFX_LICENSE_V3_KEY_LENGTH_MIN) {
1159 if (length > EFX_LICENSE_V3_KEY_LENGTH_MAX) {
1163 key_type = ((uint8_t *)keyp)[0];
1164 key_length = ((uint8_t *)keyp)[1];
1169 if (key_length > length) {
1181 EFSYS_PROBE1(fail1, boolean_t, B_FALSE);
1186 __checkReturn efx_rc_t
1187 efx_lic_v3_read_key(
1188 __in efx_nic_t *enp,
1189 __in_bcount(buffer_size)
1191 __in size_t buffer_size,
1192 __in uint32_t offset,
1193 __in uint32_t length,
1194 __out_bcount_part(key_max_size, *lengthp)
1196 __in size_t key_max_size,
1197 __out uint32_t *lengthp
1200 _NOTE(ARGUNUSED(enp))
1202 return ef10_nvram_buffer_get_item(bufferp, buffer_size,
1203 offset, length, keyp, key_max_size, lengthp);
1206 __checkReturn efx_rc_t
1207 efx_lic_v3_write_key(
1208 __in efx_nic_t *enp,
1209 __in_bcount(buffer_size)
1211 __in size_t buffer_size,
1212 __in uint32_t offset,
1213 __in_bcount(length) caddr_t keyp,
1214 __in uint32_t length,
1215 __out uint32_t *lengthp
1218 _NOTE(ARGUNUSED(enp))
1219 EFSYS_ASSERT(length <= EFX_LICENSE_V3_KEY_LENGTH_MAX);
1221 return ef10_nvram_buffer_insert_item(bufferp, buffer_size,
1222 offset, keyp, length, lengthp);
1225 __checkReturn efx_rc_t
1226 efx_lic_v3_delete_key(
1227 __in efx_nic_t *enp,
1228 __in_bcount(buffer_size)
1230 __in size_t buffer_size,
1231 __in uint32_t offset,
1232 __in uint32_t length,
1234 __out uint32_t *deltap
1239 _NOTE(ARGUNUSED(enp))
1241 if ((rc = ef10_nvram_buffer_delete_item(bufferp,
1242 buffer_size, offset, length, end)) != 0) {
1251 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1256 __checkReturn efx_rc_t
1257 efx_lic_v3_create_partition(
1258 __in efx_nic_t *enp,
1259 __in_bcount(buffer_size)
1261 __in size_t buffer_size
1266 /* Construct empty partition */
1267 if ((rc = ef10_nvram_buffer_create(enp,
1268 NVRAM_PARTITION_TYPE_LICENSE,
1269 bufferp, buffer_size)) != 0) {
1277 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1282 __checkReturn efx_rc_t
1283 efx_lic_v3_finish_partition(
1284 __in efx_nic_t *enp,
1285 __in_bcount(buffer_size)
1287 __in size_t buffer_size
1292 if ((rc = ef10_nvram_buffer_finish(bufferp,
1293 buffer_size)) != 0) {
1297 /* Validate completed partition */
1298 if ((rc = ef10_nvram_buffer_validate(enp, NVRAM_PARTITION_TYPE_LICENSE,
1299 bufferp, buffer_size)) != 0) {
1308 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1314 #endif /* EFSYS_OPT_MEDFORD */
1316 __checkReturn efx_rc_t
1318 __in efx_nic_t *enp)
1320 const efx_lic_ops_t *elop;
1321 efx_key_stats_t eks;
1324 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1325 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
1326 EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_LIC));
1328 switch (enp->en_family) {
1331 case EFX_FAMILY_SIENA:
1332 elop = &__efx_lic_v1_ops;
1334 #endif /* EFSYS_OPT_SIENA */
1336 #if EFSYS_OPT_HUNTINGTON
1337 case EFX_FAMILY_HUNTINGTON:
1338 elop = &__efx_lic_v2_ops;
1340 #endif /* EFSYS_OPT_HUNTINGTON */
1342 #if EFSYS_OPT_MEDFORD
1343 case EFX_FAMILY_MEDFORD:
1344 elop = &__efx_lic_v3_ops;
1346 #endif /* EFSYS_OPT_MEDFORD */
1354 enp->en_elop = elop;
1355 enp->en_mod_flags |= EFX_MOD_LIC;
1357 /* Probe for support */
1358 if (efx_lic_get_key_stats(enp, &eks) == 0) {
1359 enp->en_licensing_supported = B_TRUE;
1361 enp->en_licensing_supported = B_FALSE;
1367 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1372 extern __checkReturn boolean_t
1373 efx_lic_check_support(
1374 __in efx_nic_t *enp)
1376 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1377 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
1378 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1380 return enp->en_licensing_supported;
1385 __in efx_nic_t *enp)
1387 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1388 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
1389 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1391 enp->en_elop = NULL;
1392 enp->en_mod_flags &= ~EFX_MOD_LIC;
1396 __checkReturn efx_rc_t
1397 efx_lic_update_licenses(
1398 __in efx_nic_t *enp)
1400 const efx_lic_ops_t *elop = enp->en_elop;
1403 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1404 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1406 if ((rc = elop->elo_update_licenses(enp)) != 0)
1412 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1417 __checkReturn efx_rc_t
1418 efx_lic_get_key_stats(
1419 __in efx_nic_t *enp,
1420 __out efx_key_stats_t *eksp)
1422 const efx_lic_ops_t *elop = enp->en_elop;
1425 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1426 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1428 if ((rc = elop->elo_get_key_stats(enp, eksp)) != 0)
1434 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1439 __checkReturn efx_rc_t
1441 __in efx_nic_t *enp,
1442 __in uint64_t app_id,
1443 __out boolean_t *licensedp)
1445 const efx_lic_ops_t *elop = enp->en_elop;
1448 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1449 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1451 if (elop->elo_app_state == NULL)
1454 if ((rc = elop->elo_app_state(enp, app_id, licensedp)) != 0)
1460 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1465 __checkReturn efx_rc_t
1467 __in efx_nic_t *enp,
1468 __in size_t buffer_size,
1469 __out uint32_t *typep,
1470 __out size_t *lengthp,
1471 __out_opt uint8_t *bufferp
1474 const efx_lic_ops_t *elop = enp->en_elop;
1477 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1478 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1480 if (elop->elo_get_id == NULL)
1483 if ((rc = elop->elo_get_id(enp, buffer_size, typep,
1484 lengthp, bufferp)) != 0)
1490 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1495 /* Buffer management API - abstracts varying TLV format used for License partition */
1497 __checkReturn efx_rc_t
1499 __in efx_nic_t *enp,
1500 __in_bcount(buffer_size)
1502 __in size_t buffer_size,
1503 __out uint32_t *startp
1506 const efx_lic_ops_t *elop = enp->en_elop;
1509 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1510 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1512 if ((rc = elop->elo_find_start(enp, bufferp, buffer_size, startp)) != 0)
1518 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1523 __checkReturn efx_rc_t
1525 __in efx_nic_t *enp,
1526 __in_bcount(buffer_size)
1528 __in size_t buffer_size,
1529 __in uint32_t offset,
1530 __out uint32_t *endp
1533 const efx_lic_ops_t *elop = enp->en_elop;
1536 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1537 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1539 if ((rc = elop->elo_find_end(enp, bufferp, buffer_size, offset, endp)) != 0)
1545 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1550 __checkReturn __success(return != B_FALSE) boolean_t
1552 __in efx_nic_t *enp,
1553 __in_bcount(buffer_size)
1555 __in size_t buffer_size,
1556 __in uint32_t offset,
1557 __out uint32_t *startp,
1558 __out uint32_t *lengthp
1561 const efx_lic_ops_t *elop = enp->en_elop;
1563 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1564 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1566 EFSYS_ASSERT(bufferp);
1567 EFSYS_ASSERT(startp);
1568 EFSYS_ASSERT(lengthp);
1570 return (elop->elo_find_key(enp, bufferp, buffer_size, offset,
1575 /* Validate that the buffer contains a single key in a recognised format.
1576 ** An empty or terminator buffer is not accepted as a valid key.
1578 __checkReturn __success(return != B_FALSE) boolean_t
1579 efx_lic_validate_key(
1580 __in efx_nic_t *enp,
1581 __in_bcount(length) caddr_t keyp,
1582 __in uint32_t length
1585 const efx_lic_ops_t *elop = enp->en_elop;
1588 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1589 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1591 if ((rc = elop->elo_validate_key(enp, keyp, length)) == B_FALSE)
1597 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1602 __checkReturn efx_rc_t
1604 __in efx_nic_t *enp,
1605 __in_bcount(buffer_size)
1607 __in size_t buffer_size,
1608 __in uint32_t offset,
1609 __in uint32_t length,
1610 __out_bcount_part(key_max_size, *lengthp)
1612 __in size_t key_max_size,
1613 __out uint32_t *lengthp
1616 const efx_lic_ops_t *elop = enp->en_elop;
1619 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1620 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1622 if ((rc = elop->elo_read_key(enp, bufferp, buffer_size, offset,
1623 length, keyp, key_max_size, lengthp)) != 0)
1629 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1634 __checkReturn efx_rc_t
1636 __in efx_nic_t *enp,
1637 __in_bcount(buffer_size)
1639 __in size_t buffer_size,
1640 __in uint32_t offset,
1641 __in_bcount(length) caddr_t keyp,
1642 __in uint32_t length,
1643 __out uint32_t *lengthp
1646 const efx_lic_ops_t *elop = enp->en_elop;
1649 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1650 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1652 if ((rc = elop->elo_write_key(enp, bufferp, buffer_size, offset,
1653 keyp, length, lengthp)) != 0)
1659 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1664 __checkReturn efx_rc_t
1666 __in efx_nic_t *enp,
1667 __in_bcount(buffer_size)
1669 __in size_t buffer_size,
1670 __in uint32_t offset,
1671 __in uint32_t length,
1673 __out uint32_t *deltap
1676 const efx_lic_ops_t *elop = enp->en_elop;
1679 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1680 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1682 if ((rc = elop->elo_delete_key(enp, bufferp, buffer_size, offset,
1683 length, end, deltap)) != 0)
1689 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1694 __checkReturn efx_rc_t
1695 efx_lic_create_partition(
1696 __in efx_nic_t *enp,
1697 __in_bcount(buffer_size)
1699 __in size_t buffer_size
1702 const efx_lic_ops_t *elop = enp->en_elop;
1705 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1706 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1708 if ((rc = elop->elo_create_partition(enp, bufferp, buffer_size)) != 0)
1714 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1720 __checkReturn efx_rc_t
1721 efx_lic_finish_partition(
1722 __in efx_nic_t *enp,
1723 __in_bcount(buffer_size)
1725 __in size_t buffer_size
1728 const efx_lic_ops_t *elop = enp->en_elop;
1731 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1732 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1734 if ((rc = elop->elo_finish_partition(enp, bufferp, buffer_size)) != 0)
1740 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1745 #endif /* EFSYS_OPT_LICENSING */