diff options
author | Jerry Jelinek <jerry.jelinek@joyent.com> | 2020-03-30 11:59:04 +0000 |
---|---|---|
committer | Jerry Jelinek <jerry.jelinek@joyent.com> | 2020-03-30 11:59:04 +0000 |
commit | 380d528f676476b9d6662f0edea853a36789f58b (patch) | |
tree | 5cb0437ff0b585ab3d6f3ad8aedf67f220464bb2 | |
parent | d8cab3215b93aa7d16090428ff303d6ff92263f7 (diff) | |
parent | 8c16a0e6d0b3d6a8b804825076383c61979302ec (diff) | |
download | illumos-joyent-380d528f676476b9d6662f0edea853a36789f58b.tar.gz |
[illumos-gate merge]
commit 8c16a0e6d0b3d6a8b804825076383c61979302ec
12404 audioemu10k: variable may be used uninitialized
commit d52aae2365749461c362fde5a4c1a26a620cfbd3
12310 Add demangle(1) command
commit a61ed2ce7a86a4d6428f2a83eb4739fae945447e
12258 Need native CCID driver
commit ae6d4bc342613e6a5dc7b84b03ecdb0cc9cf7d26
12444 Intel v1 chip topo needs rank information
Conflicts:
usr/src/uts/common/sys/usb/clients/ccid/uccid.h
usr/src/uts/common/sys/usb/clients/ccid/ccid.h
usr/src/uts/common/io/usb/clients/ccid/ccid.c
usr/src/uts/common/Makefile.files
usr/src/test/os-tests/tests/uccid/yk-readonly.c
usr/src/test/os-tests/tests/uccid/notxn-poll.c
usr/src/test/os-tests/tests/uccid/modify.c
usr/src/test/os-tests/tests/Makefile
usr/src/man/man7d/ccid.7d
usr/src/man/man1m/ccidadm.1m
usr/src/lib/libcmdutils/common/nicenum.c
usr/src/lib/cfgadm_plugins/ccid/common/cfga_ccid.c
usr/src/common/ccid/atr.c
usr/src/cmd/devfsadm/usb_link.c
usr/src/cmd/ccidadm/ccidadm.c
usr/src/cmd/ccidadm/Makefile
30 files changed, 1084 insertions, 175 deletions
@@ -2534,6 +2534,7 @@ f usr/bin/date 0555 root bin f usr/bin/dc 0555 root bin f usr/bin/dd 0555 root bin h usr/bin/decrypt=usr/lib/isaexec +f usr/bin/demangle 0555 root bin f usr/bin/deroff 0555 root bin f usr/bin/devattr 0555 root bin f usr/bin/devfree 0555 root bin @@ -4788,6 +4789,9 @@ d usr/include/sys/usb 0755 root bin d usr/include/sys/usb/clients 0755 root bin d usr/include/sys/usb/clients/audio 0755 root bin f usr/include/sys/usb/clients/audio/usb_audio.h 0644 root bin +d usr/include/sys/usb/clients/ccid 0755 root bin +f usr/include/sys/usb/clients/ccid/ccid.h 0644 root bin +f usr/include/sys/usb/clients/ccid/uccid.h 0644 root bin d usr/include/sys/usb/clients/hid 0755 root bin f usr/include/sys/usb/clients/hid/hid.h 0644 root bin d usr/include/sys/usb/clients/mass_storage 0755 root bin @@ -4932,6 +4936,8 @@ f usr/include/wchar.h 0644 root bin f usr/include/wchar_impl.h 0644 root bin f usr/include/wctype.h 0644 root bin f usr/include/widec.h 0644 root bin +f usr/include/winscard.h 0644 root bin +f usr/include/wintypes.h 0644 root bin f usr/include/wordexp.h 0644 root bin f usr/include/xlocale.h 0644 root bin f usr/include/xti.h 0644 root bin @@ -5292,6 +5298,7 @@ f usr/lib/amd64/libpanel.so.1 0755 root bin s usr/lib/amd64/libpanel.so=libpanel.so.1 f usr/lib/amd64/libpcidb.so.1 0755 root bin f usr/lib/amd64/libpcsc.so.1 0755 root bin +s usr/lib/amd64/libpcsc.so=libpcsc.so.1 f usr/lib/amd64/libpctx.so.1 0755 root bin s usr/lib/amd64/libpctx.so=libpctx.so.1 f usr/lib/amd64/libpicl.so.1 0755 root bin @@ -6808,6 +6815,7 @@ f usr/lib/libpanel.so.1 0755 root bin s usr/lib/libpanel.so=libpanel.so.1 f usr/lib/libpcidb.so.1 0755 root bin f usr/lib/libpcsc.so.1 0755 root bin +s usr/lib/libpcsc.so=libpcsc.so.1 f usr/lib/libpctx.so.1 0755 root bin s usr/lib/libpctx.so=libpctx.so.1 f usr/lib/libpicl.so.1 0755 root bin @@ -11949,6 +11957,7 @@ f usr/share/man/man1/date.1 0444 root bin f usr/share/man/man1/dc.1 0444 root bin f usr/share/man/man1/deallocate.1 0444 root bin s usr/share/man/man1/decrypt.1=encrypt.1 +f usr/share/man/man1/demangle.1 0444 root bin f usr/share/man/man1/deroff.1 0444 root bin f usr/share/man/man1/dhcpinfo.1 0444 root bin f usr/share/man/man1/diff.1 0444 root bin diff --git a/usr/src/cmd/Makefile b/usr/src/cmd/Makefile index 7a410a3a49..dd035124e9 100644 --- a/usr/src/cmd/Makefile +++ b/usr/src/cmd/Makefile @@ -119,6 +119,7 @@ COMMON_SUBDIRS= \ date \ dc \ dd \ + demangle \ deroff \ devfsadm \ syseventd \ diff --git a/usr/src/cmd/ccidadm/Makefile b/usr/src/cmd/ccidadm/Makefile index de9761ff9d..d1d9221c80 100644 --- a/usr/src/cmd/ccidadm/Makefile +++ b/usr/src/cmd/ccidadm/Makefile @@ -18,15 +18,12 @@ PROG= ccidadm include ../Makefile.cmd include ../Makefile.ctf -ROOTCMDDIR = $(ROOTLIB)/ccid CFLAGS += $(CCVERBOSE) LDLIBS += -lofmt -lcmdutils SRCS = ccidadm.c atr.c OBJS = $(SRCS:%.c=%.o) CPPFLAGS += -I$(SRC)/common/ccid -ROOTCCIDFILES = $(PROG:%=$(ROOTCMDDIR)/%) - .KEEP_STATE: $(PROG): $(OBJS) @@ -43,9 +40,9 @@ $(PROG): $(OBJS) all: $(PROG) -install: all $(ROOTCMD) +install: all $(ROOTUSRSBINPROG) clean: - $(RM) $(OBJS) + $(RM) $(OBJS) $(PROG) include ../Makefile.targ diff --git a/usr/src/cmd/ccidadm/ccidadm.c b/usr/src/cmd/ccidadm/ccidadm.c index 1d3c2bcbfc..6309ecfcc8 100644 --- a/usr/src/cmd/ccidadm/ccidadm.c +++ b/usr/src/cmd/ccidadm/ccidadm.c @@ -220,7 +220,7 @@ static boolean_t ccidadm_list_slot_usable_str(uccid_cmd_status_t *ucs, char *buf, uint_t buflen) { - char *un = ""; + const char *un = ""; ccid_class_features_t feat; uint_t prot = CCID_CLASS_F_SHORT_APDU_XCHG | CCID_CLASS_F_EXT_APDU_XCHG; uint_t param = CCID_CLASS_F_AUTO_PARAM_NEG | CCID_CLASS_F_AUTO_PPS; diff --git a/usr/src/cmd/demangle/Makefile b/usr/src/cmd/demangle/Makefile new file mode 100644 index 0000000000..8366ac85f3 --- /dev/null +++ b/usr/src/cmd/demangle/Makefile @@ -0,0 +1,40 @@ +# +# This file and its contents are supplied under the terms of the +# Common Development and Distribution License ("CDDL"), version 1.0. +# You may only use this file in accordance with the terms of version +# 1.0 of the CDDL. +# +# A full copy of the text of the CDDL should have accompanied this +# source. A copy of the CDDL is also available via the Internet at +# http://www.illumos.org/license/CDDL. +# + +# +# Copyright 2020 Joyent, Inc. +# + +PROG= demangle +OBJS= demangle.o +SRCS= $(OBJS:%.o=%.c) + +include $(SRC)/cmd/Makefile.cmd +include $(SRC)/cmd/Makefile.ctf + +CSTD= $(CSTD_GNU99) + +LDLIBS += -ldemangle-sys -lcustr + +.KEEP_STATE: + +all: $(PROG) + +$(PROG): $(OBJS) + $(LINK.c) $(OBJS) -o $@ $(LDLIBS) + $(POST_PROCESS) + +clean: + $(RM) $(OBJS) + +install: all $(ROOTPROG) + +include $(SRC)/cmd/Makefile.targ diff --git a/usr/src/cmd/demangle/demangle.c b/usr/src/cmd/demangle/demangle.c new file mode 100644 index 0000000000..33a68edc9e --- /dev/null +++ b/usr/src/cmd/demangle/demangle.c @@ -0,0 +1,211 @@ +/* + * This file and its contents are supplied under the terms of the + * Common Development and Distribution License ("CDDL"), version 1.0. + * You may only use this file in accordance with the terms of version + * 1.0 of the CDDL. + * + * A full copy of the text of the CDDL should have accompanied this + * source. A copy of the CDDL is also available via the Internet at + * http://www.illumos.org/license/CDDL. + */ + +/* + * Copyright 2020 Joyent, Inc. + */ + +#include <ctype.h> +#include <demangle-sys.h> +#include <err.h> +#include <errno.h> +#include <libcustr.h> +#include <locale.h> +#include <stdio.h> +#include <stdlib.h> + +#define _(x) gettext(x) + +locale_t c_locale; + +static int do_symbols(sysdem_lang_t, int, char * const *); +static int do_input(sysdem_lang_t, FILE *restrict, FILE *restrict); +static int do_demangle(const char *, sysdem_lang_t, FILE *); +static void appendc(custr_t *, char); +static void xputc(int, FILE *); + +static void +usage(void) +{ + (void) fprintf(stderr, _("Usage: %s [-l lang] [sym...]\n"), + getprogname()); + exit(2); +} + +int +main(int argc, char * const *argv) +{ + sysdem_lang_t lang = SYSDEM_LANG_AUTO; + int c; + int ret; + + (void) setlocale(LC_ALL, ""); + +#if !defined(TEXT_DOMAIN) +#define TEXT_DOMAIN "SYS_TEST" +#endif + (void) textdomain(TEXT_DOMAIN); + + /* + * For detecting symbol boundaries, we want to use the C locale + * definitions for use in isalnum_l(). + */ + if ((c_locale = newlocale(LC_CTYPE_MASK, "C", NULL)) == NULL) + err(EXIT_FAILURE, _("failed to construct C locale")); + + while ((c = getopt(argc, argv, "hl:")) != -1) { + switch (c) { + case 'l': + if (sysdem_parse_lang(optarg, &lang)) + break; + + errx(EXIT_FAILURE, _("Unsupported language '%s'\n"), + optarg); + case 'h': + case '?': + usage(); + } + } + + argc -= optind; + argv += optind; + + if (argc > 0) + ret = do_symbols(lang, argc, argv); + else + ret = do_input(lang, stdin, stdout); + + return ((ret < 0) ? EXIT_FAILURE : EXIT_SUCCESS); +} + +static int +do_symbols(sysdem_lang_t lang, int argc, char * const *argv) +{ + int ret = 0; + + for (int i = 0; i < argc; i++) { + if (do_demangle(argv[i], lang, stdout) < 0) + ret = -1; + else + xputc('\n', stdout); + } + + return (ret); +} + +static int +do_input(sysdem_lang_t lang, FILE *restrict in, FILE *restrict out) +{ + custr_t *word = NULL; + int c; + int ret = 0; + boolean_t in_symbol = B_FALSE; + + if (custr_alloc(&word) != 0) + err(EXIT_FAILURE, _("failed to allocate memory")); + + while ((c = fgetc(in)) != EOF) { + if (in_symbol) { + /* + * All currently supported mangling formats only use + * alphanumeric characters, '.', '_', or '$' in + * mangled names. Once we've seen the potential start + * of a symbol ('_'), we accumulate subsequent + * charaters into 'word'. If we encounter a character + * that is not a part of that set ([A-Za-z0-9._$]), we + * treat it as a delimiter, we stop accumulating + * characters into word, and we attempt to demangle the + * accumulated string in 'word' by calling + * demangle_custr(). + * + * Similar utilities like c++filt behave in a similar + * fashion when reading from stdin to allow for + * demangling of symbols embedded in surrounding text. + */ + if (isalnum_l(c, c_locale) || c == '.' || c == '_' || + c == '$') { + appendc(word, c); + continue; + } + + /* + * Hit a symbol boundary, attempt to demangle what + * we've accumulated in word and reset word. + */ + if (do_demangle(custr_cstr(word), lang, out) < 0) + ret = -1; + + custr_reset(word); + in_symbol = B_FALSE; + } + + if (c != '_') { + xputc(c, out); + } else { + in_symbol = B_TRUE; + appendc(word, c); + } + } + + if (ferror(in)) + err(EXIT_FAILURE, _("error reading input")); + + /* + * If we were accumulating characters for a symbol and hit EOF, + * attempt to demangle what we accumulated. + */ + if (custr_len(word) > 0 && do_demangle(custr_cstr(word), lang, out) < 0) + ret = -1; + + custr_free(word); + return (ret); +} + +/* + * Attempt to demangle 'sym' as a symbol for 'lang' and write the result + * to 'out'. If 'sym' could not be demangled as 'lang' symbol, the original + * string is output instead. + * + * If an error other than 'not a mangled symbol' is encountered (e.g. ENOMEM), + * a warning is sent to stderr and -1 is returned. Otherwise, 0 is returned + * (including when 'sym' is merely not a mangled symbol of 'lang'). + */ +static int +do_demangle(const char *sym, sysdem_lang_t lang, FILE *out) +{ + char *demangled = sysdemangle(sym, lang, NULL); + + if (demangled == NULL && errno != EINVAL) { + warn(_("error while demangling '%s'"), sym); + return (-1); + } + + if (fprintf(out, "%s", (demangled != NULL) ? demangled : sym) < 0) + err(EXIT_FAILURE, _("failed to write to output")); + + free(demangled); + return (0); +} + +static void +appendc(custr_t *cus, char c) +{ + if (custr_appendc(cus, c) == 0) + return; + err(EXIT_FAILURE, _("failed to save character from input")); +} + +static void +xputc(int c, FILE *out) +{ + if (fputc(c, out) < 0) + err(EXIT_FAILURE, _("failed to write output")); +} diff --git a/usr/src/cmd/devfsadm/usb_link.c b/usr/src/cmd/devfsadm/usb_link.c index 80996a1773..b233f85daf 100644 --- a/usr/src/cmd/devfsadm/usb_link.c +++ b/usr/src/cmd/devfsadm/usb_link.c @@ -316,8 +316,8 @@ usb_process(di_minor_t minor, di_node_t node) return (DEVFSADM_CONTINUE); } - if (strcmp(di_minor_nodetype(minor), DDI_NT_CCID_ATTACHMENT_POINT) - == 0) { + if (strcmp(di_minor_nodetype(minor), DDI_NT_CCID_ATTACHMENT_POINT) == + 0) { ccid_create_link(p_path, minor_nm, node, minor); free(l_path); free(p_path); diff --git a/usr/src/common/ccid/atr.c b/usr/src/common/ccid/atr.c index db83c91ceb..d43aa585c5 100644 --- a/usr/src/common/ccid/atr.c +++ b/usr/src/common/ccid/atr.c @@ -20,7 +20,6 @@ #include "atr.h" #include <sys/debug.h> -#include <sys/limits.h> #include <sys/sysmacros.h> #ifdef _KERNEL diff --git a/usr/src/lib/cfgadm_plugins/ccid/common/cfga_ccid.c b/usr/src/lib/cfgadm_plugins/ccid/common/cfga_ccid.c index 4ce28c2aec..3a44580306 100644 --- a/usr/src/lib/cfgadm_plugins/ccid/common/cfga_ccid.c +++ b/usr/src/lib/cfgadm_plugins/ccid/common/cfga_ccid.c @@ -376,10 +376,9 @@ cfga_list_ext(const char *ap, struct cfga_list_data **ap_list, int *nlist, } /* - * XXX We should probably have a way to indicate that there's an error - * when the ICC is basically foobar'd. We should also allow the status - * ioctl to know that the slot is resetting or something else is going - * on I guess. + * We should probably have a way to indicate that there's an error when + * the ICC is basically foobar'd. We should also allow the status ioctl + * to know that the slot is resetting or something else is going on. */ if ((ucs.ucs_class.ccd_dwFeatures & (CCID_CLASS_F_SHORT_APDU_XCHG | CCID_CLASS_F_EXT_APDU_XCHG)) == 0) { diff --git a/usr/src/lib/fm/topo/modules/i86pc/chip/chip_intel.c b/usr/src/lib/fm/topo/modules/i86pc/chip/chip_intel.c index 4c5da1e8cb..df6e2b6f95 100644 --- a/usr/src/lib/fm/topo/modules/i86pc/chip/chip_intel.c +++ b/usr/src/lib/fm/topo/modules/i86pc/chip/chip_intel.c @@ -73,6 +73,8 @@ #define DIMM_HDRL "hdrl-enabled" #define DIMM_HDRL_PARITY "hdrl-parity" #define DIMM_3DRANK "3d-subranks" +#define RANK_STATUS "dimm-rank-status" +#define RANK_SIZE "dimm-rank-size" static const topo_pgroup_info_t dimm_channel_pgroup = { PGNAME(CHAN), TOPO_STABILITY_PRIVATE, TOPO_STABILITY_PRIVATE, 1 }; @@ -156,7 +158,7 @@ mc_add_ranks(topo_mod_t *mod, tnode_t *dnode, nvlist_t *auth, int dimm, (void) topo_node_fru_set(rnode, NULL, 0, &err); if (topo_method_register(mod, rnode, rank_methods) < 0) - whinge(mod, &err, "rank_create: " + whinge(mod, &err, "mc_add_ranks: " "topo_method_register failed"); if (! is_xpv() && topo_method_register(mod, rnode, @@ -455,6 +457,102 @@ mc_nb_create(topo_mod_t *mod, uint16_t chip_smbid, tnode_t *pnode, } static int +mc_rank_create_v1(topo_mod_t *mod, tnode_t *pnode, nvlist_t *auth, + nvlist_t *dimm_nvl, uint64_t rsize, uint32_t id) +{ + nvlist_t *fmri; + tnode_t *rank; + int err; + boolean_t *disabled; + uint_t ndisabled; + const char *status; + + fmri = topo_mod_hcfmri(mod, pnode, FM_HC_SCHEME_VERSION, RANK, id, + NULL, auth, NULL, NULL, NULL); + if (fmri == NULL) { + whinge(mod, NULL, "mc_rank_create_v1: topo_mod_hcfmri " + "failed\n"); + return (-1); + } + + if ((rank = topo_node_bind(mod, pnode, RANK, id, fmri)) == NULL) { + whinge(mod, NULL, "mc_rank_create_v1: node bind failed for " + "DIMM\n"); + nvlist_free(fmri); + return (-1); + } + + if (topo_method_register(mod, rank, rank_methods) < 0) { + whinge(mod, NULL, "mc_rank_create_v1: topo_method_register " + "failed for rank_methods: %d", topo_mod_errno(mod)); + } + + if (!is_xpv() && topo_method_register(mod, rank, + ntv_page_retire_methods) != 0) { + whinge(mod, NULL, "mc_rank_create_v1: topo_method_register " + "failed for page retire: %d", topo_mod_errno(mod)); + } + + if (topo_node_asru_set(rank, fmri, TOPO_ASRU_COMPUTE, &err) != 0) { + whinge(mod, NULL, "mc_rank_create_v1: failed to set asru: %d", + err); + nvlist_free(fmri); + return (topo_mod_seterrno(mod, err)); + } + + if (topo_node_fru_set(rank, NULL, 0, &err) != 0) { + whinge(mod, NULL, "mc_rank_create_v1: fru set failed: " + "%d\n", err); + nvlist_free(fmri); + return (topo_mod_seterrno(mod, err)); + } + nvlist_free(fmri); + + if (topo_pgroup_create(rank, &rank_pgroup, &err) != 0) { + whinge(mod, NULL, "mc_rank_create_v1: failed to create " + "property group: %d\n", err); + return (topo_mod_seterrno(mod, err)); + } + + /* + * The traditional northbridge driver broke down each rank into the + * interleave targets that led to it. At this time, the imc driver (the + * only v1 provider) does not supply that information and therefore we + * cannot set that. Instead we just set basic properties on this, the + * size of the rank and whether or not it is disabled. + */ + if (rsize != 0 && topo_prop_set_uint64(rank, PGNAME(RANK), RANK_SIZE, + TOPO_PROP_IMMUTABLE, rsize, &err) != 0) { + whinge(mod, NULL, "mc_rank_create_v1: failed to set %s " + "property: %d", RANK_SIZE, err); + return (topo_mod_seterrno(mod, err)); + } + + if (nvlist_lookup_boolean_array(dimm_nvl, MCINTEL_NVLIST_V1_DIMM_RDIS, + &disabled, &ndisabled) != 0) { + whinge(mod, NULL, "mc_rank_create_v1: Couldn't find disabled " + "ranks array"); + return (topo_mod_seterrno(mod, EMOD_UNKNOWN)); + } + + if (id >= ndisabled) { + whinge(mod, NULL, "mc_rank_create_v1: Found rank %u with id " + "larger than supported by hardware", id); + return (topo_mod_seterrno(mod, EMOD_UNKNOWN)); + } + + status = disabled[id] ? "disabled" : "enabled"; + if (topo_prop_set_string(rank, PGNAME(RANK), RANK_STATUS, + TOPO_PROP_IMMUTABLE, status, &err) != 0) { + whinge(mod, NULL, "mc_rank_create_v1: failed to set %s " + "property: %d", RANK_STATUS, err); + return (topo_mod_seterrno(mod, err)); + } + + return (0); +} + +static int mc_dimm_create_v1(topo_mod_t *mod, tnode_t *pnode, nvlist_t *auth, nvlist_t *dimm_nvl, uint_t id) { @@ -462,8 +560,8 @@ mc_dimm_create_v1(topo_mod_t *mod, tnode_t *pnode, nvlist_t *auth, tnode_t *dimm; nvlist_t *fmri; boolean_t present; - uint64_t size, density; - uint32_t cols, rows, width, ranks, banks; + uint64_t size, density, rsize; + uint32_t cols, rows, width, ranks, banks, i; /* * First, figure out if this DIMM is present. If not, we don't bother @@ -510,8 +608,10 @@ mc_dimm_create_v1(topo_mod_t *mod, tnode_t *pnode, nvlist_t *auth, &size) == 0) { char buf[64]; const char *suffix; + uint64_t tsize; ret |= topo_prop_set_uint64(dimm, PGNAME(DIMM), DIMM_SIZE, TOPO_PROP_IMMUTABLE, size, &err); + tsize = size; /* * We must manually cons up a dimm-size property which is the @@ -520,68 +620,115 @@ mc_dimm_create_v1(topo_mod_t *mod, tnode_t *pnode, nvlist_t *auth, * controller drivers did this in the driver, but we instead opt * to do so in user land. */ - if (size >= (1ULL << 40)) { - size /= (1ULL << 40); + if (tsize >= (1ULL << 40)) { + tsize /= (1ULL << 40); suffix = "T"; - } else if (size >= (1ULL << 30)) { - size /= (1ULL << 30); + } else if (tsize >= (1ULL << 30)) { + tsize /= (1ULL << 30); suffix = "G"; - } else if (size >= (1ULL << 20)) { - size /= (1ULL << 20); + } else if (tsize >= (1ULL << 20)) { + tsize /= (1ULL << 20); suffix = "M"; } else { suffix = NULL; } if (suffix != NULL) { - if (snprintf(buf, sizeof (buf), "%"PRIu64"%s", size, + if (snprintf(buf, sizeof (buf), "%"PRIu64"%s", tsize, suffix) >= sizeof (buf)) { whinge(mod, NULL, "failed to construct DIMM " "size due to buffer overflow"); return (topo_mod_seterrno(mod, EMOD_UNKNOWN)); } - ret |= topo_prop_set_string(dimm, PGNAME(DIMM), + ret = topo_prop_set_string(dimm, PGNAME(DIMM), DIMM_STRING_SIZE, TOPO_PROP_IMMUTABLE, buf, &err); + if (ret != 0) { + return (topo_mod_seterrno(mod, err)); + } } + } else { + size = 0; } if (nvlist_lookup_uint32(dimm_nvl, MCINTEL_NVLIST_V1_DIMM_NCOLS, &cols) == 0) { - ret |= topo_prop_set_uint32(dimm, PGNAME(DIMM), DIMM_COL, + ret = topo_prop_set_uint32(dimm, PGNAME(DIMM), DIMM_COL, TOPO_PROP_IMMUTABLE, cols, &err); + if (ret != 0) { + return (topo_mod_seterrno(mod, err)); + } } if (nvlist_lookup_uint32(dimm_nvl, MCINTEL_NVLIST_V1_DIMM_NROWS, &rows) == 0) { - ret |= topo_prop_set_uint32(dimm, PGNAME(DIMM), DIMM_ROW, + ret = topo_prop_set_uint32(dimm, PGNAME(DIMM), DIMM_ROW, TOPO_PROP_IMMUTABLE, rows, &err); + if (ret != 0) { + return (topo_mod_seterrno(mod, err)); + } } if (nvlist_lookup_uint64(dimm_nvl, MCINTEL_NVLIST_V1_DIMM_DENSITY, &density) == 0) { - ret |= topo_prop_set_uint64(dimm, PGNAME(DIMM), DIMM_DENSITY, + ret = topo_prop_set_uint64(dimm, PGNAME(DIMM), DIMM_DENSITY, TOPO_PROP_IMMUTABLE, density, &err); + if (ret != 0) { + return (topo_mod_seterrno(mod, err)); + } } if (nvlist_lookup_uint32(dimm_nvl, MCINTEL_NVLIST_V1_DIMM_WIDTH, &width) == 0) { - ret |= topo_prop_set_uint32(dimm, PGNAME(DIMM), DIMM_WIDTH, + ret = topo_prop_set_uint32(dimm, PGNAME(DIMM), DIMM_WIDTH, TOPO_PROP_IMMUTABLE, width, &err); + if (ret != 0) { + return (topo_mod_seterrno(mod, err)); + } } if (nvlist_lookup_uint32(dimm_nvl, MCINTEL_NVLIST_V1_DIMM_BANKS, &banks) == 0) { - ret |= topo_prop_set_uint32(dimm, PGNAME(DIMM), DIMM_BANKS, + ret = topo_prop_set_uint32(dimm, PGNAME(DIMM), DIMM_BANKS, TOPO_PROP_IMMUTABLE, banks, &err); + if (ret != 0) { + return (topo_mod_seterrno(mod, err)); + } + } else { + banks = 0; } if (nvlist_lookup_uint32(dimm_nvl, MCINTEL_NVLIST_V1_DIMM_RANKS, &ranks) == 0) { - ret |= topo_prop_set_uint32(dimm, PGNAME(DIMM), DIMM_RANKS, + ret = topo_prop_set_uint32(dimm, PGNAME(DIMM), DIMM_RANKS, TOPO_PROP_IMMUTABLE, ranks, &err); + if (ret != 0) { + return (topo_mod_seterrno(mod, err)); + } + } + + if (ret != 0) { + return (-1); + } + + if (topo_node_range_create(mod, dimm, RANK, 0, ranks - 1) < 0) { + whinge(mod, NULL, "mc_dimm_create_v1: rank node range " + "create failed\n"); + return (-1); + } + + rsize = 0; + if (size != 0 && banks != 0) { + rsize = size / banks; } - return (ret != 0 ? -1 : 0); + for (i = 0; i < ranks; i++) { + if (mc_rank_create_v1(mod, dimm, auth, dimm_nvl, rsize, i) != + 0) { + return (-1); + } + } + + return (0); } static int @@ -657,12 +804,12 @@ mc_imc_create_v1(topo_mod_t *mod, tnode_t *pnode, const char *name, uint_t nchans, i; if (mkrsrc(mod, pnode, name, id, auth, &fmri) != 0) { - whinge(mod, NULL, "mc_nb_create_v1: mkrsrc failed\n"); + whinge(mod, NULL, "mc_imc_create_v1: mkrsrc failed\n"); return (-1); } if ((mcnode = topo_node_bind(mod, pnode, name, id, fmri)) == NULL) { - whinge(mod, NULL, "mc_nb_create_v1: node bind failed" + whinge(mod, NULL, "mc_imc_create_v1: node bind failed" " for memory-controller\n"); nvlist_free(fmri); return (-1); @@ -670,13 +817,13 @@ mc_imc_create_v1(topo_mod_t *mod, tnode_t *pnode, const char *name, nvlist_free(fmri); if (topo_node_fru_set(mcnode, NULL, 0, &err) != 0) { - whinge(mod, NULL, "mc_nb_create_v1: fru set failed: " + whinge(mod, NULL, "mc_imc_create_v1: fru set failed: " "%d\n", err); return (topo_mod_seterrno(mod, err)); } if (topo_pgroup_create(mcnode, &mc_pgroup, &err) != 0) { - whinge(mod, NULL, "mc_nb_create_v1: failed to create " + whinge(mod, NULL, "mc_imc_create_v1: failed to create " "property group: %d\n", err); return (topo_mod_seterrno(mod, err)); } @@ -689,14 +836,20 @@ mc_imc_create_v1(topo_mod_t *mod, tnode_t *pnode, const char *name, if (nvlist_lookup_boolean_value(mc_nvl, MCINTEL_NVLIST_V1_MC_ECC, &ecc) == 0) { const char *pval = ecc ? "enabled" : "disabled"; - ret |= topo_prop_set_string(mcnode, PGNAME(MCT), MC_PROP_ECC, + ret = topo_prop_set_string(mcnode, PGNAME(MCT), MC_PROP_ECC, TOPO_PROP_IMMUTABLE, pval, &err); + if (ret != 0) { + return (topo_mod_seterrno(mod, err)); + } } if (nvlist_lookup_string(mc_nvl, MCINTEL_NVLIST_V1_MC_POLICY, &page) == 0) { - ret |= topo_prop_set_string(mcnode, PGNAME(MCT), MC_PROP_POLICY, + ret = topo_prop_set_string(mcnode, PGNAME(MCT), MC_PROP_POLICY, TOPO_PROP_IMMUTABLE, page, &err); + if (ret != 0) { + return (topo_mod_seterrno(mod, err)); + } } if (nvlist_lookup_string(mc_nvl, MCINTEL_NVLIST_V1_MC_CHAN_MODE, @@ -704,9 +857,6 @@ mc_imc_create_v1(topo_mod_t *mod, tnode_t *pnode, const char *name, cmode = NULL; } - if (ret != 0) - return (-1); - if (nvlist_lookup_nvlist_array(mc_nvl, MCINTEL_NVLIST_V1_MC_CHANNELS, &channels, &nchans) != 0) { whinge(mod, NULL, "mc_imc_create_v1: missing channels entry"); @@ -746,7 +896,7 @@ mc_nb_create_v1(topo_mod_t *mod, tnode_t *pnode, const char *name, if (topo_node_range_create(mod, pnode, name, 0, nmc - 1) < 0) { whinge(mod, NULL, - "mc_nb_create: node range create failed\n"); + "mc_nb_create_v1: node range create failed\n"); return (-1); } diff --git a/usr/src/lib/libcmdutils/common/nicenum.c b/usr/src/lib/libcmdutils/common/nicenum.c index 9b9a8fcd5e..a9161c422c 100644 --- a/usr/src/lib/libcmdutils/common/nicenum.c +++ b/usr/src/lib/libcmdutils/common/nicenum.c @@ -45,13 +45,11 @@ nicenum_scale(uint64_t n, size_t units, char *buf, size_t buflen, uint64_t divisor = 1; int index = 0; int rc = 0; - int spclen = 0; - char *spc = ""; + const char *spc = ""; char u; if (flags & NN_UNIT_SPACE) { spc = " "; - spclen = 1; } if (units == 0) @@ -92,7 +90,7 @@ nicenum_scale(uint64_t n, size_t units, char *buf, size_t buflen, u = " KMGTPE"[index]; if (index == 0) { - rc = snprintf(buf, buflen, "%llu", n); + rc = snprintf(buf, buflen, "%llu%s", n, spc); } else if (n % divisor == 0) { /* * If this is an even multiple of the base, always display @@ -102,7 +100,7 @@ nicenum_scale(uint64_t n, size_t units, char *buf, size_t buflen, } else { /* * We want to choose a precision that reflects the best choice - * for fitting in 5 characters. This can get rather tricky + * for fitting in the buffer. This can get rather tricky * when we have numbers that are very close to an order of * magnitude. For example, when displaying 10239 (which is * really 9.999K), we want only a single place of precision @@ -113,7 +111,7 @@ nicenum_scale(uint64_t n, size_t units, char *buf, size_t buflen, int i; for (i = 2; i >= 0; i--) { if ((rc = snprintf(buf, buflen, "%.*f%s%c", i, - (double)n / divisor, spc, u)) <= 5 + spclen) + (double)n / divisor, spc, u)) <= (buflen - 1)) break; } } diff --git a/usr/src/lib/libdemangle/common/demangle-sys.h b/usr/src/lib/libdemangle/common/demangle-sys.h index 05776ee5ee..3452d39667 100644 --- a/usr/src/lib/libdemangle/common/demangle-sys.h +++ b/usr/src/lib/libdemangle/common/demangle-sys.h @@ -11,7 +11,7 @@ /* * Copyright 2017 Jason King - * Copyright 2018, Joyent, Inc. + * Copyright 2019 Joyent, Inc. */ #ifndef _DEMANGLE_SYS_H @@ -34,6 +34,7 @@ typedef struct sysdem_alloc_s { void (*free)(void *, size_t); } sysdem_ops_t; +boolean_t sysdem_parse_lang(const char *, sysdem_lang_t *); char *sysdemangle(const char *, sysdem_lang_t, sysdem_ops_t *); #ifdef __cplusplus diff --git a/usr/src/lib/libdemangle/common/demangle.c b/usr/src/lib/libdemangle/common/demangle.c index 4f8e9ad678..b6db356416 100644 --- a/usr/src/lib/libdemangle/common/demangle.c +++ b/usr/src/lib/libdemangle/common/demangle.c @@ -21,6 +21,7 @@ #include <pthread.h> #include <sys/ctype.h> #include <sys/debug.h> +#include <sys/sysmacros.h> #include <stdarg.h> #include "demangle-sys.h" #include "demangle_int.h" @@ -31,19 +32,40 @@ static pthread_once_t debug_once = PTHREAD_ONCE_INIT; volatile boolean_t demangle_debug; FILE *debugf = stderr; +static struct { + const char *str; + sysdem_lang_t lang; +} lang_tbl[] = { + { "auto", SYSDEM_LANG_AUTO }, + { "c++", SYSDEM_LANG_CPP }, + { "rust", SYSDEM_LANG_RUST }, +}; + static const char * langstr(sysdem_lang_t lang) { - switch (lang) { - case SYSDEM_LANG_AUTO: - return ("auto"); - case SYSDEM_LANG_CPP: - return ("c++"); - case SYSDEM_LANG_RUST: - return ("rust"); - default: - return ("invalid"); + size_t i; + + for (i = 0; i < ARRAY_SIZE(lang_tbl); i++) { + if (lang == lang_tbl[i].lang) + return (lang_tbl[i].str); } + return ("invalid"); +} + +boolean_t +sysdem_parse_lang(const char *str, sysdem_lang_t *langp) +{ + size_t i; + + for (i = 0; i < ARRAY_SIZE(lang_tbl); i++) { + if (strcmp(str, lang_tbl[i].str) == 0) { + *langp = lang_tbl[i].lang; + return (B_TRUE); + } + } + + return (B_FALSE); } static sysdem_lang_t diff --git a/usr/src/lib/libdemangle/common/mapfile-vers b/usr/src/lib/libdemangle/common/mapfile-vers index 48c11ef0d7..2207547185 100644 --- a/usr/src/lib/libdemangle/common/mapfile-vers +++ b/usr/src/lib/libdemangle/common/mapfile-vers @@ -11,6 +11,7 @@ # # Copyright 2017 Jason King +# Copyright 2019 Joyent, Inc. # # @@ -30,6 +31,7 @@ $mapfile_version 2 SYMBOL_VERSION ILLUMOSprivate { global: + sysdem_parse_lang; sysdemangle; local: *; diff --git a/usr/src/man/man1/Makefile b/usr/src/man/man1/Makefile index d7904100eb..c80c00d8ed 100644 --- a/usr/src/man/man1/Makefile +++ b/usr/src/man/man1/Makefile @@ -14,6 +14,7 @@ # Copyright 2018 Nexenta Systems, Inc. # Copyright 2014 Garrett D'Amore <garrett@damore.org> # Copyright 2019 OmniOS Community Edition (OmniOSce) Association. +# Copyright 2020 Joyent, Inc. # include $(SRC)/Makefile.master @@ -95,6 +96,7 @@ MANFILES= acctcom.1 \ date.1 \ dc.1 \ deallocate.1 \ + demangle.1 \ deroff.1 \ dhcpinfo.1 \ diff.1 \ diff --git a/usr/src/man/man1/demangle.1 b/usr/src/man/man1/demangle.1 new file mode 100644 index 0000000000..ca2dbef35a --- /dev/null +++ b/usr/src/man/man1/demangle.1 @@ -0,0 +1,119 @@ +.\" The contents of this file are subject to the terms of the +.\" Common Development and Distribution License (the "License"). +.\" You may not use this file except in compliance with the License. +.\" +.\" You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +.\" or http://www.opensolaris.org/os/licensing. +.\" See the License for the specific language governing permissions +.\" and limitations under the License. +.\" +.\" When distributing Covered Code, include this CDDL HEADER in each +.\" file and include the License file at usr/src/OPENSOLARIS.LICENSE. +.\" If applicable, add the following below this CDDL HEADER, with the +.\" fields enclosed by brackets "[]" replaced with your own identifying +.\" information: Portions Copyright [yyyy] [name of copyright owner] +.\" +.\" Copyright 2020 Joyent, Inc. +.\" +.Dd March 3, 2020 +.Dt DEMANGLE 1 +.Os +.Sh NAME +.Nm demangle +.Nd demangle symbols +.Sh SYNOPSIS +.Nm +.Oo +.Fl l +.Ar lang +.Oc +.Op Ar symbol Ns ... +.Sh DESCRIPTION +The +.Nm +utility attempts to detect mangled symbols and transform them back into a +more human friendly version of the symbol. +.Pp +Some languages allow the same identifier to refer to multiple things +(functions, variables, etc\&.) where some additional context such as +parameter types, return types, etc\&. are used to disambiguate between the +symbols sharing the same name. +When compiling such languages into an executable form, most binary formats +do not allow for duplicate symbol names or provide a way to disambiguate +between duplicate names. +.Pp +To solve this problem, many languages will use the additional context from +the source code to transform the symbol name into a unique name. +This process is called name mangling. +While the resulting name is predictable, the mangled names are often difficult +for humans to interpret. +.Pp +The +.Nm +utility can be invoked in one of two ways. +In the first method, +.Ar symbol +is demangled and the result is written to standard out, one line per input +.Ar symbol . +If any input +.Ar symbol +cannot be demangled, the original value of +.Ar symbol +is output unchanged. +In the second method, +.Nm +reads standard in, and whenever it encounters a potential symbol, it will +attempt to replace the symbol in stdandard out with the demangled version. +If the symbol cannot be demangled, it is output unchanged. +.Pp +For either method, if an error other than attempting to demangle an non-mangled +symbol (e.g. out of memory), that error will be written to standard error. +.Sh OPTIONS +.Bl -tag -width Fl +.It Fl l Ar lang +Treat all potential symbols as symbols from +.Ar lang . +By default, +.Nm +will attempt to detect the language and demangle symbols for all supported +languages. +Current supported values of +.Ar lang +are: +.Bl -tag -width rust -offset indent +.It c++ +The C++ mangling format defined by the Itanium ABI. +While the mangling format was originally defined for the Itanium processor, g++ +and clang use this format for all their supported platforms (including x86 and +SPARC). +.It rust +The legacy rust mangling format. +.It auto +Attempt to detect the language automatically (default). +.El +.El +.Sh EXIT STATUS +.Ex -std +.Sh EXAMPLES +.Sy Example 1 +Demangle symbols given as command line arguments. +.Bd -literal +% demangle '_ZGVN9__gnu_cxx16bitmap_allocatorIwE13_S_mem_blocksE' +guard variable for __gnu_cxx::bitmap_allocator<wchar_t>::_S_mem_blocks +% +.Ed +.Pp +.Sy Example 2 +Demangle symbols from the output of another command. +.Bd -literal +% grep slice rust.c | head -1 + T("__ZN4core5slice89_$LT$impl$u20$core..iter..traits..IntoIterator$u20$for$u20$$RF$$u27$a$u20$$u5b$T$u5d$$GT$9into_iter17h450e234d27262170E", +% grep slice rust.c | head -1 | demangle + T("core::slice::<impl core::iter::traits::IntoIterator for &'a [T]>::into_iter::h450e234d27262170", +% +.Ed +.Sh INTERFACE STABILITY +The command line options are +.Sy Uncommitted . +The output format is +.Sy Not-an-Interface . diff --git a/usr/src/man/man1m/ccidadm.1m b/usr/src/man/man1m/ccidadm.1m index 686db8cb46..d1a09e25cf 100644 --- a/usr/src/man/man1m/ccidadm.1m +++ b/usr/src/man/man1m/ccidadm.1m @@ -18,14 +18,14 @@ .Nm ccidadm .Nd CCID administration utility .Sh SYNOPSIS -.Nm /usr/lib/ccid/ccidadm -.Ar list -.Nm /usr/lib/ccid/ccidadm -.Ar atr +.Nm +.Cm list +.Nm +.Cm atr .Op Fl pvx .Op Ar device -.Nm /usr/lib/ccid/ccidadm -.Ar reader +.Nm +.Cm reader .Op Ar device .Sh DESCRIPTION The @@ -48,7 +48,8 @@ Any command .Nm understands. See section -.Sx COMMANDS . +.Sx COMMANDS +for more information. .It Ar device Specifies a CCID reader or a slot, either as absolute path to the device node or in a short-hand form. @@ -85,11 +86,11 @@ in the system. A human-readable summary of the ATR data is printed when no flags are given. The following options can be used to alter the output of the .Cm atr -command:: +command: .Bl -tag -width Ds .It Fl v Verbose output, the individual bytes of the ATR are printed and decoded -bit-by-bit in a human-readable form. +in a human-readable form. Additionally the historic data in the ATR is printed as a hexadecimal dump. .It Fl x The complete ATR is printed as a hexadecimal dump. @@ -105,7 +106,75 @@ If no device is given, the command will print the capabilities of all attached CCID readers. .El .Sh EXIT STATUS -.Ex -std +The +.Nm +utility exits 0 on success, 1 on any error opening or accessing the device, and +2 if no command or an unknown command are given. +.Sh EXAMPLES +.Bl -tag -width "" +.It Sy Example 1: List all CCID devices +.Bd -literal +# ccidadm list +PRODUCT DEVICE CARD STATE TRANSPORT SUPPORTED +Yubikey 4 OTP+U2F+CCID ccid0/slot0 activated APDU (T=1) supported +Yubikey 4 OTP+U2F+CCID ccid1/slot0 unactivated APDU supported +Smart Card Reader USB ccid2/slot0 missing TPDU unsupported +Smart Card Reader USB ccid3/slot0 unactivated TPDU unsupported +.Ed +.It Sy Example 2: Get the ATR of a Yubikey +.Bd -literal +# ccidadm atr ccid0/slot0 +ATR for ccid0/slot0 (18 bytes): +ICC supports protocol(s): T=1 +Card protocol is negotiable; starts with default T=1 parameters +Reader will run ICC at ICC's Di/Fi values +T=1 properties that would be negotiated: + + Fi/Fmax Index: 1 (Fi 372/Fmax 5 MHz) + + Di Index: 3 (Di 4) + + Checksum: LRC + + Extra Guardtime: 0 + + BWI: 1 + + CWI: 5 + + Clock Stop: 0 (disallowed) + + IFSC: 254 + + CCID Supports NAD: no +.Ed +.It Sy Example 2: Get capabilities of a Smart Card Reader +.Bd -literal +# ccidadm reader ccid3 +Reader ccid3, CCID class v1.0 device: + Product: Smart Card Reader USB + Serial: <unknown> + Slots Present: 1 + Maximum Busy Slots: 1 + Supported Voltages: + + 5.0 V + + 3.0 V + + 1.8 V + Supported Protocols: + + T=0 + + T=1 + Default Clock: 3.69 MHz + Maximum Clock: 3.69 MHz + Supported Clock Rates: 1 + Default Data Rate: 9.92 Kbps + Maximum Data Rate: 318 Kbps + Supported Data Rates: 19 + Maximum IFSD (T=1 only): 254 + Synchronous Protocols Supported: + + 2-Wire Support + + 3-Wire Support + + I2C Support + Device Features: + + Automatic ICC clock frequency change + + Automatic baud rate change + + Automatic PPS made by CCID + + CCID can set ICC in clock stop mode + + NAD value other than zero accepted + + TPDU support + Maximum Message Length: 271 bytes +.Ed +.El .Sh INTERFACE STABILITY The command line interface of .Nm @@ -117,4 +186,5 @@ is .Sy Not-an-Interface and may change any time. .Sh SEE ALSO +.Xr cfgadm 1M , .Xr ccid 7D diff --git a/usr/src/man/man7d/ccid.7d b/usr/src/man/man7d/ccid.7d index 86ada626e9..f5158b0d0d 100644 --- a/usr/src/man/man7d/ccid.7d +++ b/usr/src/man/man7d/ccid.7d @@ -110,7 +110,7 @@ When a program is finished, it must explicitly end the transaction, which may have the side effect of resetting the ICC. If a program with an open transaction crashes or closes the file descriptor without taking other actions, then the transaction will be -automatically closed. +automatically closed and the ICC will be reset. Without a transaction open, it will still be possible to issue ioctls that obtain the status of the slot and the reader. .Pp @@ -159,13 +159,6 @@ The card has been removed from the slot. An hardware error has occurred, or the CCID reader has been disconnected. .El .Pp -If -.Xr poll 2 -is called while no transaction is active, none of these events will ever occur -and -.Xr poll 2 -may block indefinitely if no timeout is given. -.Pp One important note is that readers with multiple slots often still only allow I/O a single command to be outstanding across all of the slots in the system. @@ -214,7 +207,7 @@ status information. .Pp To perform general I/O to the card, a program must be in the context of a transaction as discussed in the -.Sx I/O model +.Sx I/O Model section. To open a transaction, a program must issue the .Dv UCCID_CMD_TXN_BEGIN @@ -288,7 +281,7 @@ the fields of which have the following meanings: .Bl -tag -width Fa .It Fa uint32_t ucs_version Indicates the current version of the structure. -Should be set to +This should be set to .Dv UCCID_CURRENT_VERSION . .It Fa uint32_t ucs_status This value is ignored when issuing the command. @@ -342,7 +335,7 @@ for the TPDU T=1 protocol. .It Fa ccid_params_t ucs_params The CCID parameters available on the card. .El -.Ss UCCID_CMD_TXN_BEGIN +.Ss Ic UCCID_CMD_TXN_BEGIN This command is used to begin a transaction. The command will block until exclusive access is available to the caller. @@ -356,7 +349,7 @@ with the following members: .Bl -tag -width Fa .It Fa uint32_t ucs_version Indicates the current version of the structure. -Should be set to +This should be set to .Dv UCCID_CURRENT_VERSION . .It Fa uint32_t uct_flags Flags that impact the behavior of the command. @@ -370,7 +363,7 @@ immediately. .Pp If an unknown flag is specified, an error will be returned. .El -.Ss UCCID_CMD_TXN_END +.Ss Ic UCCID_CMD_TXN_END The .Dv UCCID_CMD_TXN_END command is used to end a transaction and relinquish exclusive access @@ -382,7 +375,7 @@ with the following members: .Bl -tag -width Fa .It Fa uint32_t uct_version Indicates the current version of the structure. -Should be set to +This should be set to .Dv UCCID_CURRENT_VERSION . .It Fa uint32_t uct_flags .Bl -tag -width Dv @@ -399,7 +392,7 @@ time. If the device is closed without ending a transaction first, then the ICC will be reset. .El -.Ss UCCID_CMD_ICC_MODIFY +.Ss Ic UCCID_CMD_ICC_MODIFY This command can be used to change the state of an ICC, if present. .Pp The command uses the structure @@ -408,7 +401,7 @@ with the following members: .Bl -tag -width Fa .It Fa uint32_t uci_version Indicates the current version of the structure. -Should be set to +This should be set to .Dv UCCID_CURRENT_VERSION . .It Fa uint32_t uci_action The action to be taken on the ICC. @@ -422,7 +415,7 @@ Power off the ICC. Perform a warm reset of the ICC. .El .El -.Ss FIONREAD +.Ss Ic FIONREAD This command returns the size in bytes of a command response available for reading with .Xr read 2 . @@ -432,11 +425,116 @@ pointed to by the argument. .Sh SYSTEM CALLS This section lists the different system calls that may be issued to a CCID device. -.Ss open -.Ss close -.Ss write -.Ss read -.Ss poll +.Ss Xr open 2 +.Nm +slot device nodes can be opened using +.Xr open 2 . +Non-blocking operation can be selected by using the +.Dv O_NONBLOCK +flag when opening the device node. +A device node opened for read-only operations will not allow creating +transactions or doing I/O, but it will allow the ICC/reader status to +be queried. +.Ss Xr close 2 +When no longer needed by a program, a device node can be closed with +.Xr close 2 . +If a transaction is still active when a device node is closed, the transaction +will be ended automatically and the ICC will be reset. +Any unread data is discarded. +.Ss Xr ioctl 2 +The +.Xr ioctl 2 +system call can be used to start or end a transaction, query the reply size for +.Xr read 2 , +query the ICC and CCID reader status, or change the state of an ICC in a reader. +See section +.Sx IOCTLS +for details. +.Ss Xr write 2 +Within an active transaction the +.Xr write 2 +system call can be used to transfer an APDU (application protocol data unit) to +an ICC, one single complete APDU at a time. +Partial writes or writing more than one APDU at a time are not supported. +The data returned by the ICC must be consumed by a subsequent +.Xr read 2 +call before +.Xr write 2 +can be called again within the same transaction. +.Pp +The following errors for +.Xr write 2 +have specific meaning in +.Nm : +.Bl -tag -width Dv +.It Dv E2BIG +The number of bytes to write is larger than the maximum APDU length supported by +.Nm , +currently defined as 261 bytes. +.It Dv EACCES +The device is opened read-only, or no transaction is active. +.It Dv EBUSY +There is unread data from a previous call to +.Xr write 2 . +.It Dv ENOTSUP +The reader and/or ICC is unsupported for I/O. +.It Dv ENXIO +The ICC is inactive and can't be used for I/O. +.It Dv ENODEV +The CCID reader has been disconnected. +.El +.Ss Xr read 2 +Within an active transaction the +.Xr read 2 +system call is used to read the reply from an ICC following sending an APDU with +.Xr write 2 . +The whole reply needs to be read with a single call to +.Xr read 2 . +The size of the reply can be queried before reading by issuing the +.Dv FIONREAD +ioctl. +See section +.Sx IOCTLS +for details. +.Pp +The following errors for +.Xr read 2 +have specific meaning in +.Nm : +.Bl -tag -width Dv +.It Dv EACCES +No transaction is active. +.It Dv EBUSY +Another thread is already blocked in +.Xr read 2 +waiting for data. +.It Dv EOVERFLOW +The buffer size is too small to fit the reply. +.It Dv ENODATA +No +.Xr write 2 +was issued before and consequently there is no reply to be read. +.It Dv ENODEV +The CCID reader has been disconnected. +.El +.Ss Xr poll 2 +Within an active transaction the +.Xr poll 2 +system call is used to wait for status changes on a device node. +See section +.Sx I/O model +for details. +.Pp +The following errors for +.Xr poll 2 +have specific meaning in +.Nm : +.Bl -tag -width Dv +.It Dv EACCES +No transaction is active. +.It Dv ENODEV +The CCID reader has been disconnected. +.El .Sh SEE ALSO .Xr ccidadm 1M , .Xr cfgadm 1M , diff --git a/usr/src/pkg/manifests/developer-object-file.mf b/usr/src/pkg/manifests/developer-object-file.mf index 5519e67d93..21d064fb9f 100644 --- a/usr/src/pkg/manifests/developer-object-file.mf +++ b/usr/src/pkg/manifests/developer-object-file.mf @@ -22,6 +22,7 @@ # # Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. # Copyright 2019 OmniOS Community Edition (OmniOSce) Association. +# Copyright 2020 Joyent, Inc. # set name=pkg.fmri value=pkg:/developer/object-file@$(PKGVERS) @@ -53,6 +54,7 @@ file path=usr/bin/$(ARCH64)/mcs mode=0555 file path=usr/bin/$(ARCH64)/nm mode=0555 file path=usr/bin/$(ARCH64)/size mode=0555 file path=usr/bin/ar mode=0555 +file path=usr/bin/demangle mode=0555 file path=usr/bin/dis mode=0555 file path=usr/bin/dump mode=0555 file path=usr/bin/elfdump mode=0555 @@ -95,6 +97,7 @@ file path=usr/share/lib/ccs/ncform file path=usr/share/lib/ccs/nrform file path=usr/share/lib/ccs/yaccpar file path=usr/share/man/man1/ar.1 +file path=usr/share/man/man1/demangle.1 file path=usr/share/man/man1/dis.1 file path=usr/share/man/man1/dump.1 file path=usr/share/man/man1/elfdump.1 diff --git a/usr/src/pkg/manifests/driver-misc-ccid.mf b/usr/src/pkg/manifests/driver-misc-ccid.mf new file mode 100644 index 0000000000..e0d1ca0155 --- /dev/null +++ b/usr/src/pkg/manifests/driver-misc-ccid.mf @@ -0,0 +1,57 @@ +# +# This file and its contents are supplied under the terms of the +# Common Development and Distribution License ("CDDL"), version 1.0. +# You may only use this file in accordance with the terms of version +# 1.0 of the CDDL. +# +# A full copy of the text of the CDDL should have accompanied this +# source. A copy of the CDDL is also available via the Internet at +# http://www.illumos.org/license/CDDL. +# + +# +# Copyright 2019, Joyent Inc. +# + +# +# The default for payload-bearing actions in this package is to appear in the +# global zone only. See the include file for greater detail, as well as +# information about overriding the defaults. +# +set name=pkg.fmri value=pkg:/driver/misc/ccid@$(PKGVERS) +set name=pkg.description \ + value="Driver for USB Chip Card Interface Devices (CCID)" +set name=pkg.summary value="CCID driver" +set name=info.classification \ + value=org.opensolaris.category.2008:System/Hardware +set name=variant.arch value=i386 +dir path=kernel group=sys variant.opensolaris.zone=global +dir path=kernel/drv group=sys variant.opensolaris.zone=global +dir path=kernel/drv/$(ARCH64) group=sys variant.opensolaris.zone=global +dir path=usr group=sys +dir path=usr/include +dir path=usr/include/sys +dir path=usr/include/sys/usb +dir path=usr/include/sys/usb/clients +dir path=usr/include/sys/usb/clients/ccid +dir path=usr/lib/cfgadm variant.opensolaris.zone=global +dir path=usr/lib/cfgadm/$(ARCH64) variant.opensolaris.zone=global +dir path=usr/sbin variant.opensolaris.zone=global +dir path=usr/share +dir path=usr/share/man +dir path=usr/share/man/man1m variant.opensolaris.zone=global +dir path=usr/share/man/man7d +driver name=ccid alias=usbif,classb class=misc perms="* 0600 root sys" +file path=kernel/drv/$(ARCH64)/ccid group=sys variant.opensolaris.zone=global +file path=usr/include/sys/usb/clients/ccid/ccid.h +file path=usr/include/sys/usb/clients/ccid/uccid.h +file path=usr/lib/cfgadm/$(ARCH64)/ccid.so.1 variant.opensolaris.zone=global +file path=usr/lib/cfgadm/ccid.so.1 variant.opensolaris.zone=global +file path=usr/sbin/ccidadm mode=0555 variant.opensolaris.zone=global +file path=usr/share/man/man1m/ccidadm.1m variant.opensolaris.zone=global +file path=usr/share/man/man7d/ccid.7d +license lic_CDDL license=lic_CDDL +link path=usr/lib/cfgadm/$(ARCH64)/ccid.so target=./ccid.so.1 \ + variant.opensolaris.zone=global +link path=usr/lib/cfgadm/ccid.so target=./ccid.so.1 \ + variant.opensolaris.zone=global diff --git a/usr/src/pkg/manifests/system-library-libpcsc.mf b/usr/src/pkg/manifests/system-library-libpcsc.mf new file mode 100644 index 0000000000..fbf60f6595 --- /dev/null +++ b/usr/src/pkg/manifests/system-library-libpcsc.mf @@ -0,0 +1,32 @@ +# +# This file and its contents are supplied under the terms of the +# Common Development and Distribution License ("CDDL"), version 1.0. +# You may only use this file in accordance with the terms of version +# 1.0 of the CDDL. +# +# A full copy of the text of the CDDL should have accompanied this +# source. A copy of the CDDL is also available via the Internet at +# http://www.illumos.org/license/CDDL. +# + +# +# Copyright 2019, Joyent Inc. +# + +set name=pkg.fmri value=pkg:/system/library/libpcsc@$(PKGVERS) +set name=pkg.description \ + value="PC/SC compatible library for Smart Card access" +set name=info.classification \ + value=org.opensolaris.category.2008:System/Libraries +set name=variant.arch value=$(ARCH) +dir path=usr group=sys +dir path=usr/include +dir path=usr/lib +dir path=usr/lib/$(ARCH64) +file path=usr/include/winscard.h +file path=usr/include/wintypes.h +file path=usr/lib/$(ARCH64)/libpcsc.so.1 +file path=usr/lib/libpcsc.so.1 +link path=usr/lib/$(ARCH64)/libpcsc.so target=./libpcsc.so.1 +link path=usr/lib/libpcsc.so target=./libpcsc.so.1 +depend fmri=driver/misc/ccid type=require diff --git a/usr/src/pkg/manifests/system-test-ostest.mf b/usr/src/pkg/manifests/system-test-ostest.mf index dbaabe6dcd..6e20cc2b8e 100644 --- a/usr/src/pkg/manifests/system-test-ostest.mf +++ b/usr/src/pkg/manifests/system-test-ostest.mf @@ -35,6 +35,7 @@ dir path=opt/os-tests/tests/secflags dir path=opt/os-tests/tests/sigqueue dir path=opt/os-tests/tests/sockfs dir path=opt/os-tests/tests/stress +dir path=opt/os-tests/tests/uccid file path=opt/os-tests/README mode=0444 file path=opt/os-tests/bin/ostest mode=0555 file path=opt/os-tests/runfiles/default.run mode=0444 @@ -85,6 +86,22 @@ file path=opt/os-tests/tests/sockfs/nosignal mode=0555 file path=opt/os-tests/tests/sockfs/sockpair mode=0555 file path=opt/os-tests/tests/spoof-ras mode=0555 file path=opt/os-tests/tests/stress/dladm-kstat mode=0555 +file path=opt/os-tests/tests/uccid/atrparse mode=0555 +file path=opt/os-tests/tests/uccid/excl-badread mode=0555 +file path=opt/os-tests/tests/uccid/excl-basic mode=0555 +file path=opt/os-tests/tests/uccid/excl-close mode=0555 +file path=opt/os-tests/tests/uccid/excl-loop mode=0555 +file path=opt/os-tests/tests/uccid/excl-nonblock mode=0555 +file path=opt/os-tests/tests/uccid/excl-reset mode=0555 +file path=opt/os-tests/tests/uccid/modify mode=0555 +file path=opt/os-tests/tests/uccid/notxn-poll mode=0555 +file path=opt/os-tests/tests/uccid/pollin mode=0555 +file path=opt/os-tests/tests/uccid/pollout mode=0555 +file path=opt/os-tests/tests/uccid/status mode=0555 +file path=opt/os-tests/tests/uccid/txn-pollerr mode=0555 +file path=opt/os-tests/tests/uccid/yk mode=0555 +file path=opt/os-tests/tests/uccid/yk-poll mode=0555 +file path=opt/os-tests/tests/uccid/yk-readonly mode=0555 file path=opt/os-tests/tests/writev.32 mode=0555 file path=opt/os-tests/tests/writev.64 mode=0555 license cr_Sun license=cr_Sun diff --git a/usr/src/test/os-tests/runfiles/default.run b/usr/src/test/os-tests/runfiles/default.run index 4db81dc30e..2313f65f7b 100644 --- a/usr/src/test/os-tests/runfiles/default.run +++ b/usr/src/test/os-tests/runfiles/default.run @@ -104,3 +104,11 @@ tests = ['atrparse'] [/opt/os-tests/tests/imc_test] arch = i86pc + +# +# Except atrparse all tests require special hardware (CCID YubiKey) to run, +# hence they aren't included in the default runfile. +# +[/opt/os-tests/tests/uccid] +arch = i86pc +tests = ['atrparse'] diff --git a/usr/src/test/os-tests/tests/uccid/modify.c b/usr/src/test/os-tests/tests/uccid/modify.c index 1ac44f3ba4..137c461701 100644 --- a/usr/src/test/os-tests/tests/uccid/modify.c +++ b/usr/src/test/os-tests/tests/uccid/modify.c @@ -53,14 +53,36 @@ main(int argc, char *argv[]) err(EXIT_FAILURE, "failed to open %s", argv[1]); } - /* try power off the card outside of a transaction */ + /* power off the card outside of a transaction */ bzero(&uci, sizeof (uci)); uci.uci_version = UCCID_CURRENT_VERSION; uci.uci_action = UCCID_ICC_POWER_OFF; ret = ioctl(fd, UCCID_CMD_ICC_MODIFY, &uci); - VERIFY3S(ret, ==, -1); - VERIFY3S(errno, ==, EACCES); + VERIFY3S(ret, ==, 0); + + /* make sure the card is inactive now */ + bzero(&ucs, sizeof (ucs)); + ucs.ucs_version = UCCID_CURRENT_VERSION; + ret = ioctl(fd, UCCID_CMD_STATUS, &ucs); + VERIFY3S(ret, ==, 0); + VERIFY3U(ucs.ucs_status & UCCID_STATUS_F_CARD_ACTIVE, ==, 0); + + /* power on the card outside of a transaction */ + bzero(&uci, sizeof (uci)); + uci.uci_version = UCCID_CURRENT_VERSION; + uci.uci_action = UCCID_ICC_POWER_ON; + ret = ioctl(fd, UCCID_CMD_ICC_MODIFY, &uci); + VERIFY3S(ret, ==, 0); + + /* make sure the card is active again */ + bzero(&ucs, sizeof (ucs)); + ucs.ucs_version = UCCID_CURRENT_VERSION; + ret = ioctl(fd, UCCID_CMD_STATUS, &ucs); + VERIFY3S(ret, ==, 0); + VERIFY3U(ucs.ucs_status & UCCID_STATUS_F_CARD_ACTIVE, !=, 0); + + /* enter transaction */ bzero(&begin, sizeof (begin)); begin.uct_version = UCCID_CURRENT_VERSION; if (ioctl(fd, UCCID_CMD_TXN_BEGIN, &begin) != 0) { diff --git a/usr/src/test/os-tests/tests/uccid/notxn-poll.c b/usr/src/test/os-tests/tests/uccid/notxn-poll.c index b45f06b218..3a756b5fbc 100644 --- a/usr/src/test/os-tests/tests/uccid/notxn-poll.c +++ b/usr/src/test/os-tests/tests/uccid/notxn-poll.c @@ -14,8 +14,8 @@ */ /* - * Verify that trying to poll without a transaction / excl access works but - * returns no events. + * Verify that trying to poll without a transaction / excl access fails + * with EACCES. */ #include <err.h> @@ -50,8 +50,8 @@ main(int argc, char *argv[]) pfds[0].revents = 0; ret = poll(pfds, 1, 0); - VERIFY3S(ret, ==, 0); - VERIFY3S(pfds[0].revents, ==, 0); + VERIFY3S(ret, ==, -1); + VERIFY3S(errno, ==, EACCES); return (0); } diff --git a/usr/src/test/os-tests/tests/uccid/yk-readonly.c b/usr/src/test/os-tests/tests/uccid/yk-readonly.c index dfe7390ea1..1f5d503891 100644 --- a/usr/src/test/os-tests/tests/uccid/yk-readonly.c +++ b/usr/src/test/os-tests/tests/uccid/yk-readonly.c @@ -54,31 +54,47 @@ main(int argc, char *argv[]) bzero(&begin, sizeof (begin)); begin.uct_version = UCCID_CURRENT_VERSION; if (ioctl(fd, UCCID_CMD_TXN_BEGIN, &begin) == 0) { - err(EXIT_FAILURE, "didn't fail to issue begin ioctl"); + errx(EXIT_FAILURE, "didn't fail to issue begin ioctl"); } if ((ret = write(fd, yk_req, sizeof (yk_req))) != -1) { - err(EXIT_FAILURE, "didn't fail to write data"); + errx(EXIT_FAILURE, "didn't fail to write data"); + } + + if (errno != EBADF) { + err(EXIT_FAILURE, "wrong errno for failed write, " + "expected EBADF"); } if ((ret = read(fd, buf, sizeof (buf))) != -1) { - err(EXIT_FAILURE, "didn't fail to read data"); + errx(EXIT_FAILURE, "didn't fail to read data"); + } + + if (errno != EACCES) { + err(EXIT_FAILURE, "wrong errno for failed read, " + "expected EACCES"); } + /* get card status */ bzero(&ucs, sizeof (ucs)); ucs.ucs_version = UCCID_CURRENT_VERSION; if ((ret = ioctl(fd, UCCID_CMD_STATUS, &ucs)) != 0) { err(EXIT_FAILURE, "failed to get status"); } - /* try power off the card outside of a transaction */ + + /* try to power off the card while opened read-only */ bzero(&uci, sizeof (uci)); uci.uci_version = UCCID_CURRENT_VERSION; uci.uci_action = UCCID_ICC_POWER_OFF; if ((ret = ioctl(fd, UCCID_CMD_ICC_MODIFY, &uci)) == 0) { - err(EXIT_FAILURE, "didn't fail to power off ICC"); + errx(EXIT_FAILURE, "didn't fail to power off ICC"); } + if (errno != EBADF) { + err(EXIT_FAILURE, "wrong errno for failed write, " + "expected EBADF"); + } return (0); } diff --git a/usr/src/uts/common/io/audio/drv/audioemu10k/audioemu10k.c b/usr/src/uts/common/io/audio/drv/audioemu10k/audioemu10k.c index caf47337ae..c114dcea61 100644 --- a/usr/src/uts/common/io/audio/drv/audioemu10k/audioemu10k.c +++ b/usr/src/uts/common/io/audio/drv/audioemu10k/audioemu10k.c @@ -827,6 +827,11 @@ emu10k_reset_rec(emu10k_portc_t *portc) case 65536: sz = 31; break; + default: + /* + * Can't really reach here, but this keeps the compiler quiet. + */ + return; } emu10k_write_reg(devc, ADCBA, 0, portc->buf_paddr); emu10k_write_reg(devc, ADCBS, 0, sz); diff --git a/usr/src/uts/common/io/usb/clients/ccid/ccid.c b/usr/src/uts/common/io/usb/clients/ccid/ccid.c index 22578d4a1c..61003875d4 100644 --- a/usr/src/uts/common/io/usb/clients/ccid/ccid.c +++ b/usr/src/uts/common/io/usb/clients/ccid/ccid.c @@ -138,7 +138,10 @@ * Readers provide four different modes for us to be able to transmit data to * and from the card. These are: * - * 1. Character Mode 2. TPDU Mode 3. Short APDU Mode 4. Extended APDU Mode + * 1. Character Mode + * 2. TPDU Mode + * 3. Short APDU Mode + * 4. Extended APDU Mode * * Readers either support mode 1, mode 2, mode 3, or mode 3 and 4. All readers * that support extended APDUs support short APDUs. At this time, we do not @@ -916,8 +919,8 @@ ccid_slot_excl_req(ccid_slot_t *slot, ccid_minor_t *cmp, boolean_t nosleep) list_insert_tail(&slot->cs_excl_waiters, cmp); while (slot->cs_excl_minor != NULL || (slot->cs_flags & CCID_SLOT_F_NOEXCL_MASK) != 0) { - if (cv_wait_sig(&cmp->cm_excl_cv, &slot->cs_ccid->ccid_mutex) - == 0) { + if (cv_wait_sig(&cmp->cm_excl_cv, &slot->cs_ccid->ccid_mutex) == + 0) { /* * Remove ourselves from the list and try to signal the * next thread. @@ -1043,13 +1046,14 @@ static uint8_t ccid_command_resp_param2(ccid_command_t *cc) { const ccid_header_t *cch; + uint8_t val; VERIFY3P(cc, !=, NULL); VERIFY3P(cc->cc_response, !=, NULL); cch = (ccid_header_t *)cc->cc_response->b_rptr; - - return (cch->ch_param2); + bcopy(&cch->ch_param2, &val, sizeof (val)); + return (val); } /* @@ -1073,7 +1077,7 @@ ccid_command_complete(ccid_command_t *cc) ccid_slot_t *slot; slot = &ccid->ccid_slots[cc->cc_slot]; - ASSERT(slot->cs_icc.icc_complete != NULL); + ASSERT3P(slot->cs_icc.icc_complete, !=, NULL); slot->cs_icc.icc_complete(ccid, slot, cc); } else { list_insert_tail(&ccid->ccid_complete_queue, cc); @@ -1169,8 +1173,6 @@ ccid_reply_bulk_cb(usb_pipe_handle_t ph, usb_bulk_req_t *ubrp) return; } - slot = &ccid->ccid_slots[cc->cc_slot]; - if (mlen >= sizeof (ccid_header_t)) { bcopy(ubrp->bulk_data->b_rptr, &cch, sizeof (cch)); header_valid = B_TRUE; @@ -1209,6 +1211,8 @@ ccid_reply_bulk_cb(usb_pipe_handle_t ph, usb_bulk_req_t *ubrp) return; } + slot = &ccid->ccid_slots[cc->cc_slot]; + /* * If the sequence or slot number don't match the head of the list or * the response type is unexpected for this command then we should be @@ -1949,14 +1953,18 @@ ccid_hw_error(ccid_t *ccid, ccid_intr_hwerr_t *hwerr) ccid_slot_t *slot; /* Make sure the slot number is within range. */ - if (hwerr->cih_slot >= ccid->ccid_nslots) + if (hwerr->cih_slot >= ccid->ccid_nslots) { + ccid->ccid_stats.cst_intr_inval++; return; + } slot = &ccid->ccid_slots[hwerr->cih_slot]; /* The only error condition defined by the spec is overcurrent. */ - if (hwerr->cih_code != CCID_INTR_HWERR_OVERCURRENT) + if (hwerr->cih_code != CCID_INTR_HWERR_OVERCURRENT) { + ccid->ccid_stats.cst_intr_inval++; return; + } /* * The worker thread will take care of this situation. @@ -2263,10 +2271,7 @@ ccid_slot_power_on(ccid_t *ccid, ccid_slot_t *slot, ccid_class_voltage_t volts, VERIFY(MUTEX_HELD(&ccid->ccid_mutex)); mutex_exit(&ccid->ccid_mutex); - if ((ret = ccid_command_power_on(ccid, slot, volts, atr)) - != 0) { - freemsg(*atr); - + if ((ret = ccid_command_power_on(ccid, slot, volts, atr)) != 0) { /* * If we got ENXIO, then we know that there is no ICC * present. This could happen for a number of reasons. @@ -2370,8 +2375,8 @@ ccid_slot_inserted(ccid_t *ccid, ccid_slot_t *slot) * the moment we do. */ if ((ccid->ccid_class.ccd_dwFeatures & - (CCID_CLASS_F_AUTO_ICC_ACTIVATE | CCID_CLASS_F_AUTO_ICC_VOLTAGE)) - == 0) { + (CCID_CLASS_F_AUTO_ICC_ACTIVATE | CCID_CLASS_F_AUTO_ICC_VOLTAGE)) == + 0) { /* Skip auto-voltage */ cvolt++; } @@ -2380,13 +2385,15 @@ ccid_slot_inserted(ccid_t *ccid, ccid_slot_t *slot) int ret; if (volts[cvolt] != CCID_CLASS_VOLT_AUTO && - (ccid->ccid_class.ccd_bVoltageSupport & volts[cvolt]) - == 0) { + (ccid->ccid_class.ccd_bVoltageSupport & volts[cvolt]) == + 0) { continue; } - if ((ret = ccid_slot_power_on(ccid, slot, volts[cvolt], &atr)) - != 0) { + ret = ccid_slot_power_on(ccid, slot, volts[cvolt], &atr); + if (ret != 0) { + freemsg(atr); + atr = NULL; continue; } @@ -2531,8 +2538,8 @@ ccid_worker(void *arg) ccid_slot_removed(ccid, slot, B_TRUE); } else { (void) ccid_slot_inserted(ccid, slot); - if ((slot->cs_flags & CCID_SLOT_F_ACTIVE) - != 0) { + if ((slot->cs_flags & CCID_SLOT_F_ACTIVE) != + 0) { ccid_slot_excl_maybe_signal(slot); } } @@ -3718,8 +3725,8 @@ ccid_read(dev_t dev, struct uio *uiop, cred_t *credp) * a lot of the surrounding logic and fits with the current consumer * model. */ - if ((slot->cs_io.ci_flags & (CCID_IO_F_IN_PROGRESS | CCID_IO_F_DONE)) - == 0) { + if ((slot->cs_io.ci_flags & (CCID_IO_F_IN_PROGRESS | CCID_IO_F_DONE)) == + 0) { mutex_exit(&ccid->ccid_mutex); return (ENODATA); } @@ -3791,8 +3798,8 @@ ccid_read(dev_t dev, struct uio *uiop, cred_t *credp) if (mlen > uiop->uio_resid) { ret = EOVERFLOW; } else { - if ((ret = ccid_read_copyout(uiop, slot->cs_io.ci_data)) - == 0) { + ret = ccid_read_copyout(uiop, slot->cs_io.ci_data); + if (ret == 0) { done = B_TRUE; } } @@ -3935,7 +3942,7 @@ ccid_ioctl_status(ccid_slot_t *slot, intptr_t arg, int mode) if (ddi_copyin((void *)arg, &ucs, sizeof (ucs), mode & FKIOCTL) != 0) return (EFAULT); - if (ucs.ucs_version != UCCID_CURRENT_VERSION) + if (ucs.ucs_version != UCCID_VERSION_ONE) return (EINVAL); ucs.ucs_status = 0; @@ -3943,6 +3950,11 @@ ccid_ioctl_status(ccid_slot_t *slot, intptr_t arg, int mode) ucs.ucs_slot = slot->cs_slotno; mutex_enter(&slot->cs_ccid->ccid_mutex); + if ((slot->cs_ccid->ccid_flags & CCID_F_DISCONNECTED) != 0) { + mutex_exit(&slot->cs_ccid->ccid_mutex); + return (ENODEV); + } + if ((slot->cs_flags & CCID_SLOT_F_PRESENT) != 0) ucs.ucs_status |= UCCID_STATUS_F_CARD_PRESENT; if ((slot->cs_flags & CCID_SLOT_F_ACTIVE) != 0) @@ -3998,7 +4010,7 @@ ccid_ioctl_txn_begin(ccid_slot_t *slot, ccid_minor_t *cmp, intptr_t arg, if (ddi_copyin((void *)arg, &uct, sizeof (uct), mode & FKIOCTL) != 0) return (EFAULT); - if (uct.uct_version != UCCID_CURRENT_VERSION) + if (uct.uct_version != UCCID_VERSION_ONE) return (EINVAL); if ((uct.uct_flags & ~UCCID_TXN_DONT_BLOCK) != 0) @@ -4006,9 +4018,14 @@ ccid_ioctl_txn_begin(ccid_slot_t *slot, ccid_minor_t *cmp, intptr_t arg, nowait = (uct.uct_flags & UCCID_TXN_DONT_BLOCK) != 0; mutex_enter(&slot->cs_ccid->ccid_mutex); + if ((slot->cs_ccid->ccid_flags & CCID_F_DISCONNECTED) != 0) { + mutex_exit(&slot->cs_ccid->ccid_mutex); + return (ENODEV); + } + if ((cmp->cm_flags & CCID_MINOR_F_WRITABLE) == 0) { mutex_exit(&slot->cs_ccid->ccid_mutex); - return (EACCES); + return (EBADF); } ret = ccid_slot_excl_req(slot, cmp, nowait); @@ -4026,11 +4043,16 @@ ccid_ioctl_txn_end(ccid_slot_t *slot, ccid_minor_t *cmp, intptr_t arg, int mode) return (EFAULT); } - if (uct.uct_version != UCCID_CURRENT_VERSION) { + if (uct.uct_version != UCCID_VERSION_ONE) { return (EINVAL); } mutex_enter(&slot->cs_ccid->ccid_mutex); + if ((slot->cs_ccid->ccid_flags & CCID_F_DISCONNECTED) != 0) { + mutex_exit(&slot->cs_ccid->ccid_mutex); + return (ENODEV); + } + if (slot->cs_excl_minor != cmp) { mutex_exit(&slot->cs_ccid->ccid_mutex); return (EINVAL); @@ -4065,12 +4087,21 @@ ccid_ioctl_fionread(ccid_slot_t *slot, ccid_minor_t *cmp, intptr_t arg, int data; mutex_enter(&slot->cs_ccid->ccid_mutex); - if ((cmp->cm_flags & (CCID_MINOR_F_WRITABLE | CCID_MINOR_F_HAS_EXCL)) == - (CCID_MINOR_F_WRITABLE | CCID_MINOR_F_HAS_EXCL)) { + if ((slot->cs_ccid->ccid_flags & CCID_F_DISCONNECTED) != 0) { + mutex_exit(&slot->cs_ccid->ccid_mutex); + return (ENODEV); + } + + if ((cmp->cm_flags & CCID_MINOR_F_HAS_EXCL) == 0) { mutex_exit(&slot->cs_ccid->ccid_mutex); return (EACCES); } + if ((cmp->cm_flags & CCID_MINOR_F_WRITABLE) == 0) { + mutex_exit(&slot->cs_ccid->ccid_mutex); + return (EBADF); + } + if ((slot->cs_io.ci_flags & CCID_IO_F_DONE) != 0) { mutex_exit(&slot->cs_ccid->ccid_mutex); return (ENODATA); @@ -4090,8 +4121,8 @@ ccid_ioctl_fionread(ccid_slot_t *slot, ccid_minor_t *cmp, intptr_t arg, data = MIN(s, INT_MAX); } - if (ddi_copyout(&data, (void *)arg, sizeof (data), mode & FKIOCTL) - != 0) { + if (ddi_copyout(&data, (void *)arg, sizeof (data), mode & FKIOCTL) != + 0) { mutex_exit(&slot->cs_ccid->ccid_mutex); return (EFAULT); } @@ -4112,7 +4143,7 @@ ccid_ioctl_icc_modify(ccid_slot_t *slot, ccid_minor_t *cmp, intptr_t arg, return (EFAULT); } - if (uci.uci_version != UCCID_CURRENT_VERSION) { + if (uci.uci_version != UCCID_VERSION_ONE) { return (EINVAL); } @@ -4127,10 +4158,14 @@ ccid_ioctl_icc_modify(ccid_slot_t *slot, ccid_minor_t *cmp, intptr_t arg, ccid = slot->cs_ccid; mutex_enter(&ccid->ccid_mutex); - if ((cmp->cm_flags & (CCID_MINOR_F_WRITABLE | CCID_MINOR_F_HAS_EXCL)) != - (CCID_MINOR_F_WRITABLE | CCID_MINOR_F_HAS_EXCL)) { - mutex_exit(&ccid->ccid_mutex); - return (EACCES); + if ((slot->cs_ccid->ccid_flags & CCID_F_DISCONNECTED) != 0) { + mutex_exit(&slot->cs_ccid->ccid_mutex); + return (ENODEV); + } + + if ((cmp->cm_flags & CCID_MINOR_F_WRITABLE) == 0) { + mutex_exit(&slot->cs_ccid->ccid_mutex); + return (EBADF); } switch (uci.uci_action) { @@ -4168,13 +4203,6 @@ ccid_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *credp, cmp = idx->cmi_data.cmi_user; slot = cmp->cm_slot; - mutex_enter(&slot->cs_ccid->ccid_mutex); - if ((slot->cs_ccid->ccid_flags & CCID_F_DISCONNECTED) != 0) { - mutex_exit(&slot->cs_ccid->ccid_mutex); - return (ENODEV); - } - mutex_exit(&slot->cs_ccid->ccid_mutex); - switch (cmd) { case UCCID_CMD_TXN_BEGIN: return (ccid_ioctl_txn_begin(slot, cmp, arg, mode)); @@ -4218,22 +4246,25 @@ ccid_chpoll(dev_t dev, short events, int anyyet, short *reventsp, return (ENODEV); } - if ((cmp->cm_flags & CCID_MINOR_F_HAS_EXCL) != 0) { - /* - * If the CCID_IO_F_DONE flag is set, then we're always - * readable. However, flags are insufficient to be writeable. - */ - if ((slot->cs_io.ci_flags & CCID_IO_F_DONE) != 0) { - ready |= POLLIN | POLLRDNORM; - } else if ((slot->cs_flags & CCID_SLOT_F_ACTIVE) != 0 && - (slot->cs_io.ci_flags & CCID_IO_F_POLLOUT_FLAGS) == 0 && - slot->cs_icc.icc_tx != NULL) { - ready |= POLLOUT; - } + if (!(cmp->cm_flags & CCID_MINOR_F_HAS_EXCL) != 0) { + mutex_exit(&ccid->ccid_mutex); + return (EACCES); + } - if ((slot->cs_flags & CCID_SLOT_F_PRESENT) == 0) { - ready |= POLLHUP; - } + /* + * If the CCID_IO_F_DONE flag is set, then we're always + * readable. However, flags are insufficient to be writeable. + */ + if ((slot->cs_io.ci_flags & CCID_IO_F_DONE) != 0) { + ready |= POLLIN | POLLRDNORM; + } else if ((slot->cs_flags & CCID_SLOT_F_ACTIVE) != 0 && + (slot->cs_io.ci_flags & CCID_IO_F_POLLOUT_FLAGS) == 0 && + slot->cs_icc.icc_tx != NULL) { + ready |= POLLOUT; + } + + if ((slot->cs_flags & CCID_SLOT_F_PRESENT) == 0) { + ready |= POLLHUP; } *reventsp = ready & events; diff --git a/usr/src/uts/common/sys/usb/clients/ccid/ccid.h b/usr/src/uts/common/sys/usb/clients/ccid/ccid.h index 0437a957ba..c5ed9ad1f2 100644 --- a/usr/src/uts/common/sys/usb/clients/ccid/ccid.h +++ b/usr/src/uts/common/sys/usb/clients/ccid/ccid.h @@ -175,23 +175,23 @@ typedef union ccid_params { typedef enum ccid_intr_code { CCID_INTR_CODE_SLOT_CHANGE = 0x50, CCID_INTR_CODE_HW_ERROR = 0x51 -} __packed ccid_intr_code_t; +} ccid_intr_code_t; typedef enum ccid_intr_hwerr_code { CCID_INTR_HWERR_OVERCURRENT = 0x01 -} __packed ccid_intr_hwerr_code_t; +} ccid_intr_hwerr_code_t; typedef struct ccid_intr_slot { uint8_t cis_type; uint8_t cis_state[]; -} __packed ccid_intr_slot_t; +} ccid_intr_slot_t; typedef struct ccid_intr_hwerr { uint8_t cih_type; uint8_t cih_slot; uint8_t cih_seq; uint8_t cih_code; -} __packed ccid_intr_hwerr_t; +} ccid_intr_hwerr_t; /* * Message request codes. These codes are based on CCID r1.1.0 Table 6.1-1 @@ -214,7 +214,7 @@ typedef enum ccid_request_code { CCID_REQEUST_ABORT = 0x72, /* PC_to_RDR_Abort */ CCID_REQUEST_DATA_CLOCK = 0x73 /* PC_to_RDR_SetDataRateAnd */ /* ClockFrequency */ -} __packed ccid_request_code_t; +} ccid_request_code_t; /* * Message request codes. These codes are based on CCID r1.1.0 Table 6.2-1 @@ -228,7 +228,7 @@ typedef enum ccid_response_code { CCID_RESPONSE_ESCAPE = 0x83, /* RDR_to_PC_Escape */ CCID_RESPONSE_DATA_CLOCK = 0x84 /* RDR_to_PC_DataRateAnd */ /* ClockFrequency */ -} __packed ccid_response_code_t; +} ccid_response_code_t; /* * This represents the CCID command header that is used for every request and @@ -265,13 +265,13 @@ typedef enum { CCID_REPLY_ICC_ACTIVE = 0, CCID_REPLY_ICC_INACTIVE, CCID_REPLY_ICC_MISSING -} __packed ccid_reply_icc_status_t; +} ccid_reply_icc_status_t; typedef enum { CCID_REPLY_STATUS_COMPLETE = 0, CCID_REPLY_STATUS_FAILED, CCID_REPLY_STATUS_MORE_TIME -} __packed ccid_reply_command_status_t; +} ccid_reply_command_status_t; /* * Errors that are defined based when commands fail. These are based on CCID @@ -294,7 +294,7 @@ typedef enum ccid_command_err { CCID_ERR_PIN_CANCELLED = 0xef, CCID_ERR_CMD_SLOT_BUSY = 0xe0, CCID_ERR_CMD_NOT_SUPPORTED = 0x00 -} __packed ccid_command_err_t; +} ccid_command_err_t; /* * Maximum size of an APDU (application data unit) payload. There are both short diff --git a/usr/src/uts/common/sys/usb/clients/ccid/uccid.h b/usr/src/uts/common/sys/usb/clients/ccid/uccid.h index 9aee0559b6..f016df3879 100644 --- a/usr/src/uts/common/sys/usb/clients/ccid/uccid.h +++ b/usr/src/uts/common/sys/usb/clients/ccid/uccid.h @@ -56,7 +56,7 @@ extern "C" { typedef struct uccid_cmd_txn_begin { uint32_t uct_version; uint32_t uct_flags; -} __packed uccid_cmd_txn_begin_t; +} uccid_cmd_txn_begin_t; /* * Relinquish exclusive access. Takes a uccid_cmd_txn_end_t. The callers should @@ -72,7 +72,7 @@ typedef struct uccid_cmd_txn_begin { typedef struct uccid_cmd_txn_end { uint32_t uct_version; uint32_t uct_flags; -} __packed uccid_cmd_txn_end_t; +} uccid_cmd_txn_end_t; /* * Obtain the status of the slot. Returns a filled-in uccid_cmd_status_t. @@ -109,7 +109,7 @@ typedef struct uccid_cmd_status { ccid_class_descr_t ucs_class; uccid_prot_t ucs_prot; ccid_params_t ucs_params; -} __packed uccid_cmd_status_t; +} uccid_cmd_status_t; /* * Modify the state of the ICC, if present. @@ -123,7 +123,7 @@ typedef struct uccid_cmd_status { typedef struct uccid_cmd_icc_modify { uint32_t uci_version; uint32_t uci_action; -} __packed uccid_cmd_icc_modify_t; +} uccid_cmd_icc_modify_t; #ifdef __cplusplus } |