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