xref: /linux/tools/arch/x86/intel_sdsi/intel_sdsi.c (revision 6e7fd890f1d6ac83805409e9c346240de2705584)
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 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 
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 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 
167 struct 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 
177 struct 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 
185 enum 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 
194 static 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 
217 static 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 
257 static 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 	else
297 		printf("Socket ID:                      %ld\n", s->regs.extra.v2.socket_id & 0xF);
298 
299 	return 0;
300 }
301 
302 static 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 
314 static 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 
326 static 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 
337 static 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 
427 static 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 certificate
496 			sizeof(*sc) +			// size of the state certificate
497 			(4 * sc->num_licenses) +	// total size of the blob size blocks
498 			sizeof(*lki) +			// size of the license key info
499 			offset;				// offset to this blob content
500 		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 
529 static 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 
590 static 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 
620 static 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 
650 static 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 
673 static 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 
735 static void sdsi_free_dev(struct sdsi_dev *s)
736 {
737 	free(s->dev_path);
738 	free(s->dev_name);
739 	free(s);
740 }
741 
742 static void usage(char *prog)
743 {
744 	printf("Usage: %s [-l] [-d DEVNO [-i] [-s] [-m | -C] [-a FILE] [-c FILE]\n", prog);
745 }
746 
747 static 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 
760 int 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