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 #include "efx_regs_mcdi_aoe.h"
44 #if EFSYS_OPT_SIENA | EFSYS_OPT_HUNTINGTON
46 __checkReturn efx_rc_t
47 efx_lic_v1v2_find_start(
49 __in_bcount(buffer_size)
51 __in size_t buffer_size,
52 __out uint32_t *startp);
54 __checkReturn efx_rc_t
55 efx_lic_v1v2_find_end(
57 __in_bcount(buffer_size)
59 __in size_t buffer_size,
61 __out uint32_t *endp);
63 __checkReturn __success(return != B_FALSE) boolean_t
64 efx_lic_v1v2_find_key(
66 __in_bcount(buffer_size)
68 __in size_t buffer_size,
70 __out uint32_t *startp,
71 __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,
77 __in uint32_t length);
79 __checkReturn efx_rc_t
80 efx_lic_v1v2_read_key(
82 __in_bcount(buffer_size)
84 __in size_t buffer_size,
87 __out_bcount_part(key_max_size, *lengthp)
89 __in size_t key_max_size,
90 __out uint32_t *lengthp);
92 __checkReturn efx_rc_t
93 efx_lic_v1v2_write_key(
95 __in_bcount(buffer_size)
97 __in size_t buffer_size,
99 __in_bcount(length) caddr_t keyp,
100 __in uint32_t length,
101 __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);
114 __checkReturn efx_rc_t
115 efx_lic_v1v2_create_partition(
117 __in_bcount(buffer_size)
119 __in size_t buffer_size);
121 __checkReturn efx_rc_t
122 efx_lic_v1v2_finish_partition(
124 __in_bcount(buffer_size)
126 __in size_t buffer_size);
128 #endif /* EFSYS_OPT_HUNTINGTON | EFSYS_OPT_SIENA */
133 static __checkReturn efx_rc_t
134 efx_mcdi_fc_license_update_license(
135 __in efx_nic_t *enp);
137 static __checkReturn efx_rc_t
138 efx_mcdi_fc_license_get_key_stats(
140 __out efx_key_stats_t *eksp);
142 static const efx_lic_ops_t __efx_lic_v1_ops = {
143 efx_mcdi_fc_license_update_license, /* elo_update_licenses */
144 efx_mcdi_fc_license_get_key_stats, /* elo_get_key_stats */
145 NULL, /* elo_app_state */
146 NULL, /* elo_get_id */
147 efx_lic_v1v2_find_start, /* elo_find_start */
148 efx_lic_v1v2_find_end, /* elo_find_end */
149 efx_lic_v1v2_find_key, /* elo_find_key */
150 efx_lic_v1v2_validate_key, /* elo_validate_key */
151 efx_lic_v1v2_read_key, /* elo_read_key */
152 efx_lic_v1v2_write_key, /* elo_write_key */
153 efx_lic_v1v2_delete_key, /* elo_delete_key */
154 efx_lic_v1v2_create_partition, /* elo_create_partition */
155 efx_lic_v1v2_finish_partition, /* elo_finish_partition */
158 #endif /* EFSYS_OPT_SIENA */
160 #if EFSYS_OPT_HUNTINGTON
162 static __checkReturn efx_rc_t
163 efx_mcdi_licensing_update_licenses(
164 __in efx_nic_t *enp);
166 static __checkReturn efx_rc_t
167 efx_mcdi_licensing_get_key_stats(
169 __out efx_key_stats_t *eksp);
171 static __checkReturn efx_rc_t
172 efx_mcdi_licensed_app_state(
174 __in uint64_t app_id,
175 __out boolean_t *licensedp);
177 static const efx_lic_ops_t __efx_lic_v2_ops = {
178 efx_mcdi_licensing_update_licenses, /* elo_update_licenses */
179 efx_mcdi_licensing_get_key_stats, /* elo_get_key_stats */
180 efx_mcdi_licensed_app_state, /* elo_app_state */
181 NULL, /* elo_get_id */
182 efx_lic_v1v2_find_start, /* elo_find_start */
183 efx_lic_v1v2_find_end, /* elo_find_end */
184 efx_lic_v1v2_find_key, /* elo_find_key */
185 efx_lic_v1v2_validate_key, /* elo_validate_key */
186 efx_lic_v1v2_read_key, /* elo_read_key */
187 efx_lic_v1v2_write_key, /* elo_write_key */
188 efx_lic_v1v2_delete_key, /* elo_delete_key */
189 efx_lic_v1v2_create_partition, /* elo_create_partition */
190 efx_lic_v1v2_finish_partition, /* elo_finish_partition */
193 #endif /* EFSYS_OPT_HUNTINGTON */
195 #if EFSYS_OPT_MEDFORD || EFSYS_OPT_MEDFORD2
197 static __checkReturn efx_rc_t
198 efx_mcdi_licensing_v3_update_licenses(
199 __in efx_nic_t *enp);
201 static __checkReturn efx_rc_t
202 efx_mcdi_licensing_v3_report_license(
204 __out efx_key_stats_t *eksp);
206 static __checkReturn efx_rc_t
207 efx_mcdi_licensing_v3_app_state(
209 __in uint64_t app_id,
210 __out boolean_t *licensedp);
212 static __checkReturn efx_rc_t
213 efx_mcdi_licensing_v3_get_id(
215 __in size_t buffer_size,
216 __out uint32_t *typep,
217 __out size_t *lengthp,
218 __out_bcount_part_opt(buffer_size, *lengthp)
221 __checkReturn efx_rc_t
222 efx_lic_v3_find_start(
224 __in_bcount(buffer_size)
226 __in size_t buffer_size,
227 __out uint32_t *startp);
229 __checkReturn efx_rc_t
232 __in_bcount(buffer_size)
234 __in size_t buffer_size,
235 __in uint32_t offset,
236 __out uint32_t *endp);
238 __checkReturn __success(return != B_FALSE) boolean_t
241 __in_bcount(buffer_size)
243 __in size_t buffer_size,
244 __in uint32_t offset,
245 __out uint32_t *startp,
246 __out uint32_t *lengthp);
248 __checkReturn __success(return != B_FALSE) boolean_t
249 efx_lic_v3_validate_key(
251 __in_bcount(length) caddr_t keyp,
252 __in uint32_t length);
254 __checkReturn efx_rc_t
257 __in_bcount(buffer_size)
259 __in size_t buffer_size,
260 __in uint32_t offset,
261 __in uint32_t length,
262 __out_bcount_part(key_max_size, *lengthp)
264 __in size_t key_max_size,
265 __out uint32_t *lengthp);
267 __checkReturn efx_rc_t
268 efx_lic_v3_write_key(
270 __in_bcount(buffer_size)
272 __in size_t buffer_size,
273 __in uint32_t offset,
274 __in_bcount(length) caddr_t keyp,
275 __in uint32_t length,
276 __out uint32_t *lengthp);
278 __checkReturn efx_rc_t
279 efx_lic_v3_delete_key(
281 __in_bcount(buffer_size)
283 __in size_t buffer_size,
284 __in uint32_t offset,
285 __in uint32_t length,
287 __out uint32_t *deltap);
289 __checkReturn efx_rc_t
290 efx_lic_v3_create_partition(
292 __in_bcount(buffer_size)
294 __in size_t buffer_size);
296 __checkReturn efx_rc_t
297 efx_lic_v3_finish_partition(
299 __in_bcount(buffer_size)
301 __in size_t buffer_size);
303 static const efx_lic_ops_t __efx_lic_v3_ops = {
304 efx_mcdi_licensing_v3_update_licenses, /* elo_update_licenses */
305 efx_mcdi_licensing_v3_report_license, /* elo_get_key_stats */
306 efx_mcdi_licensing_v3_app_state, /* elo_app_state */
307 efx_mcdi_licensing_v3_get_id, /* elo_get_id */
308 efx_lic_v3_find_start, /* elo_find_start */
309 efx_lic_v3_find_end, /* elo_find_end */
310 efx_lic_v3_find_key, /* elo_find_key */
311 efx_lic_v3_validate_key, /* elo_validate_key */
312 efx_lic_v3_read_key, /* elo_read_key */
313 efx_lic_v3_write_key, /* elo_write_key */
314 efx_lic_v3_delete_key, /* elo_delete_key */
315 efx_lic_v3_create_partition, /* elo_create_partition */
316 efx_lic_v3_finish_partition, /* elo_finish_partition */
319 #endif /* EFSYS_OPT_MEDFORD || EFSYS_OPT_MEDFORD2 */
322 /* V1 Licensing - used in Siena Modena only */
326 static __checkReturn efx_rc_t
327 efx_mcdi_fc_license_update_license(
331 EFX_MCDI_DECLARE_BUF(payload, MC_CMD_FC_IN_LICENSE_LEN, 0);
334 EFSYS_ASSERT(enp->en_family == EFX_FAMILY_SIENA);
336 req.emr_cmd = MC_CMD_FC;
337 req.emr_in_buf = payload;
338 req.emr_in_length = MC_CMD_FC_IN_LICENSE_LEN;
339 req.emr_out_buf = payload;
340 req.emr_out_length = 0;
342 MCDI_IN_SET_DWORD(req, FC_IN_CMD,
343 MC_CMD_FC_OP_LICENSE);
345 MCDI_IN_SET_DWORD(req, FC_IN_LICENSE_OP,
346 MC_CMD_FC_IN_LICENSE_UPDATE_LICENSE);
348 efx_mcdi_execute(enp, &req);
350 if (req.emr_rc != 0) {
355 if (req.emr_out_length_used != 0) {
365 EFSYS_PROBE1(fail1, efx_rc_t, rc);
370 static __checkReturn efx_rc_t
371 efx_mcdi_fc_license_get_key_stats(
373 __out efx_key_stats_t *eksp)
376 EFX_MCDI_DECLARE_BUF(payload, MC_CMD_FC_IN_LICENSE_LEN,
377 MC_CMD_FC_OUT_LICENSE_LEN);
380 EFSYS_ASSERT(enp->en_family == EFX_FAMILY_SIENA);
382 req.emr_cmd = MC_CMD_FC;
383 req.emr_in_buf = payload;
384 req.emr_in_length = MC_CMD_FC_IN_LICENSE_LEN;
385 req.emr_out_buf = payload;
386 req.emr_out_length = MC_CMD_FC_OUT_LICENSE_LEN;
388 MCDI_IN_SET_DWORD(req, FC_IN_CMD,
389 MC_CMD_FC_OP_LICENSE);
391 MCDI_IN_SET_DWORD(req, FC_IN_LICENSE_OP,
392 MC_CMD_FC_IN_LICENSE_GET_KEY_STATS);
394 efx_mcdi_execute_quiet(enp, &req);
396 if (req.emr_rc != 0) {
401 if (req.emr_out_length_used < MC_CMD_FC_OUT_LICENSE_LEN) {
407 MCDI_OUT_DWORD(req, FC_OUT_LICENSE_VALID_KEYS);
409 MCDI_OUT_DWORD(req, FC_OUT_LICENSE_INVALID_KEYS);
410 eksp->eks_blacklisted =
411 MCDI_OUT_DWORD(req, FC_OUT_LICENSE_BLACKLISTED_KEYS);
412 eksp->eks_unverifiable = 0;
413 eksp->eks_wrong_node = 0;
414 eksp->eks_licensed_apps_lo = 0;
415 eksp->eks_licensed_apps_hi = 0;
416 eksp->eks_licensed_features_lo = 0;
417 eksp->eks_licensed_features_hi = 0;
424 EFSYS_PROBE1(fail1, efx_rc_t, rc);
429 #endif /* EFSYS_OPT_SIENA */
431 /* V1 and V2 Partition format - based on a 16-bit TLV format */
433 #if EFSYS_OPT_SIENA | EFSYS_OPT_HUNTINGTON
436 * V1/V2 format - defined in SF-108542-TC section 4.2:
437 * Type (T): 16bit - revision/HMAC algorithm
438 * Length (L): 16bit - value length in bytes
439 * Value (V): L bytes - payload
441 #define EFX_LICENSE_V1V2_PAYLOAD_LENGTH_MAX (256)
442 #define EFX_LICENSE_V1V2_HEADER_LENGTH (2 * sizeof (uint16_t))
444 __checkReturn efx_rc_t
445 efx_lic_v1v2_find_start(
447 __in_bcount(buffer_size)
449 __in size_t buffer_size,
450 __out uint32_t *startp)
452 _NOTE(ARGUNUSED(enp, bufferp, buffer_size))
458 __checkReturn efx_rc_t
459 efx_lic_v1v2_find_end(
461 __in_bcount(buffer_size)
463 __in size_t buffer_size,
464 __in uint32_t offset,
465 __out uint32_t *endp)
467 _NOTE(ARGUNUSED(enp, bufferp, buffer_size))
469 *endp = offset + EFX_LICENSE_V1V2_HEADER_LENGTH;
473 __checkReturn __success(return != B_FALSE) boolean_t
474 efx_lic_v1v2_find_key(
476 __in_bcount(buffer_size)
478 __in size_t buffer_size,
479 __in uint32_t offset,
480 __out uint32_t *startp,
481 __out uint32_t *lengthp)
487 _NOTE(ARGUNUSED(enp))
489 if ((size_t)buffer_size - offset < EFX_LICENSE_V1V2_HEADER_LENGTH)
492 tlv_type = __LE_TO_CPU_16(((uint16_t *)&bufferp[offset])[0]);
493 tlv_length = __LE_TO_CPU_16(((uint16_t *)&bufferp[offset])[1]);
494 if ((tlv_length > EFX_LICENSE_V1V2_PAYLOAD_LENGTH_MAX) ||
495 (tlv_type == 0 && tlv_length == 0)) {
499 *lengthp = tlv_length + EFX_LICENSE_V1V2_HEADER_LENGTH;
505 EFSYS_PROBE1(fail1, boolean_t, B_FALSE);
510 __checkReturn __success(return != B_FALSE) boolean_t
511 efx_lic_v1v2_validate_key(
513 __in_bcount(length) caddr_t keyp,
514 __in uint32_t length)
519 _NOTE(ARGUNUSED(enp))
521 if (length < EFX_LICENSE_V1V2_HEADER_LENGTH) {
525 tlv_type = __LE_TO_CPU_16(((uint16_t *)keyp)[0]);
526 tlv_length = __LE_TO_CPU_16(((uint16_t *)keyp)[1]);
528 if (tlv_length > EFX_LICENSE_V1V2_PAYLOAD_LENGTH_MAX) {
534 if ((tlv_length + EFX_LICENSE_V1V2_HEADER_LENGTH) != length) {
547 EFSYS_PROBE1(fail1, boolean_t, B_FALSE);
553 __checkReturn efx_rc_t
554 efx_lic_v1v2_read_key(
556 __in_bcount(buffer_size)
558 __in size_t buffer_size,
559 __in uint32_t offset,
560 __in uint32_t length,
561 __out_bcount_part(key_max_size, *lengthp)
563 __in size_t key_max_size,
564 __out uint32_t *lengthp)
568 _NOTE(ARGUNUSED(enp, buffer_size))
569 EFSYS_ASSERT(length <= (EFX_LICENSE_V1V2_PAYLOAD_LENGTH_MAX +
570 EFX_LICENSE_V1V2_HEADER_LENGTH));
572 if (key_max_size < length) {
576 memcpy(keyp, &bufferp[offset], length);
583 EFSYS_PROBE1(fail1, efx_rc_t, rc);
588 __checkReturn efx_rc_t
589 efx_lic_v1v2_write_key(
591 __in_bcount(buffer_size)
593 __in size_t buffer_size,
594 __in uint32_t offset,
595 __in_bcount(length) caddr_t keyp,
596 __in uint32_t length,
597 __out uint32_t *lengthp)
601 _NOTE(ARGUNUSED(enp))
602 EFSYS_ASSERT(length <= (EFX_LICENSE_V1V2_PAYLOAD_LENGTH_MAX +
603 EFX_LICENSE_V1V2_HEADER_LENGTH));
605 /* Ensure space for terminator remains */
606 if ((offset + length) >
607 (buffer_size - EFX_LICENSE_V1V2_HEADER_LENGTH)) {
612 memcpy(bufferp + offset, keyp, length);
619 EFSYS_PROBE1(fail1, efx_rc_t, rc);
624 __checkReturn efx_rc_t
625 efx_lic_v1v2_delete_key(
627 __in_bcount(buffer_size)
629 __in size_t buffer_size,
630 __in uint32_t offset,
631 __in uint32_t length,
633 __out uint32_t *deltap)
635 uint32_t move_start = offset + length;
636 uint32_t move_length = end - move_start;
638 _NOTE(ARGUNUSED(enp, buffer_size))
639 EFSYS_ASSERT(end <= buffer_size);
641 /* Shift everything after the key down */
642 memmove(bufferp + offset, bufferp + move_start, move_length);
649 __checkReturn efx_rc_t
650 efx_lic_v1v2_create_partition(
652 __in_bcount(buffer_size)
654 __in size_t buffer_size)
656 _NOTE(ARGUNUSED(enp, buffer_size))
657 EFSYS_ASSERT(EFX_LICENSE_V1V2_HEADER_LENGTH <= buffer_size);
659 /* Write terminator */
660 memset(bufferp, '\0', EFX_LICENSE_V1V2_HEADER_LENGTH);
665 __checkReturn efx_rc_t
666 efx_lic_v1v2_finish_partition(
668 __in_bcount(buffer_size)
670 __in size_t buffer_size)
672 _NOTE(ARGUNUSED(enp, bufferp, buffer_size))
677 #endif /* EFSYS_OPT_HUNTINGTON | EFSYS_OPT_SIENA */
680 /* V2 Licensing - used by Huntington family only. See SF-113611-TC */
682 #if EFSYS_OPT_HUNTINGTON
684 static __checkReturn efx_rc_t
685 efx_mcdi_licensed_app_state(
687 __in uint64_t app_id,
688 __out boolean_t *licensedp)
691 EFX_MCDI_DECLARE_BUF(payload, MC_CMD_GET_LICENSED_APP_STATE_IN_LEN,
692 MC_CMD_GET_LICENSED_APP_STATE_OUT_LEN);
696 EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON);
698 /* V2 licensing supports 32bit app id only */
699 if ((app_id >> 32) != 0) {
704 req.emr_cmd = MC_CMD_GET_LICENSED_APP_STATE;
705 req.emr_in_buf = payload;
706 req.emr_in_length = MC_CMD_GET_LICENSED_APP_STATE_IN_LEN;
707 req.emr_out_buf = payload;
708 req.emr_out_length = MC_CMD_GET_LICENSED_APP_STATE_OUT_LEN;
710 MCDI_IN_SET_DWORD(req, GET_LICENSED_APP_STATE_IN_APP_ID,
711 app_id & 0xffffffff);
713 efx_mcdi_execute(enp, &req);
715 if (req.emr_rc != 0) {
720 if (req.emr_out_length_used < MC_CMD_GET_LICENSED_APP_STATE_OUT_LEN) {
725 app_state = (MCDI_OUT_DWORD(req, GET_LICENSED_APP_STATE_OUT_STATE));
726 if (app_state != MC_CMD_GET_LICENSED_APP_STATE_OUT_NOT_LICENSED) {
729 *licensedp = B_FALSE;
739 EFSYS_PROBE1(fail1, efx_rc_t, rc);
744 static __checkReturn efx_rc_t
745 efx_mcdi_licensing_update_licenses(
749 EFX_MCDI_DECLARE_BUF(payload, MC_CMD_LICENSING_IN_LEN, 0);
752 EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON);
754 req.emr_cmd = MC_CMD_LICENSING;
755 req.emr_in_buf = payload;
756 req.emr_in_length = MC_CMD_LICENSING_IN_LEN;
757 req.emr_out_buf = payload;
758 req.emr_out_length = 0;
760 MCDI_IN_SET_DWORD(req, LICENSING_IN_OP,
761 MC_CMD_LICENSING_IN_OP_UPDATE_LICENSE);
763 efx_mcdi_execute(enp, &req);
765 if (req.emr_rc != 0) {
770 if (req.emr_out_length_used != 0) {
780 EFSYS_PROBE1(fail1, efx_rc_t, rc);
785 static __checkReturn efx_rc_t
786 efx_mcdi_licensing_get_key_stats(
788 __out efx_key_stats_t *eksp)
791 EFX_MCDI_DECLARE_BUF(payload, MC_CMD_LICENSING_IN_LEN,
792 MC_CMD_LICENSING_OUT_LEN);
795 EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON);
797 req.emr_cmd = MC_CMD_LICENSING;
798 req.emr_in_buf = payload;
799 req.emr_in_length = MC_CMD_LICENSING_IN_LEN;
800 req.emr_out_buf = payload;
801 req.emr_out_length = MC_CMD_LICENSING_OUT_LEN;
803 MCDI_IN_SET_DWORD(req, LICENSING_IN_OP,
804 MC_CMD_LICENSING_IN_OP_GET_KEY_STATS);
806 efx_mcdi_execute(enp, &req);
808 if (req.emr_rc != 0) {
813 if (req.emr_out_length_used < MC_CMD_LICENSING_OUT_LEN) {
819 MCDI_OUT_DWORD(req, LICENSING_OUT_VALID_APP_KEYS);
821 MCDI_OUT_DWORD(req, LICENSING_OUT_INVALID_APP_KEYS);
822 eksp->eks_blacklisted =
823 MCDI_OUT_DWORD(req, LICENSING_OUT_BLACKLISTED_APP_KEYS);
824 eksp->eks_unverifiable =
825 MCDI_OUT_DWORD(req, LICENSING_OUT_UNVERIFIABLE_APP_KEYS);
826 eksp->eks_wrong_node =
827 MCDI_OUT_DWORD(req, LICENSING_OUT_WRONG_NODE_APP_KEYS);
828 eksp->eks_licensed_apps_lo = 0;
829 eksp->eks_licensed_apps_hi = 0;
830 eksp->eks_licensed_features_lo = 0;
831 eksp->eks_licensed_features_hi = 0;
838 EFSYS_PROBE1(fail1, efx_rc_t, rc);
843 #endif /* EFSYS_OPT_HUNTINGTON */
845 /* V3 Licensing - used starting from Medford family. See SF-114884-SW */
847 #if EFSYS_OPT_MEDFORD || EFSYS_OPT_MEDFORD2
849 static __checkReturn efx_rc_t
850 efx_mcdi_licensing_v3_update_licenses(
854 EFX_MCDI_DECLARE_BUF(payload, MC_CMD_LICENSING_V3_IN_LEN, 0);
857 EFSYS_ASSERT((enp->en_family == EFX_FAMILY_MEDFORD) ||
858 (enp->en_family == EFX_FAMILY_MEDFORD2));
860 req.emr_cmd = MC_CMD_LICENSING_V3;
861 req.emr_in_buf = payload;
862 req.emr_in_length = MC_CMD_LICENSING_V3_IN_LEN;
863 req.emr_out_buf = NULL;
864 req.emr_out_length = 0;
866 MCDI_IN_SET_DWORD(req, LICENSING_V3_IN_OP,
867 MC_CMD_LICENSING_V3_IN_OP_UPDATE_LICENSE);
869 efx_mcdi_execute(enp, &req);
871 if (req.emr_rc != 0) {
879 EFSYS_PROBE1(fail1, efx_rc_t, rc);
884 static __checkReturn efx_rc_t
885 efx_mcdi_licensing_v3_report_license(
887 __out efx_key_stats_t *eksp)
890 EFX_MCDI_DECLARE_BUF(payload, MC_CMD_LICENSING_V3_IN_LEN,
891 MC_CMD_LICENSING_V3_OUT_LEN);
894 EFSYS_ASSERT((enp->en_family == EFX_FAMILY_MEDFORD) ||
895 (enp->en_family == EFX_FAMILY_MEDFORD2));
897 req.emr_cmd = MC_CMD_LICENSING_V3;
898 req.emr_in_buf = payload;
899 req.emr_in_length = MC_CMD_LICENSING_V3_IN_LEN;
900 req.emr_out_buf = payload;
901 req.emr_out_length = MC_CMD_LICENSING_V3_OUT_LEN;
903 MCDI_IN_SET_DWORD(req, LICENSING_V3_IN_OP,
904 MC_CMD_LICENSING_V3_IN_OP_REPORT_LICENSE);
906 efx_mcdi_execute_quiet(enp, &req);
908 if (req.emr_rc != 0) {
913 if (req.emr_out_length_used < MC_CMD_LICENSING_V3_OUT_LEN) {
919 MCDI_OUT_DWORD(req, LICENSING_V3_OUT_VALID_KEYS);
921 MCDI_OUT_DWORD(req, LICENSING_V3_OUT_INVALID_KEYS);
922 eksp->eks_blacklisted = 0;
923 eksp->eks_unverifiable =
924 MCDI_OUT_DWORD(req, LICENSING_V3_OUT_UNVERIFIABLE_KEYS);
925 eksp->eks_wrong_node =
926 MCDI_OUT_DWORD(req, LICENSING_V3_OUT_WRONG_NODE_KEYS);
927 eksp->eks_licensed_apps_lo =
928 MCDI_OUT_DWORD(req, LICENSING_V3_OUT_LICENSED_APPS_LO);
929 eksp->eks_licensed_apps_hi =
930 MCDI_OUT_DWORD(req, LICENSING_V3_OUT_LICENSED_APPS_HI);
931 eksp->eks_licensed_features_lo =
932 MCDI_OUT_DWORD(req, LICENSING_V3_OUT_LICENSED_FEATURES_LO);
933 eksp->eks_licensed_features_hi =
934 MCDI_OUT_DWORD(req, LICENSING_V3_OUT_LICENSED_FEATURES_HI);
941 EFSYS_PROBE1(fail1, efx_rc_t, rc);
946 static __checkReturn efx_rc_t
947 efx_mcdi_licensing_v3_app_state(
949 __in uint64_t app_id,
950 __out boolean_t *licensedp)
953 EFX_MCDI_DECLARE_BUF(payload, MC_CMD_GET_LICENSED_V3_APP_STATE_IN_LEN,
954 MC_CMD_GET_LICENSED_V3_APP_STATE_OUT_LEN);
958 EFSYS_ASSERT((enp->en_family == EFX_FAMILY_MEDFORD) ||
959 (enp->en_family == EFX_FAMILY_MEDFORD2));
961 req.emr_cmd = MC_CMD_GET_LICENSED_V3_APP_STATE;
962 req.emr_in_buf = payload;
963 req.emr_in_length = MC_CMD_GET_LICENSED_V3_APP_STATE_IN_LEN;
964 req.emr_out_buf = payload;
965 req.emr_out_length = MC_CMD_GET_LICENSED_V3_APP_STATE_OUT_LEN;
967 MCDI_IN_SET_DWORD(req, GET_LICENSED_V3_APP_STATE_IN_APP_ID_LO,
968 app_id & 0xffffffff);
969 MCDI_IN_SET_DWORD(req, GET_LICENSED_V3_APP_STATE_IN_APP_ID_HI,
972 efx_mcdi_execute(enp, &req);
974 if (req.emr_rc != 0) {
979 if (req.emr_out_length_used <
980 MC_CMD_GET_LICENSED_V3_APP_STATE_OUT_LEN) {
985 app_state = (MCDI_OUT_DWORD(req, GET_LICENSED_V3_APP_STATE_OUT_STATE));
986 if (app_state != MC_CMD_GET_LICENSED_V3_APP_STATE_OUT_NOT_LICENSED) {
989 *licensedp = B_FALSE;
997 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1002 static __checkReturn efx_rc_t
1003 efx_mcdi_licensing_v3_get_id(
1004 __in efx_nic_t *enp,
1005 __in size_t buffer_size,
1006 __out uint32_t *typep,
1007 __out size_t *lengthp,
1008 __out_bcount_part_opt(buffer_size, *lengthp)
1012 EFX_MCDI_DECLARE_BUF(payload, MC_CMD_LICENSING_GET_ID_V3_IN_LEN,
1013 MC_CMD_LICENSING_GET_ID_V3_OUT_LENMAX);
1016 req.emr_cmd = MC_CMD_LICENSING_GET_ID_V3;
1017 req.emr_in_buf = payload;
1018 req.emr_in_length = MC_CMD_LICENSING_GET_ID_V3_IN_LEN;
1019 req.emr_out_buf = payload;
1020 req.emr_out_length = MC_CMD_LICENSING_GET_ID_V3_OUT_LENMAX;
1022 efx_mcdi_execute_quiet(enp, &req);
1024 if (req.emr_rc != 0) {
1029 if (req.emr_out_length_used < MC_CMD_LICENSING_GET_ID_V3_OUT_LENMIN) {
1034 *typep = MCDI_OUT_DWORD(req, LICENSING_GET_ID_V3_OUT_LICENSE_TYPE);
1036 MCDI_OUT_DWORD(req, LICENSING_GET_ID_V3_OUT_LICENSE_ID_LENGTH);
1038 if (bufferp != NULL) {
1040 payload + MC_CMD_LICENSING_GET_ID_V3_OUT_LICENSE_ID_OFST,
1041 MIN(buffer_size, *lengthp));
1049 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1054 /* V3 format uses Huntington TLV format partition. See SF-108797-SW */
1055 #define EFX_LICENSE_V3_KEY_LENGTH_MIN (64)
1056 #define EFX_LICENSE_V3_KEY_LENGTH_MAX (160)
1058 __checkReturn efx_rc_t
1059 efx_lic_v3_find_start(
1060 __in efx_nic_t *enp,
1061 __in_bcount(buffer_size)
1063 __in size_t buffer_size,
1064 __out uint32_t *startp)
1066 _NOTE(ARGUNUSED(enp))
1068 return (ef10_nvram_buffer_find_item_start(bufferp, buffer_size,
1072 __checkReturn efx_rc_t
1073 efx_lic_v3_find_end(
1074 __in efx_nic_t *enp,
1075 __in_bcount(buffer_size)
1077 __in size_t buffer_size,
1078 __in uint32_t offset,
1079 __out uint32_t *endp)
1081 _NOTE(ARGUNUSED(enp))
1083 return (ef10_nvram_buffer_find_end(bufferp, buffer_size, offset, endp));
1086 __checkReturn __success(return != B_FALSE) boolean_t
1087 efx_lic_v3_find_key(
1088 __in efx_nic_t *enp,
1089 __in_bcount(buffer_size)
1091 __in size_t buffer_size,
1092 __in uint32_t offset,
1093 __out uint32_t *startp,
1094 __out uint32_t *lengthp)
1096 _NOTE(ARGUNUSED(enp))
1098 return ef10_nvram_buffer_find_item(bufferp, buffer_size,
1099 offset, startp, lengthp);
1102 __checkReturn __success(return != B_FALSE) boolean_t
1103 efx_lic_v3_validate_key(
1104 __in efx_nic_t *enp,
1105 __in_bcount(length) caddr_t keyp,
1106 __in uint32_t length)
1108 /* Check key is a valid V3 key */
1112 _NOTE(ARGUNUSED(enp))
1114 if (length < EFX_LICENSE_V3_KEY_LENGTH_MIN) {
1118 if (length > EFX_LICENSE_V3_KEY_LENGTH_MAX) {
1122 key_type = ((uint8_t *)keyp)[0];
1123 key_length = ((uint8_t *)keyp)[1];
1128 if (key_length > length) {
1140 EFSYS_PROBE1(fail1, boolean_t, B_FALSE);
1145 __checkReturn efx_rc_t
1146 efx_lic_v3_read_key(
1147 __in efx_nic_t *enp,
1148 __in_bcount(buffer_size)
1150 __in size_t buffer_size,
1151 __in uint32_t offset,
1152 __in uint32_t length,
1153 __out_bcount_part(key_max_size, *lengthp)
1155 __in size_t key_max_size,
1156 __out uint32_t *lengthp)
1160 _NOTE(ARGUNUSED(enp))
1162 return ef10_nvram_buffer_get_item(bufferp, buffer_size,
1163 offset, length, &tag, keyp, key_max_size, lengthp);
1166 __checkReturn efx_rc_t
1167 efx_lic_v3_write_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_bcount(length) caddr_t keyp,
1174 __in uint32_t length,
1175 __out uint32_t *lengthp)
1177 _NOTE(ARGUNUSED(enp))
1178 EFSYS_ASSERT(length <= EFX_LICENSE_V3_KEY_LENGTH_MAX);
1180 return ef10_nvram_buffer_insert_item(bufferp, buffer_size,
1181 offset, TLV_TAG_LICENSE, keyp, length, lengthp);
1184 __checkReturn efx_rc_t
1185 efx_lic_v3_delete_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 uint32_t length,
1193 __out uint32_t *deltap)
1197 _NOTE(ARGUNUSED(enp))
1199 if ((rc = ef10_nvram_buffer_delete_item(bufferp,
1200 buffer_size, offset, length, end)) != 0) {
1209 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1214 __checkReturn efx_rc_t
1215 efx_lic_v3_create_partition(
1216 __in efx_nic_t *enp,
1217 __in_bcount(buffer_size)
1219 __in size_t buffer_size)
1223 _NOTE(ARGUNUSED(enp))
1225 /* Construct empty partition */
1226 if ((rc = ef10_nvram_buffer_create(
1227 NVRAM_PARTITION_TYPE_LICENSE,
1228 bufferp, buffer_size)) != 0) {
1236 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1241 __checkReturn efx_rc_t
1242 efx_lic_v3_finish_partition(
1243 __in efx_nic_t *enp,
1244 __in_bcount(buffer_size)
1246 __in size_t buffer_size)
1250 _NOTE(ARGUNUSED(enp))
1252 if ((rc = ef10_nvram_buffer_finish(bufferp,
1253 buffer_size)) != 0) {
1257 /* Validate completed partition */
1258 if ((rc = ef10_nvram_buffer_validate(
1259 NVRAM_PARTITION_TYPE_LICENSE,
1260 bufferp, buffer_size)) != 0) {
1269 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1275 #endif /* EFSYS_OPT_MEDFORD || EFSYS_OPT_MEDFORD2 */
1277 __checkReturn efx_rc_t
1279 __in efx_nic_t *enp)
1281 const efx_lic_ops_t *elop;
1282 efx_key_stats_t eks;
1285 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1286 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
1287 EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_LIC));
1289 switch (enp->en_family) {
1292 case EFX_FAMILY_SIENA:
1293 elop = &__efx_lic_v1_ops;
1295 #endif /* EFSYS_OPT_SIENA */
1297 #if EFSYS_OPT_HUNTINGTON
1298 case EFX_FAMILY_HUNTINGTON:
1299 elop = &__efx_lic_v2_ops;
1301 #endif /* EFSYS_OPT_HUNTINGTON */
1303 #if EFSYS_OPT_MEDFORD
1304 case EFX_FAMILY_MEDFORD:
1305 elop = &__efx_lic_v3_ops;
1307 #endif /* EFSYS_OPT_MEDFORD */
1309 #if EFSYS_OPT_MEDFORD2
1310 case EFX_FAMILY_MEDFORD2:
1311 elop = &__efx_lic_v3_ops;
1313 #endif /* EFSYS_OPT_MEDFORD2 */
1321 enp->en_elop = elop;
1322 enp->en_mod_flags |= EFX_MOD_LIC;
1324 /* Probe for support */
1325 if (efx_lic_get_key_stats(enp, &eks) == 0) {
1326 enp->en_licensing_supported = B_TRUE;
1328 enp->en_licensing_supported = B_FALSE;
1334 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1339 extern __checkReturn boolean_t
1340 efx_lic_check_support(
1341 __in efx_nic_t *enp)
1343 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1344 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
1345 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1347 return (enp->en_licensing_supported);
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 enp->en_elop = NULL;
1359 enp->en_mod_flags &= ~EFX_MOD_LIC;
1363 __checkReturn efx_rc_t
1364 efx_lic_update_licenses(
1365 __in efx_nic_t *enp)
1367 const efx_lic_ops_t *elop = enp->en_elop;
1370 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1371 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1373 if ((rc = elop->elo_update_licenses(enp)) != 0)
1379 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1384 __checkReturn efx_rc_t
1385 efx_lic_get_key_stats(
1386 __in efx_nic_t *enp,
1387 __out efx_key_stats_t *eksp)
1389 const efx_lic_ops_t *elop = enp->en_elop;
1392 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1393 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1395 if ((rc = elop->elo_get_key_stats(enp, eksp)) != 0)
1401 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1406 __checkReturn efx_rc_t
1408 __in efx_nic_t *enp,
1409 __in uint64_t app_id,
1410 __out boolean_t *licensedp)
1412 const efx_lic_ops_t *elop = enp->en_elop;
1415 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1416 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1418 if (elop->elo_app_state == NULL)
1421 if ((rc = elop->elo_app_state(enp, app_id, licensedp)) != 0)
1427 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1432 __checkReturn efx_rc_t
1434 __in efx_nic_t *enp,
1435 __in size_t buffer_size,
1436 __out uint32_t *typep,
1437 __out size_t *lengthp,
1438 __out_opt uint8_t *bufferp)
1440 const efx_lic_ops_t *elop = enp->en_elop;
1443 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1444 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1446 if (elop->elo_get_id == NULL)
1449 if ((rc = elop->elo_get_id(enp, buffer_size, typep,
1450 lengthp, bufferp)) != 0)
1456 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1462 * Buffer management API - abstracts varying TLV format used for License
1466 __checkReturn efx_rc_t
1468 __in efx_nic_t *enp,
1469 __in_bcount(buffer_size)
1471 __in size_t buffer_size,
1472 __out uint32_t *startp)
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 ((rc = elop->elo_find_start(enp, bufferp, buffer_size, startp)) != 0)
1486 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1491 __checkReturn efx_rc_t
1493 __in efx_nic_t *enp,
1494 __in_bcount(buffer_size)
1496 __in size_t buffer_size,
1497 __in uint32_t offset,
1498 __out uint32_t *endp)
1500 const efx_lic_ops_t *elop = enp->en_elop;
1503 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1504 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1506 rc = elop->elo_find_end(enp, bufferp, buffer_size, offset, endp);
1513 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1518 __checkReturn __success(return != B_FALSE) boolean_t
1520 __in efx_nic_t *enp,
1521 __in_bcount(buffer_size)
1523 __in size_t buffer_size,
1524 __in uint32_t offset,
1525 __out uint32_t *startp,
1526 __out uint32_t *lengthp)
1528 const efx_lic_ops_t *elop = enp->en_elop;
1530 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1531 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1533 EFSYS_ASSERT(bufferp);
1534 EFSYS_ASSERT(startp);
1535 EFSYS_ASSERT(lengthp);
1537 return (elop->elo_find_key(enp, bufferp, buffer_size, offset,
1543 * Validate that the buffer contains a single key in a recognised format.
1544 * An empty or terminator buffer is not accepted as a valid key.
1546 __checkReturn __success(return != B_FALSE) boolean_t
1547 efx_lic_validate_key(
1548 __in efx_nic_t *enp,
1549 __in_bcount(length) caddr_t keyp,
1550 __in uint32_t length)
1552 const efx_lic_ops_t *elop = enp->en_elop;
1555 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1556 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1558 if ((rc = elop->elo_validate_key(enp, keyp, length)) == B_FALSE)
1564 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1569 __checkReturn efx_rc_t
1571 __in efx_nic_t *enp,
1572 __in_bcount(buffer_size)
1574 __in size_t buffer_size,
1575 __in uint32_t offset,
1576 __in uint32_t length,
1577 __out_bcount_part(key_max_size, *lengthp)
1579 __in size_t key_max_size,
1580 __out uint32_t *lengthp)
1582 const efx_lic_ops_t *elop = enp->en_elop;
1585 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1586 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1588 if ((rc = elop->elo_read_key(enp, bufferp, buffer_size, offset,
1589 length, keyp, key_max_size, lengthp)) != 0)
1595 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1600 __checkReturn efx_rc_t
1602 __in efx_nic_t *enp,
1603 __in_bcount(buffer_size)
1605 __in size_t buffer_size,
1606 __in uint32_t offset,
1607 __in_bcount(length) caddr_t keyp,
1608 __in uint32_t length,
1609 __out uint32_t *lengthp)
1611 const efx_lic_ops_t *elop = enp->en_elop;
1614 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1615 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1617 if ((rc = elop->elo_write_key(enp, bufferp, buffer_size, offset,
1618 keyp, length, lengthp)) != 0)
1624 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1629 __checkReturn efx_rc_t
1631 __in efx_nic_t *enp,
1632 __in_bcount(buffer_size)
1634 __in size_t buffer_size,
1635 __in uint32_t offset,
1636 __in uint32_t length,
1638 __out uint32_t *deltap)
1640 const efx_lic_ops_t *elop = enp->en_elop;
1643 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1644 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1646 if ((rc = elop->elo_delete_key(enp, bufferp, buffer_size, offset,
1647 length, end, deltap)) != 0)
1653 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1658 __checkReturn efx_rc_t
1659 efx_lic_create_partition(
1660 __in efx_nic_t *enp,
1661 __in_bcount(buffer_size)
1663 __in size_t buffer_size)
1665 const efx_lic_ops_t *elop = enp->en_elop;
1668 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1669 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1671 if ((rc = elop->elo_create_partition(enp, bufferp, buffer_size)) != 0)
1677 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1683 __checkReturn efx_rc_t
1684 efx_lic_finish_partition(
1685 __in efx_nic_t *enp,
1686 __in_bcount(buffer_size)
1688 __in size_t buffer_size)
1690 const efx_lic_ops_t *elop = enp->en_elop;
1693 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1694 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1696 if ((rc = elop->elo_finish_partition(enp, bufferp, buffer_size)) != 0)
1702 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1707 #endif /* EFSYS_OPT_LICENSING */