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);
48 __checkReturn efx_rc_t
49 efx_lic_v1v2_find_end(
51 __in_bcount(buffer_size)
53 __in size_t buffer_size,
55 __out uint32_t *endp);
57 __checkReturn __success(return != B_FALSE) boolean_t
58 efx_lic_v1v2_find_key(
60 __in_bcount(buffer_size)
62 __in size_t buffer_size,
64 __out uint32_t *startp,
65 __out uint32_t *lengthp);
67 __checkReturn __success(return != B_FALSE) boolean_t
68 efx_lic_v1v2_validate_key(
70 __in_bcount(length) caddr_t keyp,
71 __in uint32_t length);
73 __checkReturn efx_rc_t
74 efx_lic_v1v2_read_key(
76 __in_bcount(buffer_size)
78 __in size_t buffer_size,
81 __out_bcount_part(key_max_size, *lengthp)
83 __in size_t key_max_size,
84 __out uint32_t *lengthp);
86 __checkReturn efx_rc_t
87 efx_lic_v1v2_write_key(
89 __in_bcount(buffer_size)
91 __in size_t buffer_size,
93 __in_bcount(length) caddr_t keyp,
95 __out uint32_t *lengthp);
97 __checkReturn efx_rc_t
98 efx_lic_v1v2_delete_key(
100 __in_bcount(buffer_size)
102 __in size_t buffer_size,
103 __in uint32_t offset,
104 __in uint32_t length,
106 __out uint32_t *deltap);
108 __checkReturn efx_rc_t
109 efx_lic_v1v2_create_partition(
111 __in_bcount(buffer_size)
113 __in size_t buffer_size);
115 __checkReturn efx_rc_t
116 efx_lic_v1v2_finish_partition(
118 __in_bcount(buffer_size)
120 __in size_t buffer_size);
122 #endif /* EFSYS_OPT_HUNTINGTON | EFSYS_OPT_SIENA */
127 static __checkReturn efx_rc_t
128 efx_mcdi_fc_license_update_license(
129 __in efx_nic_t *enp);
131 static __checkReturn efx_rc_t
132 efx_mcdi_fc_license_get_key_stats(
134 __out efx_key_stats_t *eksp);
136 static const efx_lic_ops_t __efx_lic_v1_ops = {
137 efx_mcdi_fc_license_update_license, /* elo_update_licenses */
138 efx_mcdi_fc_license_get_key_stats, /* elo_get_key_stats */
139 NULL, /* elo_app_state */
140 NULL, /* elo_get_id */
141 efx_lic_v1v2_find_start, /* elo_find_start */
142 efx_lic_v1v2_find_end, /* elo_find_end */
143 efx_lic_v1v2_find_key, /* elo_find_key */
144 efx_lic_v1v2_validate_key, /* elo_validate_key */
145 efx_lic_v1v2_read_key, /* elo_read_key */
146 efx_lic_v1v2_write_key, /* elo_write_key */
147 efx_lic_v1v2_delete_key, /* elo_delete_key */
148 efx_lic_v1v2_create_partition, /* elo_create_partition */
149 efx_lic_v1v2_finish_partition, /* elo_finish_partition */
152 #endif /* EFSYS_OPT_SIENA */
154 #if EFSYS_OPT_HUNTINGTON
156 static __checkReturn efx_rc_t
157 efx_mcdi_licensing_update_licenses(
158 __in efx_nic_t *enp);
160 static __checkReturn efx_rc_t
161 efx_mcdi_licensing_get_key_stats(
163 __out efx_key_stats_t *eksp);
165 static __checkReturn efx_rc_t
166 efx_mcdi_licensed_app_state(
168 __in uint64_t app_id,
169 __out boolean_t *licensedp);
171 static const efx_lic_ops_t __efx_lic_v2_ops = {
172 efx_mcdi_licensing_update_licenses, /* elo_update_licenses */
173 efx_mcdi_licensing_get_key_stats, /* elo_get_key_stats */
174 efx_mcdi_licensed_app_state, /* elo_app_state */
175 NULL, /* elo_get_id */
176 efx_lic_v1v2_find_start, /* elo_find_start */
177 efx_lic_v1v2_find_end, /* elo_find_end */
178 efx_lic_v1v2_find_key, /* elo_find_key */
179 efx_lic_v1v2_validate_key, /* elo_validate_key */
180 efx_lic_v1v2_read_key, /* elo_read_key */
181 efx_lic_v1v2_write_key, /* elo_write_key */
182 efx_lic_v1v2_delete_key, /* elo_delete_key */
183 efx_lic_v1v2_create_partition, /* elo_create_partition */
184 efx_lic_v1v2_finish_partition, /* elo_finish_partition */
187 #endif /* EFSYS_OPT_HUNTINGTON */
189 #if EFSYS_OPT_MEDFORD
191 static __checkReturn efx_rc_t
192 efx_mcdi_licensing_v3_update_licenses(
193 __in efx_nic_t *enp);
195 static __checkReturn efx_rc_t
196 efx_mcdi_licensing_v3_report_license(
198 __out efx_key_stats_t *eksp);
200 static __checkReturn efx_rc_t
201 efx_mcdi_licensing_v3_app_state(
203 __in uint64_t app_id,
204 __out boolean_t *licensedp);
206 static __checkReturn efx_rc_t
207 efx_mcdi_licensing_v3_get_id(
209 __in size_t buffer_size,
210 __out uint32_t *typep,
211 __out size_t *lengthp,
212 __out_bcount_part_opt(buffer_size, *lengthp)
215 __checkReturn efx_rc_t
216 efx_lic_v3_find_start(
218 __in_bcount(buffer_size)
220 __in size_t buffer_size,
221 __out uint32_t *startp);
223 __checkReturn efx_rc_t
226 __in_bcount(buffer_size)
228 __in size_t buffer_size,
229 __in uint32_t offset,
230 __out uint32_t *endp);
232 __checkReturn __success(return != B_FALSE) boolean_t
235 __in_bcount(buffer_size)
237 __in size_t buffer_size,
238 __in uint32_t offset,
239 __out uint32_t *startp,
240 __out uint32_t *lengthp);
242 __checkReturn __success(return != B_FALSE) boolean_t
243 efx_lic_v3_validate_key(
245 __in_bcount(length) caddr_t keyp,
246 __in uint32_t length);
248 __checkReturn efx_rc_t
251 __in_bcount(buffer_size)
253 __in size_t buffer_size,
254 __in uint32_t offset,
255 __in uint32_t length,
256 __out_bcount_part(key_max_size, *lengthp)
258 __in size_t key_max_size,
259 __out uint32_t *lengthp);
261 __checkReturn efx_rc_t
262 efx_lic_v3_write_key(
264 __in_bcount(buffer_size)
266 __in size_t buffer_size,
267 __in uint32_t offset,
268 __in_bcount(length) caddr_t keyp,
269 __in uint32_t length,
270 __out uint32_t *lengthp);
272 __checkReturn efx_rc_t
273 efx_lic_v3_delete_key(
275 __in_bcount(buffer_size)
277 __in size_t buffer_size,
278 __in uint32_t offset,
279 __in uint32_t length,
281 __out uint32_t *deltap);
283 __checkReturn efx_rc_t
284 efx_lic_v3_create_partition(
286 __in_bcount(buffer_size)
288 __in size_t buffer_size);
290 __checkReturn efx_rc_t
291 efx_lic_v3_finish_partition(
293 __in_bcount(buffer_size)
295 __in size_t buffer_size);
297 static const efx_lic_ops_t __efx_lic_v3_ops = {
298 efx_mcdi_licensing_v3_update_licenses, /* elo_update_licenses */
299 efx_mcdi_licensing_v3_report_license, /* elo_get_key_stats */
300 efx_mcdi_licensing_v3_app_state, /* elo_app_state */
301 efx_mcdi_licensing_v3_get_id, /* elo_get_id */
302 efx_lic_v3_find_start, /* elo_find_start */
303 efx_lic_v3_find_end, /* elo_find_end */
304 efx_lic_v3_find_key, /* elo_find_key */
305 efx_lic_v3_validate_key, /* elo_validate_key */
306 efx_lic_v3_read_key, /* elo_read_key */
307 efx_lic_v3_write_key, /* elo_write_key */
308 efx_lic_v3_delete_key, /* elo_delete_key */
309 efx_lic_v3_create_partition, /* elo_create_partition */
310 efx_lic_v3_finish_partition, /* elo_finish_partition */
313 #endif /* EFSYS_OPT_MEDFORD */
316 /* V1 Licensing - used in Siena Modena only */
320 static __checkReturn efx_rc_t
321 efx_mcdi_fc_license_update_license(
325 uint8_t payload[MC_CMD_FC_IN_LICENSE_LEN];
328 EFSYS_ASSERT(enp->en_family == EFX_FAMILY_SIENA);
330 (void) memset(payload, 0, sizeof (payload));
331 req.emr_cmd = MC_CMD_FC;
332 req.emr_in_buf = payload;
333 req.emr_in_length = MC_CMD_FC_IN_LICENSE_LEN;
334 req.emr_out_buf = payload;
335 req.emr_out_length = 0;
337 MCDI_IN_SET_DWORD(req, FC_IN_CMD,
338 MC_CMD_FC_OP_LICENSE);
340 MCDI_IN_SET_DWORD(req, FC_IN_LICENSE_OP,
341 MC_CMD_FC_IN_LICENSE_UPDATE_LICENSE);
343 efx_mcdi_execute(enp, &req);
345 if (req.emr_rc != 0) {
350 if (req.emr_out_length_used != 0) {
360 EFSYS_PROBE1(fail1, efx_rc_t, rc);
365 static __checkReturn efx_rc_t
366 efx_mcdi_fc_license_get_key_stats(
368 __out efx_key_stats_t *eksp)
371 uint8_t payload[MAX(MC_CMD_FC_IN_LICENSE_LEN,
372 MC_CMD_FC_OUT_LICENSE_LEN)];
375 EFSYS_ASSERT(enp->en_family == EFX_FAMILY_SIENA);
377 (void) memset(payload, 0, sizeof (payload));
378 req.emr_cmd = MC_CMD_FC;
379 req.emr_in_buf = payload;
380 req.emr_in_length = MC_CMD_FC_IN_LICENSE_LEN;
381 req.emr_out_buf = payload;
382 req.emr_out_length = MC_CMD_FC_OUT_LICENSE_LEN;
384 MCDI_IN_SET_DWORD(req, FC_IN_CMD,
385 MC_CMD_FC_OP_LICENSE);
387 MCDI_IN_SET_DWORD(req, FC_IN_LICENSE_OP,
388 MC_CMD_FC_IN_LICENSE_GET_KEY_STATS);
390 efx_mcdi_execute_quiet(enp, &req);
392 if (req.emr_rc != 0) {
397 if (req.emr_out_length_used < MC_CMD_FC_OUT_LICENSE_LEN) {
403 MCDI_OUT_DWORD(req, FC_OUT_LICENSE_VALID_KEYS);
405 MCDI_OUT_DWORD(req, FC_OUT_LICENSE_INVALID_KEYS);
406 eksp->eks_blacklisted =
407 MCDI_OUT_DWORD(req, FC_OUT_LICENSE_BLACKLISTED_KEYS);
408 eksp->eks_unverifiable = 0;
409 eksp->eks_wrong_node = 0;
410 eksp->eks_licensed_apps_lo = 0;
411 eksp->eks_licensed_apps_hi = 0;
412 eksp->eks_licensed_features_lo = 0;
413 eksp->eks_licensed_features_hi = 0;
420 EFSYS_PROBE1(fail1, efx_rc_t, rc);
425 #endif /* EFSYS_OPT_SIENA */
427 /* V1 and V2 Partition format - based on a 16-bit TLV format */
429 #if EFSYS_OPT_SIENA | EFSYS_OPT_HUNTINGTON
432 * V1/V2 format - defined in SF-108542-TC section 4.2:
433 * Type (T): 16bit - revision/HMAC algorithm
434 * Length (L): 16bit - value length in bytes
435 * Value (V): L bytes - payload
437 #define EFX_LICENSE_V1V2_PAYLOAD_LENGTH_MAX (256)
438 #define EFX_LICENSE_V1V2_HEADER_LENGTH (2 * sizeof (uint16_t))
440 __checkReturn efx_rc_t
441 efx_lic_v1v2_find_start(
443 __in_bcount(buffer_size)
445 __in size_t buffer_size,
446 __out uint32_t *startp)
448 _NOTE(ARGUNUSED(enp, bufferp, buffer_size))
454 __checkReturn efx_rc_t
455 efx_lic_v1v2_find_end(
457 __in_bcount(buffer_size)
459 __in size_t buffer_size,
460 __in uint32_t offset,
461 __out uint32_t *endp)
463 _NOTE(ARGUNUSED(enp, bufferp, buffer_size))
465 *endp = offset + EFX_LICENSE_V1V2_HEADER_LENGTH;
469 __checkReturn __success(return != B_FALSE) boolean_t
470 efx_lic_v1v2_find_key(
472 __in_bcount(buffer_size)
474 __in size_t buffer_size,
475 __in uint32_t offset,
476 __out uint32_t *startp,
477 __out uint32_t *lengthp)
483 _NOTE(ARGUNUSED(enp))
485 if ((size_t)buffer_size - offset < EFX_LICENSE_V1V2_HEADER_LENGTH)
488 tlv_type = __LE_TO_CPU_16(((uint16_t *)&bufferp[offset])[0]);
489 tlv_length = __LE_TO_CPU_16(((uint16_t *)&bufferp[offset])[1]);
490 if ((tlv_length > EFX_LICENSE_V1V2_PAYLOAD_LENGTH_MAX) ||
491 (tlv_type == 0 && tlv_length == 0)) {
495 *lengthp = tlv_length + EFX_LICENSE_V1V2_HEADER_LENGTH;
501 EFSYS_PROBE1(fail1, boolean_t, B_FALSE);
506 __checkReturn __success(return != B_FALSE) boolean_t
507 efx_lic_v1v2_validate_key(
509 __in_bcount(length) caddr_t keyp,
510 __in uint32_t length)
515 _NOTE(ARGUNUSED(enp))
517 if (length < EFX_LICENSE_V1V2_HEADER_LENGTH) {
521 tlv_type = __LE_TO_CPU_16(((uint16_t *)keyp)[0]);
522 tlv_length = __LE_TO_CPU_16(((uint16_t *)keyp)[1]);
524 if (tlv_length > EFX_LICENSE_V1V2_PAYLOAD_LENGTH_MAX) {
530 if ((tlv_length + EFX_LICENSE_V1V2_HEADER_LENGTH) != length) {
543 EFSYS_PROBE1(fail1, boolean_t, B_FALSE);
549 __checkReturn efx_rc_t
550 efx_lic_v1v2_read_key(
552 __in_bcount(buffer_size)
554 __in size_t buffer_size,
555 __in uint32_t offset,
556 __in uint32_t length,
557 __out_bcount_part(key_max_size, *lengthp)
559 __in size_t key_max_size,
560 __out uint32_t *lengthp)
564 _NOTE(ARGUNUSED(enp, buffer_size))
565 EFSYS_ASSERT(length <= (EFX_LICENSE_V1V2_PAYLOAD_LENGTH_MAX +
566 EFX_LICENSE_V1V2_HEADER_LENGTH));
568 if (key_max_size < length) {
572 memcpy(keyp, &bufferp[offset], length);
579 EFSYS_PROBE1(fail1, efx_rc_t, rc);
584 __checkReturn efx_rc_t
585 efx_lic_v1v2_write_key(
587 __in_bcount(buffer_size)
589 __in size_t buffer_size,
590 __in uint32_t offset,
591 __in_bcount(length) caddr_t keyp,
592 __in uint32_t length,
593 __out uint32_t *lengthp)
597 _NOTE(ARGUNUSED(enp))
598 EFSYS_ASSERT(length <= (EFX_LICENSE_V1V2_PAYLOAD_LENGTH_MAX +
599 EFX_LICENSE_V1V2_HEADER_LENGTH));
601 /* Ensure space for terminator remains */
602 if ((offset + length) >
603 (buffer_size - EFX_LICENSE_V1V2_HEADER_LENGTH)) {
608 memcpy(bufferp + offset, keyp, length);
615 EFSYS_PROBE1(fail1, efx_rc_t, rc);
620 __checkReturn efx_rc_t
621 efx_lic_v1v2_delete_key(
623 __in_bcount(buffer_size)
625 __in size_t buffer_size,
626 __in uint32_t offset,
627 __in uint32_t length,
629 __out uint32_t *deltap)
631 uint32_t move_start = offset + length;
632 uint32_t move_length = end - move_start;
634 _NOTE(ARGUNUSED(enp, buffer_size))
635 EFSYS_ASSERT(end <= buffer_size);
637 /* Shift everything after the key down */
638 memmove(bufferp + offset, bufferp + move_start, move_length);
645 __checkReturn efx_rc_t
646 efx_lic_v1v2_create_partition(
648 __in_bcount(buffer_size)
650 __in size_t buffer_size)
652 _NOTE(ARGUNUSED(enp, buffer_size))
653 EFSYS_ASSERT(EFX_LICENSE_V1V2_HEADER_LENGTH <= buffer_size);
655 /* Write terminator */
656 memset(bufferp, '\0', EFX_LICENSE_V1V2_HEADER_LENGTH);
661 __checkReturn efx_rc_t
662 efx_lic_v1v2_finish_partition(
664 __in_bcount(buffer_size)
666 __in size_t buffer_size)
668 _NOTE(ARGUNUSED(enp, bufferp, buffer_size))
673 #endif /* EFSYS_OPT_HUNTINGTON | EFSYS_OPT_SIENA */
676 /* V2 Licensing - used by Huntington family only. See SF-113611-TC */
678 #if EFSYS_OPT_HUNTINGTON
680 static __checkReturn efx_rc_t
681 efx_mcdi_licensed_app_state(
683 __in uint64_t app_id,
684 __out boolean_t *licensedp)
687 uint8_t payload[MAX(MC_CMD_GET_LICENSED_APP_STATE_IN_LEN,
688 MC_CMD_GET_LICENSED_APP_STATE_OUT_LEN)];
692 EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON);
694 /* V2 licensing supports 32bit app id only */
695 if ((app_id >> 32) != 0) {
700 (void) memset(payload, 0, sizeof (payload));
701 req.emr_cmd = MC_CMD_GET_LICENSED_APP_STATE;
702 req.emr_in_buf = payload;
703 req.emr_in_length = MC_CMD_GET_LICENSED_APP_STATE_IN_LEN;
704 req.emr_out_buf = payload;
705 req.emr_out_length = MC_CMD_GET_LICENSED_APP_STATE_OUT_LEN;
707 MCDI_IN_SET_DWORD(req, GET_LICENSED_APP_STATE_IN_APP_ID,
708 app_id & 0xffffffff);
710 efx_mcdi_execute(enp, &req);
712 if (req.emr_rc != 0) {
717 if (req.emr_out_length_used < MC_CMD_GET_LICENSED_APP_STATE_OUT_LEN) {
722 app_state = (MCDI_OUT_DWORD(req, GET_LICENSED_APP_STATE_OUT_STATE));
723 if (app_state != MC_CMD_GET_LICENSED_APP_STATE_OUT_NOT_LICENSED) {
726 *licensedp = B_FALSE;
736 EFSYS_PROBE1(fail1, efx_rc_t, rc);
741 static __checkReturn efx_rc_t
742 efx_mcdi_licensing_update_licenses(
746 uint8_t payload[MC_CMD_LICENSING_IN_LEN];
749 EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON);
751 (void) memset(payload, 0, sizeof (payload));
752 req.emr_cmd = MC_CMD_LICENSING;
753 req.emr_in_buf = payload;
754 req.emr_in_length = MC_CMD_LICENSING_IN_LEN;
755 req.emr_out_buf = payload;
756 req.emr_out_length = 0;
758 MCDI_IN_SET_DWORD(req, LICENSING_IN_OP,
759 MC_CMD_LICENSING_IN_OP_UPDATE_LICENSE);
761 efx_mcdi_execute(enp, &req);
763 if (req.emr_rc != 0) {
768 if (req.emr_out_length_used != 0) {
778 EFSYS_PROBE1(fail1, efx_rc_t, rc);
783 static __checkReturn efx_rc_t
784 efx_mcdi_licensing_get_key_stats(
786 __out efx_key_stats_t *eksp)
789 uint8_t payload[MAX(MC_CMD_LICENSING_IN_LEN,
790 MC_CMD_LICENSING_OUT_LEN)];
793 EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON);
795 (void) memset(payload, 0, sizeof (payload));
796 req.emr_cmd = MC_CMD_LICENSING;
797 req.emr_in_buf = payload;
798 req.emr_in_length = MC_CMD_LICENSING_IN_LEN;
799 req.emr_out_buf = payload;
800 req.emr_out_length = MC_CMD_LICENSING_OUT_LEN;
802 MCDI_IN_SET_DWORD(req, LICENSING_IN_OP,
803 MC_CMD_LICENSING_IN_OP_GET_KEY_STATS);
805 efx_mcdi_execute(enp, &req);
807 if (req.emr_rc != 0) {
812 if (req.emr_out_length_used < MC_CMD_LICENSING_OUT_LEN) {
818 MCDI_OUT_DWORD(req, LICENSING_OUT_VALID_APP_KEYS);
820 MCDI_OUT_DWORD(req, LICENSING_OUT_INVALID_APP_KEYS);
821 eksp->eks_blacklisted =
822 MCDI_OUT_DWORD(req, LICENSING_OUT_BLACKLISTED_APP_KEYS);
823 eksp->eks_unverifiable =
824 MCDI_OUT_DWORD(req, LICENSING_OUT_UNVERIFIABLE_APP_KEYS);
825 eksp->eks_wrong_node =
826 MCDI_OUT_DWORD(req, LICENSING_OUT_WRONG_NODE_APP_KEYS);
827 eksp->eks_licensed_apps_lo = 0;
828 eksp->eks_licensed_apps_hi = 0;
829 eksp->eks_licensed_features_lo = 0;
830 eksp->eks_licensed_features_hi = 0;
837 EFSYS_PROBE1(fail1, efx_rc_t, rc);
842 #endif /* EFSYS_OPT_HUNTINGTON */
844 /* V3 Licensing - used starting from Medford family. See SF-114884-SW */
846 #if EFSYS_OPT_MEDFORD
848 static __checkReturn efx_rc_t
849 efx_mcdi_licensing_v3_update_licenses(
853 uint8_t payload[MC_CMD_LICENSING_V3_IN_LEN];
856 EFSYS_ASSERT(enp->en_family == EFX_FAMILY_MEDFORD);
858 (void) memset(payload, 0, sizeof (payload));
859 req.emr_cmd = MC_CMD_LICENSING_V3;
860 req.emr_in_buf = payload;
861 req.emr_in_length = MC_CMD_LICENSING_V3_IN_LEN;
862 req.emr_out_buf = NULL;
863 req.emr_out_length = 0;
865 MCDI_IN_SET_DWORD(req, LICENSING_V3_IN_OP,
866 MC_CMD_LICENSING_V3_IN_OP_UPDATE_LICENSE);
868 efx_mcdi_execute(enp, &req);
870 if (req.emr_rc != 0) {
878 EFSYS_PROBE1(fail1, efx_rc_t, rc);
883 static __checkReturn efx_rc_t
884 efx_mcdi_licensing_v3_report_license(
886 __out efx_key_stats_t *eksp)
889 uint8_t payload[MAX(MC_CMD_LICENSING_V3_IN_LEN,
890 MC_CMD_LICENSING_V3_OUT_LEN)];
893 EFSYS_ASSERT(enp->en_family == EFX_FAMILY_MEDFORD);
895 (void) memset(payload, 0, sizeof (payload));
896 req.emr_cmd = MC_CMD_LICENSING_V3;
897 req.emr_in_buf = payload;
898 req.emr_in_length = MC_CMD_LICENSING_V3_IN_LEN;
899 req.emr_out_buf = payload;
900 req.emr_out_length = MC_CMD_LICENSING_V3_OUT_LEN;
902 MCDI_IN_SET_DWORD(req, LICENSING_V3_IN_OP,
903 MC_CMD_LICENSING_V3_IN_OP_REPORT_LICENSE);
905 efx_mcdi_execute_quiet(enp, &req);
907 if (req.emr_rc != 0) {
912 if (req.emr_out_length_used < MC_CMD_LICENSING_V3_OUT_LEN) {
918 MCDI_OUT_DWORD(req, LICENSING_V3_OUT_VALID_KEYS);
920 MCDI_OUT_DWORD(req, LICENSING_V3_OUT_INVALID_KEYS);
921 eksp->eks_blacklisted = 0;
922 eksp->eks_unverifiable =
923 MCDI_OUT_DWORD(req, LICENSING_V3_OUT_UNVERIFIABLE_KEYS);
924 eksp->eks_wrong_node =
925 MCDI_OUT_DWORD(req, LICENSING_V3_OUT_WRONG_NODE_KEYS);
926 eksp->eks_licensed_apps_lo =
927 MCDI_OUT_DWORD(req, LICENSING_V3_OUT_LICENSED_APPS_LO);
928 eksp->eks_licensed_apps_hi =
929 MCDI_OUT_DWORD(req, LICENSING_V3_OUT_LICENSED_APPS_HI);
930 eksp->eks_licensed_features_lo =
931 MCDI_OUT_DWORD(req, LICENSING_V3_OUT_LICENSED_FEATURES_LO);
932 eksp->eks_licensed_features_hi =
933 MCDI_OUT_DWORD(req, LICENSING_V3_OUT_LICENSED_FEATURES_HI);
940 EFSYS_PROBE1(fail1, efx_rc_t, rc);
945 static __checkReturn efx_rc_t
946 efx_mcdi_licensing_v3_app_state(
948 __in uint64_t app_id,
949 __out boolean_t *licensedp)
952 uint8_t payload[MAX(MC_CMD_GET_LICENSED_V3_APP_STATE_IN_LEN,
953 MC_CMD_GET_LICENSED_V3_APP_STATE_OUT_LEN)];
957 EFSYS_ASSERT(enp->en_family == EFX_FAMILY_MEDFORD);
959 (void) memset(payload, 0, sizeof (payload));
960 req.emr_cmd = MC_CMD_GET_LICENSED_V3_APP_STATE;
961 req.emr_in_buf = payload;
962 req.emr_in_length = MC_CMD_GET_LICENSED_V3_APP_STATE_IN_LEN;
963 req.emr_out_buf = payload;
964 req.emr_out_length = MC_CMD_GET_LICENSED_V3_APP_STATE_OUT_LEN;
966 MCDI_IN_SET_DWORD(req, GET_LICENSED_V3_APP_STATE_IN_APP_ID_LO,
967 app_id & 0xffffffff);
968 MCDI_IN_SET_DWORD(req, GET_LICENSED_V3_APP_STATE_IN_APP_ID_HI,
971 efx_mcdi_execute(enp, &req);
973 if (req.emr_rc != 0) {
978 if (req.emr_out_length_used <
979 MC_CMD_GET_LICENSED_V3_APP_STATE_OUT_LEN) {
984 app_state = (MCDI_OUT_DWORD(req, GET_LICENSED_V3_APP_STATE_OUT_STATE));
985 if (app_state != MC_CMD_GET_LICENSED_V3_APP_STATE_OUT_NOT_LICENSED) {
988 *licensedp = B_FALSE;
996 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1001 static __checkReturn efx_rc_t
1002 efx_mcdi_licensing_v3_get_id(
1003 __in efx_nic_t *enp,
1004 __in size_t buffer_size,
1005 __out uint32_t *typep,
1006 __out size_t *lengthp,
1007 __out_bcount_part_opt(buffer_size, *lengthp)
1011 uint8_t payload[MAX(MC_CMD_LICENSING_GET_ID_V3_IN_LEN,
1012 MC_CMD_LICENSING_GET_ID_V3_OUT_LENMIN)];
1015 req.emr_cmd = MC_CMD_LICENSING_GET_ID_V3;
1017 if (bufferp == NULL) {
1018 /* Request id type and length only */
1019 req.emr_in_buf = bufferp;
1020 req.emr_in_length = MC_CMD_LICENSING_GET_ID_V3_IN_LEN;
1021 req.emr_out_buf = bufferp;
1022 req.emr_out_length = MC_CMD_LICENSING_GET_ID_V3_OUT_LENMIN;
1023 (void) memset(payload, 0, sizeof (payload));
1025 /* Request full buffer */
1026 req.emr_in_buf = bufferp;
1027 req.emr_in_length = MC_CMD_LICENSING_GET_ID_V3_IN_LEN;
1028 req.emr_out_buf = bufferp;
1029 req.emr_out_length =
1030 MIN(buffer_size, MC_CMD_LICENSING_GET_ID_V3_OUT_LENMAX);
1031 (void) memset(bufferp, 0, req.emr_out_length);
1034 efx_mcdi_execute_quiet(enp, &req);
1036 if (req.emr_rc != 0) {
1041 if (req.emr_out_length_used < MC_CMD_LICENSING_GET_ID_V3_OUT_LENMIN) {
1046 *typep = MCDI_OUT_DWORD(req, LICENSING_GET_ID_V3_OUT_LICENSE_TYPE);
1048 MCDI_OUT_DWORD(req, LICENSING_GET_ID_V3_OUT_LICENSE_ID_LENGTH);
1050 if (bufferp == NULL) {
1052 * Modify length requirements to indicate to caller the extra
1053 * buffering needed to read the complete output.
1055 *lengthp += MC_CMD_LICENSING_GET_ID_V3_OUT_LENMIN;
1057 /* Shift ID down to start of buffer */
1059 bufferp + MC_CMD_LICENSING_GET_ID_V3_OUT_LICENSE_ID_OFST,
1061 memset(bufferp + (*lengthp), 0,
1062 MC_CMD_LICENSING_GET_ID_V3_OUT_LICENSE_ID_OFST);
1070 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1075 /* V3 format uses Huntington TLV format partition. See SF-108797-SW */
1076 #define EFX_LICENSE_V3_KEY_LENGTH_MIN (64)
1077 #define EFX_LICENSE_V3_KEY_LENGTH_MAX (160)
1079 __checkReturn efx_rc_t
1080 efx_lic_v3_find_start(
1081 __in efx_nic_t *enp,
1082 __in_bcount(buffer_size)
1084 __in size_t buffer_size,
1085 __out uint32_t *startp)
1087 _NOTE(ARGUNUSED(enp))
1089 return (ef10_nvram_buffer_find_item_start(bufferp, buffer_size,
1093 __checkReturn efx_rc_t
1094 efx_lic_v3_find_end(
1095 __in efx_nic_t *enp,
1096 __in_bcount(buffer_size)
1098 __in size_t buffer_size,
1099 __in uint32_t offset,
1100 __out uint32_t *endp)
1102 _NOTE(ARGUNUSED(enp))
1104 return (ef10_nvram_buffer_find_end(bufferp, buffer_size, offset, endp));
1107 __checkReturn __success(return != B_FALSE) boolean_t
1108 efx_lic_v3_find_key(
1109 __in efx_nic_t *enp,
1110 __in_bcount(buffer_size)
1112 __in size_t buffer_size,
1113 __in uint32_t offset,
1114 __out uint32_t *startp,
1115 __out uint32_t *lengthp)
1117 _NOTE(ARGUNUSED(enp))
1119 return ef10_nvram_buffer_find_item(bufferp, buffer_size,
1120 offset, startp, lengthp);
1123 __checkReturn __success(return != B_FALSE) boolean_t
1124 efx_lic_v3_validate_key(
1125 __in efx_nic_t *enp,
1126 __in_bcount(length) caddr_t keyp,
1127 __in uint32_t length)
1129 /* Check key is a valid V3 key */
1133 _NOTE(ARGUNUSED(enp))
1135 if (length < EFX_LICENSE_V3_KEY_LENGTH_MIN) {
1139 if (length > EFX_LICENSE_V3_KEY_LENGTH_MAX) {
1143 key_type = ((uint8_t *)keyp)[0];
1144 key_length = ((uint8_t *)keyp)[1];
1149 if (key_length > length) {
1161 EFSYS_PROBE1(fail1, boolean_t, B_FALSE);
1166 __checkReturn efx_rc_t
1167 efx_lic_v3_read_key(
1168 __in efx_nic_t *enp,
1169 __in_bcount(buffer_size)
1171 __in size_t buffer_size,
1172 __in uint32_t offset,
1173 __in uint32_t length,
1174 __out_bcount_part(key_max_size, *lengthp)
1176 __in size_t key_max_size,
1177 __out uint32_t *lengthp)
1179 _NOTE(ARGUNUSED(enp))
1181 return ef10_nvram_buffer_get_item(bufferp, buffer_size,
1182 offset, length, keyp, key_max_size, lengthp);
1185 __checkReturn efx_rc_t
1186 efx_lic_v3_write_key(
1187 __in efx_nic_t *enp,
1188 __in_bcount(buffer_size)
1190 __in size_t buffer_size,
1191 __in uint32_t offset,
1192 __in_bcount(length) caddr_t keyp,
1193 __in uint32_t length,
1194 __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)
1216 _NOTE(ARGUNUSED(enp))
1218 if ((rc = ef10_nvram_buffer_delete_item(bufferp,
1219 buffer_size, offset, length, end)) != 0) {
1228 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1233 __checkReturn efx_rc_t
1234 efx_lic_v3_create_partition(
1235 __in efx_nic_t *enp,
1236 __in_bcount(buffer_size)
1238 __in size_t buffer_size)
1242 /* Construct empty partition */
1243 if ((rc = ef10_nvram_buffer_create(enp,
1244 NVRAM_PARTITION_TYPE_LICENSE,
1245 bufferp, buffer_size)) != 0) {
1253 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1258 __checkReturn efx_rc_t
1259 efx_lic_v3_finish_partition(
1260 __in efx_nic_t *enp,
1261 __in_bcount(buffer_size)
1263 __in size_t buffer_size)
1267 if ((rc = ef10_nvram_buffer_finish(bufferp,
1268 buffer_size)) != 0) {
1272 /* Validate completed partition */
1273 if ((rc = ef10_nvram_buffer_validate(enp, NVRAM_PARTITION_TYPE_LICENSE,
1274 bufferp, buffer_size)) != 0) {
1283 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1289 #endif /* EFSYS_OPT_MEDFORD */
1291 __checkReturn efx_rc_t
1293 __in efx_nic_t *enp)
1295 const efx_lic_ops_t *elop;
1296 efx_key_stats_t eks;
1299 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1300 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
1301 EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_LIC));
1303 switch (enp->en_family) {
1306 case EFX_FAMILY_SIENA:
1307 elop = &__efx_lic_v1_ops;
1309 #endif /* EFSYS_OPT_SIENA */
1311 #if EFSYS_OPT_HUNTINGTON
1312 case EFX_FAMILY_HUNTINGTON:
1313 elop = &__efx_lic_v2_ops;
1315 #endif /* EFSYS_OPT_HUNTINGTON */
1317 #if EFSYS_OPT_MEDFORD
1318 case EFX_FAMILY_MEDFORD:
1319 elop = &__efx_lic_v3_ops;
1321 #endif /* EFSYS_OPT_MEDFORD */
1329 enp->en_elop = elop;
1330 enp->en_mod_flags |= EFX_MOD_LIC;
1332 /* Probe for support */
1333 if (efx_lic_get_key_stats(enp, &eks) == 0) {
1334 enp->en_licensing_supported = B_TRUE;
1336 enp->en_licensing_supported = B_FALSE;
1342 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1347 extern __checkReturn boolean_t
1348 efx_lic_check_support(
1349 __in efx_nic_t *enp)
1351 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1352 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
1353 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1355 return (enp->en_licensing_supported);
1360 __in efx_nic_t *enp)
1362 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1363 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
1364 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1366 enp->en_elop = NULL;
1367 enp->en_mod_flags &= ~EFX_MOD_LIC;
1371 __checkReturn efx_rc_t
1372 efx_lic_update_licenses(
1373 __in efx_nic_t *enp)
1375 const efx_lic_ops_t *elop = enp->en_elop;
1378 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1379 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1381 if ((rc = elop->elo_update_licenses(enp)) != 0)
1387 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1392 __checkReturn efx_rc_t
1393 efx_lic_get_key_stats(
1394 __in efx_nic_t *enp,
1395 __out efx_key_stats_t *eksp)
1397 const efx_lic_ops_t *elop = enp->en_elop;
1400 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1401 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1403 if ((rc = elop->elo_get_key_stats(enp, eksp)) != 0)
1409 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1414 __checkReturn efx_rc_t
1416 __in efx_nic_t *enp,
1417 __in uint64_t app_id,
1418 __out boolean_t *licensedp)
1420 const efx_lic_ops_t *elop = enp->en_elop;
1423 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1424 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1426 if (elop->elo_app_state == NULL)
1429 if ((rc = elop->elo_app_state(enp, app_id, licensedp)) != 0)
1435 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1440 __checkReturn efx_rc_t
1442 __in efx_nic_t *enp,
1443 __in size_t buffer_size,
1444 __out uint32_t *typep,
1445 __out size_t *lengthp,
1446 __out_opt uint8_t *bufferp)
1448 const efx_lic_ops_t *elop = enp->en_elop;
1451 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1452 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1454 if (elop->elo_get_id == NULL)
1457 if ((rc = elop->elo_get_id(enp, buffer_size, typep,
1458 lengthp, bufferp)) != 0)
1464 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1470 * Buffer management API - abstracts varying TLV format used for License
1474 __checkReturn efx_rc_t
1476 __in efx_nic_t *enp,
1477 __in_bcount(buffer_size)
1479 __in size_t buffer_size,
1480 __out uint32_t *startp)
1482 const efx_lic_ops_t *elop = enp->en_elop;
1485 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1486 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1488 if ((rc = elop->elo_find_start(enp, bufferp, buffer_size, startp)) != 0)
1494 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1499 __checkReturn efx_rc_t
1501 __in efx_nic_t *enp,
1502 __in_bcount(buffer_size)
1504 __in size_t buffer_size,
1505 __in uint32_t offset,
1506 __out uint32_t *endp)
1508 const efx_lic_ops_t *elop = enp->en_elop;
1511 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1512 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1514 rc = elop->elo_find_end(enp, bufferp, buffer_size, offset, endp);
1521 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1526 __checkReturn __success(return != B_FALSE) boolean_t
1528 __in efx_nic_t *enp,
1529 __in_bcount(buffer_size)
1531 __in size_t buffer_size,
1532 __in uint32_t offset,
1533 __out uint32_t *startp,
1534 __out uint32_t *lengthp)
1536 const efx_lic_ops_t *elop = enp->en_elop;
1538 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1539 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1541 EFSYS_ASSERT(bufferp);
1542 EFSYS_ASSERT(startp);
1543 EFSYS_ASSERT(lengthp);
1545 return (elop->elo_find_key(enp, bufferp, buffer_size, offset,
1551 * Validate that the buffer contains a single key in a recognised format.
1552 * An empty or terminator buffer is not accepted as a valid key.
1554 __checkReturn __success(return != B_FALSE) boolean_t
1555 efx_lic_validate_key(
1556 __in efx_nic_t *enp,
1557 __in_bcount(length) caddr_t keyp,
1558 __in uint32_t length)
1560 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 if ((rc = elop->elo_validate_key(enp, keyp, length)) == B_FALSE)
1572 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1577 __checkReturn efx_rc_t
1579 __in efx_nic_t *enp,
1580 __in_bcount(buffer_size)
1582 __in size_t buffer_size,
1583 __in uint32_t offset,
1584 __in uint32_t length,
1585 __out_bcount_part(key_max_size, *lengthp)
1587 __in size_t key_max_size,
1588 __out uint32_t *lengthp)
1590 const efx_lic_ops_t *elop = enp->en_elop;
1593 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1594 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1596 if ((rc = elop->elo_read_key(enp, bufferp, buffer_size, offset,
1597 length, keyp, key_max_size, lengthp)) != 0)
1603 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1608 __checkReturn efx_rc_t
1610 __in efx_nic_t *enp,
1611 __in_bcount(buffer_size)
1613 __in size_t buffer_size,
1614 __in uint32_t offset,
1615 __in_bcount(length) caddr_t keyp,
1616 __in uint32_t length,
1617 __out uint32_t *lengthp)
1619 const efx_lic_ops_t *elop = enp->en_elop;
1622 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1623 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1625 if ((rc = elop->elo_write_key(enp, bufferp, buffer_size, offset,
1626 keyp, length, lengthp)) != 0)
1632 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1637 __checkReturn efx_rc_t
1639 __in efx_nic_t *enp,
1640 __in_bcount(buffer_size)
1642 __in size_t buffer_size,
1643 __in uint32_t offset,
1644 __in uint32_t length,
1646 __out uint32_t *deltap)
1648 const efx_lic_ops_t *elop = enp->en_elop;
1651 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1652 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1654 if ((rc = elop->elo_delete_key(enp, bufferp, buffer_size, offset,
1655 length, end, deltap)) != 0)
1661 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1666 __checkReturn efx_rc_t
1667 efx_lic_create_partition(
1668 __in efx_nic_t *enp,
1669 __in_bcount(buffer_size)
1671 __in size_t buffer_size)
1673 const efx_lic_ops_t *elop = enp->en_elop;
1676 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1677 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1679 if ((rc = elop->elo_create_partition(enp, bufferp, buffer_size)) != 0)
1685 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1691 __checkReturn efx_rc_t
1692 efx_lic_finish_partition(
1693 __in efx_nic_t *enp,
1694 __in_bcount(buffer_size)
1696 __in size_t buffer_size)
1698 const efx_lic_ops_t *elop = enp->en_elop;
1701 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1702 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1704 if ((rc = elop->elo_finish_partition(enp, bufferp, buffer_size)) != 0)
1710 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1715 #endif /* EFSYS_OPT_LICENSING */