Commit 7fdc03a7 authored by David E. Box's avatar David E. Box Committed by Hans de Goede
Browse files

tools/arch/x86: intel_sdsi: Add support for reading meter certificates

parent 429e789c
Loading
Loading
Loading
Loading
+108 −2
Original line number Diff line number Diff line
@@ -40,8 +40,10 @@
#define GUID_V2			0xF210D9EF
#define REGS_SIZE_GUID_V2	80
#define STATE_CERT_MAX_SIZE	4096
#define METER_CERT_MAX_SIZE	4096
#define STATE_MAX_NUM_LICENSES	16
#define STATE_MAX_NUM_IN_BUNDLE	(uint32_t)8
#define METER_MAX_NUM_BUNDLES	8

#define __round_mask(x, y) ((__typeof__(x))((y) - 1))
#define round_up(x, y) ((((x) - 1) | __round_mask(x, y)) + 1)
@@ -151,6 +153,21 @@ struct bundle_encoding {
	uint32_t encoding_rsvd[7];
};

struct meter_certificate {
	uint32_t block_signature;
	uint32_t counter_unit;
	uint64_t ppin;
	uint32_t bundle_length;
	uint32_t reserved;
	uint32_t mmrc_encoding;
	uint32_t mmrc_counter;
};

struct bundle_encoding_counter {
	uint32_t encoding;
	uint32_t counter;
};

struct sdsi_dev {
	struct sdsi_regs regs;
	struct state_certificate sc;
@@ -161,6 +178,7 @@ struct sdsi_dev {

enum command {
	CMD_SOCKET_INFO,
	CMD_METER_CERT,
	CMD_STATE_CERT,
	CMD_PROV_AKC,
	CMD_PROV_CAP,
@@ -308,6 +326,86 @@ static void get_feature(uint32_t encoding, char *feature)
	feature[0] = name[3];
}

static int sdsi_meter_cert_show(struct sdsi_dev *s)
{
	char buf[METER_CERT_MAX_SIZE] = {0};
	struct bundle_encoding_counter *bec;
	struct meter_certificate *mc;
	uint32_t count = 0;
	FILE *cert_ptr;
	int ret, size;

	ret = sdsi_update_registers(s);
	if (ret)
		return ret;

	if (!s->regs.en_features.sdsi) {
		fprintf(stderr, "SDSi feature is present but not enabled.\n");
		fprintf(stderr, " Unable to read meter certificate\n");
		return -1;
	}

	if (!s->regs.en_features.metering) {
		fprintf(stderr, "Metering not supporting on this socket.\n");
		return -1;
	}

	ret = chdir(s->dev_path);
	if (ret == -1) {
		perror("chdir");
		return ret;
	}

	cert_ptr = fopen("meter_certificate", "r");
	if (!cert_ptr) {
		perror("Could not open 'meter_certificate' file");
		return -1;
	}

	size = fread(buf, 1, sizeof(buf), cert_ptr);
	if (!size) {
		fprintf(stderr, "Could not read 'meter_certificate' file\n");
		fclose(cert_ptr);
		return -1;
	}
	fclose(cert_ptr);

	mc = (struct meter_certificate *)buf;

	printf("\n");
	printf("Meter certificate for device %s\n", s->dev_name);
	printf("\n");
	printf("Block Signature:       0x%x\n", mc->block_signature);
	printf("Count Unit:            %dms\n", mc->counter_unit);
	printf("PPIN:                  0x%lx\n", mc->ppin);
	printf("Feature Bundle Length: %d\n", mc->bundle_length);
	printf("MMRC encoding:         %d\n", mc->mmrc_encoding);
	printf("MMRC counter:          %d\n", mc->mmrc_counter);
	if (mc->bundle_length % 8) {
		fprintf(stderr, "Invalid bundle length\n");
		return -1;
	}

	if (mc->bundle_length > METER_MAX_NUM_BUNDLES * 8)  {
		fprintf(stderr, "More than %d bundles: %d\n",
			METER_MAX_NUM_BUNDLES, mc->bundle_length / 8);
		return -1;
	}

	bec = (void *)(mc) + sizeof(mc);

	printf("Number of Feature Counters:          %d\n", mc->bundle_length / 8);
	while (count++ < mc->bundle_length / 8) {
		char feature[5];

		feature[4] = '\0';
		get_feature(bec[count].encoding, feature);
		printf("    %s:          %d\n", feature, bec[count].counter);
	}

	return 0;
}

static int sdsi_state_cert_show(struct sdsi_dev *s)
{
	char buf[STATE_CERT_MAX_SIZE] = {0};
@@ -627,7 +725,7 @@ static void sdsi_free_dev(struct sdsi_dev *s)

static void usage(char *prog)
{
	printf("Usage: %s [-l] [-d DEVNO [-i] [-s] [-a FILE] [-c FILE]]\n", prog);
	printf("Usage: %s [-l] [-d DEVNO [-i] [-s] [-m] [-a FILE] [-c FILE]]\n", prog);
}

static void show_help(void)
@@ -637,6 +735,7 @@ static void show_help(void)
	printf("  %-18s\t%s\n", "-d, --devno DEVNO",    "On Demand device number");
	printf("  %-18s\t%s\n", "-i, --info",           "show socket information");
	printf("  %-18s\t%s\n", "-s, --state",          "show state certificate");
	printf("  %-18s\t%s\n", "-m, --meter",          "show meter certificate");
	printf("  %-18s\t%s\n", "-a, --akc FILE",       "provision socket with AKC FILE");
	printf("  %-18s\t%s\n", "-c, --cap FILE>",      "provision socket with CAP FILE");
}
@@ -658,6 +757,7 @@ int main(int argc, char *argv[])
		{"help",	no_argument,		0, 'h'},
		{"info",	no_argument,		0, 'i'},
		{"list",	no_argument,		0, 'l'},
		{"meter",	no_argument,		0, 'm'},
		{"state",	no_argument,		0, 's'},
		{0,		0,			0, 0 }
	};
@@ -665,7 +765,7 @@ int main(int argc, char *argv[])

	progname = argv[0];

	while ((opt = getopt_long_only(argc, argv, "+a:c:d:hils", long_options,
	while ((opt = getopt_long_only(argc, argv, "+a:c:d:hilms", long_options,
			&option_index)) != -1) {
		switch (opt) {
		case 'd':
@@ -678,6 +778,9 @@ int main(int argc, char *argv[])
		case 'i':
			command = CMD_SOCKET_INFO;
			break;
		case 'm':
			command = CMD_METER_CERT;
			break;
		case 's':
			command = CMD_STATE_CERT;
			break;
@@ -715,6 +818,9 @@ int main(int argc, char *argv[])
		case CMD_SOCKET_INFO:
			ret = sdsi_read_reg(s);
			break;
		case CMD_METER_CERT:
			ret = sdsi_meter_cert_show(s);
			break;
		case CMD_STATE_CERT:
			ret = sdsi_state_cert_show(s);
			break;