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