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