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 EFX_MCDI_DECLARE_BUF(payload, MC_CMD_FC_IN_LICENSE_LEN, 0);
346 EFSYS_ASSERT(enp->en_family == EFX_FAMILY_SIENA);
348 req.emr_cmd = MC_CMD_FC;
349 req.emr_in_buf = payload;
350 req.emr_in_length = MC_CMD_FC_IN_LICENSE_LEN;
351 req.emr_out_buf = payload;
352 req.emr_out_length = 0;
354 MCDI_IN_SET_DWORD(req, FC_IN_CMD,
355 MC_CMD_FC_OP_LICENSE);
357 MCDI_IN_SET_DWORD(req, FC_IN_LICENSE_OP,
358 MC_CMD_FC_IN_LICENSE_UPDATE_LICENSE);
360 efx_mcdi_execute(enp, &req);
362 if (req.emr_rc != 0) {
367 if (req.emr_out_length_used != 0) {
377 EFSYS_PROBE1(fail1, efx_rc_t, rc);
382 static __checkReturn efx_rc_t
383 efx_mcdi_fc_license_get_key_stats(
385 __out efx_key_stats_t *eksp)
388 EFX_MCDI_DECLARE_BUF(payload, MC_CMD_FC_IN_LICENSE_LEN,
389 MC_CMD_FC_OUT_LICENSE_LEN);
392 EFSYS_ASSERT(enp->en_family == EFX_FAMILY_SIENA);
394 req.emr_cmd = MC_CMD_FC;
395 req.emr_in_buf = payload;
396 req.emr_in_length = MC_CMD_FC_IN_LICENSE_LEN;
397 req.emr_out_buf = payload;
398 req.emr_out_length = MC_CMD_FC_OUT_LICENSE_LEN;
400 MCDI_IN_SET_DWORD(req, FC_IN_CMD,
401 MC_CMD_FC_OP_LICENSE);
403 MCDI_IN_SET_DWORD(req, FC_IN_LICENSE_OP,
404 MC_CMD_FC_IN_LICENSE_GET_KEY_STATS);
406 efx_mcdi_execute_quiet(enp, &req);
408 if (req.emr_rc != 0) {
413 if (req.emr_out_length_used < MC_CMD_FC_OUT_LICENSE_LEN) {
419 MCDI_OUT_DWORD(req, FC_OUT_LICENSE_VALID_KEYS);
421 MCDI_OUT_DWORD(req, FC_OUT_LICENSE_INVALID_KEYS);
422 eksp->eks_blacklisted =
423 MCDI_OUT_DWORD(req, FC_OUT_LICENSE_BLACKLISTED_KEYS);
424 eksp->eks_unverifiable = 0;
425 eksp->eks_wrong_node = 0;
426 eksp->eks_licensed_apps_lo = 0;
427 eksp->eks_licensed_apps_hi = 0;
428 eksp->eks_licensed_features_lo = 0;
429 eksp->eks_licensed_features_hi = 0;
436 EFSYS_PROBE1(fail1, efx_rc_t, rc);
441 #endif /* EFSYS_OPT_SIENA */
443 /* V1 and V2 Partition format - based on a 16-bit TLV format */
445 #if EFSYS_OPT_SIENA | EFSYS_OPT_HUNTINGTON
448 * V1/V2 format - defined in SF-108542-TC section 4.2:
449 * Type (T): 16bit - revision/HMAC algorithm
450 * Length (L): 16bit - value length in bytes
451 * Value (V): L bytes - payload
453 #define EFX_LICENSE_V1V2_PAYLOAD_LENGTH_MAX (256)
454 #define EFX_LICENSE_V1V2_HEADER_LENGTH (2 * sizeof(uint16_t))
456 __checkReturn efx_rc_t
457 efx_lic_v1v2_find_start(
459 __in_bcount(buffer_size)
461 __in size_t buffer_size,
462 __out uint32_t *startp
465 _NOTE(ARGUNUSED(enp, bufferp, buffer_size))
471 __checkReturn efx_rc_t
472 efx_lic_v1v2_find_end(
474 __in_bcount(buffer_size)
476 __in size_t buffer_size,
477 __in uint32_t offset,
481 _NOTE(ARGUNUSED(enp, bufferp, buffer_size))
483 *endp = offset + EFX_LICENSE_V1V2_HEADER_LENGTH;
487 __checkReturn __success(return != B_FALSE) boolean_t
488 efx_lic_v1v2_find_key(
490 __in_bcount(buffer_size)
492 __in size_t buffer_size,
493 __in uint32_t offset,
494 __out uint32_t *startp,
495 __out uint32_t *lengthp
502 _NOTE(ARGUNUSED(enp))
504 if ((size_t)buffer_size - offset < EFX_LICENSE_V1V2_HEADER_LENGTH)
507 tlv_type = __LE_TO_CPU_16(((uint16_t *)&bufferp[offset])[0]);
508 tlv_length = __LE_TO_CPU_16(((uint16_t *)&bufferp[offset])[1]);
509 if ((tlv_length > EFX_LICENSE_V1V2_PAYLOAD_LENGTH_MAX) ||
510 (tlv_type == 0 && tlv_length == 0)) {
514 *lengthp = tlv_length + EFX_LICENSE_V1V2_HEADER_LENGTH;
525 __checkReturn __success(return != B_FALSE) boolean_t
526 efx_lic_v1v2_validate_key(
528 __in_bcount(length) caddr_t keyp,
535 _NOTE(ARGUNUSED(enp))
537 if (length < EFX_LICENSE_V1V2_HEADER_LENGTH) {
541 tlv_type = __LE_TO_CPU_16(((uint16_t *)keyp)[0]);
542 tlv_length = __LE_TO_CPU_16(((uint16_t *)keyp)[1]);
544 if (tlv_length > EFX_LICENSE_V1V2_PAYLOAD_LENGTH_MAX) {
550 if ((tlv_length + EFX_LICENSE_V1V2_HEADER_LENGTH) != length) {
569 __checkReturn efx_rc_t
570 efx_lic_v1v2_read_key(
572 __in_bcount(buffer_size)
574 __in size_t buffer_size,
575 __in uint32_t offset,
576 __in uint32_t length,
577 __out_bcount_part(key_max_size, *lengthp)
579 __in size_t key_max_size,
580 __out uint32_t *lengthp
585 _NOTE(ARGUNUSED(enp))
586 EFSYS_ASSERT(length <= (EFX_LICENSE_V1V2_PAYLOAD_LENGTH_MAX +
587 EFX_LICENSE_V1V2_HEADER_LENGTH));
589 if (key_max_size < length) {
593 memcpy(keyp, &bufferp[offset], length);
600 EFSYS_PROBE1(fail1, efx_rc_t, rc);
605 __checkReturn efx_rc_t
606 efx_lic_v1v2_write_key(
608 __in_bcount(buffer_size)
610 __in size_t buffer_size,
611 __in uint32_t offset,
612 __in_bcount(length) caddr_t keyp,
613 __in uint32_t length,
614 __out uint32_t *lengthp
619 _NOTE(ARGUNUSED(enp))
620 EFSYS_ASSERT(length <= (EFX_LICENSE_V1V2_PAYLOAD_LENGTH_MAX +
621 EFX_LICENSE_V1V2_HEADER_LENGTH));
623 /* Ensure space for terminator remains */
624 if ((offset + length) >
625 (buffer_size - EFX_LICENSE_V1V2_HEADER_LENGTH)) {
630 memcpy(bufferp + offset, keyp, length);
637 EFSYS_PROBE1(fail1, efx_rc_t, rc);
642 __checkReturn efx_rc_t
643 efx_lic_v1v2_delete_key(
645 __in_bcount(buffer_size)
647 __in size_t buffer_size,
648 __in uint32_t offset,
649 __in uint32_t length,
651 __out uint32_t *deltap
654 uint32_t move_start = offset + length;
655 uint32_t move_length = end - move_start;
657 _NOTE(ARGUNUSED(enp))
658 EFSYS_ASSERT(end <= buffer_size);
660 /* Shift everything after the key down */
661 memmove(bufferp + offset, bufferp + move_start, move_length);
668 __checkReturn efx_rc_t
669 efx_lic_v1v2_create_partition(
671 __in_bcount(buffer_size)
673 __in size_t buffer_size
676 _NOTE(ARGUNUSED(enp))
677 EFSYS_ASSERT(EFX_LICENSE_V1V2_HEADER_LENGTH <= buffer_size);
679 /* Write terminator */
680 memset(bufferp, '\0', EFX_LICENSE_V1V2_HEADER_LENGTH);
685 __checkReturn efx_rc_t
686 efx_lic_v1v2_finish_partition(
688 __in_bcount(buffer_size)
690 __in size_t buffer_size
693 _NOTE(ARGUNUSED(enp, bufferp, buffer_size))
698 #endif /* EFSYS_OPT_HUNTINGTON | EFSYS_OPT_SIENA */
701 /* V2 Licensing - used by Huntington family only. See SF-113611-TC */
703 #if EFSYS_OPT_HUNTINGTON
705 static __checkReturn efx_rc_t
706 efx_mcdi_licensed_app_state(
708 __in uint64_t app_id,
709 __out boolean_t *licensedp)
712 EFX_MCDI_DECLARE_BUF(payload, MC_CMD_GET_LICENSED_APP_STATE_IN_LEN,
713 MC_CMD_GET_LICENSED_APP_STATE_OUT_LEN);
717 EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON);
719 /* V2 licensing supports 32bit app id only */
720 if ((app_id >> 32) != 0) {
725 req.emr_cmd = MC_CMD_GET_LICENSED_APP_STATE;
726 req.emr_in_buf = payload;
727 req.emr_in_length = MC_CMD_GET_LICENSED_APP_STATE_IN_LEN;
728 req.emr_out_buf = payload;
729 req.emr_out_length = MC_CMD_GET_LICENSED_APP_STATE_OUT_LEN;
731 MCDI_IN_SET_DWORD(req, GET_LICENSED_APP_STATE_IN_APP_ID,
732 app_id & 0xffffffff);
734 efx_mcdi_execute(enp, &req);
736 if (req.emr_rc != 0) {
741 if (req.emr_out_length_used < MC_CMD_GET_LICENSED_APP_STATE_OUT_LEN) {
746 app_state = (MCDI_OUT_DWORD(req, GET_LICENSED_APP_STATE_OUT_STATE));
747 if (app_state != MC_CMD_GET_LICENSED_APP_STATE_OUT_NOT_LICENSED) {
750 *licensedp = B_FALSE;
760 EFSYS_PROBE1(fail1, efx_rc_t, rc);
765 static __checkReturn efx_rc_t
766 efx_mcdi_licensing_update_licenses(
770 EFX_MCDI_DECLARE_BUF(payload, MC_CMD_LICENSING_IN_LEN, 0);
773 EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON);
775 req.emr_cmd = MC_CMD_LICENSING;
776 req.emr_in_buf = payload;
777 req.emr_in_length = MC_CMD_LICENSING_IN_LEN;
778 req.emr_out_buf = payload;
779 req.emr_out_length = 0;
781 MCDI_IN_SET_DWORD(req, LICENSING_IN_OP,
782 MC_CMD_LICENSING_IN_OP_UPDATE_LICENSE);
784 efx_mcdi_execute(enp, &req);
786 if (req.emr_rc != 0) {
791 if (req.emr_out_length_used != 0) {
801 EFSYS_PROBE1(fail1, efx_rc_t, rc);
806 static __checkReturn efx_rc_t
807 efx_mcdi_licensing_get_key_stats(
809 __out efx_key_stats_t *eksp)
812 EFX_MCDI_DECLARE_BUF(payload, MC_CMD_LICENSING_IN_LEN,
813 MC_CMD_LICENSING_OUT_LEN);
816 EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON);
818 req.emr_cmd = MC_CMD_LICENSING;
819 req.emr_in_buf = payload;
820 req.emr_in_length = MC_CMD_LICENSING_IN_LEN;
821 req.emr_out_buf = payload;
822 req.emr_out_length = MC_CMD_LICENSING_OUT_LEN;
824 MCDI_IN_SET_DWORD(req, LICENSING_IN_OP,
825 MC_CMD_LICENSING_IN_OP_GET_KEY_STATS);
827 efx_mcdi_execute(enp, &req);
829 if (req.emr_rc != 0) {
834 if (req.emr_out_length_used < MC_CMD_LICENSING_OUT_LEN) {
840 MCDI_OUT_DWORD(req, LICENSING_OUT_VALID_APP_KEYS);
842 MCDI_OUT_DWORD(req, LICENSING_OUT_INVALID_APP_KEYS);
843 eksp->eks_blacklisted =
844 MCDI_OUT_DWORD(req, LICENSING_OUT_BLACKLISTED_APP_KEYS);
845 eksp->eks_unverifiable =
846 MCDI_OUT_DWORD(req, LICENSING_OUT_UNVERIFIABLE_APP_KEYS);
847 eksp->eks_wrong_node =
848 MCDI_OUT_DWORD(req, LICENSING_OUT_WRONG_NODE_APP_KEYS);
849 eksp->eks_licensed_apps_lo = 0;
850 eksp->eks_licensed_apps_hi = 0;
851 eksp->eks_licensed_features_lo = 0;
852 eksp->eks_licensed_features_hi = 0;
859 EFSYS_PROBE1(fail1, efx_rc_t, rc);
864 #endif /* EFSYS_OPT_HUNTINGTON */
866 /* V3 Licensing - used starting from Medford family. See SF-114884-SW */
868 #if EFSYS_OPT_MEDFORD
870 static __checkReturn efx_rc_t
871 efx_mcdi_licensing_v3_update_licenses(
875 EFX_MCDI_DECLARE_BUF(payload, MC_CMD_LICENSING_V3_IN_LEN, 0);
878 EFSYS_ASSERT(enp->en_family == EFX_FAMILY_MEDFORD);
880 req.emr_cmd = MC_CMD_LICENSING_V3;
881 req.emr_in_buf = payload;
882 req.emr_in_length = MC_CMD_LICENSING_V3_IN_LEN;
883 req.emr_out_buf = NULL;
884 req.emr_out_length = 0;
886 MCDI_IN_SET_DWORD(req, LICENSING_V3_IN_OP,
887 MC_CMD_LICENSING_V3_IN_OP_UPDATE_LICENSE);
889 efx_mcdi_execute(enp, &req);
891 if (req.emr_rc != 0) {
899 EFSYS_PROBE1(fail1, efx_rc_t, rc);
904 static __checkReturn efx_rc_t
905 efx_mcdi_licensing_v3_report_license(
907 __out efx_key_stats_t *eksp)
910 EFX_MCDI_DECLARE_BUF(payload, MC_CMD_LICENSING_V3_IN_LEN,
911 MC_CMD_LICENSING_V3_OUT_LEN);
914 EFSYS_ASSERT(enp->en_family == EFX_FAMILY_MEDFORD);
916 req.emr_cmd = MC_CMD_LICENSING_V3;
917 req.emr_in_buf = payload;
918 req.emr_in_length = MC_CMD_LICENSING_V3_IN_LEN;
919 req.emr_out_buf = payload;
920 req.emr_out_length = MC_CMD_LICENSING_V3_OUT_LEN;
922 MCDI_IN_SET_DWORD(req, LICENSING_V3_IN_OP,
923 MC_CMD_LICENSING_V3_IN_OP_REPORT_LICENSE);
925 efx_mcdi_execute_quiet(enp, &req);
927 if (req.emr_rc != 0) {
932 if (req.emr_out_length_used < MC_CMD_LICENSING_V3_OUT_LEN) {
938 MCDI_OUT_DWORD(req, LICENSING_V3_OUT_VALID_KEYS);
940 MCDI_OUT_DWORD(req, LICENSING_V3_OUT_INVALID_KEYS);
941 eksp->eks_blacklisted = 0;
942 eksp->eks_unverifiable =
943 MCDI_OUT_DWORD(req, LICENSING_V3_OUT_UNVERIFIABLE_KEYS);
944 eksp->eks_wrong_node =
945 MCDI_OUT_DWORD(req, LICENSING_V3_OUT_WRONG_NODE_KEYS);
946 eksp->eks_licensed_apps_lo =
947 MCDI_OUT_DWORD(req, LICENSING_V3_OUT_LICENSED_APPS_LO);
948 eksp->eks_licensed_apps_hi =
949 MCDI_OUT_DWORD(req, LICENSING_V3_OUT_LICENSED_APPS_HI);
950 eksp->eks_licensed_features_lo =
951 MCDI_OUT_DWORD(req, LICENSING_V3_OUT_LICENSED_FEATURES_LO);
952 eksp->eks_licensed_features_hi =
953 MCDI_OUT_DWORD(req, LICENSING_V3_OUT_LICENSED_FEATURES_HI);
960 EFSYS_PROBE1(fail1, efx_rc_t, rc);
965 static __checkReturn efx_rc_t
966 efx_mcdi_licensing_v3_app_state(
968 __in uint64_t app_id,
969 __out boolean_t *licensedp)
972 EFX_MCDI_DECLARE_BUF(payload, MC_CMD_GET_LICENSED_V3_APP_STATE_IN_LEN,
973 MC_CMD_GET_LICENSED_V3_APP_STATE_OUT_LEN);
977 EFSYS_ASSERT(enp->en_family == EFX_FAMILY_MEDFORD);
979 req.emr_cmd = MC_CMD_GET_LICENSED_V3_APP_STATE;
980 req.emr_in_buf = payload;
981 req.emr_in_length = MC_CMD_GET_LICENSED_V3_APP_STATE_IN_LEN;
982 req.emr_out_buf = payload;
983 req.emr_out_length = MC_CMD_GET_LICENSED_V3_APP_STATE_OUT_LEN;
985 MCDI_IN_SET_DWORD(req, GET_LICENSED_V3_APP_STATE_IN_APP_ID_LO,
986 app_id & 0xffffffff);
987 MCDI_IN_SET_DWORD(req, GET_LICENSED_V3_APP_STATE_IN_APP_ID_HI,
990 efx_mcdi_execute(enp, &req);
992 if (req.emr_rc != 0) {
997 if (req.emr_out_length_used < MC_CMD_GET_LICENSED_V3_APP_STATE_OUT_LEN) {
1002 app_state = (MCDI_OUT_DWORD(req, GET_LICENSED_V3_APP_STATE_OUT_STATE));
1003 if (app_state != MC_CMD_GET_LICENSED_V3_APP_STATE_OUT_NOT_LICENSED) {
1004 *licensedp = B_TRUE;
1006 *licensedp = B_FALSE;
1014 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1019 static __checkReturn efx_rc_t
1020 efx_mcdi_licensing_v3_get_id(
1021 __in efx_nic_t *enp,
1022 __in size_t buffer_size,
1023 __out uint32_t *typep,
1024 __out size_t *lengthp,
1025 __out_bcount_part_opt(buffer_size, *lengthp)
1029 EFX_MCDI_DECLARE_BUF(payload, MC_CMD_LICENSING_GET_ID_V3_IN_LEN,
1030 MC_CMD_LICENSING_GET_ID_V3_OUT_LENMAX);
1033 req.emr_cmd = MC_CMD_LICENSING_GET_ID_V3;
1034 req.emr_in_buf = payload;
1035 req.emr_in_length = MC_CMD_LICENSING_GET_ID_V3_IN_LEN;
1036 req.emr_out_buf = payload;
1037 req.emr_out_length = MC_CMD_LICENSING_GET_ID_V3_OUT_LENMAX;
1039 efx_mcdi_execute_quiet(enp, &req);
1041 if (req.emr_rc != 0) {
1046 if (req.emr_out_length_used < MC_CMD_LICENSING_GET_ID_V3_OUT_LENMIN) {
1051 *typep = MCDI_OUT_DWORD(req, LICENSING_GET_ID_V3_OUT_LICENSE_TYPE);
1052 *lengthp = MCDI_OUT_DWORD(req, LICENSING_GET_ID_V3_OUT_LICENSE_ID_LENGTH);
1054 if (bufferp != NULL) {
1056 payload + MC_CMD_LICENSING_GET_ID_V3_OUT_LICENSE_ID_OFST,
1057 MIN(buffer_size, *lengthp));
1065 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1070 /* V3 format uses Huntington TLV format partition. See SF-108797-SW */
1071 #define EFX_LICENSE_V3_KEY_LENGTH_MIN (64)
1072 #define EFX_LICENSE_V3_KEY_LENGTH_MAX (160)
1074 __checkReturn efx_rc_t
1075 efx_lic_v3_find_start(
1076 __in efx_nic_t *enp,
1077 __in_bcount(buffer_size)
1079 __in size_t buffer_size,
1080 __out uint32_t *startp
1083 _NOTE(ARGUNUSED(enp))
1085 return ef10_nvram_buffer_find_item_start(bufferp, buffer_size, startp);
1088 __checkReturn efx_rc_t
1089 efx_lic_v3_find_end(
1090 __in efx_nic_t *enp,
1091 __in_bcount(buffer_size)
1093 __in size_t buffer_size,
1094 __in uint32_t offset,
1095 __out uint32_t *endp
1098 _NOTE(ARGUNUSED(enp))
1100 return ef10_nvram_buffer_find_end(bufferp, buffer_size, offset, endp);
1103 __checkReturn __success(return != B_FALSE) boolean_t
1104 efx_lic_v3_find_key(
1105 __in efx_nic_t *enp,
1106 __in_bcount(buffer_size)
1108 __in size_t buffer_size,
1109 __in uint32_t offset,
1110 __out uint32_t *startp,
1111 __out uint32_t *lengthp
1114 _NOTE(ARGUNUSED(enp))
1116 return ef10_nvram_buffer_find_item(bufferp, buffer_size,
1117 offset, startp, lengthp);
1120 __checkReturn __success(return != B_FALSE) boolean_t
1121 efx_lic_v3_validate_key(
1122 __in efx_nic_t *enp,
1123 __in_bcount(length) caddr_t keyp,
1124 __in uint32_t length
1127 /* Check key is a valid V3 key */
1131 _NOTE(ARGUNUSED(enp))
1133 if (length < EFX_LICENSE_V3_KEY_LENGTH_MIN) {
1137 if (length > EFX_LICENSE_V3_KEY_LENGTH_MAX) {
1141 key_type = ((uint8_t *)keyp)[0];
1142 key_length = ((uint8_t *)keyp)[1];
1147 if (key_length > length) {
1164 __checkReturn efx_rc_t
1165 efx_lic_v3_read_key(
1166 __in efx_nic_t *enp,
1167 __in_bcount(buffer_size)
1169 __in size_t buffer_size,
1170 __in uint32_t offset,
1171 __in uint32_t length,
1172 __out_bcount_part(key_max_size, *lengthp)
1174 __in size_t key_max_size,
1175 __out uint32_t *lengthp
1178 _NOTE(ARGUNUSED(enp))
1180 return ef10_nvram_buffer_get_item(bufferp, buffer_size,
1181 offset, length, keyp, key_max_size, lengthp);
1184 __checkReturn efx_rc_t
1185 efx_lic_v3_write_key(
1186 __in efx_nic_t *enp,
1187 __in_bcount(buffer_size)
1189 __in size_t buffer_size,
1190 __in uint32_t offset,
1191 __in_bcount(length) caddr_t keyp,
1192 __in uint32_t length,
1193 __out uint32_t *lengthp
1196 _NOTE(ARGUNUSED(enp))
1197 EFSYS_ASSERT(length <= EFX_LICENSE_V3_KEY_LENGTH_MAX);
1199 return ef10_nvram_buffer_insert_item(bufferp, buffer_size,
1200 offset, keyp, length, lengthp);
1203 __checkReturn efx_rc_t
1204 efx_lic_v3_delete_key(
1205 __in efx_nic_t *enp,
1206 __in_bcount(buffer_size)
1208 __in size_t buffer_size,
1209 __in uint32_t offset,
1210 __in uint32_t length,
1212 __out uint32_t *deltap
1217 _NOTE(ARGUNUSED(enp))
1219 if ((rc = ef10_nvram_buffer_delete_item(bufferp,
1220 buffer_size, offset, length, end)) != 0) {
1229 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1234 __checkReturn efx_rc_t
1235 efx_lic_v3_create_partition(
1236 __in efx_nic_t *enp,
1237 __in_bcount(buffer_size)
1239 __in size_t buffer_size
1244 /* Construct empty partition */
1245 if ((rc = ef10_nvram_buffer_create(enp,
1246 NVRAM_PARTITION_TYPE_LICENSE,
1247 bufferp, buffer_size)) != 0) {
1255 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1260 __checkReturn efx_rc_t
1261 efx_lic_v3_finish_partition(
1262 __in efx_nic_t *enp,
1263 __in_bcount(buffer_size)
1265 __in size_t buffer_size
1270 if ((rc = ef10_nvram_buffer_finish(bufferp,
1271 buffer_size)) != 0) {
1275 /* Validate completed partition */
1276 if ((rc = ef10_nvram_buffer_validate(enp, NVRAM_PARTITION_TYPE_LICENSE,
1277 bufferp, buffer_size)) != 0) {
1286 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1292 #endif /* EFSYS_OPT_MEDFORD */
1294 __checkReturn efx_rc_t
1296 __in efx_nic_t *enp)
1298 const efx_lic_ops_t *elop;
1299 efx_key_stats_t eks;
1302 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1303 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
1304 EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_LIC));
1306 switch (enp->en_family) {
1309 case EFX_FAMILY_SIENA:
1310 elop = &__efx_lic_v1_ops;
1312 #endif /* EFSYS_OPT_SIENA */
1314 #if EFSYS_OPT_HUNTINGTON
1315 case EFX_FAMILY_HUNTINGTON:
1316 elop = &__efx_lic_v2_ops;
1318 #endif /* EFSYS_OPT_HUNTINGTON */
1320 #if EFSYS_OPT_MEDFORD
1321 case EFX_FAMILY_MEDFORD:
1322 elop = &__efx_lic_v3_ops;
1324 #endif /* EFSYS_OPT_MEDFORD */
1332 enp->en_elop = elop;
1333 enp->en_mod_flags |= EFX_MOD_LIC;
1335 /* Probe for support */
1336 if (efx_lic_get_key_stats(enp, &eks) == 0) {
1337 enp->en_licensing_supported = B_TRUE;
1339 enp->en_licensing_supported = B_FALSE;
1345 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1350 extern __checkReturn boolean_t
1351 efx_lic_check_support(
1352 __in efx_nic_t *enp)
1354 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1355 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
1356 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1358 return enp->en_licensing_supported;
1363 __in efx_nic_t *enp)
1365 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1366 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
1367 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1369 enp->en_elop = NULL;
1370 enp->en_mod_flags &= ~EFX_MOD_LIC;
1374 __checkReturn efx_rc_t
1375 efx_lic_update_licenses(
1376 __in efx_nic_t *enp)
1378 const efx_lic_ops_t *elop = enp->en_elop;
1381 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1382 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1384 if ((rc = elop->elo_update_licenses(enp)) != 0)
1390 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1395 __checkReturn efx_rc_t
1396 efx_lic_get_key_stats(
1397 __in efx_nic_t *enp,
1398 __out efx_key_stats_t *eksp)
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_get_key_stats(enp, eksp)) != 0)
1412 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1417 __checkReturn efx_rc_t
1419 __in efx_nic_t *enp,
1420 __in uint64_t app_id,
1421 __out boolean_t *licensedp)
1423 const efx_lic_ops_t *elop = enp->en_elop;
1426 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1427 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1429 if (elop->elo_app_state == NULL)
1432 if ((rc = elop->elo_app_state(enp, app_id, licensedp)) != 0)
1438 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1443 __checkReturn efx_rc_t
1445 __in efx_nic_t *enp,
1446 __in size_t buffer_size,
1447 __out uint32_t *typep,
1448 __out size_t *lengthp,
1449 __out_opt uint8_t *bufferp
1452 const efx_lic_ops_t *elop = enp->en_elop;
1455 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1456 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1458 if (elop->elo_get_id == NULL)
1461 if ((rc = elop->elo_get_id(enp, buffer_size, typep,
1462 lengthp, bufferp)) != 0)
1468 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1473 /* Buffer management API - abstracts varying TLV format used for License partition */
1475 __checkReturn efx_rc_t
1477 __in efx_nic_t *enp,
1478 __in_bcount(buffer_size)
1480 __in size_t buffer_size,
1481 __out uint32_t *startp
1484 const efx_lic_ops_t *elop = enp->en_elop;
1487 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1488 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1490 if ((rc = elop->elo_find_start(enp, bufferp, buffer_size, startp)) != 0)
1496 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1501 __checkReturn efx_rc_t
1503 __in efx_nic_t *enp,
1504 __in_bcount(buffer_size)
1506 __in size_t buffer_size,
1507 __in uint32_t offset,
1508 __out uint32_t *endp
1511 const efx_lic_ops_t *elop = enp->en_elop;
1514 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1515 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1517 if ((rc = elop->elo_find_end(enp, bufferp, buffer_size, offset, endp)) != 0)
1523 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1528 __checkReturn __success(return != B_FALSE) boolean_t
1530 __in efx_nic_t *enp,
1531 __in_bcount(buffer_size)
1533 __in size_t buffer_size,
1534 __in uint32_t offset,
1535 __out uint32_t *startp,
1536 __out uint32_t *lengthp
1539 const efx_lic_ops_t *elop = enp->en_elop;
1541 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1542 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1544 EFSYS_ASSERT(bufferp);
1545 EFSYS_ASSERT(startp);
1546 EFSYS_ASSERT(lengthp);
1548 return (elop->elo_find_key(enp, bufferp, buffer_size, offset,
1553 /* Validate that the buffer contains a single key in a recognised format.
1554 ** An empty or terminator buffer is not accepted as a valid key.
1556 __checkReturn __success(return != B_FALSE) boolean_t
1557 efx_lic_validate_key(
1558 __in efx_nic_t *enp,
1559 __in_bcount(length) caddr_t keyp,
1560 __in uint32_t length
1563 const efx_lic_ops_t *elop = enp->en_elop;
1566 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1567 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1569 if ((rc = elop->elo_validate_key(enp, keyp, length)) == B_FALSE)
1575 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1580 __checkReturn efx_rc_t
1582 __in efx_nic_t *enp,
1583 __in_bcount(buffer_size)
1585 __in size_t buffer_size,
1586 __in uint32_t offset,
1587 __in uint32_t length,
1588 __out_bcount_part(key_max_size, *lengthp)
1590 __in size_t key_max_size,
1591 __out uint32_t *lengthp
1594 const efx_lic_ops_t *elop = enp->en_elop;
1597 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1598 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1600 if ((rc = elop->elo_read_key(enp, bufferp, buffer_size, offset,
1601 length, keyp, key_max_size, lengthp)) != 0)
1607 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1612 __checkReturn efx_rc_t
1614 __in efx_nic_t *enp,
1615 __in_bcount(buffer_size)
1617 __in size_t buffer_size,
1618 __in uint32_t offset,
1619 __in_bcount(length) caddr_t keyp,
1620 __in uint32_t length,
1621 __out uint32_t *lengthp
1624 const efx_lic_ops_t *elop = enp->en_elop;
1627 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1628 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1630 if ((rc = elop->elo_write_key(enp, bufferp, buffer_size, offset,
1631 keyp, length, lengthp)) != 0)
1637 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1642 __checkReturn efx_rc_t
1644 __in efx_nic_t *enp,
1645 __in_bcount(buffer_size)
1647 __in size_t buffer_size,
1648 __in uint32_t offset,
1649 __in uint32_t length,
1651 __out uint32_t *deltap
1654 const efx_lic_ops_t *elop = enp->en_elop;
1657 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1658 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1660 if ((rc = elop->elo_delete_key(enp, bufferp, buffer_size, offset,
1661 length, end, deltap)) != 0)
1667 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1672 __checkReturn efx_rc_t
1673 efx_lic_create_partition(
1674 __in efx_nic_t *enp,
1675 __in_bcount(buffer_size)
1677 __in size_t buffer_size
1680 const efx_lic_ops_t *elop = enp->en_elop;
1683 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1684 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1686 if ((rc = elop->elo_create_partition(enp, bufferp, buffer_size)) != 0)
1692 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1698 __checkReturn efx_rc_t
1699 efx_lic_finish_partition(
1700 __in efx_nic_t *enp,
1701 __in_bcount(buffer_size)
1703 __in size_t buffer_size
1706 const efx_lic_ops_t *elop = enp->en_elop;
1709 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1710 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1712 if ((rc = elop->elo_finish_partition(enp, bufferp, buffer_size)) != 0)
1718 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1723 #endif /* EFSYS_OPT_LICENSING */