mirror of
https://github.com/ibm-s390-linux/s390-tools.git
synced 2026-08-05 02:14:52 +00:00
This patch adds CEX7S exploitation support to lszcrypt and chzcrypt. Signed-off-by: Harald Freudenberger <freude@linux.ibm.com> Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
753 lines
20 KiB
C
753 lines
20 KiB
C
/**
|
|
* lszcrypt - Display zcrypt devices and configuration settings
|
|
*
|
|
* Copyright IBM Corp. 2008, 2019
|
|
*
|
|
* s390-tools is free software; you can redistribute it and/or modify
|
|
* it under the terms of the MIT license. See LICENSE for details.
|
|
*/
|
|
|
|
#include <err.h>
|
|
#include <stdint.h>
|
|
|
|
#include "lib/util_base.h"
|
|
#include "lib/util_file.h"
|
|
#include "lib/util_libc.h"
|
|
#include "lib/util_opt.h"
|
|
#include "lib/util_panic.h"
|
|
#include "lib/util_path.h"
|
|
#include "lib/util_prg.h"
|
|
#include "lib/util_proc.h"
|
|
#include "lib/util_rec.h"
|
|
#include "lib/util_scandir.h"
|
|
#include "lib/zt_common.h"
|
|
|
|
/*
|
|
* Private data
|
|
*/
|
|
struct lszcrypt_l {
|
|
int verbose;
|
|
} l;
|
|
|
|
struct lszcrypt_l *lszcrypt_l = &l;
|
|
|
|
/*
|
|
* Capabilities
|
|
*/
|
|
#define CAP_RSA2K "RSA 2K Clear Key"
|
|
#define CAP_RSA4K "RSA 4K Clear Key"
|
|
#define CAP_CCA "CCA Secure Key"
|
|
#define CAP_RNG "Long RNG"
|
|
#define CAP_EP11 "EP11 Secure Key"
|
|
|
|
/*
|
|
* Card types
|
|
*/
|
|
#define MASK_APSC 0x80000000
|
|
#define MASK_RSA4K 0x60000000
|
|
#define MASK_COPRO 0x10000000
|
|
#define MASK_ACCEL 0x08000000
|
|
#define MASK_EP11 0x04000000
|
|
|
|
/*
|
|
* Classification
|
|
*/
|
|
#define MASK_CLASS_FULL 0x00800000
|
|
#define CLASS_FULL "full function set"
|
|
#define MASK_CLASS_STATELESS 0x00400000
|
|
#define CLASS_STATELESS "restricted function set"
|
|
|
|
/*
|
|
* facility bits
|
|
*/
|
|
#define MAX_FAC_BITS 9
|
|
static struct fac_bits_s {
|
|
int mask;
|
|
char c;
|
|
} fac_bits[MAX_FAC_BITS] = {
|
|
{ 0x80000000, 'S' },
|
|
{ 0x40000000, 'M' },
|
|
{ 0x20000000, 'C' },
|
|
{ 0x10000000, 'D' },
|
|
{ 0x08000000, 'A' },
|
|
{ 0x04000000, 'X' },
|
|
{ 0x02000000, 'N' },
|
|
{ 0x00800000, 'F' },
|
|
{ 0x00400000, 'R' },
|
|
};
|
|
|
|
/*
|
|
* Program configuration
|
|
*/
|
|
const struct util_prg prg = {
|
|
.desc = "Display zcrypt device and configuration information.",
|
|
.args = "[DEVICE_IDS]",
|
|
.copyright_vec = {
|
|
{
|
|
.owner = "IBM Corp.",
|
|
.pub_first = 2008,
|
|
.pub_last = 2019,
|
|
},
|
|
UTIL_PRG_COPYRIGHT_END
|
|
}
|
|
};
|
|
|
|
/*
|
|
* Configuration of command line options
|
|
*/
|
|
static struct util_opt opt_vec[] = {
|
|
{
|
|
.option = {"bus", 0, NULL, 'b'},
|
|
.desc = "Show AP bus attributes then exit",
|
|
},
|
|
{
|
|
.option = { "capability", required_argument, NULL, 'c'},
|
|
.argument = "DEVICE_ID",
|
|
.desc = "Show the capabilities of a cryptographic device",
|
|
},
|
|
{
|
|
.option = {"domains", 0, NULL, 'd'},
|
|
.desc = "Show the configured AP usage and control domains",
|
|
},
|
|
{
|
|
.option = {"verbose", 0, NULL, 'V'},
|
|
.desc = "Print verbose messages",
|
|
},
|
|
UTIL_OPT_HELP,
|
|
UTIL_OPT_VERSION,
|
|
UTIL_OPT_END
|
|
};
|
|
|
|
/*
|
|
* Show bus
|
|
*/
|
|
static void show_bus(void)
|
|
{
|
|
long domain, max_domain, config_time, value;
|
|
unsigned long long poll_timeout;
|
|
const char *poll_thread, *ap_interrupts;
|
|
char *ap;
|
|
|
|
/* check if ap driver is available */
|
|
ap = util_path_sysfs("bus/ap");
|
|
if (!util_path_is_dir(ap))
|
|
errx(EXIT_FAILURE, "Crypto device driver not available.");
|
|
|
|
util_file_read_l(&domain, 10, "%s/ap_domain", ap);
|
|
util_file_read_l(&max_domain, 10, "%s/ap_max_domain_id", ap);
|
|
util_file_read_l(&config_time, 10, "%s/config_time", ap);
|
|
util_file_read_ull(&poll_timeout, 10, "%s/poll_timeout", ap);
|
|
util_file_read_l(&value, 10, "%s/poll_thread", ap);
|
|
if (value == 1)
|
|
poll_thread = "enabled";
|
|
else
|
|
poll_thread = "disabled";
|
|
util_file_read_l(&value, 10, "%s/ap_interrupts", ap);
|
|
if (value == 1)
|
|
ap_interrupts = "enabled";
|
|
else
|
|
ap_interrupts = "disabled";
|
|
printf("ap_domain=0x%lx\n", domain);
|
|
printf("ap_max_domain_id=0x%lx\n", max_domain);
|
|
if (util_path_is_reg_file("%s/ap_interrupts", ap))
|
|
printf("ap_interrupts are %s\n", ap_interrupts);
|
|
printf("config_time=%ld (seconds)\n", config_time);
|
|
printf("poll_thread is %s\n", poll_thread);
|
|
if (util_path_is_reg_file("%s/poll_timeout", ap))
|
|
printf("poll_timeout=%llu (nanoseconds)\n", poll_timeout);
|
|
free(ap);
|
|
}
|
|
|
|
/*
|
|
* Print domain array using util_rec
|
|
*/
|
|
static void show_domains_util_rec(char *domain_array[])
|
|
{
|
|
struct util_rec *rec = util_rec_new_wide("-");
|
|
char buf[256];
|
|
int i, x, n;
|
|
|
|
util_rec_def(rec, "domain", UTIL_REC_ALIGN_RIGHT, 6, "DOMAIN");
|
|
for (i = 0; i < 16; i++) {
|
|
sprintf(buf, "%02x", i);
|
|
util_rec_def(rec, buf, UTIL_REC_ALIGN_RIGHT, 2, buf);
|
|
}
|
|
|
|
util_rec_print_hdr(rec);
|
|
n = 0;
|
|
for (i = 0; i < 16; i++) {
|
|
sprintf(buf, "%02x", i * 16);
|
|
util_rec_set(rec, "domain", buf);
|
|
for (x = 0; x < 16; x++) {
|
|
sprintf(buf, "%02x", x);
|
|
util_rec_set(rec, buf, domain_array[n++]);
|
|
}
|
|
util_rec_print(rec);
|
|
}
|
|
util_rec_free(rec);
|
|
printf("------------------------------------------------------\n");
|
|
printf("C: Control domain\n");
|
|
printf("U: Usage domain\n");
|
|
printf("B: Both (Control + Usage domain)\n");
|
|
}
|
|
|
|
/*
|
|
* Show domains
|
|
*/
|
|
static void show_domains(void)
|
|
{
|
|
char ctrl_domain_mask[80], usag_domain_mask[80], byte_str[3] = {};
|
|
int ctrl_chunk, usag_chunk;
|
|
char *ap, *domain_array[32 * 8 + 4];
|
|
int i, x, n;
|
|
uint8_t dom_mask_bit;
|
|
|
|
/* check if ap driver is available */
|
|
ap = util_path_sysfs("bus/ap");
|
|
if (!util_path_is_dir(ap))
|
|
errx(EXIT_FAILURE, "Crypto device driver not available.");
|
|
|
|
util_file_read_line(ctrl_domain_mask, sizeof(ctrl_domain_mask),
|
|
"%s/ap_control_domain_mask", ap);
|
|
if (strstr(ctrl_domain_mask, "not"))
|
|
errx(EXIT_FAILURE, "Control domain mask not available.");
|
|
util_file_read_line(usag_domain_mask, sizeof(usag_domain_mask),
|
|
"%s/ap_usage_domain_mask", ap);
|
|
if (strstr(usag_domain_mask, "not"))
|
|
errx(EXIT_FAILURE, "Usage domain mask not available.");
|
|
/* remove leading '0x' from domain mask string */
|
|
memmove(&ctrl_domain_mask[0], &ctrl_domain_mask[2],
|
|
sizeof(ctrl_domain_mask) - 2);
|
|
memmove(&usag_domain_mask[0], &usag_domain_mask[2],
|
|
sizeof(usag_domain_mask) - 2);
|
|
n = 0;
|
|
for (i = 0; i < 32; i++) {
|
|
dom_mask_bit = 0x80;
|
|
memcpy(byte_str, &ctrl_domain_mask[i * 2], 2);
|
|
sscanf(byte_str, "%02x", &ctrl_chunk);
|
|
memcpy(byte_str, &usag_domain_mask[i * 2], 2);
|
|
sscanf(byte_str, "%02x", &usag_chunk);
|
|
for (x = 1; x <= 8; x++) {
|
|
if (ctrl_chunk & dom_mask_bit &&
|
|
usag_chunk & dom_mask_bit)
|
|
domain_array[n] = "B"; /* c/u */
|
|
else if (ctrl_chunk & dom_mask_bit)
|
|
domain_array[n] = "C";
|
|
else if (usag_chunk & dom_mask_bit)
|
|
domain_array[n] = "U";
|
|
else
|
|
domain_array[n] = ".";
|
|
dom_mask_bit = dom_mask_bit >> 1;
|
|
n += 1;
|
|
}
|
|
}
|
|
for (i = n; i < 260; i++)
|
|
domain_array[n++] = "";
|
|
|
|
show_domains_util_rec(domain_array);
|
|
}
|
|
|
|
/*
|
|
* Show capability
|
|
*/
|
|
static void show_capability(const char *id_str)
|
|
{
|
|
unsigned long func_val;
|
|
long hwtype, id;
|
|
char *p, *ap, *dev, card[16], cbuf[256];
|
|
|
|
/* check if ap driver is available */
|
|
ap = util_path_sysfs("bus/ap");
|
|
if (!util_path_is_dir(ap))
|
|
errx(EXIT_FAILURE, "Crypto device driver not available.");
|
|
|
|
id = strtol(id_str, &p, 0);
|
|
if (id < 0 || id > 255 || p == id_str || *p != '\0')
|
|
errx(EXIT_FAILURE, "Error - '%s' is an invalid cryptographic device id.", id_str);
|
|
snprintf(card, sizeof(card), "card%02lx", id);
|
|
dev = util_path_sysfs("devices/ap/%s", card);
|
|
if (!util_path_is_dir(dev))
|
|
errx(EXIT_FAILURE, "Error - cryptographic device %s does not exist.", card);
|
|
util_file_read_l(&hwtype, 10, "%s/hwtype", dev);
|
|
/* If sysfs attribute is missing, set functions to 0 */
|
|
if (util_file_read_ul(&func_val, 16, "%s/ap_functions", dev))
|
|
func_val = 0x00000000;
|
|
/* Skip devices, which are not supported by zcrypt layer */
|
|
if (!util_path_is_readable("%s/type", dev) ||
|
|
!util_path_is_readable("%s/online", dev)) {
|
|
printf("Detailed capability information for %s (hardware type %ld) is not available.\n",
|
|
card, hwtype);
|
|
return;
|
|
}
|
|
cbuf[0] = '\0';
|
|
if (func_val & MASK_CLASS_FULL)
|
|
snprintf(cbuf, sizeof(cbuf), "%s", CLASS_FULL);
|
|
else if (func_val & MASK_CLASS_STATELESS)
|
|
snprintf(cbuf, sizeof(cbuf), "%s", CLASS_STATELESS);
|
|
printf("%s provides capability for:\n", card);
|
|
switch (hwtype) {
|
|
case 6:
|
|
case 8:
|
|
if (func_val & MASK_RSA4K)
|
|
printf("%s", CAP_RSA4K);
|
|
else
|
|
printf("%s", CAP_RSA2K);
|
|
break;
|
|
case 7:
|
|
case 9:
|
|
printf("%s\n", CAP_RSA4K);
|
|
if (cbuf[0])
|
|
printf("%s (%s)\n", CAP_CCA, cbuf);
|
|
else
|
|
printf("%s\n", CAP_CCA);
|
|
printf("%s", CAP_RNG);
|
|
break;
|
|
case 10: /* CEX4S */
|
|
case 11: /* CEX5S */
|
|
case 12: /* CEX6S */
|
|
case 13: /* CEX7S */
|
|
if (func_val & MASK_ACCEL) {
|
|
if (func_val & MASK_RSA4K)
|
|
printf("%s", CAP_RSA4K);
|
|
else
|
|
printf("%s", CAP_RSA2K);
|
|
} else if (func_val & MASK_COPRO) {
|
|
printf("%s\n", CAP_RSA4K);
|
|
if (cbuf[0])
|
|
printf("%s (%s)\n", CAP_CCA, cbuf);
|
|
else
|
|
printf("%s\n", CAP_CCA);
|
|
printf("%s", CAP_RNG);
|
|
} else if (func_val & MASK_EP11) {
|
|
printf("%s", CAP_EP11);
|
|
} else {
|
|
printf("Detailed capability information for %s (hardware type %ld) is not available.",
|
|
card, hwtype);
|
|
}
|
|
break;
|
|
default:
|
|
printf("Detailed capability information for %s (hardware type %ld) is not available.",
|
|
card, hwtype);
|
|
break;
|
|
}
|
|
printf("\n");
|
|
}
|
|
|
|
/*
|
|
* Read subdevice default attributes
|
|
*/
|
|
static void read_subdev_rec_default(struct util_rec *rec, const char *grp_dev,
|
|
const char *sub_dev)
|
|
{
|
|
char buf[256];
|
|
unsigned long facility;
|
|
|
|
if (util_file_read_line(buf, sizeof(buf), "%s/type", grp_dev))
|
|
util_rec_set(rec, "type", "-");
|
|
else
|
|
util_rec_set(rec, "type", buf);
|
|
|
|
if (util_file_read_line(buf, sizeof(buf), "%s/%s/online",
|
|
grp_dev, sub_dev))
|
|
util_rec_set(rec, "online", "-");
|
|
else
|
|
if (strcmp(buf, "0") == 0)
|
|
util_rec_set(rec, "online", "offline");
|
|
else
|
|
util_rec_set(rec, "online", "online");
|
|
|
|
util_file_read_ul(&facility, 16, "%s/ap_functions", grp_dev);
|
|
if (facility & MASK_COPRO)
|
|
util_rec_set(rec, "mode", "CCA-Coproc");
|
|
else if (facility & MASK_ACCEL)
|
|
util_rec_set(rec, "mode", "Accelerator");
|
|
else if (facility & MASK_EP11)
|
|
util_rec_set(rec, "mode", "EP11-Coproc");
|
|
else
|
|
util_rec_set(rec, "mode", "Unknown");
|
|
|
|
util_file_read_line(buf, sizeof(buf), "%s/%s/request_count",
|
|
grp_dev, sub_dev);
|
|
util_rec_set(rec, "requests", buf);
|
|
}
|
|
|
|
/*
|
|
* Read subdevice verbose attributes
|
|
*/
|
|
static void read_subdev_rec_verbose(struct util_rec *rec, const char *grp_dev,
|
|
const char *sub_dev)
|
|
{
|
|
int i;
|
|
unsigned long facility;
|
|
char buf[256], afile[PATH_MAX];
|
|
long depth, pending1, pending2;
|
|
|
|
if (l.verbose == 0)
|
|
return;
|
|
|
|
util_file_read_l(&pending1, 10, "%s/%s/pendingq_count",
|
|
grp_dev, sub_dev);
|
|
util_file_read_l(&pending2, 10, "%s/%s/requestq_count",
|
|
grp_dev, sub_dev);
|
|
util_rec_set(rec, "pending", "%ld", pending1 + pending2);
|
|
|
|
util_file_read_line(buf, sizeof(buf), "%s/hwtype", grp_dev);
|
|
util_rec_set(rec, "hwtype", buf);
|
|
|
|
util_file_read_l(&depth, 10, "%s/depth", grp_dev);
|
|
util_rec_set(rec, "depth", "%02d", depth + 1);
|
|
|
|
util_file_read_ul(&facility, 16, "%s/ap_functions", grp_dev);
|
|
for (i = 0; i < MAX_FAC_BITS; i++)
|
|
buf[i] = facility & fac_bits[i].mask ? fac_bits[i].c : '-';
|
|
buf[i] = '\0';
|
|
util_rec_set(rec, "facility", buf);
|
|
|
|
snprintf(afile, sizeof(afile), "%s/%s/driver", grp_dev, sub_dev);
|
|
afile[sizeof(afile) - 1] = '\0';
|
|
memset(buf, 0, sizeof(buf));
|
|
if (readlink(afile, buf, sizeof(buf)) > 0)
|
|
util_rec_set(rec, "driver", strrchr(buf, '/') + 1);
|
|
else
|
|
util_rec_set(rec, "driver", "-no-driver-");
|
|
}
|
|
|
|
/*
|
|
* Show one subdevice
|
|
*/
|
|
static void show_subdevice(struct util_rec *rec, const char *grp_dev,
|
|
const char *sub_dev)
|
|
{
|
|
if (!util_path_is_dir("%s/%s", grp_dev, sub_dev))
|
|
errx(EXIT_FAILURE, "Error - cryptographic device %s/%s does not exist.", grp_dev, sub_dev);
|
|
|
|
/*
|
|
* If not verbose mode, skip devices which are not supported
|
|
* by the zcrypt layer.
|
|
*/
|
|
if (l.verbose == 0 &&
|
|
(!util_path_is_readable("%s/type", grp_dev) ||
|
|
!util_path_is_readable("%s/%s/online", grp_dev, sub_dev)))
|
|
return;
|
|
|
|
util_rec_set(rec, "card", sub_dev);
|
|
read_subdev_rec_default(rec, grp_dev, sub_dev);
|
|
read_subdev_rec_verbose(rec, grp_dev, sub_dev);
|
|
|
|
util_rec_print(rec);
|
|
}
|
|
|
|
/*
|
|
* Show subdevices
|
|
*/
|
|
static void show_subdevices(struct util_rec *rec, const char *grp_dev)
|
|
{
|
|
struct dirent **dev_vec;
|
|
int i, count;
|
|
|
|
count = util_scandir(&dev_vec, alphasort, grp_dev, "..\\....");
|
|
if (count < 1)
|
|
errx(EXIT_FAILURE, "Error - no subdevices found for %s.\n", grp_dev);
|
|
for (i = 0; i < count; i++)
|
|
show_subdevice(rec, grp_dev, dev_vec[i]->d_name);
|
|
}
|
|
|
|
/*
|
|
* Read default attributes
|
|
*/
|
|
static void read_rec_default(struct util_rec *rec, const char *grp_dev)
|
|
{
|
|
char buf[256];
|
|
unsigned long facility;
|
|
|
|
if (util_file_read_line(buf, sizeof(buf), "%s/type", grp_dev))
|
|
util_rec_set(rec, "type", "-");
|
|
else
|
|
util_rec_set(rec, "type", buf);
|
|
|
|
util_file_read_ul(&facility, 16, "%s/ap_functions", grp_dev);
|
|
if (facility & MASK_COPRO)
|
|
util_rec_set(rec, "mode", "CCA-Coproc");
|
|
else if (facility & MASK_ACCEL)
|
|
util_rec_set(rec, "mode", "Accelerator");
|
|
else if (facility & MASK_EP11)
|
|
util_rec_set(rec, "mode", "EP11-Coproc");
|
|
else
|
|
util_rec_set(rec, "mode", "Unknown");
|
|
|
|
if (util_file_read_line(buf, sizeof(buf), "%s/online", grp_dev))
|
|
util_rec_set(rec, "online", "-");
|
|
else
|
|
if (strcmp(buf, "0") == 0)
|
|
util_rec_set(rec, "online", "offline");
|
|
else
|
|
util_rec_set(rec, "online", "online");
|
|
|
|
util_file_read_line(buf, sizeof(buf), "%s/request_count", grp_dev);
|
|
util_rec_set(rec, "requests", buf);
|
|
}
|
|
|
|
/*
|
|
* Read verbose attributes
|
|
*/
|
|
static void read_rec_verbose(struct util_rec *rec, const char *grp_dev)
|
|
{
|
|
int i;
|
|
unsigned long facility;
|
|
char buf[256], afile[PATH_MAX];
|
|
long depth, pending1, pending2;
|
|
|
|
if (l.verbose == 0)
|
|
return;
|
|
|
|
util_file_read_l(&pending1, 10, "%s/pendingq_count", grp_dev);
|
|
util_file_read_l(&pending2, 10, "%s/requestq_count", grp_dev);
|
|
util_rec_set(rec, "pending", "%ld", pending1 + pending2);
|
|
|
|
util_file_read_line(buf, sizeof(buf), "%s/hwtype", grp_dev);
|
|
util_rec_set(rec, "hwtype", buf);
|
|
|
|
util_file_read_l(&depth, 10, "%s/depth", grp_dev);
|
|
util_rec_set(rec, "depth", "%02d", depth + 1);
|
|
|
|
util_file_read_ul(&facility, 16, "%s/ap_functions", grp_dev);
|
|
for (i = 0; i < MAX_FAC_BITS; i++)
|
|
buf[i] = facility & fac_bits[i].mask ? fac_bits[i].c : '-';
|
|
buf[i] = '\0';
|
|
util_rec_set(rec, "facility", buf);
|
|
|
|
snprintf(afile, sizeof(afile), "%s/driver", grp_dev);
|
|
afile[sizeof(afile) - 1] = '\0';
|
|
memset(buf, 0, sizeof(buf));
|
|
if (readlink(afile, buf, sizeof(buf)) > 0)
|
|
util_rec_set(rec, "driver", strrchr(buf, '/') + 1);
|
|
else
|
|
util_rec_set(rec, "driver", "-no-driver-");
|
|
}
|
|
|
|
/*
|
|
* Show device: device is in the form "card00", "card01", ...
|
|
*/
|
|
static void show_device(struct util_rec *rec, const char *device)
|
|
{
|
|
char *grp_dev, card[16];
|
|
|
|
util_rec_set(rec, "card", card);
|
|
|
|
strcpy(card, &device[4]);
|
|
grp_dev = util_path_sysfs("devices/ap/%s", device);
|
|
if (!util_path_is_dir(grp_dev))
|
|
errx(EXIT_FAILURE, "Error - cryptographic device %s does not exist.", device);
|
|
|
|
/*
|
|
* If not verbose mode, skip devices which are not supported
|
|
* by the zcrypt layer.
|
|
*/
|
|
if (l.verbose == 0 &&
|
|
(!util_path_is_readable("%s/type", grp_dev) ||
|
|
!util_path_is_readable("%s/online", grp_dev))) {
|
|
goto out_free;
|
|
}
|
|
util_rec_set(rec, "card", card);
|
|
|
|
read_rec_default(rec, grp_dev);
|
|
read_rec_verbose(rec, grp_dev);
|
|
|
|
util_rec_print(rec);
|
|
show_subdevices(rec, grp_dev);
|
|
out_free:
|
|
free(grp_dev);
|
|
}
|
|
|
|
/*
|
|
* Define the *default* attributes
|
|
*/
|
|
static void define_rec_default(struct util_rec *rec)
|
|
{
|
|
util_rec_def(rec, "card", UTIL_REC_ALIGN_LEFT, 11, "CARD.DOMAIN");
|
|
util_rec_def(rec, "type", UTIL_REC_ALIGN_LEFT, 5, "TYPE");
|
|
util_rec_def(rec, "mode", UTIL_REC_ALIGN_LEFT, 11, "MODE");
|
|
util_rec_def(rec, "online", UTIL_REC_ALIGN_LEFT, 7, "STATUS");
|
|
util_rec_def(rec, "requests", UTIL_REC_ALIGN_RIGHT, 8, "REQUESTS");
|
|
}
|
|
|
|
/*
|
|
* Define the *verbose* attributes
|
|
*/
|
|
static void define_rec_verbose(struct util_rec *rec)
|
|
{
|
|
if (l.verbose == 0)
|
|
return;
|
|
util_rec_def(rec, "pending", UTIL_REC_ALIGN_RIGHT, 8, "PENDING");
|
|
util_rec_def(rec, "hwtype", UTIL_REC_ALIGN_RIGHT, 6, "HWTYPE");
|
|
util_rec_def(rec, "depth", UTIL_REC_ALIGN_RIGHT, 6, "QDEPTH");
|
|
util_rec_def(rec, "facility", UTIL_REC_ALIGN_LEFT, 10, "FUNCTIONS");
|
|
util_rec_def(rec, "driver", UTIL_REC_ALIGN_LEFT, 11, "DRIVER");
|
|
}
|
|
|
|
/*
|
|
* Show all devices
|
|
*/
|
|
static void show_devices_all(void)
|
|
{
|
|
struct util_rec *rec = util_rec_new_wide("-");
|
|
struct dirent **dev_vec;
|
|
int i, count;
|
|
char *ap, *path;
|
|
|
|
/* check if ap driver is available */
|
|
ap = util_path_sysfs("bus/ap");
|
|
if (!util_path_is_dir(ap))
|
|
errx(EXIT_FAILURE, "Crypto device driver not available.");
|
|
|
|
/* Define the record */
|
|
define_rec_default(rec);
|
|
define_rec_verbose(rec);
|
|
|
|
/* Scan the devices */
|
|
path = util_path_sysfs("devices/ap/");
|
|
count = util_scandir(&dev_vec, alphasort, path, "card[0-9a-fA-F]+");
|
|
if (count < 1)
|
|
errx(EXIT_FAILURE, "No crypto card devices found.");
|
|
util_rec_print_hdr(rec);
|
|
for (i = 0; i < count; i++)
|
|
show_device(rec, dev_vec[i]->d_name);
|
|
free(path);
|
|
}
|
|
|
|
/*
|
|
* Show devices specified on commandline
|
|
*/
|
|
static void show_devices_argv(char *argv[])
|
|
{
|
|
struct util_rec *rec = util_rec_new_wide("-");
|
|
struct dirent **dev_vec, **subdev_vec;
|
|
char *ap, *grp_dev, *path, *card, *sub_dev;
|
|
int id, dom, i, n, dev_cnt, sub_cnt;
|
|
|
|
/* check if ap driver is available */
|
|
ap = util_path_sysfs("bus/ap");
|
|
if (!util_path_is_dir(ap))
|
|
errx(EXIT_FAILURE, "Crypto device driver not available.");
|
|
|
|
/* Define the record */
|
|
define_rec_default(rec);
|
|
define_rec_verbose(rec);
|
|
|
|
util_rec_print_hdr(rec);
|
|
for (i = 0; argv[i] != NULL; i++) {
|
|
id = -1;
|
|
dom = -1;
|
|
if (sscanf(argv[i], "%x.%x", &id, &dom) >= 1) {
|
|
/* at least the id field was valid */
|
|
if (id >= 0 && dom >= 0) { /* single subdevice */
|
|
util_asprintf(&sub_dev, "%02x.%04x", id, dom);
|
|
grp_dev = util_path_sysfs("devices/ap/card%02x",
|
|
id);
|
|
show_subdevice(rec, grp_dev, sub_dev);
|
|
free(grp_dev);
|
|
free(sub_dev);
|
|
} else { /* group device */
|
|
util_asprintf(&card, "card%02x", id);
|
|
show_device(rec, card);
|
|
free(card);
|
|
}
|
|
return;
|
|
}
|
|
if (sscanf(argv[i]+1, "%x", &dom) == 1) {
|
|
/* list specific domains of all adapters */
|
|
path = util_path_sysfs("devices/ap/");
|
|
dev_cnt = util_scandir(&dev_vec, alphasort, path,
|
|
"card[0-9a-fA-F]+");
|
|
if (dev_cnt < 1)
|
|
errx(EXIT_FAILURE, "No crypto card devices found.");
|
|
free(path);
|
|
for (i = 0; i < dev_cnt; i++) {
|
|
path = util_path_sysfs("devices/ap/%s",
|
|
dev_vec[i]->d_name);
|
|
sub_cnt = util_scandir(&subdev_vec, alphasort,
|
|
path,
|
|
"[0-9a-fA-F]+.%04x",
|
|
dom);
|
|
if (sub_cnt < 1)
|
|
errx(EXIT_FAILURE, "No queue devices with given domain value found.");
|
|
for (n = 0; n < sub_cnt; n++) {
|
|
show_subdevice(rec, path,
|
|
subdev_vec[n]->d_name);
|
|
}
|
|
free(path);
|
|
}
|
|
return;
|
|
}
|
|
printf("Invalid adpater id!\n");
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Describe adapter ids
|
|
*/
|
|
void print_adapter_id_help(void)
|
|
{
|
|
printf("\n");
|
|
printf("DEVICE_IDS\n");
|
|
printf(" List of cryptographic device ids separated by blanks which will be displayed.\n");
|
|
printf(" DEVICE_ID could either be card device id ('<card-id>') or queue device id\n");
|
|
printf(" '<card-id>.<domain-id>'). To filter all devices according to a dedicated\n");
|
|
printf(" domain just provide '.<domain-id>'.\n");
|
|
printf(" If no ids are given, all available devices are displayed.\n");
|
|
printf("\n");
|
|
printf("EXAMPLE:\n");
|
|
printf(" List all cryptographic devices with card id '02'.\n");
|
|
printf(" #>lszcrypt 02\n");
|
|
printf("\n");
|
|
printf(" List cryptographic devices with card id '02' and domain id '0005'.\n");
|
|
printf(" #>lszcrypt 02.0005\n");
|
|
printf("\n");
|
|
}
|
|
|
|
/*
|
|
* Entry point
|
|
*/
|
|
int main(int argc, char **argv)
|
|
{
|
|
int c;
|
|
|
|
util_prg_init(&prg);
|
|
util_opt_init(opt_vec, NULL);
|
|
while (1) {
|
|
c = util_opt_getopt_long(argc, argv);
|
|
if (c == -1)
|
|
break;
|
|
switch (c) {
|
|
case 'b':
|
|
show_bus();
|
|
return EXIT_SUCCESS;
|
|
case 'c':
|
|
show_capability(optarg);
|
|
return EXIT_SUCCESS;
|
|
case 'd':
|
|
show_domains();
|
|
return EXIT_SUCCESS;
|
|
case 'V':
|
|
l.verbose++;
|
|
break;
|
|
case 'h':
|
|
util_prg_print_help();
|
|
util_opt_print_help();
|
|
print_adapter_id_help();
|
|
return EXIT_SUCCESS;
|
|
case 'v':
|
|
util_prg_print_version();
|
|
return EXIT_SUCCESS;
|
|
default:
|
|
util_opt_print_parse_error(c, argv);
|
|
return EXIT_FAILURE;
|
|
}
|
|
}
|
|
if (optind == argc)
|
|
show_devices_all();
|
|
else
|
|
show_devices_argv(&argv[optind]);
|
|
return EXIT_SUCCESS;
|
|
}
|