1 /*
2  * Copyright (c) 2009-2015 Solarflare Communications Inc.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  *
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.
13  *
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.
25  *
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.
29  */
30 
31 #include "efx.h"
32 #include "efx_impl.h"
33 
34 #if EFSYS_OPT_LICENSING
35 
36 #include "ef10_tlv_layout.h"
37 
38 #if EFSYS_OPT_SIENA | EFSYS_OPT_HUNTINGTON
39 
40 	__checkReturn		efx_rc_t
41 efx_lic_v1v2_find_start(
42 	__in			efx_nic_t *enp,
43 	__in_bcount(buffer_size)
44 				caddr_t bufferp,
45 	__in			size_t buffer_size,
46 	__out			uint32_t *startp
47 	);
48 
49 	__checkReturn		efx_rc_t
50 efx_lic_v1v2_find_end(
51 	__in			efx_nic_t *enp,
52 	__in_bcount(buffer_size)
53 				caddr_t bufferp,
54 	__in			size_t buffer_size,
55 	__in			uint32_t offset,
56 	__out			uint32_t *endp
57 	);
58 
59 	__checkReturn	__success(return != B_FALSE)	boolean_t
60 efx_lic_v1v2_find_key(
61 	__in			efx_nic_t *enp,
62 	__in_bcount(buffer_size)
63 				caddr_t bufferp,
64 	__in			size_t buffer_size,
65 	__in			uint32_t offset,
66 	__out			uint32_t *startp,
67 	__out			uint32_t *lengthp
68 	);
69 
70 	__checkReturn	__success(return != B_FALSE)	boolean_t
71 efx_lic_v1v2_validate_key(
72 	__in			efx_nic_t *enp,
73 	__in_bcount(length)	caddr_t keyp,
74 	__in			uint32_t length
75 	);
76 
77 	__checkReturn		efx_rc_t
78 efx_lic_v1v2_read_key(
79 	__in			efx_nic_t *enp,
80 	__in_bcount(buffer_size)
81 				caddr_t bufferp,
82 	__in			size_t buffer_size,
83 	__in			uint32_t offset,
84 	__in			uint32_t length,
85 	__out_bcount_part(key_max_size, *lengthp)
86 				caddr_t keyp,
87 	__in			size_t key_max_size,
88 	__out			uint32_t *lengthp
89 	);
90 
91 	__checkReturn		efx_rc_t
92 efx_lic_v1v2_write_key(
93 	__in			efx_nic_t *enp,
94 	__in_bcount(buffer_size)
95 				caddr_t bufferp,
96 	__in			size_t buffer_size,
97 	__in			uint32_t offset,
98 	__in_bcount(length)	caddr_t keyp,
99 	__in			uint32_t length,
100 	__out			uint32_t *lengthp
101 	);
102 
103 	__checkReturn		efx_rc_t
104 efx_lic_v1v2_delete_key(
105 	__in			efx_nic_t *enp,
106 	__in_bcount(buffer_size)
107 				caddr_t bufferp,
108 	__in			size_t buffer_size,
109 	__in			uint32_t offset,
110 	__in			uint32_t length,
111 	__in			uint32_t end,
112 	__out			uint32_t *deltap
113 	);
114 
115 	__checkReturn		efx_rc_t
116 efx_lic_v1v2_create_partition(
117 	__in			efx_nic_t *enp,
118 	__in_bcount(buffer_size)
119 				caddr_t bufferp,
120 	__in			size_t buffer_size
121 	);
122 
123 	__checkReturn		efx_rc_t
124 efx_lic_v1v2_finish_partition(
125 	__in			efx_nic_t *enp,
126 	__in_bcount(buffer_size)
127 				caddr_t bufferp,
128 	__in			size_t buffer_size
129 	);
130 
131 #endif	/* EFSYS_OPT_HUNTINGTON | EFSYS_OPT_SIENA */
132 
133 
134 #if EFSYS_OPT_SIENA
135 
136 static	__checkReturn	efx_rc_t
137 efx_mcdi_fc_license_update_license(
138 	__in		efx_nic_t *enp);
139 
140 static	__checkReturn	efx_rc_t
141 efx_mcdi_fc_license_get_key_stats(
142 	__in		efx_nic_t *enp,
143 	__out		efx_key_stats_t *eksp);
144 
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 */
159 };
160 
161 #endif	/* EFSYS_OPT_SIENA */
162 
163 #if EFSYS_OPT_HUNTINGTON
164 
165 static	__checkReturn	efx_rc_t
166 efx_mcdi_licensing_update_licenses(
167 	__in		efx_nic_t *enp);
168 
169 static	__checkReturn	efx_rc_t
170 efx_mcdi_licensing_get_key_stats(
171 	__in		efx_nic_t *enp,
172 	__out		efx_key_stats_t *eksp);
173 
174 static	__checkReturn	efx_rc_t
175 efx_mcdi_licensed_app_state(
176 	__in		efx_nic_t *enp,
177 	__in		uint64_t app_id,
178 	__out		boolean_t *licensedp);
179 
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 */
194 };
195 
196 #endif	/* EFSYS_OPT_HUNTINGTON */
197 
198 #if EFSYS_OPT_MEDFORD
199 
200 static	__checkReturn	efx_rc_t
201 efx_mcdi_licensing_v3_update_licenses(
202 	__in		efx_nic_t *enp);
203 
204 static	__checkReturn	efx_rc_t
205 efx_mcdi_licensing_v3_report_license(
206 	__in		efx_nic_t *enp,
207 	__out		efx_key_stats_t *eksp);
208 
209 static	__checkReturn	efx_rc_t
210 efx_mcdi_licensing_v3_app_state(
211 	__in		efx_nic_t *enp,
212 	__in		uint64_t app_id,
213 	__out		boolean_t *licensedp);
214 
215 static	__checkReturn	efx_rc_t
216 efx_mcdi_licensing_v3_get_id(
217 	__in		efx_nic_t *enp,
218 	__in		size_t buffer_size,
219 	__out		uint32_t *typep,
220 	__out		size_t *lengthp,
221 	__out_bcount_part_opt(buffer_size, *lengthp)
222 			uint8_t *bufferp);
223 
224 	__checkReturn		efx_rc_t
225 efx_lic_v3_find_start(
226 	__in			efx_nic_t *enp,
227 	__in_bcount(buffer_size)
228 				caddr_t bufferp,
229 	__in			size_t buffer_size,
230 	__out			uint32_t *startp
231 	);
232 
233 	__checkReturn		efx_rc_t
234 efx_lic_v3_find_end(
235 	__in			efx_nic_t *enp,
236 	__in_bcount(buffer_size)
237 				caddr_t bufferp,
238 	__in			size_t buffer_size,
239 	__in			uint32_t offset,
240 	__out			uint32_t *endp
241 	);
242 
243 	__checkReturn	__success(return != B_FALSE)	boolean_t
244 efx_lic_v3_find_key(
245 	__in			efx_nic_t *enp,
246 	__in_bcount(buffer_size)
247 				caddr_t bufferp,
248 	__in			size_t buffer_size,
249 	__in			uint32_t offset,
250 	__out			uint32_t *startp,
251 	__out			uint32_t *lengthp
252 	);
253 
254 	__checkReturn	__success(return != B_FALSE)	boolean_t
255 efx_lic_v3_validate_key(
256 	__in			efx_nic_t *enp,
257 	__in_bcount(length)	caddr_t keyp,
258 	__in			uint32_t length
259 	);
260 
261 	__checkReturn		efx_rc_t
262 efx_lic_v3_read_key(
263 	__in			efx_nic_t *enp,
264 	__in_bcount(buffer_size)
265 				caddr_t bufferp,
266 	__in			size_t buffer_size,
267 	__in			uint32_t offset,
268 	__in			uint32_t length,
269 	__out_bcount_part(key_max_size, *lengthp)
270 				caddr_t keyp,
271 	__in			size_t key_max_size,
272 	__out			uint32_t *lengthp
273 	);
274 
275 	__checkReturn		efx_rc_t
276 efx_lic_v3_write_key(
277 	__in			efx_nic_t *enp,
278 	__in_bcount(buffer_size)
279 				caddr_t bufferp,
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
285 	);
286 
287 	__checkReturn		efx_rc_t
288 efx_lic_v3_delete_key(
289 	__in			efx_nic_t *enp,
290 	__in_bcount(buffer_size)
291 				caddr_t bufferp,
292 	__in			size_t buffer_size,
293 	__in			uint32_t offset,
294 	__in			uint32_t length,
295 	__in			uint32_t end,
296 	__out			uint32_t *deltap
297 	);
298 
299 	__checkReturn		efx_rc_t
300 efx_lic_v3_create_partition(
301 	__in			efx_nic_t *enp,
302 	__in_bcount(buffer_size)
303 				caddr_t bufferp,
304 	__in			size_t buffer_size
305 	);
306 
307 	__checkReturn		efx_rc_t
308 efx_lic_v3_finish_partition(
309 	__in			efx_nic_t *enp,
310 	__in_bcount(buffer_size)
311 				caddr_t bufferp,
312 	__in			size_t buffer_size
313 	);
314 
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 */
329 };
330 
331 #endif	/* EFSYS_OPT_MEDFORD */
332 
333 
334 /* V1 Licensing - used in Siena Modena only */
335 
336 #if EFSYS_OPT_SIENA
337 
338 static	__checkReturn	efx_rc_t
efx_mcdi_fc_license_update_license(__in efx_nic_t * enp)339 efx_mcdi_fc_license_update_license(
340 	__in		efx_nic_t *enp)
341 {
342 	efx_mcdi_req_t req;
343 	uint8_t payload[MC_CMD_FC_IN_LICENSE_LEN];
344 	efx_rc_t rc;
345 
346 	EFSYS_ASSERT(enp->en_family == EFX_FAMILY_SIENA);
347 
348 	(void) memset(payload, 0, sizeof (payload));
349 	req.emr_cmd = MC_CMD_FC_OP_LICENSE;
350 	req.emr_in_buf = payload;
351 	req.emr_in_length = MC_CMD_FC_IN_LICENSE_LEN;
352 	req.emr_out_buf = payload;
353 	req.emr_out_length = 0;
354 
355 	MCDI_IN_SET_DWORD(req, FC_IN_LICENSE_OP,
356 	    MC_CMD_FC_IN_LICENSE_UPDATE_LICENSE);
357 
358 	efx_mcdi_execute(enp, &req);
359 
360 	if (req.emr_rc != 0) {
361 		rc = req.emr_rc;
362 		goto fail1;
363 	}
364 
365 	if (req.emr_out_length_used != 0) {
366 		rc = EIO;
367 		goto fail2;
368 	}
369 
370 	return (0);
371 
372 fail2:
373 	EFSYS_PROBE(fail2);
374 fail1:
375 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
376 
377 	return (rc);
378 }
379 
380 static	__checkReturn	efx_rc_t
efx_mcdi_fc_license_get_key_stats(__in efx_nic_t * enp,__out efx_key_stats_t * eksp)381 efx_mcdi_fc_license_get_key_stats(
382 	__in		efx_nic_t *enp,
383 	__out		efx_key_stats_t *eksp)
384 {
385 	efx_mcdi_req_t req;
386 	uint8_t payload[MAX(MC_CMD_FC_IN_LICENSE_LEN,
387 			    MC_CMD_FC_OUT_LICENSE_LEN)];
388 	efx_rc_t rc;
389 
390 	EFSYS_ASSERT(enp->en_family == EFX_FAMILY_SIENA);
391 
392 	(void) memset(payload, 0, sizeof (payload));
393 	req.emr_cmd = MC_CMD_FC_OP_LICENSE;
394 	req.emr_in_buf = payload;
395 	req.emr_in_length = MC_CMD_FC_IN_LICENSE_LEN;
396 	req.emr_out_buf = payload;
397 	req.emr_out_length = MC_CMD_FC_OUT_LICENSE_LEN;
398 
399 	MCDI_IN_SET_DWORD(req, FC_IN_LICENSE_OP,
400 	    MC_CMD_FC_IN_LICENSE_GET_KEY_STATS);
401 
402 	efx_mcdi_execute(enp, &req);
403 
404 	if (req.emr_rc != 0) {
405 		rc = req.emr_rc;
406 		goto fail1;
407 	}
408 
409 	if (req.emr_out_length_used < MC_CMD_FC_OUT_LICENSE_LEN) {
410 		rc = EMSGSIZE;
411 		goto fail2;
412 	}
413 
414 	eksp->eks_valid =
415 		MCDI_OUT_DWORD(req, FC_OUT_LICENSE_VALID_KEYS);
416 	eksp->eks_invalid =
417 		MCDI_OUT_DWORD(req, FC_OUT_LICENSE_INVALID_KEYS);
418 	eksp->eks_blacklisted =
419 		MCDI_OUT_DWORD(req, FC_OUT_LICENSE_BLACKLISTED_KEYS);
420 	eksp->eks_unverifiable = 0;
421 	eksp->eks_wrong_node = 0;
422 	eksp->eks_licensed_apps_lo = 0;
423 	eksp->eks_licensed_apps_hi = 0;
424 	eksp->eks_licensed_features_lo = 0;
425 	eksp->eks_licensed_features_hi = 0;
426 
427 	return (0);
428 
429 fail2:
430 	EFSYS_PROBE(fail2);
431 fail1:
432 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
433 
434 	return (rc);
435 }
436 
437 #endif	/* EFSYS_OPT_SIENA */
438 
439 /* V1 and V2 Partition format - based on a 16-bit TLV format */
440 
441 #if EFSYS_OPT_SIENA | EFSYS_OPT_HUNTINGTON
442 
443 /*
444  * V1/V2 format - defined in SF-108542-TC section 4.2:
445  *  Type (T):   16bit - revision/HMAC algorithm
446  *  Length (L): 16bit - value length in bytes
447  *  Value (V):  L bytes - payload
448  */
449 #define EFX_LICENSE_V1V2_PAYLOAD_LENGTH_MAX    (256)
450 #define EFX_LICENSE_V1V2_HEADER_LENGTH         (2*sizeof(uint16_t))
451 
452 	__checkReturn		efx_rc_t
efx_lic_v1v2_find_start(__in efx_nic_t * enp,__in_bcount (buffer_size)caddr_t bufferp,__in size_t buffer_size,__out uint32_t * startp)453 efx_lic_v1v2_find_start(
454 	__in			efx_nic_t *enp,
455 	__in_bcount(buffer_size)
456 				caddr_t bufferp,
457 	__in			size_t buffer_size,
458 	__out			uint32_t *startp
459 	)
460 {
461 	_NOTE(ARGUNUSED(enp, bufferp, buffer_size))
462 
463 	*startp = 0;
464 	return (0);
465 }
466 
467 	__checkReturn		efx_rc_t
efx_lic_v1v2_find_end(__in efx_nic_t * enp,__in_bcount (buffer_size)caddr_t bufferp,__in size_t buffer_size,__in uint32_t offset,__out uint32_t * endp)468 efx_lic_v1v2_find_end(
469 	__in			efx_nic_t *enp,
470 	__in_bcount(buffer_size)
471 				caddr_t bufferp,
472 	__in			size_t buffer_size,
473 	__in			uint32_t offset,
474 	__out			uint32_t *endp
475 	)
476 {
477 	_NOTE(ARGUNUSED(enp, bufferp, buffer_size))
478 
479 	*endp = offset + EFX_LICENSE_V1V2_HEADER_LENGTH;
480 	return (0);
481 }
482 
483 	__checkReturn	__success(return != B_FALSE)	boolean_t
efx_lic_v1v2_find_key(__in efx_nic_t * enp,__in_bcount (buffer_size)caddr_t bufferp,__in size_t buffer_size,__in uint32_t offset,__out uint32_t * startp,__out uint32_t * lengthp)484 efx_lic_v1v2_find_key(
485 	__in			efx_nic_t *enp,
486 	__in_bcount(buffer_size)
487 				caddr_t bufferp,
488 	__in			size_t buffer_size,
489 	__in			uint32_t offset,
490 	__out			uint32_t *startp,
491 	__out			uint32_t *lengthp
492 	)
493 {
494 	boolean_t found;
495 	uint16_t tlv_type;
496 	uint16_t tlv_length;
497 
498 	_NOTE(ARGUNUSED(enp))
499 
500 	if((size_t)buffer_size - offset < EFX_LICENSE_V1V2_HEADER_LENGTH)
501 		goto fail1;
502 
503 	tlv_type = __LE_TO_CPU_16(((uint16_t*)&bufferp[offset])[0]);
504 	tlv_length = __LE_TO_CPU_16(((uint16_t*)&bufferp[offset])[1]);
505 	if ((tlv_length > EFX_LICENSE_V1V2_PAYLOAD_LENGTH_MAX) ||
506 	    (tlv_type == 0 && tlv_length == 0)) {
507 		found = B_FALSE;
508 	} else {
509 		*startp = offset;
510 		*lengthp = tlv_length + EFX_LICENSE_V1V2_HEADER_LENGTH;
511 		found = B_TRUE;
512 	}
513 	return (found);
514 
515 fail1:
516 	EFSYS_PROBE(fail1);
517 
518 	return (B_FALSE);
519 }
520 
521 	__checkReturn	__success(return != B_FALSE)	boolean_t
efx_lic_v1v2_validate_key(__in efx_nic_t * enp,__in_bcount (length)caddr_t keyp,__in uint32_t length)522 efx_lic_v1v2_validate_key(
523 	__in			efx_nic_t *enp,
524 	__in_bcount(length)	caddr_t keyp,
525 	__in			uint32_t length
526 	)
527 {
528 	const efx_lic_ops_t *elop = enp->en_elop;
529 	efx_rc_t rc;
530 	uint16_t tlv_type;
531 	uint16_t tlv_length;
532 
533 	_NOTE(ARGUNUSED(enp))
534 
535 	if (length < EFX_LICENSE_V1V2_HEADER_LENGTH) {
536 		goto fail1;
537 	}
538 
539 	tlv_type = __LE_TO_CPU_16(((uint16_t*)keyp)[0]);
540 	tlv_length = __LE_TO_CPU_16(((uint16_t*)keyp)[1]);
541 
542 	if(tlv_length > EFX_LICENSE_V1V2_PAYLOAD_LENGTH_MAX) {
543 		goto fail2;
544 	}
545 	if (tlv_type == 0) {
546 		goto fail3;
547 	}
548 	if ((tlv_length + EFX_LICENSE_V1V2_HEADER_LENGTH) != length) {
549 		goto fail4;
550 	}
551 
552 	return (B_TRUE);
553 
554 fail4:
555 	EFSYS_PROBE(fail4);
556 fail3:
557 	EFSYS_PROBE(fail3);
558 fail2:
559 	EFSYS_PROBE(fail2);
560 fail1:
561 	EFSYS_PROBE(fail1);
562 
563 	return (B_FALSE);
564 }
565 
566 
567 	__checkReturn		efx_rc_t
efx_lic_v1v2_read_key(__in efx_nic_t * enp,__in_bcount (buffer_size)caddr_t bufferp,__in size_t buffer_size,__in uint32_t offset,__in uint32_t length,__out_bcount_part (key_max_size,* lengthp)caddr_t keyp,__in size_t key_max_size,__out uint32_t * lengthp)568 efx_lic_v1v2_read_key(
569 	__in			efx_nic_t *enp,
570 	__in_bcount(buffer_size)
571 				caddr_t bufferp,
572 	__in			size_t buffer_size,
573 	__in			uint32_t offset,
574 	__in			uint32_t length,
575 	__out_bcount_part(key_max_size, *lengthp)
576 				caddr_t keyp,
577 	__in			size_t key_max_size,
578 	__out			uint32_t *lengthp
579 	)
580 {
581 	efx_rc_t rc;
582 
583 	_NOTE(ARGUNUSED(enp))
584 	EFSYS_ASSERT(length <= (EFX_LICENSE_V1V2_PAYLOAD_LENGTH_MAX +
585 	    EFX_LICENSE_V1V2_HEADER_LENGTH));
586 
587 	if (key_max_size < length) {
588 		rc = ENOSPC;
589 		goto fail1;
590 	}
591 	(void) memcpy(keyp, &bufferp[offset], length);
592 
593 	*lengthp = length;
594 
595 	return (0);
596 
597 fail1:
598 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
599 
600 	return (rc);
601 }
602 
603 	__checkReturn		efx_rc_t
efx_lic_v1v2_write_key(__in efx_nic_t * enp,__in_bcount (buffer_size)caddr_t bufferp,__in size_t buffer_size,__in uint32_t offset,__in_bcount (length)caddr_t keyp,__in uint32_t length,__out uint32_t * lengthp)604 efx_lic_v1v2_write_key(
605 	__in			efx_nic_t *enp,
606 	__in_bcount(buffer_size)
607 				caddr_t bufferp,
608 	__in			size_t buffer_size,
609 	__in			uint32_t offset,
610 	__in_bcount(length)	caddr_t keyp,
611 	__in			uint32_t length,
612 	__out			uint32_t *lengthp
613 	)
614 {
615 	efx_rc_t rc;
616 
617 	_NOTE(ARGUNUSED(enp))
618 	EFSYS_ASSERT(length <= (EFX_LICENSE_V1V2_PAYLOAD_LENGTH_MAX +
619 	    EFX_LICENSE_V1V2_HEADER_LENGTH));
620 
621 	// Ensure space for terminator remains
622 	if ((offset + length) >
623 	    (buffer_size - EFX_LICENSE_V1V2_HEADER_LENGTH) ) {
624 		rc = ENOSPC;
625 		goto fail1;
626 	}
627 
628 	(void) memcpy(bufferp + offset, keyp, length);
629 
630 	*lengthp = length;
631 
632 	return (0);
633 
634 fail1:
635 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
636 
637 	return (rc);
638 }
639 
640 	__checkReturn		efx_rc_t
efx_lic_v1v2_delete_key(__in efx_nic_t * enp,__in_bcount (buffer_size)caddr_t bufferp,__in size_t buffer_size,__in uint32_t offset,__in uint32_t length,__in uint32_t end,__out uint32_t * deltap)641 efx_lic_v1v2_delete_key(
642 	__in			efx_nic_t *enp,
643 	__in_bcount(buffer_size)
644 				caddr_t bufferp,
645 	__in			size_t buffer_size,
646 	__in			uint32_t offset,
647 	__in			uint32_t length,
648 	__in			uint32_t end,
649 	__out			uint32_t *deltap
650 	)
651 {
652 	efx_rc_t rc;
653 	uint32_t move_start = offset + length;
654 	uint32_t move_length = end - move_start;
655 
656 	_NOTE(ARGUNUSED(enp))
657 	EFSYS_ASSERT(end <= buffer_size);
658 
659 	// Shift everything after the key down
660 	memmove(bufferp + offset, bufferp + move_start, move_length);
661 
662 	*deltap = length;
663 
664 	return (0);
665 }
666 
667 	__checkReturn		efx_rc_t
efx_lic_v1v2_create_partition(__in efx_nic_t * enp,__in_bcount (buffer_size)caddr_t bufferp,__in size_t buffer_size)668 efx_lic_v1v2_create_partition(
669 	__in			efx_nic_t *enp,
670 	__in_bcount(buffer_size)
671 				caddr_t bufferp,
672 	__in			size_t buffer_size
673 	)
674 {
675 	_NOTE(ARGUNUSED(enp))
676 	EFSYS_ASSERT(EFX_LICENSE_V1V2_HEADER_LENGTH <= buffer_size);
677 
678 	// Write terminator
679 	(void) memset(bufferp, '\0', EFX_LICENSE_V1V2_HEADER_LENGTH);
680 	return (0);
681 }
682 
683 
684 	__checkReturn		efx_rc_t
efx_lic_v1v2_finish_partition(__in efx_nic_t * enp,__in_bcount (buffer_size)caddr_t bufferp,__in size_t buffer_size)685 efx_lic_v1v2_finish_partition(
686 	__in			efx_nic_t *enp,
687 	__in_bcount(buffer_size)
688 				caddr_t bufferp,
689 	__in			size_t buffer_size
690 	)
691 {
692 	_NOTE(ARGUNUSED(enp, bufferp, buffer_size))
693 
694 	return (0);
695 }
696 
697 #endif	/* EFSYS_OPT_HUNTINGTON | EFSYS_OPT_SIENA */
698 
699 
700 /* V2 Licensing - used by Huntington family only. See SF-113611-TC */
701 
702 #if EFSYS_OPT_HUNTINGTON
703 
704 static	__checkReturn	efx_rc_t
efx_mcdi_licensed_app_state(__in efx_nic_t * enp,__in uint64_t app_id,__out boolean_t * licensedp)705 efx_mcdi_licensed_app_state(
706 	__in		efx_nic_t *enp,
707 	__in		uint64_t app_id,
708 	__out		boolean_t *licensedp)
709 {
710 	efx_mcdi_req_t req;
711 	uint8_t payload[MAX(MC_CMD_GET_LICENSED_APP_STATE_IN_LEN,
712 			    MC_CMD_GET_LICENSED_APP_STATE_OUT_LEN)];
713 	uint32_t app_state;
714 	efx_rc_t rc;
715 
716 	EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON);
717 
718 	/* V2 licensing supports 32bit app id only */
719 	if ((app_id >> 32) != 0) {
720 		rc = EINVAL;
721 		goto fail1;
722 	}
723 
724 	(void) memset(payload, 0, sizeof (payload));
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;
730 
731 	MCDI_IN_SET_DWORD(req, GET_LICENSED_APP_STATE_IN_APP_ID,
732 		    app_id & 0xffffffff);
733 
734 	efx_mcdi_execute(enp, &req);
735 
736 	if (req.emr_rc != 0) {
737 		rc = req.emr_rc;
738 		goto fail2;
739 	}
740 
741 	if (req.emr_out_length_used < MC_CMD_GET_LICENSED_APP_STATE_OUT_LEN) {
742 		rc = EMSGSIZE;
743 		goto fail3;
744 	}
745 
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) {
748 		*licensedp = B_TRUE;
749 	} else {
750 		*licensedp = B_FALSE;
751 	}
752 
753 	return (0);
754 
755 fail3:
756 	EFSYS_PROBE(fail3);
757 fail2:
758 	EFSYS_PROBE(fail2);
759 fail1:
760 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
761 
762 	return (rc);
763 }
764 
765 static	__checkReturn	efx_rc_t
efx_mcdi_licensing_update_licenses(__in efx_nic_t * enp)766 efx_mcdi_licensing_update_licenses(
767 	__in		efx_nic_t *enp)
768 {
769 	efx_mcdi_req_t req;
770 	uint8_t payload[MC_CMD_LICENSING_IN_LEN];
771 	efx_rc_t rc;
772 
773 	EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON);
774 
775 	(void) memset(payload, 0, sizeof (payload));
776 	req.emr_cmd = MC_CMD_LICENSING;
777 	req.emr_in_buf = payload;
778 	req.emr_in_length = MC_CMD_LICENSING_IN_LEN;
779 	req.emr_out_buf = payload;
780 	req.emr_out_length = 0;
781 
782 	MCDI_IN_SET_DWORD(req, LICENSING_IN_OP,
783 	    MC_CMD_LICENSING_IN_OP_UPDATE_LICENSE);
784 
785 	efx_mcdi_execute(enp, &req);
786 
787 	if (req.emr_rc != 0) {
788 		rc = req.emr_rc;
789 		goto fail1;
790 	}
791 
792 	if (req.emr_out_length_used != 0) {
793 		rc = EIO;
794 		goto fail2;
795 	}
796 
797 	return (0);
798 
799 fail2:
800 	EFSYS_PROBE(fail2);
801 fail1:
802 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
803 
804 	return (rc);
805 }
806 
807 static	__checkReturn	efx_rc_t
efx_mcdi_licensing_get_key_stats(__in efx_nic_t * enp,__out efx_key_stats_t * eksp)808 efx_mcdi_licensing_get_key_stats(
809 	__in		efx_nic_t *enp,
810 	__out		efx_key_stats_t *eksp)
811 {
812 	efx_mcdi_req_t req;
813 	uint8_t payload[MAX(MC_CMD_LICENSING_IN_LEN,
814 			    MC_CMD_LICENSING_OUT_LEN)];
815 	efx_rc_t rc;
816 
817 	EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON);
818 
819 	(void) memset(payload, 0, sizeof (payload));
820 	req.emr_cmd = MC_CMD_LICENSING;
821 	req.emr_in_buf = payload;
822 	req.emr_in_length = MC_CMD_LICENSING_IN_LEN;
823 	req.emr_out_buf = payload;
824 	req.emr_out_length = MC_CMD_LICENSING_OUT_LEN;
825 
826 	MCDI_IN_SET_DWORD(req, LICENSING_IN_OP,
827 	    MC_CMD_LICENSING_IN_OP_GET_KEY_STATS);
828 
829 	efx_mcdi_execute(enp, &req);
830 
831 	if (req.emr_rc != 0) {
832 		rc = req.emr_rc;
833 		goto fail1;
834 	}
835 
836 	if (req.emr_out_length_used < MC_CMD_LICENSING_OUT_LEN) {
837 		rc = EMSGSIZE;
838 		goto fail2;
839 	}
840 
841 	eksp->eks_valid =
842 		MCDI_OUT_DWORD(req, LICENSING_OUT_VALID_APP_KEYS);
843 	eksp->eks_invalid =
844 		MCDI_OUT_DWORD(req, LICENSING_OUT_INVALID_APP_KEYS);
845 	eksp->eks_blacklisted =
846 		MCDI_OUT_DWORD(req, LICENSING_OUT_BLACKLISTED_APP_KEYS);
847 	eksp->eks_unverifiable =
848 		MCDI_OUT_DWORD(req, LICENSING_OUT_UNVERIFIABLE_APP_KEYS);
849 	eksp->eks_wrong_node =
850 		MCDI_OUT_DWORD(req, LICENSING_OUT_WRONG_NODE_APP_KEYS);
851 	eksp->eks_licensed_apps_lo = 0;
852 	eksp->eks_licensed_apps_hi = 0;
853 	eksp->eks_licensed_features_lo = 0;
854 	eksp->eks_licensed_features_hi = 0;
855 
856 	return (0);
857 
858 fail2:
859 	EFSYS_PROBE(fail2);
860 fail1:
861 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
862 
863 	return (rc);
864 }
865 
866 #endif	/* EFSYS_OPT_HUNTINGTON */
867 
868 /* V3 Licensing - used starting from Medford family. See SF-114884-SW */
869 
870 #if EFSYS_OPT_MEDFORD
871 
872 static	__checkReturn	efx_rc_t
efx_mcdi_licensing_v3_update_licenses(__in efx_nic_t * enp)873 efx_mcdi_licensing_v3_update_licenses(
874 	__in		efx_nic_t *enp)
875 {
876 	efx_mcdi_req_t req;
877 	uint8_t payload[MC_CMD_LICENSING_V3_IN_LEN];
878 	efx_rc_t rc;
879 
880 	EFSYS_ASSERT(enp->en_family == EFX_FAMILY_MEDFORD);
881 
882 	(void) memset(payload, 0, sizeof (payload));
883 	req.emr_cmd = MC_CMD_LICENSING_V3;
884 	req.emr_in_buf = payload;
885 	req.emr_in_length = MC_CMD_LICENSING_V3_IN_LEN;
886 	req.emr_out_buf = NULL;
887 	req.emr_out_length = 0;
888 
889 	MCDI_IN_SET_DWORD(req, LICENSING_V3_IN_OP,
890 	    MC_CMD_LICENSING_V3_IN_OP_UPDATE_LICENSE);
891 
892 	efx_mcdi_execute(enp, &req);
893 
894 	if (req.emr_rc != 0) {
895 		rc = req.emr_rc;
896 		goto fail1;
897 	}
898 
899 	return (0);
900 
901 fail1:
902 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
903 
904 	return (rc);
905 }
906 
907 static	__checkReturn	efx_rc_t
efx_mcdi_licensing_v3_report_license(__in efx_nic_t * enp,__out efx_key_stats_t * eksp)908 efx_mcdi_licensing_v3_report_license(
909 	__in		efx_nic_t *enp,
910 	__out		efx_key_stats_t *eksp)
911 {
912 	efx_mcdi_req_t req;
913 	uint8_t payload[MAX(MC_CMD_LICENSING_V3_IN_LEN,
914 			    MC_CMD_LICENSING_V3_OUT_LEN)];
915 	efx_rc_t rc;
916 
917 	EFSYS_ASSERT(enp->en_family == EFX_FAMILY_MEDFORD);
918 
919 	(void) memset(payload, 0, sizeof (payload));
920 	req.emr_cmd = MC_CMD_LICENSING_V3;
921 	req.emr_in_buf = payload;
922 	req.emr_in_length = MC_CMD_LICENSING_V3_IN_LEN;
923 	req.emr_out_buf = payload;
924 	req.emr_out_length = MC_CMD_LICENSING_V3_OUT_LEN;
925 
926 	MCDI_IN_SET_DWORD(req, LICENSING_V3_IN_OP,
927 	    MC_CMD_LICENSING_V3_IN_OP_REPORT_LICENSE);
928 
929 	efx_mcdi_execute(enp, &req);
930 
931 	if (req.emr_rc != 0) {
932 		rc = req.emr_rc;
933 		goto fail1;
934 	}
935 
936 	if (req.emr_out_length_used < MC_CMD_LICENSING_V3_OUT_LEN) {
937 		rc = EMSGSIZE;
938 		goto fail2;
939 	}
940 
941 	eksp->eks_valid =
942 		MCDI_OUT_DWORD(req, LICENSING_V3_OUT_VALID_KEYS);
943 	eksp->eks_invalid =
944 		MCDI_OUT_DWORD(req, LICENSING_V3_OUT_INVALID_KEYS);
945 	eksp->eks_blacklisted = 0;
946 	eksp->eks_unverifiable =
947 		MCDI_OUT_DWORD(req, LICENSING_V3_OUT_UNVERIFIABLE_KEYS);
948 	eksp->eks_wrong_node =
949 		MCDI_OUT_DWORD(req, LICENSING_V3_OUT_WRONG_NODE_KEYS);
950 	eksp->eks_licensed_apps_lo =
951 		MCDI_OUT_DWORD(req, LICENSING_V3_OUT_LICENSED_APPS_LO);
952 	eksp->eks_licensed_apps_hi =
953 		MCDI_OUT_DWORD(req, LICENSING_V3_OUT_LICENSED_APPS_HI);
954 	eksp->eks_licensed_features_lo =
955 		MCDI_OUT_DWORD(req, LICENSING_V3_OUT_LICENSED_FEATURES_LO);
956 	eksp->eks_licensed_features_hi =
957 		MCDI_OUT_DWORD(req, LICENSING_V3_OUT_LICENSED_FEATURES_HI);
958 
959 	return (0);
960 
961 fail2:
962 	EFSYS_PROBE(fail2);
963 fail1:
964 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
965 
966 	return (rc);
967 }
968 
969 static	__checkReturn	efx_rc_t
efx_mcdi_licensing_v3_app_state(__in efx_nic_t * enp,__in uint64_t app_id,__out boolean_t * licensedp)970 efx_mcdi_licensing_v3_app_state(
971 	__in		efx_nic_t *enp,
972 	__in		uint64_t app_id,
973 	__out		boolean_t *licensedp)
974 {
975 	efx_mcdi_req_t req;
976 	uint8_t payload[MAX(MC_CMD_GET_LICENSED_V3_APP_STATE_IN_LEN,
977 			    MC_CMD_GET_LICENSED_V3_APP_STATE_OUT_LEN)];
978 	uint32_t app_state;
979 	efx_rc_t rc;
980 
981 	EFSYS_ASSERT(enp->en_family == EFX_FAMILY_MEDFORD);
982 
983 	(void) memset(payload, 0, sizeof (payload));
984 	req.emr_cmd = MC_CMD_GET_LICENSED_V3_APP_STATE;
985 	req.emr_in_buf = payload;
986 	req.emr_in_length = MC_CMD_GET_LICENSED_V3_APP_STATE_IN_LEN;
987 	req.emr_out_buf = payload;
988 	req.emr_out_length = MC_CMD_GET_LICENSED_V3_APP_STATE_OUT_LEN;
989 
990 	MCDI_IN_SET_DWORD(req, GET_LICENSED_V3_APP_STATE_IN_APP_ID_LO,
991 		    app_id & 0xffffffff);
992 	MCDI_IN_SET_DWORD(req, GET_LICENSED_V3_APP_STATE_IN_APP_ID_HI,
993 		    app_id >> 32);
994 
995 	efx_mcdi_execute(enp, &req);
996 
997 	if (req.emr_rc != 0) {
998 		rc = req.emr_rc;
999 		goto fail1;
1000 	}
1001 
1002 	if (req.emr_out_length_used < MC_CMD_GET_LICENSED_V3_APP_STATE_OUT_LEN) {
1003 		rc = EMSGSIZE;
1004 		goto fail2;
1005 	}
1006 
1007 	app_state = (MCDI_OUT_DWORD(req, GET_LICENSED_V3_APP_STATE_OUT_STATE));
1008 	if (app_state != MC_CMD_GET_LICENSED_V3_APP_STATE_OUT_NOT_LICENSED) {
1009 		*licensedp = B_TRUE;
1010 	} else {
1011 		*licensedp = B_FALSE;
1012 	}
1013 
1014 	return (0);
1015 
1016 fail2:
1017 	EFSYS_PROBE(fail2);
1018 fail1:
1019 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
1020 
1021 	return (rc);
1022 }
1023 
1024 static	__checkReturn	efx_rc_t
efx_mcdi_licensing_v3_get_id(__in efx_nic_t * enp,__in size_t buffer_size,__out uint32_t * typep,__out size_t * lengthp,__out_bcount_part_opt (buffer_size,* lengthp)uint8_t * bufferp)1025 efx_mcdi_licensing_v3_get_id(
1026 	__in		efx_nic_t *enp,
1027 	__in		size_t buffer_size,
1028 	__out		uint32_t *typep,
1029 	__out		size_t *lengthp,
1030 	__out_bcount_part_opt(buffer_size, *lengthp)
1031 			uint8_t *bufferp)
1032 {
1033 	efx_mcdi_req_t req;
1034 	uint8_t payload[MAX(MC_CMD_LICENSING_GET_ID_V3_IN_LEN,
1035 			    MC_CMD_LICENSING_GET_ID_V3_OUT_LENMIN)];
1036 	efx_rc_t rc;
1037 
1038 	req.emr_cmd = MC_CMD_LICENSING_GET_ID_V3;
1039 
1040 	if (bufferp == NULL) {
1041 		/* Request id type and length only */
1042 		req.emr_in_buf = bufferp;
1043 		req.emr_in_length = MC_CMD_LICENSING_GET_ID_V3_IN_LEN;
1044 		req.emr_out_buf = bufferp;
1045 		req.emr_out_length = MC_CMD_LICENSING_GET_ID_V3_OUT_LENMIN;
1046 		(void) memset(payload, 0, sizeof (payload));
1047 	} else {
1048 		/* Request full buffer */
1049 		req.emr_in_buf = bufferp;
1050 		req.emr_in_length = MC_CMD_LICENSING_GET_ID_V3_IN_LEN;
1051 		req.emr_out_buf = bufferp;
1052 		req.emr_out_length = MIN(buffer_size, MC_CMD_LICENSING_GET_ID_V3_OUT_LENMAX);
1053 		(void) memset(bufferp, 0, req.emr_out_length);
1054 	}
1055 
1056 	efx_mcdi_execute(enp, &req);
1057 
1058 	if (req.emr_rc != 0) {
1059 		rc = req.emr_rc;
1060 		goto fail1;
1061 	}
1062 
1063 	if (req.emr_out_length_used < MC_CMD_LICENSING_GET_ID_V3_OUT_LENMIN) {
1064 		rc = EMSGSIZE;
1065 		goto fail2;
1066 	}
1067 
1068 	*typep = MCDI_OUT_DWORD(req, LICENSING_GET_ID_V3_OUT_LICENSE_TYPE);
1069 	*lengthp = MCDI_OUT_DWORD(req, LICENSING_GET_ID_V3_OUT_LICENSE_ID_LENGTH);
1070 
1071 	if (bufferp == NULL) {
1072 		/* modify length requirements to indicate to caller the extra buffering
1073 		** needed to read the complete output.
1074 		*/
1075 		*lengthp += MC_CMD_LICENSING_GET_ID_V3_OUT_LENMIN;
1076 	} else {
1077 		/* Shift ID down to start of buffer */
1078 		memmove(bufferp,
1079 		  bufferp+MC_CMD_LICENSING_GET_ID_V3_OUT_LICENSE_ID_OFST,
1080 		  *lengthp);
1081 		(void) memset(bufferp+(*lengthp), 0,
1082 		    MC_CMD_LICENSING_GET_ID_V3_OUT_LICENSE_ID_OFST);
1083 	}
1084 
1085 	return (0);
1086 
1087 fail2:
1088 	EFSYS_PROBE(fail2);
1089 fail1:
1090 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
1091 
1092 	return (rc);
1093 }
1094 
1095 /* V3 format uses Huntington TLV format partition. See SF-108797-SW */
1096 #define EFX_LICENSE_V3_KEY_LENGTH_MIN    (64)
1097 #define EFX_LICENSE_V3_KEY_LENGTH_MAX    (128)
1098 #define EFX_LICENSE_V3_HASH_LENGTH       (64)
1099 
1100 	__checkReturn		efx_rc_t
efx_lic_v3_find_start(__in efx_nic_t * enp,__in_bcount (buffer_size)caddr_t bufferp,__in size_t buffer_size,__out uint32_t * startp)1101 efx_lic_v3_find_start(
1102 	__in			efx_nic_t *enp,
1103 	__in_bcount(buffer_size)
1104 				caddr_t bufferp,
1105 	__in			size_t buffer_size,
1106 	__out			uint32_t *startp
1107 	)
1108 {
1109 	_NOTE(ARGUNUSED(enp))
1110 
1111 	return ef10_nvram_buffer_find_item_start(bufferp, buffer_size, startp);
1112 }
1113 
1114 	__checkReturn		efx_rc_t
efx_lic_v3_find_end(__in efx_nic_t * enp,__in_bcount (buffer_size)caddr_t bufferp,__in size_t buffer_size,__in uint32_t offset,__out uint32_t * endp)1115 efx_lic_v3_find_end(
1116 	__in			efx_nic_t *enp,
1117 	__in_bcount(buffer_size)
1118 				caddr_t bufferp,
1119 	__in			size_t buffer_size,
1120 	__in			uint32_t offset,
1121 	__out			uint32_t *endp
1122 	)
1123 {
1124 	_NOTE(ARGUNUSED(enp))
1125 
1126 	return ef10_nvram_buffer_find_end(bufferp, buffer_size, offset, endp);
1127 }
1128 
1129 	__checkReturn	__success(return != B_FALSE)	boolean_t
efx_lic_v3_find_key(__in efx_nic_t * enp,__in_bcount (buffer_size)caddr_t bufferp,__in size_t buffer_size,__in uint32_t offset,__out uint32_t * startp,__out uint32_t * lengthp)1130 efx_lic_v3_find_key(
1131 	__in			efx_nic_t *enp,
1132 	__in_bcount(buffer_size)
1133 				caddr_t bufferp,
1134 	__in			size_t buffer_size,
1135 	__in			uint32_t offset,
1136 	__out			uint32_t *startp,
1137 	__out			uint32_t *lengthp
1138 	)
1139 {
1140 	_NOTE(ARGUNUSED(enp))
1141 
1142 	return ef10_nvram_buffer_find_item(bufferp, buffer_size,
1143 	    offset, startp, lengthp);
1144 }
1145 
1146 	__checkReturn	__success(return != B_FALSE)	boolean_t
efx_lic_v3_validate_key(__in efx_nic_t * enp,__in_bcount (length)caddr_t keyp,__in uint32_t length)1147 efx_lic_v3_validate_key(
1148 	__in			efx_nic_t *enp,
1149 	__in_bcount(length)	caddr_t keyp,
1150 	__in			uint32_t length
1151 	)
1152 {
1153 	// Check key is a valid V3 key
1154 	efx_rc_t rc;
1155 	uint8_t key_type;
1156 	uint8_t key_length;
1157 
1158 	_NOTE(ARGUNUSED(enp))
1159 
1160 	if (length < EFX_LICENSE_V3_KEY_LENGTH_MIN) {
1161 		goto fail1;
1162 	}
1163 
1164 	key_type = ((uint8_t*)keyp)[0];
1165 	key_length = ((uint8_t*)keyp)[1] + EFX_LICENSE_V3_HASH_LENGTH;
1166 
1167 	if(key_length > EFX_LICENSE_V3_KEY_LENGTH_MAX) {
1168 		goto fail2;
1169 	}
1170 	if (key_type < 3) {
1171 		goto fail3;
1172 	}
1173 	if (key_length != length) {
1174 		goto fail4;
1175 	}
1176 	return (B_TRUE);
1177 
1178 fail4:
1179 	EFSYS_PROBE(fail4);
1180 fail3:
1181 	EFSYS_PROBE(fail3);
1182 fail2:
1183 	EFSYS_PROBE(fail2);
1184 fail1:
1185 	EFSYS_PROBE(fail1);
1186 
1187 	return (B_FALSE);
1188 }
1189 
1190 	__checkReturn		efx_rc_t
efx_lic_v3_read_key(__in efx_nic_t * enp,__in_bcount (buffer_size)caddr_t bufferp,__in size_t buffer_size,__in uint32_t offset,__in uint32_t length,__out_bcount_part (key_max_size,* lengthp)caddr_t keyp,__in size_t key_max_size,__out uint32_t * lengthp)1191 efx_lic_v3_read_key(
1192 	__in			efx_nic_t *enp,
1193 	__in_bcount(buffer_size)
1194 				caddr_t bufferp,
1195 	__in			size_t buffer_size,
1196 	__in			uint32_t offset,
1197 	__in			uint32_t length,
1198 	__out_bcount_part(key_max_size, *lengthp)
1199 				caddr_t keyp,
1200 	__in			size_t key_max_size,
1201 	__out			uint32_t *lengthp
1202 	)
1203 {
1204 	_NOTE(ARGUNUSED(enp))
1205 
1206 	return ef10_nvram_buffer_get_item(bufferp, buffer_size,
1207 		    offset, length, keyp, key_max_size, lengthp);
1208 }
1209 
1210 	__checkReturn		efx_rc_t
efx_lic_v3_write_key(__in efx_nic_t * enp,__in_bcount (buffer_size)caddr_t bufferp,__in size_t buffer_size,__in uint32_t offset,__in_bcount (length)caddr_t keyp,__in uint32_t length,__out uint32_t * lengthp)1211 efx_lic_v3_write_key(
1212 	__in			efx_nic_t *enp,
1213 	__in_bcount(buffer_size)
1214 				caddr_t bufferp,
1215 	__in			size_t buffer_size,
1216 	__in			uint32_t offset,
1217 	__in_bcount(length)	caddr_t keyp,
1218 	__in			uint32_t length,
1219 	__out			uint32_t *lengthp
1220 	)
1221 {
1222 	_NOTE(ARGUNUSED(enp))
1223 	EFSYS_ASSERT(length <= EFX_LICENSE_V3_KEY_LENGTH_MAX);
1224 
1225 	return ef10_nvram_buffer_insert_item(bufferp, buffer_size,
1226 		    offset, keyp, length, lengthp);
1227 }
1228 
1229 	__checkReturn		efx_rc_t
efx_lic_v3_delete_key(__in efx_nic_t * enp,__in_bcount (buffer_size)caddr_t bufferp,__in size_t buffer_size,__in uint32_t offset,__in uint32_t length,__in uint32_t end,__out uint32_t * deltap)1230 efx_lic_v3_delete_key(
1231 	__in			efx_nic_t *enp,
1232 	__in_bcount(buffer_size)
1233 				caddr_t bufferp,
1234 	__in			size_t buffer_size,
1235 	__in			uint32_t offset,
1236 	__in			uint32_t length,
1237 	__in			uint32_t end,
1238 	__out			uint32_t *deltap
1239 	)
1240 {
1241 	efx_rc_t rc;
1242 
1243 	_NOTE(ARGUNUSED(enp))
1244 
1245 	if ((rc = ef10_nvram_buffer_delete_item(bufferp,
1246 			buffer_size, offset, length, end)) != 0) {
1247 		goto fail1;
1248 	}
1249 
1250 	*deltap = length;
1251 
1252 	return (0);
1253 
1254 fail1:
1255 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
1256 
1257 	return (rc);
1258 }
1259 
1260 	__checkReturn		efx_rc_t
efx_lic_v3_create_partition(__in efx_nic_t * enp,__in_bcount (buffer_size)caddr_t bufferp,__in size_t buffer_size)1261 efx_lic_v3_create_partition(
1262 	__in			efx_nic_t *enp,
1263 	__in_bcount(buffer_size)
1264 				caddr_t bufferp,
1265 	__in			size_t buffer_size
1266 	)
1267 {
1268 	efx_rc_t rc;
1269 
1270 	// Construct empty partition
1271 	if ((rc = ef10_nvram_buffer_create(enp,
1272 	    NVRAM_PARTITION_TYPE_LICENSE,
1273 	    bufferp, buffer_size)) != 0) {
1274 		rc = EFAULT;
1275 		goto fail1;
1276 	}
1277 
1278 	return (0);
1279 
1280 fail1:
1281 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
1282 
1283 	return (rc);
1284 }
1285 
1286 	__checkReturn		efx_rc_t
efx_lic_v3_finish_partition(__in efx_nic_t * enp,__in_bcount (buffer_size)caddr_t bufferp,__in size_t buffer_size)1287 efx_lic_v3_finish_partition(
1288 	__in			efx_nic_t *enp,
1289 	__in_bcount(buffer_size)
1290 				caddr_t bufferp,
1291 	__in			size_t buffer_size
1292 	)
1293 {
1294 	efx_rc_t rc;
1295 
1296 	if ((rc = ef10_nvram_buffer_finish(bufferp,
1297 			buffer_size)) != 0) {
1298 		goto fail1;
1299 	}
1300 
1301 	// Validate completed partition
1302 	if ((rc = ef10_nvram_buffer_validate(enp, NVRAM_PARTITION_TYPE_LICENSE,
1303 					bufferp, buffer_size)) != 0) {
1304 		goto fail2;
1305 	}
1306 
1307 	return (0);
1308 
1309 fail2:
1310 	EFSYS_PROBE(fail2);
1311 fail1:
1312 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
1313 
1314 	return (rc);
1315 }
1316 
1317 
1318 #endif	/* EFSYS_OPT_MEDFORD */
1319 
1320 	__checkReturn		efx_rc_t
efx_lic_init(__in efx_nic_t * enp)1321 efx_lic_init(
1322 	__in			efx_nic_t *enp)
1323 {
1324 	const efx_lic_ops_t *elop;
1325 	efx_rc_t rc;
1326 
1327 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1328 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
1329 	EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_LIC));
1330 
1331 	switch (enp->en_family) {
1332 
1333 #if EFSYS_OPT_SIENA
1334 	case EFX_FAMILY_SIENA:
1335 		elop = &__efx_lic_v1_ops;
1336 		break;
1337 #endif	/* EFSYS_OPT_SIENA */
1338 
1339 #if EFSYS_OPT_HUNTINGTON
1340 	case EFX_FAMILY_HUNTINGTON:
1341 		elop = &__efx_lic_v2_ops;
1342 		break;
1343 #endif	/* EFSYS_OPT_HUNTINGTON */
1344 
1345 #if EFSYS_OPT_MEDFORD
1346 	case EFX_FAMILY_MEDFORD:
1347 		elop = &__efx_lic_v3_ops;
1348 		break;
1349 #endif	/* EFSYS_OPT_MEDFORD */
1350 
1351 	default:
1352 		EFSYS_ASSERT(0);
1353 		rc = ENOTSUP;
1354 		goto fail1;
1355 	}
1356 
1357 	enp->en_elop = elop;
1358 	enp->en_mod_flags |= EFX_MOD_LIC;
1359 
1360 	return (0);
1361 
1362 fail1:
1363 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
1364 
1365 	return (rc);
1366 }
1367 
1368 				void
efx_lic_fini(__in efx_nic_t * enp)1369 efx_lic_fini(
1370 	__in			efx_nic_t *enp)
1371 {
1372 	const efx_lic_ops_t *elop = enp->en_elop;
1373 
1374 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1375 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
1376 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1377 
1378 	enp->en_elop = NULL;
1379 	enp->en_mod_flags &= ~EFX_MOD_LIC;
1380 }
1381 
1382 
1383 	__checkReturn	efx_rc_t
efx_lic_update_licenses(__in efx_nic_t * enp)1384 efx_lic_update_licenses(
1385 	__in		efx_nic_t *enp)
1386 {
1387 	const efx_lic_ops_t *elop = enp->en_elop;
1388 	efx_rc_t rc;
1389 
1390 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1391 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1392 
1393 	if ((rc = elop->elo_update_licenses(enp)) != 0)
1394 		goto fail1;
1395 
1396 	return (0);
1397 
1398 fail1:
1399 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
1400 
1401 	return (rc);
1402 }
1403 
1404 	__checkReturn	efx_rc_t
efx_lic_get_key_stats(__in efx_nic_t * enp,__out efx_key_stats_t * eksp)1405 efx_lic_get_key_stats(
1406 	__in		efx_nic_t *enp,
1407 	__out		efx_key_stats_t *eksp)
1408 {
1409 	const efx_lic_ops_t *elop = enp->en_elop;
1410 	efx_rc_t rc;
1411 
1412 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1413 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1414 
1415 	if ((rc = elop->elo_get_key_stats(enp, eksp)) != 0)
1416 		goto fail1;
1417 
1418 	return (0);
1419 
1420 fail1:
1421 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
1422 
1423 	return (rc);
1424 }
1425 
1426 	__checkReturn	efx_rc_t
efx_lic_app_state(__in efx_nic_t * enp,__in uint64_t app_id,__out boolean_t * licensedp)1427 efx_lic_app_state(
1428 	__in		efx_nic_t *enp,
1429 	__in		uint64_t app_id,
1430 	__out		boolean_t *licensedp)
1431 {
1432 	const efx_lic_ops_t *elop = enp->en_elop;
1433 	efx_rc_t rc;
1434 
1435 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1436 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1437 
1438 	if (elop->elo_app_state == NULL) {
1439 		rc = ENOTSUP;
1440 		goto fail1;
1441 	}
1442 	if ((rc = elop->elo_app_state(enp, app_id, licensedp)) != 0)
1443 		goto fail2;
1444 
1445 	return (0);
1446 
1447 fail2:
1448 	EFSYS_PROBE(fail2);
1449 fail1:
1450 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
1451 
1452 	return (rc);
1453 }
1454 
1455 	__checkReturn	efx_rc_t
efx_lic_get_id(__in efx_nic_t * enp,__in size_t buffer_size,__out uint32_t * typep,__out size_t * lengthp,__out_opt uint8_t * bufferp)1456 efx_lic_get_id(
1457 	__in		efx_nic_t *enp,
1458 	__in		size_t buffer_size,
1459 	__out		uint32_t *typep,
1460 	__out		size_t *lengthp,
1461 	__out_opt	uint8_t *bufferp
1462 	)
1463 {
1464 	const efx_lic_ops_t *elop = enp->en_elop;
1465 	efx_rc_t rc;
1466 
1467 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1468 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1469 
1470 	if (elop->elo_get_id == NULL) {
1471 		rc = ENOTSUP;
1472 		goto fail1;
1473 	}
1474 
1475 	if ((rc = elop->elo_get_id(enp, buffer_size, typep,
1476 				    lengthp, bufferp)) != 0)
1477 		goto fail2;
1478 
1479 	return (0);
1480 
1481 fail2:
1482 	EFSYS_PROBE(fail2);
1483 fail1:
1484 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
1485 
1486 	return (rc);
1487 }
1488 
1489 /* Buffer management API - abstracts varying TLV format used for License partition */
1490 
1491 	__checkReturn		efx_rc_t
efx_lic_find_start(__in efx_nic_t * enp,__in_bcount (buffer_size)caddr_t bufferp,__in size_t buffer_size,__out uint32_t * startp)1492 efx_lic_find_start(
1493 	__in			efx_nic_t *enp,
1494 	__in_bcount(buffer_size)
1495 				caddr_t bufferp,
1496 	__in			size_t buffer_size,
1497 	__out			uint32_t *startp
1498 	)
1499 {
1500 	const efx_lic_ops_t *elop = enp->en_elop;
1501 	efx_rc_t rc;
1502 
1503 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1504 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1505 
1506 	if ((rc = elop->elo_find_start(enp, bufferp, buffer_size, startp)) != 0)
1507 		goto fail1;
1508 
1509 	return (0);
1510 
1511 fail1:
1512 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
1513 
1514 	return (rc);
1515 }
1516 
1517 	__checkReturn		efx_rc_t
efx_lic_find_end(__in efx_nic_t * enp,__in_bcount (buffer_size)caddr_t bufferp,__in size_t buffer_size,__in uint32_t offset,__out uint32_t * endp)1518 efx_lic_find_end(
1519 	__in			efx_nic_t *enp,
1520 	__in_bcount(buffer_size)
1521 				caddr_t bufferp,
1522 	__in			size_t buffer_size,
1523 	__in			uint32_t offset,
1524 	__out			uint32_t *endp
1525 	)
1526 {
1527 	const efx_lic_ops_t *elop = enp->en_elop;
1528 	efx_rc_t rc;
1529 
1530 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1531 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1532 
1533 	if ((rc = elop->elo_find_end(enp, bufferp, buffer_size, offset, endp)) != 0)
1534 		goto fail1;
1535 
1536 	return (0);
1537 
1538 fail1:
1539 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
1540 
1541 	return (rc);
1542 }
1543 
1544 	__checkReturn	__success(return != B_FALSE)	boolean_t
efx_lic_find_key(__in efx_nic_t * enp,__in_bcount (buffer_size)caddr_t bufferp,__in size_t buffer_size,__in uint32_t offset,__out uint32_t * startp,__out uint32_t * lengthp)1545 efx_lic_find_key(
1546 	__in			efx_nic_t *enp,
1547 	__in_bcount(buffer_size)
1548 				caddr_t bufferp,
1549 	__in			size_t buffer_size,
1550 	__in			uint32_t offset,
1551 	__out			uint32_t *startp,
1552 	__out			uint32_t *lengthp
1553 	)
1554 {
1555 	const efx_lic_ops_t *elop = enp->en_elop;
1556 	boolean_t rc;
1557 
1558 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1559 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1560 
1561 	EFSYS_ASSERT(bufferp);
1562 	EFSYS_ASSERT(startp);
1563 	EFSYS_ASSERT(lengthp);
1564 
1565 	return (elop->elo_find_key(enp, bufferp, buffer_size, offset,
1566 				    startp, lengthp));
1567 }
1568 
1569 
1570 /* Validate that the buffer contains a single key in a recognised format.
1571 ** An empty or terminator buffer is not accepted as a valid key.
1572 */
1573 	__checkReturn	__success(return != B_FALSE)	boolean_t
efx_lic_validate_key(__in efx_nic_t * enp,__in_bcount (length)caddr_t keyp,__in uint32_t length)1574 efx_lic_validate_key(
1575 	__in			efx_nic_t *enp,
1576 	__in_bcount(length)	caddr_t keyp,
1577 	__in			uint32_t length
1578 	)
1579 {
1580 	const efx_lic_ops_t *elop = enp->en_elop;
1581 	boolean_t rc;
1582 	uint16_t tlv_type;
1583 	uint16_t tlv_length;
1584 
1585 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1586 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1587 
1588 	if ((rc = elop->elo_validate_key(enp, keyp, length)) == B_FALSE)
1589 		goto fail1;
1590 
1591 	return (B_TRUE);
1592 
1593 fail1:
1594 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
1595 
1596 	return (rc);
1597 }
1598 
1599 	__checkReturn		efx_rc_t
efx_lic_read_key(__in efx_nic_t * enp,__in_bcount (buffer_size)caddr_t bufferp,__in size_t buffer_size,__in uint32_t offset,__in uint32_t length,__out_bcount_part (key_max_size,* lengthp)caddr_t keyp,__in size_t key_max_size,__out uint32_t * lengthp)1600 efx_lic_read_key(
1601 	__in			efx_nic_t *enp,
1602 	__in_bcount(buffer_size)
1603 				caddr_t bufferp,
1604 	__in			size_t buffer_size,
1605 	__in			uint32_t offset,
1606 	__in			uint32_t length,
1607 	__out_bcount_part(key_max_size, *lengthp)
1608 				caddr_t keyp,
1609 	__in			size_t key_max_size,
1610 	__out			uint32_t *lengthp
1611 	)
1612 {
1613 	const efx_lic_ops_t *elop = enp->en_elop;
1614 	efx_rc_t rc;
1615 
1616 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1617 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1618 
1619 	if ((rc = elop->elo_read_key(enp, bufferp, buffer_size, offset,
1620 				    length, keyp, key_max_size, lengthp)) != 0)
1621 		goto fail1;
1622 
1623 	return (0);
1624 
1625 fail1:
1626 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
1627 
1628 	return (rc);
1629 }
1630 
1631 	__checkReturn		efx_rc_t
efx_lic_write_key(__in efx_nic_t * enp,__in_bcount (buffer_size)caddr_t bufferp,__in size_t buffer_size,__in uint32_t offset,__in_bcount (length)caddr_t keyp,__in uint32_t length,__out uint32_t * lengthp)1632 efx_lic_write_key(
1633 	__in			efx_nic_t *enp,
1634 	__in_bcount(buffer_size)
1635 				caddr_t bufferp,
1636 	__in			size_t buffer_size,
1637 	__in			uint32_t offset,
1638 	__in_bcount(length)	caddr_t keyp,
1639 	__in			uint32_t length,
1640 	__out			uint32_t *lengthp
1641 	)
1642 {
1643 	const efx_lic_ops_t *elop = enp->en_elop;
1644 	efx_rc_t rc;
1645 
1646 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1647 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1648 
1649 	if ((rc = elop->elo_write_key(enp, bufferp, buffer_size, offset,
1650 				    keyp, length, lengthp)) != 0)
1651 		goto fail1;
1652 
1653 	return (0);
1654 
1655 fail1:
1656 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
1657 
1658 	return (rc);
1659 }
1660 
1661 	__checkReturn		efx_rc_t
efx_lic_delete_key(__in efx_nic_t * enp,__in_bcount (buffer_size)caddr_t bufferp,__in size_t buffer_size,__in uint32_t offset,__in uint32_t length,__in uint32_t end,__out uint32_t * deltap)1662 efx_lic_delete_key(
1663 	__in			efx_nic_t *enp,
1664 	__in_bcount(buffer_size)
1665 				caddr_t bufferp,
1666 	__in			size_t buffer_size,
1667 	__in			uint32_t offset,
1668 	__in			uint32_t length,
1669 	__in			uint32_t end,
1670 	__out			uint32_t *deltap
1671 	)
1672 {
1673 	const efx_lic_ops_t *elop = enp->en_elop;
1674 	efx_rc_t rc;
1675 
1676 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1677 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1678 
1679 	if ((rc = elop->elo_delete_key(enp, bufferp, buffer_size, offset,
1680 				    length, end, deltap)) != 0)
1681 		goto fail1;
1682 
1683 	return (0);
1684 
1685 fail1:
1686 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
1687 
1688 	return (rc);
1689 }
1690 
1691 	__checkReturn		efx_rc_t
efx_lic_create_partition(__in efx_nic_t * enp,__in_bcount (buffer_size)caddr_t bufferp,__in size_t buffer_size)1692 efx_lic_create_partition(
1693 	__in			efx_nic_t *enp,
1694 	__in_bcount(buffer_size)
1695 				caddr_t bufferp,
1696 	__in			size_t buffer_size
1697 	)
1698 {
1699 	const efx_lic_ops_t *elop = enp->en_elop;
1700 	efx_rc_t rc;
1701 
1702 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1703 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1704 
1705 	if ((rc = elop->elo_create_partition(enp, bufferp, buffer_size)) != 0)
1706 		goto fail1;
1707 
1708 	return (0);
1709 
1710 fail1:
1711 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
1712 
1713 	return (rc);
1714 }
1715 
1716 
1717 	__checkReturn		efx_rc_t
efx_lic_finish_partition(__in efx_nic_t * enp,__in_bcount (buffer_size)caddr_t bufferp,__in size_t buffer_size)1718 efx_lic_finish_partition(
1719 	__in			efx_nic_t *enp,
1720 	__in_bcount(buffer_size)
1721 				caddr_t bufferp,
1722 	__in			size_t buffer_size
1723 	)
1724 {
1725 	const efx_lic_ops_t *elop = enp->en_elop;
1726 	efx_rc_t rc;
1727 
1728 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1729 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1730 
1731 	if ((rc = elop->elo_finish_partition(enp, bufferp, buffer_size)) != 0)
1732 		goto fail1;
1733 
1734 	return (0);
1735 
1736 fail1:
1737 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
1738 
1739 	return (rc);
1740 }
1741 
1742 #endif	/* EFSYS_OPT_LICENSING */
1743