dpdk/drivers/common/sfc_efx/base/efx_lic.c
<<
>>
Prefs
   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
  20efx_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
  28efx_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
  37efx_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
  47efx_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
  53efx_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
  66efx_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
  77efx_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
  88efx_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
  95efx_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
 106static  __checkReturn   efx_rc_t
 107efx_mcdi_fc_license_update_license(
 108        __in            efx_nic_t *enp);
 109
 110static  __checkReturn   efx_rc_t
 111efx_mcdi_fc_license_get_key_stats(
 112        __in            efx_nic_t *enp,
 113        __out           efx_key_stats_t *eksp);
 114
 115static 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
 135static  __checkReturn   efx_rc_t
 136efx_mcdi_licensing_update_licenses(
 137        __in            efx_nic_t *enp);
 138
 139static  __checkReturn   efx_rc_t
 140efx_mcdi_licensing_get_key_stats(
 141        __in            efx_nic_t *enp,
 142        __out           efx_key_stats_t *eksp);
 143
 144static  __checkReturn   efx_rc_t
 145efx_mcdi_licensed_app_state(
 146        __in            efx_nic_t *enp,
 147        __in            uint64_t app_id,
 148        __out           boolean_t *licensedp);
 149
 150static 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
 170static  __checkReturn   efx_rc_t
 171efx_mcdi_licensing_v3_update_licenses(
 172        __in            efx_nic_t *enp);
 173
 174static  __checkReturn   efx_rc_t
 175efx_mcdi_licensing_v3_report_license(
 176        __in            efx_nic_t *enp,
 177        __out           efx_key_stats_t *eksp);
 178
 179static  __checkReturn   efx_rc_t
 180efx_mcdi_licensing_v3_app_state(
 181        __in            efx_nic_t *enp,
 182        __in            uint64_t app_id,
 183        __out           boolean_t *licensedp);
 184
 185static  __checkReturn   efx_rc_t
 186efx_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
 195efx_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
 203efx_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
 212efx_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
 222efx_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
 228efx_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
 241efx_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
 252efx_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
 263efx_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
 270efx_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
 276static 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
 299static  __checkReturn   efx_rc_t
 300efx_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
 335fail2:
 336        EFSYS_PROBE(fail2);
 337fail1:
 338        EFSYS_PROBE1(fail1, efx_rc_t, rc);
 339
 340        return (rc);
 341}
 342
 343static  __checkReturn   efx_rc_t
 344efx_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
 394fail2:
 395        EFSYS_PROBE(fail2);
 396fail1:
 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
 418efx_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
 432efx_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
 447efx_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
 477fail1:
 478        EFSYS_PROBE1(fail1, boolean_t, B_FALSE);
 479
 480        return (B_FALSE);
 481}
 482
 483        __checkReturn   __success(return != B_FALSE)    boolean_t
 484efx_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
 513fail4:
 514        EFSYS_PROBE(fail4);
 515fail3:
 516        EFSYS_PROBE(fail3);
 517fail2:
 518        EFSYS_PROBE(fail2);
 519fail1:
 520        EFSYS_PROBE1(fail1, boolean_t, B_FALSE);
 521
 522        return (B_FALSE);
 523}
 524
 525
 526        __checkReturn           efx_rc_t
 527efx_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
 555fail1:
 556        EFSYS_PROBE1(fail1, efx_rc_t, rc);
 557
 558        return (rc);
 559}
 560
 561        __checkReturn           efx_rc_t
 562efx_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
 591fail1:
 592        EFSYS_PROBE1(fail1, efx_rc_t, rc);
 593
 594        return (rc);
 595}
 596
 597        __checkReturn           efx_rc_t
 598efx_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
 623efx_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
 639efx_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
 657static  __checkReturn   efx_rc_t
 658efx_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
 707fail3:
 708        EFSYS_PROBE(fail3);
 709fail2:
 710        EFSYS_PROBE(fail2);
 711fail1:
 712        EFSYS_PROBE1(fail1, efx_rc_t, rc);
 713
 714        return (rc);
 715}
 716
 717static  __checkReturn   efx_rc_t
 718efx_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
 750fail2:
 751        EFSYS_PROBE(fail2);
 752fail1:
 753        EFSYS_PROBE1(fail1, efx_rc_t, rc);
 754
 755        return (rc);
 756}
 757
 758static  __checkReturn   efx_rc_t
 759efx_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
 808fail2:
 809        EFSYS_PROBE(fail2);
 810fail1:
 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
 822static  __checkReturn   efx_rc_t
 823efx_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
 851fail1:
 852        EFSYS_PROBE1(fail1, efx_rc_t, rc);
 853
 854        return (rc);
 855}
 856
 857static  __checkReturn   efx_rc_t
 858efx_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
 911fail2:
 912        EFSYS_PROBE(fail2);
 913fail1:
 914        EFSYS_PROBE1(fail1, efx_rc_t, rc);
 915
 916        return (rc);
 917}
 918
 919static  __checkReturn   efx_rc_t
 920efx_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
 967fail2:
 968        EFSYS_PROBE(fail2);
 969fail1:
 970        EFSYS_PROBE1(fail1, efx_rc_t, rc);
 971
 972        return (rc);
 973}
 974
 975static  __checkReturn   efx_rc_t
 976efx_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
