871 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * sdsi: Intel On Demand (formerly Software Defined Silicon) tool for4 * provisioning certificates and activation payloads on supported cpus.5 *6 * See https://github.com/intel/intel-sdsi/blob/master/os-interface.rst7 * for register descriptions.8 *9 * Copyright (C) 2022 Intel Corporation. All rights reserved.10 */11 12#include <dirent.h>13#include <errno.h>14#include <fcntl.h>15#include <getopt.h>16#include <stdbool.h>17#include <stdio.h>18#include <stdint.h>19#include <stdlib.h>20#include <string.h>21#include <unistd.h>22 23#include <sys/types.h>24 25#ifndef __packed26#define __packed __attribute__((packed))27#endif28 29#define min(x, y) ({ \30 typeof(x) _min1 = (x); \31 typeof(y) _min2 = (y); \32 (void) (&_min1 == &_min2); \33 _min1 < _min2 ? _min1 : _min2; })34 35#define SDSI_DEV "intel_vsec.sdsi"36#define AUX_DEV_PATH "/sys/bus/auxiliary/devices/"37#define SDSI_PATH (AUX_DEV_DIR SDSI_DEV)38#define GUID_V1 0x6dd19139#define REGS_SIZE_GUID_V1 7240#define GUID_V2 0xF210D9EF41#define REGS_SIZE_GUID_V2 8042#define STATE_CERT_MAX_SIZE 409643#define METER_CERT_MAX_SIZE 409644#define STATE_MAX_NUM_LICENSES 1645#define STATE_MAX_NUM_IN_BUNDLE (uint32_t)846#define FEAT_LEN 5 /* 4 plus NUL terminator */47 48#define __round_mask(x, y) ((__typeof__(x))((y) - 1))49#define round_up(x, y) ((((x) - 1) | __round_mask(x, y)) + 1)50 51struct nvram_content_auth_err_sts {52 uint64_t reserved:3;53 uint64_t sdsi_content_auth_err:1;54 uint64_t reserved1:1;55 uint64_t sdsi_metering_auth_err:1;56 uint64_t reserved2:58;57};58 59struct enabled_features {60 uint64_t reserved:3;61 uint64_t sdsi:1;62 uint64_t reserved1:8;63 uint64_t attestation:1;64 uint64_t reserved2:13;65 uint64_t metering:1;66 uint64_t reserved3:37;67};68 69struct key_provision_status {70 uint64_t reserved:1;71 uint64_t license_key_provisioned:1;72 uint64_t reserved2:62;73};74 75struct auth_fail_count {76 uint64_t key_failure_count:3;77 uint64_t key_failure_threshold:3;78 uint64_t auth_failure_count:3;79 uint64_t auth_failure_threshold:3;80 uint64_t reserved:52;81};82 83struct availability {84 uint64_t reserved:48;85 uint64_t available:3;86 uint64_t threshold:3;87 uint64_t reserved2:10;88};89 90struct nvram_update_limit {91 uint64_t reserved:12;92 uint64_t sdsi_50_pct:1;93 uint64_t sdsi_75_pct:1;94 uint64_t sdsi_90_pct:1;95 uint64_t reserved2:49;96};97 98struct sdsi_regs {99 uint64_t ppin;100 struct nvram_content_auth_err_sts auth_err_sts;101 struct enabled_features en_features;102 struct key_provision_status key_prov_sts;103 struct auth_fail_count auth_fail_count;104 struct availability prov_avail;105 struct nvram_update_limit limits;106 uint64_t pcu_cr3_capid_cfg;107 union {108 struct {109 uint64_t socket_id;110 } v1;111 struct {112 uint64_t reserved;113 uint64_t socket_id;114 uint64_t reserved2;115 } v2;116 } extra;117};118#define CONTENT_TYPE_LK_ENC 0xD119#define CONTENT_TYPE_LK_BLOB_ENC 0xE120 121struct state_certificate {122 uint32_t content_type;123 uint32_t region_rev_id;124 uint32_t header_size;125 uint32_t total_size;126 uint32_t key_size;127 uint32_t num_licenses;128};129 130struct license_key_info {131 uint32_t key_rev_id;132 uint64_t key_image_content[6];133} __packed;134 135#define LICENSE_BLOB_SIZE(l) (((l) & 0x7fffffff) * 4)136#define LICENSE_VALID(l) (!!((l) & 0x80000000))137 138// License Group Types139#define LBT_ONE_TIME_UPGRADE 1140#define LBT_METERED_UPGRADE 2141 142struct license_blob_content {143 uint32_t type;144 uint64_t id;145 uint64_t ppin;146 uint64_t previous_ppin;147 uint32_t rev_id;148 uint32_t num_bundles;149} __packed;150 151struct bundle_encoding {152 uint32_t encoding;153 uint32_t encoding_rsvd[7];154};155 156struct meter_certificate {157 uint32_t signature;158 uint32_t version;159 uint64_t ppin;160 uint32_t counter_unit;161 uint32_t bundle_length;162 uint64_t reserved;163 uint32_t mmrc_encoding;164 uint32_t mmrc_counter;165};166 167struct bundle_encoding_counter {168 uint32_t encoding;169 uint32_t counter;170};171#define METER_BUNDLE_SIZE sizeof(struct bundle_encoding_counter)172#define BUNDLE_COUNT(length) ((length) / METER_BUNDLE_SIZE)173#define METER_MAX_NUM_BUNDLES \174 ((METER_CERT_MAX_SIZE - sizeof(struct meter_certificate)) / \175 sizeof(struct bundle_encoding_counter))176 177struct sdsi_dev {178 struct sdsi_regs regs;179 struct state_certificate sc;180 char *dev_name;181 char *dev_path;182 uint32_t guid;183};184 185enum command {186 CMD_SOCKET_INFO,187 CMD_METER_CERT,188 CMD_METER_CURRENT_CERT,189 CMD_STATE_CERT,190 CMD_PROV_AKC,191 CMD_PROV_CAP,192};193 194static void sdsi_list_devices(void)195{196 struct dirent *entry;197 DIR *aux_dir;198 bool found = false;199 200 aux_dir = opendir(AUX_DEV_PATH);201 if (!aux_dir) {202 fprintf(stderr, "Cannot open directory %s\n", AUX_DEV_PATH);203 return;204 }205 206 while ((entry = readdir(aux_dir))) {207 if (!strncmp(SDSI_DEV, entry->d_name, strlen(SDSI_DEV))) {208 found = true;209 printf("%s\n", entry->d_name);210 }211 }212 213 if (!found)214 fprintf(stderr, "No On Demand devices found.\n");215}216 217static int sdsi_update_registers(struct sdsi_dev *s)218{219 FILE *regs_ptr;220 int ret;221 222 memset(&s->regs, 0, sizeof(s->regs));223 224 /* Open the registers file */225 ret = chdir(s->dev_path);226 if (ret == -1) {227 perror("chdir");228 return ret;229 }230 231 regs_ptr = fopen("registers", "r");232 if (!regs_ptr) {233 perror("Could not open 'registers' file");234 return -1;235 }236 237 if (s->guid != GUID_V1 && s->guid != GUID_V2) {238 fprintf(stderr, "Unrecognized guid, 0x%x\n", s->guid);239 fclose(regs_ptr);240 return -1;241 }242 243 /* Update register info for this guid */244 ret = fread(&s->regs, sizeof(uint8_t), sizeof(s->regs), regs_ptr);245 if ((s->guid == GUID_V1 && ret != REGS_SIZE_GUID_V1) ||246 (s->guid == GUID_V2 && ret != REGS_SIZE_GUID_V2)) {247 fprintf(stderr, "Could not read 'registers' file\n");248 fclose(regs_ptr);249 return -1;250 }251 252 fclose(regs_ptr);253 254 return 0;255}256 257static int sdsi_read_reg(struct sdsi_dev *s)258{259 int ret;260 261 ret = sdsi_update_registers(s);262 if (ret)263 return ret;264 265 /* Print register info for this guid */266 printf("\n");267 printf("Socket information for device %s\n", s->dev_name);268 printf("\n");269 printf("PPIN: 0x%lx\n", s->regs.ppin);270 printf("NVRAM Content Authorization Error Status\n");271 printf(" SDSi Auth Err Sts: %s\n", !!s->regs.auth_err_sts.sdsi_content_auth_err ? "Error" : "Okay");272 273 if (!!s->regs.en_features.metering)274 printf(" Metering Auth Err Sts: %s\n", !!s->regs.auth_err_sts.sdsi_metering_auth_err ? "Error" : "Okay");275 276 printf("Enabled Features\n");277 printf(" On Demand: %s\n", !!s->regs.en_features.sdsi ? "Enabled" : "Disabled");278 printf(" Attestation: %s\n", !!s->regs.en_features.attestation ? "Enabled" : "Disabled");279 printf(" On Demand: %s\n", !!s->regs.en_features.sdsi ? "Enabled" : "Disabled");280 printf(" Metering: %s\n", !!s->regs.en_features.metering ? "Enabled" : "Disabled");281 printf("License Key (AKC) Provisioned: %s\n", !!s->regs.key_prov_sts.license_key_provisioned ? "Yes" : "No");282 printf("Authorization Failure Count\n");283 printf(" AKC Failure Count: %d\n", s->regs.auth_fail_count.key_failure_count);284 printf(" AKC Failure Threshold: %d\n", s->regs.auth_fail_count.key_failure_threshold);285 printf(" CAP Failure Count: %d\n", s->regs.auth_fail_count.auth_failure_count);286 printf(" CAP Failure Threshold: %d\n", s->regs.auth_fail_count.auth_failure_threshold);287 printf("Provisioning Availability\n");288 printf(" Updates Available: %d\n", s->regs.prov_avail.available);289 printf(" Updates Threshold: %d\n", s->regs.prov_avail.threshold);290 printf("NVRAM Udate Limit\n");291 printf(" 50%% Limit Reached: %s\n", !!s->regs.limits.sdsi_50_pct ? "Yes" : "No");292 printf(" 75%% Limit Reached: %s\n", !!s->regs.limits.sdsi_75_pct ? "Yes" : "No");293 printf(" 90%% Limit Reached: %s\n", !!s->regs.limits.sdsi_90_pct ? "Yes" : "No");294 if (s->guid == GUID_V1)295 printf("Socket ID: %ld\n", s->regs.extra.v1.socket_id & 0xF);296 else297 printf("Socket ID: %ld\n", s->regs.extra.v2.socket_id & 0xF);298 299 return 0;300}301 302static char *license_blob_type(uint32_t type)303{304 switch (type) {305 case LBT_ONE_TIME_UPGRADE:306 return "One time upgrade";307 case LBT_METERED_UPGRADE:308 return "Metered upgrade";309 default:310 return "Unknown license blob type";311 }312}313 314static char *content_type(uint32_t type)315{316 switch (type) {317 case CONTENT_TYPE_LK_ENC:318 return "Licencse key encoding";319 case CONTENT_TYPE_LK_BLOB_ENC:320 return "License key + Blob encoding";321 default:322 return "Unknown content type";323 }324}325 326static void get_feature(uint32_t encoding, char feature[5])327{328 char *name = (char *)&encoding;329 330 feature[4] = '\0';331 feature[3] = name[0];332 feature[2] = name[1];333 feature[1] = name[2];334 feature[0] = name[3];335}336 337static int sdsi_meter_cert_show(struct sdsi_dev *s, bool show_current)338{339 char buf[METER_CERT_MAX_SIZE] = {0};340 struct bundle_encoding_counter *bec;341 struct meter_certificate *mc;342 uint32_t count = 0;343 FILE *cert_ptr;344 char *cert_fname;345 int ret, size;346 char name[FEAT_LEN];347 348 ret = sdsi_update_registers(s);349 if (ret)350 return ret;351 352 if (!s->regs.en_features.sdsi) {353 fprintf(stderr, "SDSi feature is present but not enabled.\n");354 return -1;355 }356 357 if (!s->regs.en_features.metering) {358 fprintf(stderr, "Metering not supporting on this socket.\n");359 return -1;360 }361 362 ret = chdir(s->dev_path);363 if (ret == -1) {364 perror("chdir");365 return ret;366 }367 368 cert_fname = show_current ? "meter_current" : "meter_certificate";369 cert_ptr = fopen(cert_fname, "r");370 371 if (!cert_ptr) {372 fprintf(stderr, "Could not open '%s' file: %s", cert_fname, strerror(errno));373 return -1;374 }375 376 size = fread(buf, 1, sizeof(buf), cert_ptr);377 if (!size) {378 fprintf(stderr, "Could not read '%s' file\n", cert_fname);379 fclose(cert_ptr);380 return -1;381 }382 fclose(cert_ptr);383 384 mc = (struct meter_certificate *)buf;385 386 printf("\n");387 printf("Meter certificate for device %s\n", s->dev_name);388 printf("\n");389 390 get_feature(mc->signature, name);391 printf("Signature: %s\n", name);392 393 printf("Version: %d\n", mc->version);394 printf("Count Unit: %dms\n", mc->counter_unit);395 printf("PPIN: 0x%lx\n", mc->ppin);396 printf("Feature Bundle Length: %d\n", mc->bundle_length);397 398 get_feature(mc->mmrc_encoding, name);399 printf("MMRC encoding: %s\n", name);400 401 printf("MMRC counter: %d\n", mc->mmrc_counter);402 if (mc->bundle_length % METER_BUNDLE_SIZE) {403 fprintf(stderr, "Invalid bundle length\n");404 return -1;405 }406 407 if (mc->bundle_length > METER_MAX_NUM_BUNDLES * METER_BUNDLE_SIZE) {408 fprintf(stderr, "More than %ld bundles: actual %ld\n",409 METER_MAX_NUM_BUNDLES, BUNDLE_COUNT(mc->bundle_length));410 return -1;411 }412 413 bec = (struct bundle_encoding_counter *)(mc + 1);414 415 printf("Number of Feature Counters: %ld\n", BUNDLE_COUNT(mc->bundle_length));416 while (count < BUNDLE_COUNT(mc->bundle_length)) {417 char feature[FEAT_LEN];418 419 get_feature(bec[count].encoding, feature);420 printf(" %s: %d\n", feature, bec[count].counter);421 ++count;422 }423 424 return 0;425}426 427static int sdsi_state_cert_show(struct sdsi_dev *s)428{429 char buf[STATE_CERT_MAX_SIZE] = {0};430 struct state_certificate *sc;431 struct license_key_info *lki;432 uint32_t offset = 0;433 uint32_t count = 0;434 FILE *cert_ptr;435 int ret, size;436 437 ret = sdsi_update_registers(s);438 if (ret)439 return ret;440 441 if (!s->regs.en_features.sdsi) {442 fprintf(stderr, "On Demand feature is present but not enabled.");443 fprintf(stderr, " Unable to read state certificate");444 return -1;445 }446 447 ret = chdir(s->dev_path);448 if (ret == -1) {449 perror("chdir");450 return ret;451 }452 453 cert_ptr = fopen("state_certificate", "r");454 if (!cert_ptr) {455 perror("Could not open 'state_certificate' file");456 return -1;457 }458 459 size = fread(buf, 1, sizeof(buf), cert_ptr);460 if (!size) {461 fprintf(stderr, "Could not read 'state_certificate' file\n");462 fclose(cert_ptr);463 return -1;464 }465 fclose(cert_ptr);466 467 sc = (struct state_certificate *)buf;468 469 /* Print register info for this guid */470 printf("\n");471 printf("State certificate for device %s\n", s->dev_name);472 printf("\n");473 printf("Content Type: %s\n", content_type(sc->content_type));474 printf("Region Revision ID: %d\n", sc->region_rev_id);475 printf("Header Size: %d\n", sc->header_size * 4);476 printf("Total Size: %d\n", sc->total_size);477 printf("OEM Key Size: %d\n", sc->key_size * 4);478 printf("Number of Licenses: %d\n", sc->num_licenses);479 480 /* Skip over the license sizes 4 bytes per license) to get the license key info */481 lki = (void *)sc + sizeof(*sc) + (4 * sc->num_licenses);482 483 printf("License blob Info:\n");484 printf(" License Key Revision ID: 0x%x\n", lki->key_rev_id);485 printf(" License Key Image Content: 0x%lx%lx%lx%lx%lx%lx\n",486 lki->key_image_content[5], lki->key_image_content[4],487 lki->key_image_content[3], lki->key_image_content[2],488 lki->key_image_content[1], lki->key_image_content[0]);489 490 while (count++ < sc->num_licenses) {491 uint32_t blob_size_field = *(uint32_t *)(buf + 0x14 + count * 4);492 uint32_t blob_size = LICENSE_BLOB_SIZE(blob_size_field);493 bool license_valid = LICENSE_VALID(blob_size_field);494 struct license_blob_content *lbc =495 (void *)(sc) + // start of the state certificate496 sizeof(*sc) + // size of the state certificate497 (4 * sc->num_licenses) + // total size of the blob size blocks498 sizeof(*lki) + // size of the license key info499 offset; // offset to this blob content500 struct bundle_encoding *bundle = (void *)(lbc) + sizeof(*lbc);501 char feature[FEAT_LEN];502 uint32_t i;503 504 printf(" Blob %d:\n", count - 1);505 printf(" License blob size: %u\n", blob_size);506 printf(" License is valid: %s\n", license_valid ? "Yes" : "No");507 printf(" License blob type: %s\n", license_blob_type(lbc->type));508 printf(" License blob ID: 0x%lx\n", lbc->id);509 printf(" PPIN: 0x%lx\n", lbc->ppin);510 printf(" Previous PPIN: 0x%lx\n", lbc->previous_ppin);511 printf(" Blob revision ID: %u\n", lbc->rev_id);512 printf(" Number of Features: %u\n", lbc->num_bundles);513 514 for (i = 0; i < min(lbc->num_bundles, STATE_MAX_NUM_IN_BUNDLE); i++) {515 get_feature(bundle[i].encoding, feature);516 printf(" Feature %d: %s\n", i, feature);517 }518 519 if (lbc->num_bundles > STATE_MAX_NUM_IN_BUNDLE)520 fprintf(stderr, " Warning: %d > %d licenses in bundle reported.\n",521 lbc->num_bundles, STATE_MAX_NUM_IN_BUNDLE);522 523 offset += blob_size;524 };525 526 return 0;527}528 529static int sdsi_provision(struct sdsi_dev *s, char *bin_file, enum command command)530{531 int bin_fd, prov_fd, size, ret;532 char buf[STATE_CERT_MAX_SIZE] = { 0 };533 char cap[] = "provision_cap";534 char akc[] = "provision_akc";535 char *prov_file;536 537 if (!bin_file) {538 fprintf(stderr, "No binary file provided\n");539 return -1;540 }541 542 /* Open the binary */543 bin_fd = open(bin_file, O_RDONLY);544 if (bin_fd == -1) {545 fprintf(stderr, "Could not open file %s: %s\n", bin_file, strerror(errno));546 return bin_fd;547 }548 549 prov_file = (command == CMD_PROV_AKC) ? akc : cap;550 551 ret = chdir(s->dev_path);552 if (ret == -1) {553 perror("chdir");554 close(bin_fd);555 return ret;556 }557 558 /* Open the provision file */559 prov_fd = open(prov_file, O_WRONLY);560 if (prov_fd == -1) {561 fprintf(stderr, "Could not open file %s: %s\n", prov_file, strerror(errno));562 close(bin_fd);563 return prov_fd;564 }565 566 /* Read the binary file into the buffer */567 size = read(bin_fd, buf, STATE_CERT_MAX_SIZE);568 if (size == -1) {569 close(bin_fd);570 close(prov_fd);571 return -1;572 }573 574 ret = write(prov_fd, buf, size);575 if (ret == -1) {576 close(bin_fd);577 close(prov_fd);578 perror("Provisioning failed");579 return ret;580 }581 582 printf("Provisioned %s file %s successfully\n", prov_file, bin_file);583 584 close(bin_fd);585 close(prov_fd);586 587 return 0;588}589 590static int sdsi_provision_akc(struct sdsi_dev *s, char *bin_file)591{592 int ret;593 594 ret = sdsi_update_registers(s);595 if (ret)596 return ret;597 598 if (!s->regs.en_features.sdsi) {599 fprintf(stderr, "On Demand feature is present but not enabled. Unable to provision");600 return -1;601 }602 603 if (!s->regs.prov_avail.available) {604 fprintf(stderr, "Maximum number of updates (%d) has been reached.\n",605 s->regs.prov_avail.threshold);606 return -1;607 }608 609 if (s->regs.auth_fail_count.key_failure_count ==610 s->regs.auth_fail_count.key_failure_threshold) {611 fprintf(stderr, "Maximum number of AKC provision failures (%d) has been reached.\n",612 s->regs.auth_fail_count.key_failure_threshold);613 fprintf(stderr, "Power cycle the system to reset the counter\n");614 return -1;615 }616 617 return sdsi_provision(s, bin_file, CMD_PROV_AKC);618}619 620static int sdsi_provision_cap(struct sdsi_dev *s, char *bin_file)621{622 int ret;623 624 ret = sdsi_update_registers(s);625 if (ret)626 return ret;627 628 if (!s->regs.en_features.sdsi) {629 fprintf(stderr, "On Demand feature is present but not enabled. Unable to provision");630 return -1;631 }632 633 if (!s->regs.prov_avail.available) {634 fprintf(stderr, "Maximum number of updates (%d) has been reached.\n",635 s->regs.prov_avail.threshold);636 return -1;637 }638 639 if (s->regs.auth_fail_count.auth_failure_count ==640 s->regs.auth_fail_count.auth_failure_threshold) {641 fprintf(stderr, "Maximum number of CAP provision failures (%d) has been reached.\n",642 s->regs.auth_fail_count.auth_failure_threshold);643 fprintf(stderr, "Power cycle the system to reset the counter\n");644 return -1;645 }646 647 return sdsi_provision(s, bin_file, CMD_PROV_CAP);648}649 650static int read_sysfs_data(const char *file, int *value)651{652 char buff[16];653 FILE *fp;654 655 fp = fopen(file, "r");656 if (!fp) {657 perror(file);658 return -1;659 }660 661 if (!fgets(buff, 16, fp)) {662 fprintf(stderr, "Failed to read file '%s'", file);663 fclose(fp);664 return -1;665 }666 667 fclose(fp);668 *value = strtol(buff, NULL, 0);669 670 return 0;671}672 673static struct sdsi_dev *sdsi_create_dev(char *dev_no)674{675 int dev_name_len = sizeof(SDSI_DEV) + strlen(dev_no) + 1;676 struct sdsi_dev *s;677 int guid;678 DIR *dir;679 680 s = (struct sdsi_dev *)malloc(sizeof(*s));681 if (!s) {682 perror("malloc");683 return NULL;684 }685 686 s->dev_name = (char *)malloc(sizeof(SDSI_DEV) + strlen(dev_no) + 1);687 if (!s->dev_name) {688 perror("malloc");689 free(s);690 return NULL;691 }692 693 snprintf(s->dev_name, dev_name_len, "%s.%s", SDSI_DEV, dev_no);694 695 s->dev_path = (char *)malloc(sizeof(AUX_DEV_PATH) + dev_name_len);696 if (!s->dev_path) {697 perror("malloc");698 free(s->dev_name);699 free(s);700 return NULL;701 }702 703 snprintf(s->dev_path, sizeof(AUX_DEV_PATH) + dev_name_len, "%s%s", AUX_DEV_PATH,704 s->dev_name);705 dir = opendir(s->dev_path);706 if (!dir) {707 fprintf(stderr, "Could not open directory '%s': %s\n", s->dev_path,708 strerror(errno));709 free(s->dev_path);710 free(s->dev_name);711 free(s);712 return NULL;713 }714 715 if (chdir(s->dev_path) == -1) {716 perror("chdir");717 free(s->dev_path);718 free(s->dev_name);719 free(s);720 return NULL;721 }722 723 if (read_sysfs_data("guid", &guid)) {724 free(s->dev_path);725 free(s->dev_name);726 free(s);727 return NULL;728 }729 730 s->guid = guid;731 732 return s;733}734 735static void sdsi_free_dev(struct sdsi_dev *s)736{737 free(s->dev_path);738 free(s->dev_name);739 free(s);740}741 742static void usage(char *prog)743{744 printf("Usage: %s [-l] [-d DEVNO [-i] [-s] [-m | -C] [-a FILE] [-c FILE]\n", prog);745}746 747static void show_help(void)748{749 printf("Commands:\n");750 printf(" %-18s\t%s\n", "-l, --list", "list available On Demand devices");751 printf(" %-18s\t%s\n", "-d, --devno DEVNO", "On Demand device number");752 printf(" %-18s\t%s\n", "-i, --info", "show socket information");753 printf(" %-18s\t%s\n", "-s, --state", "show state certificate data");754 printf(" %-18s\t%s\n", "-m, --meter", "show meter certificate data");755 printf(" %-18s\t%s\n", "-C, --meter_current", "show live unattested meter data");756 printf(" %-18s\t%s\n", "-a, --akc FILE", "provision socket with AKC FILE");757 printf(" %-18s\t%s\n", "-c, --cap FILE>", "provision socket with CAP FILE");758}759 760int main(int argc, char *argv[])761{762 char bin_file[PATH_MAX], *dev_no = NULL;763 bool device_selected = false;764 char *progname;765 enum command command = -1;766 struct sdsi_dev *s;767 int ret = 0, opt;768 int option_index = 0;769 770 static struct option long_options[] = {771 {"akc", required_argument, 0, 'a'},772 {"cap", required_argument, 0, 'c'},773 {"devno", required_argument, 0, 'd'},774 {"help", no_argument, 0, 'h'},775 {"info", no_argument, 0, 'i'},776 {"list", no_argument, 0, 'l'},777 {"meter", no_argument, 0, 'm'},778 {"meter_current", no_argument, 0, 'C'},779 {"state", no_argument, 0, 's'},780 {0, 0, 0, 0 }781 };782 783 784 progname = argv[0];785 786 while ((opt = getopt_long_only(argc, argv, "+a:c:d:hilmCs", long_options,787 &option_index)) != -1) {788 switch (opt) {789 case 'd':790 dev_no = optarg;791 device_selected = true;792 break;793 case 'l':794 sdsi_list_devices();795 return 0;796 case 'i':797 command = CMD_SOCKET_INFO;798 break;799 case 'm':800 command = CMD_METER_CERT;801 break;802 case 'C':803 command = CMD_METER_CURRENT_CERT;804 break;805 case 's':806 command = CMD_STATE_CERT;807 break;808 case 'a':809 case 'c':810 if (!access(optarg, F_OK) == 0) {811 fprintf(stderr, "Could not open file '%s': %s\n", optarg,812 strerror(errno));813 return -1;814 }815 816 if (!realpath(optarg, bin_file)) {817 perror("realpath");818 return -1;819 }820 821 command = (opt == 'a') ? CMD_PROV_AKC : CMD_PROV_CAP;822 break;823 case 'h':824 usage(progname);825 show_help();826 return 0;827 default:828 usage(progname);829 return -1;830 }831 }832 833 if (device_selected) {834 s = sdsi_create_dev(dev_no);835 if (!s)836 return -1;837 838 switch (command) {839 case CMD_SOCKET_INFO:840 ret = sdsi_read_reg(s);841 break;842 case CMD_METER_CERT:843 ret = sdsi_meter_cert_show(s, false);844 break;845 case CMD_METER_CURRENT_CERT:846 ret = sdsi_meter_cert_show(s, true);847 break;848 case CMD_STATE_CERT:849 ret = sdsi_state_cert_show(s);850 break;851 case CMD_PROV_AKC:852 ret = sdsi_provision_akc(s, bin_file);853 break;854 case CMD_PROV_CAP:855 ret = sdsi_provision_cap(s, bin_file);856 break;857 default:858 fprintf(stderr, "No command specified\n");859 return -1;860 }861 862 sdsi_free_dev(s);863 864 } else {865 fprintf(stderr, "No device specified\n");866 return -1;867 }868 869 return ret;870}871