1019fail2:
1020        EFSYS_PROBE(fail2);
1021fail1:
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
1032efx_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
1046efx_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
1060efx_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
1076efx_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
1106fail4:
1107        EFSYS_PROBE(fail4);
1108fail3:
1109        EFSYS_PROBE(fail3);
1110fail2:
1111        EFSYS_PROBE(fail2);
1112fail1:
1113        EFSYS_PROBE1(fail1, boolean_t, B_FALSE);
1114
1115        return (B_FALSE);
1116}
1117
1118        __checkReturn           efx_rc_t
1119efx_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
1140efx_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
1158efx_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
1181fail1:
1182        EFSYS_PROBE1(fail1, efx_rc_t, rc);
1183
1184        return (rc);
1185}
1186
1187        __checkReturn           efx_rc_t
1188efx_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
1208fail1:
1209        EFSYS_PROBE1(fail1, efx_rc_t, rc);
1210
1211        return (rc);
1212}
1213
1214        __checkReturn           efx_rc_t
1215efx_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
1239fail2:
1240        EFSYS_PROBE(fail2);
1241fail1:
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
1251efx_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
1306fail1:
1307        EFSYS_PROBE1(fail1, efx_rc_t, rc);
1308
1309        return (rc);
1310}
1311
1312extern  __checkReturn   boolean_t
1313efx_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
1324efx_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
1337efx_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
1351fail1:
1352        EFSYS_PROBE1(fail1, efx_rc_t, rc);
1353
1354        return (rc);
1355}
1356
1357        __checkReturn   efx_rc_t
1358efx_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
1373fail1:
1374        EFSYS_PROBE1(fail1, efx_rc_t, rc);
1375
1376        return (rc);
1377}
1378
1379        __checkReturn   efx_rc_t
1380efx_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
1399fail1:
1400        EFSYS_PROBE1(fail1, efx_rc_t, rc);
1401
1402        return (rc);
1403}
1404
1405        __checkReturn   efx_rc_t
1406efx_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
1428fail1:
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
1440efx_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
1458fail1:
1459        EFSYS_PROBE1(fail1, efx_rc_t, rc);
1460
1461        return (rc);
1462}
1463
1464        __checkReturn           efx_rc_t
1465efx_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
1485fail1:
1486        EFSYS_PROBE1(fail1, efx_rc_t, rc);
1487
1488        return (rc);
1489}
1490
1491        __checkReturn   __success(return != B_FALSE)    boolean_t
1492efx_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
1520efx_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
1536fail1:
1537        EFSYS_PROBE1(fail1, efx_rc_t, rc);
1538
1539        return (rc);
1540}
1541
1542        __checkReturn           efx_rc_t
1543efx_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
1567fail1:
1568        EFSYS_PROBE1(fail1, efx_rc_t, rc);
1569
1570        return (rc);
1571}
1572
1573        __checkReturn           efx_rc_t
1574efx_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
1596fail1:
1597        EFSYS_PROBE1(fail1, efx_rc_t, rc);
1598
1599        return (rc);
1600}
1601
1602        __checkReturn           efx_rc_t
1603efx_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
1625fail1:
1626        EFSYS_PROBE1(fail1, efx_rc_t, rc);
1627
1628        return (rc);
1629}
1630
1631        __checkReturn           efx_rc_t
1632efx_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
1649fail1:
1650        EFSYS_PROBE1(fail1, efx_rc_t, rc);
1651
1652        return (rc);
1653}
1654
1655
1656        __checkReturn           efx_rc_t
1657efx_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
1674fail1:
1675        EFSYS_PROBE1(fail1, efx_rc_t, rc);
1676
1677        return (rc);
1678}
1679
1680#endif  /* EFSYS_OPT_LICENSING */
1681