aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.am2
-rw-r--r--src/Makefile.in2
-rw-r--r--src/sg_inq.c435
-rw-r--r--src/sg_logs.c73
-rw-r--r--src/sg_ses.c13
-rw-r--r--src/sg_unmap.c8
-rw-r--r--src/sg_vpd.c343
-rw-r--r--src/sg_vpd_common.c199
-rw-r--r--src/sg_vpd_common.h59
-rw-r--r--src/sg_vpd_vendor.c345
10 files changed, 926 insertions, 553 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index 021100d3..f75bc7cb 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -62,6 +62,8 @@ AM_CFLAGS = -Wall -W $(DBG_CFLAGS)
# AM_CFLAGS = -Wall -W -Wextra -Wmisleading-indentation -Wduplicated-cond -Wduplicated-branches -Wlogical-op -Wnull-dereference -Wshadow -Wjump-misses-init
# AM_CFLAGS = -Wall -W -pedantic -std=c11
# AM_CFLAGS = -Wall -W -pedantic -std=c11 --analyze
+# AM_CFLAGS = -Wall -W -pedantic -std=c++98
+# AM_CFLAGS = -Wall -W -pedantic -std=c++11
# AM_CFLAGS = -Wall -W -pedantic -std=c++14
# AM_CFLAGS = -Wall -W -pedantic -std=c++1z
# AM_CFLAGS = -Wall -W -pedantic -std=c++20
diff --git a/src/Makefile.in b/src/Makefile.in
index f8b5a25d..c5217b1e 100644
--- a/src/Makefile.in
+++ b/src/Makefile.in
@@ -664,6 +664,8 @@ AM_CFLAGS = -Wall -W $(DBG_CFLAGS)
# AM_CFLAGS = -Wall -W -Wextra -Wmisleading-indentation -Wduplicated-cond -Wduplicated-branches -Wlogical-op -Wnull-dereference -Wshadow -Wjump-misses-init
# AM_CFLAGS = -Wall -W -pedantic -std=c11
# AM_CFLAGS = -Wall -W -pedantic -std=c11 --analyze
+# AM_CFLAGS = -Wall -W -pedantic -std=c++98
+# AM_CFLAGS = -Wall -W -pedantic -std=c++11
# AM_CFLAGS = -Wall -W -pedantic -std=c++14
# AM_CFLAGS = -Wall -W -pedantic -std=c++1z
# AM_CFLAGS = -Wall -W -pedantic -std=c++20
diff --git a/src/sg_inq.c b/src/sg_inq.c
index 681073fe..47834743 100644
--- a/src/sg_inq.c
+++ b/src/sg_inq.c
@@ -53,7 +53,7 @@
#include "sg_vpd_common.h" /* for shared VPD page processing with sg_vpd */
-static const char * version_str = "2.28 20220811"; /* spc6r06, sbc5r03 */
+static const char * version_str = "2.28 20220818"; /* spc6r06, sbc5r03 */
#define MY_NAME "sg_inq"
@@ -88,10 +88,6 @@ static const char * version_str = "2.28 20220811"; /* spc6r06, sbc5r03 */
// #undef SG_SCSI_STRINGS
// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< TESTING
-#ifndef SG_NVME_VPD_NICR
-#define SG_NVME_VPD_NICR 0xde
-#endif
-
#define VPD_NOPE_WANT_STD_INQ -2 /* request for standard inquiry */
/* Vendor specific VPD pages (typically >= 0xc0) */
@@ -146,6 +142,8 @@ static void prepare_ata_identify(const struct opts_t * op, int inhex_len);
/* Note that this table is sorted by acronym */
static struct svpd_values_name_t t10_vpd_pg[] = {
+ {VPD_AUTOMATION_DEV_SN, 0, 1, "adsn", "Automation device serial "
+ "number (SSC)"},
{VPD_ATA_INFO, 0, -1, "ai", "ATA information (SAT)"},
{VPD_BLOCK_DEV_CHARS, 0, 0, "bdc",
"Block device characteristics (SBC)"},
@@ -153,6 +151,7 @@ static struct svpd_values_name_t t10_vpd_pg[] = {
"extension (SBC)"},
{VPD_BLOCK_LIMITS, 0, 0, "bl", "Block limits (SBC)"},
{VPD_BLOCK_LIMITS_EXT, 0, 0, "ble", "Block limits extension (SBC)"},
+ {VPD_CFA_PROFILE_INFO, 0, 0, "cfa", "CFA profile information"},
{VPD_CON_POS_RANGE, 0, 0, "cpr", "Concurrent positioning ranges "
"(SBC)"},
{VPD_DEVICE_CONSTITUENTS, 0, -1, "dc", "Device constituents"},
@@ -169,6 +168,7 @@ static struct svpd_values_name_t t10_vpd_pg[] = {
#endif
{VPD_EXT_INQ, 0, -1, "ei", "Extended inquiry data"},
{VPD_FORMAT_PRESETS, 0, 0, "fp", "Format presets"},
+ {VPD_LB_PROTECTION, 0, 0, "lbpro", "Logical block protection (SSC)"},
{VPD_LB_PROVISIONING, 0, 0, "lbpv", "Logical block provisioning "
"(SBC)"},
{VPD_MAN_ASS_SN, 0, 1, "mas", "Manufacturer assigned serial number (SSC)"},
@@ -176,12 +176,14 @@ static struct svpd_values_name_t t10_vpd_pg[] = {
"Manufacturer assigned serial number (ADC)"},
{VPD_MAN_NET_ADDR, 0, -1, "mna", "Management network addresses"},
{VPD_MODE_PG_POLICY, 0, -1, "mpp", "Mode page policy"},
- {VPD_POWER_CONDITION, 0, -1, "po", "Power condition"},
+ {VPD_POWER_CONDITION, 0, -1, "po", "Power condition"},/* "pc" in sg_vpd */
{VPD_POWER_CONSUMPTION, 0, -1, "psm", "Power consumption"},
{VPD_PROTO_LU, 0, -1, "pslu", "Protocol-specific logical unit "
"information"},
{VPD_PROTO_PORT, 0, -1, "pspo", "Protocol-specific port information"},
{VPD_REFERRALS, 0, 0, "ref", "Referrals (SBC)"},
+ {VPD_SA_DEV_CAP, 0, 1, "sad",
+ "Sequential access device capabilities (SSC)"},
{VPD_SUP_BLOCK_LENS, 0, 0, "sbl", "Supported block lengths and "
"protection types (SBC)"},
{VPD_SCSI_FEATURE_SETS, 0, -1, "sfs", "SCSI Feature sets"},
@@ -190,6 +192,7 @@ static struct svpd_values_name_t t10_vpd_pg[] = {
{VPD_UNIT_SERIAL_NUM, 0, -1, "sn", "Unit serial number"},
{VPD_SCSI_PORTS, 0, -1, "sp", "SCSI ports"},
{VPD_SUPPORTED_VPDS, 0, -1, "sv", "Supported VPD pages"},
+ {VPD_TA_SUPPORTED, 0, 1, "tas", "TapeAlert supported flags (SSC)"},
{VPD_3PARTY_COPY, 0, -1, "tpc", "Third party copy"},
{VPD_ZBC_DEV_CHARS, 0, 0, "zbdch", "Zoned block device "
"characteristics"},
@@ -331,9 +334,10 @@ usage()
" --version|-V print version string then exit\n"
" --vpd|-e vital product data (set page with "
"'--page=PG')\n\n"
- "Performs a SCSI INQUIRY command on DEVICE or decodes INQUIRY "
- "response\nheld in file FN. If no options given then does a "
- "'standard' INQUIRY.\nCan list VPD pages with '--vpd' or "
+ "Sends a SCSI INQUIRY command to the DEVICE and decodes the "
+ "response.\nAlternatively it decodes the INQUIRY response held "
+ "in file FN. If no\noptions given then it sends a 'standard' "
+ "INQUIRY command to DEVICE. Can\nlist VPD pages with '--vpd' or "
"'--page=PG' option.\n");
}
@@ -344,11 +348,11 @@ usage_old()
#ifdef SG_LIB_LINUX
pr2serr("Usage: sg_inq [-a] [-A] [-b] [-B=0|1] [-c] [-cl] [-d] [-e] "
"[-h]\n"
- " [-H] [-i] [I=FN] [-l=LEN] [-L] [-m] [-M] "
- "[-o]\n"
- " [-p=VPD_PG] [-P] [-r] [-s] [-u] [-U] [-v] [-V] "
- "[-x]\n"
- " [-36] [-?] DEVICE\n"
+ " [-H] [-i] [-I=FN] [-j[=JO]] [-l=LEN] [-L] [-m] "
+ "[-M]\n"
+ " [-o] [-p=VPD_PG] [-P] [-r] [-s] [-u] [-U] [-v] "
+ "[-V]\n"
+ " [-x] [-36] [-?] DEVICE\n"
" where:\n"
" -a decode ATA information VPD page (0x89)\n"
" -A treat <device> as (directly attached) ATA device\n");
@@ -374,6 +378,8 @@ usage_old()
" -H output in hex (ASCII to the right) [same as '-h']\n"
" -i decode device identification VPD page (0x83)\n"
" -I=FN use ASCII hex in file FN instead of DEVICE\n"
+ " -j[=JO] output in JSON instead of human readable "
+ "text.\n"
" -l=LEN requested response length (def: 0 "
"-> fetch 36\n"
" bytes first, then fetch again as "
@@ -395,7 +401,8 @@ usage_old()
" -x decode extended INQUIRY data VPD page (0x86)\n"
" -36 perform standard INQUIRY with a 36 byte response\n"
" -? output this usage message\n\n"
- "If no options given then does a standard SCSI INQUIRY\n");
+ "If no options given then sends a standard SCSI INQUIRY "
+ "command and\ndecodes the response.\n");
}
static void
@@ -749,7 +756,22 @@ old_parse_cmd_line(struct opts_t * op, int argc, char * argv[])
op->do_block = n;
} else if (0 == strncmp("I=", cp, 2))
op->inhex_fn = cp + 2;
- else if (0 == strncmp("l=", cp, 2)) {
+ else if ('j' == *cp) { /* handle either '-j' or '-j=<JO>' */
+ const char * c2p = (('=' == *(cp + 1)) ? cp + 2 : NULL);
+
+ if (! sgj_init_state(&op->json_st, c2p)) {
+ int bad_char = op->json_st.first_bad_char;
+ char e[1500];
+
+ if (bad_char) {
+ pr2serr("bad argument to --json= option, unrecognized "
+ "character '%c'\n\n", bad_char);
+ }
+ sg_json_usage(0, e, sizeof(e));
+ pr2serr("%s", e);
+ return SG_LIB_SYNTAX_ERROR;
+ }
+ } else if (0 == strncmp("l=", cp, 2)) {
num = sscanf(cp + 2, "%d", &n);
if ((1 != num) || (n < 1)) {
pr2serr("Inappropriate value after 'l=' option\n");
@@ -849,6 +871,7 @@ enumerate_vpds()
{
const struct svpd_values_name_t * vnp;
+ printf("T10 defined VPD pages:\n");
for (vnp = t10_vpd_pg; vnp->acron; ++vnp) {
if (vnp->name) {
if (vnp->value < 0)
@@ -858,6 +881,7 @@ enumerate_vpds()
vnp->name);
}
}
+ printf("Vendor specific VPD pages:\n");
for (vnp = vs_vpd_pg; vnp->acron; ++vnp) {
if (vnp->name) {
if (vnp->value < 0)
@@ -1092,6 +1116,16 @@ svpd_inhex_decode_all(struct opts_t * op, sgj_opaque_p jop)
return res;
}
+static int
+no_ascii_4hex(const struct opts_t * op)
+{
+ if (op->do_hex < 2)
+ return 1;
+ else if (2 == op->do_hex)
+ return 0;
+ else
+ return -1;
+}
static void
decode_supported_vpd_4inq(uint8_t * buff, int len, struct opts_t * op,
@@ -1104,7 +1138,7 @@ decode_supported_vpd_4inq(uint8_t * buff, int len, struct opts_t * op,
char b[64];
if (op->do_hex) {
- hex2stdout(buff, len, (1 == op->do_hex) ? 0 : -1);
+ hex2stdout(buff, len, no_ascii_4hex(op));
return;
}
if (len < 4) {
@@ -1165,14 +1199,14 @@ vpd_page_is_supported(uint8_t * vpd_pg0, int v0_len, int pg_num, int vb)
/* ASCII Information VPD pages (page numbers: 0x1 to 0x7f) */
static void
-decode_ascii_inf(uint8_t * buff, int len, int do_hex)
+decode_ascii_inf(uint8_t * buff, int len, struct opts_t * op)
{
int al, k, bump;
uint8_t * bp;
uint8_t * p;
- if (do_hex) {
- hex2stdout(buff, len, (1 == do_hex) ? 0 : -1);
+ if (op->do_hex) {
+ hex2stdout(buff, len, no_ascii_4hex(op));
return;
}
if (len < 4) {
@@ -1247,8 +1281,7 @@ decode_scsi_ports_vpd_4inq(uint8_t * buff, int len, struct opts_t * op,
if (ip_tid_len > 0) {
if (op->do_hex) {
printf(" Initiator port transport id:\n");
- hex2stdout((bp + 8), ip_tid_len,
- (1 == op->do_hex) ? 1 : -1);
+ hex2stdout((bp + 8), ip_tid_len, no_ascii_4hex(op));
} else {
char b[1024];
@@ -1271,8 +1304,7 @@ decode_scsi_ports_vpd_4inq(uint8_t * buff, int len, struct opts_t * op,
if (tpd_len > 0) {
sgj_pr_hr(jsp, " Target port descriptor(s):\n");
if (op->do_hex)
- hex2stdout(bp + bump + 4, tpd_len,
- (1 == op->do_hex) ? 1 : -1);
+ hex2stdout(bp + bump + 4, tpd_len, no_ascii_4hex(op));
else {
sgj_opaque_p ja2p = sgj_named_subarray_r(jsp, jo2p,
"target_port_descriptor_list");
@@ -1953,7 +1985,8 @@ export_dev_ids(uint8_t * buff, int len, int verbose)
"around offset=%d\n", off);
}
-/* VPD_BLOCK_LIMITS sbc */
+/* VPD_BLOCK_LIMITS 0xb0 ["bl"] (SBC) */
+/* VPD_SA_DEV_CAP 0xb0 ["sad"] (SSC) */
/* Sequential access device characteristics, ssc+smc */
/* OSD information, osd */
static void
@@ -1963,7 +1996,7 @@ decode_b0_vpd(uint8_t * buff, int len, struct opts_t * op, sgj_opaque_p jop)
sgj_state * jsp = &op->json_st;
if (op->do_hex) {
- hex2stdout(buff, len, (1 == op->do_hex) ? 0 : -1);
+ hex2stdout(buff, len, no_ascii_4hex(op));
return;
}
switch (pdt) {
@@ -1981,8 +2014,8 @@ decode_b0_vpd(uint8_t * buff, int len, struct opts_t * op, sgj_opaque_p jop)
break;
case PDT_OSD:
default:
- printf(" Unable to decode pdt=0x%x, in hex:\n", pdt);
- hex2stdout(buff, len, 0);
+ pr2serr(" Unable to decode pdt=0x%x, in hex:\n", pdt);
+ hex2stderr(buff, len, 0);
break;
}
}
@@ -1990,49 +2023,60 @@ decode_b0_vpd(uint8_t * buff, int len, struct opts_t * op, sgj_opaque_p jop)
/* VPD_BLOCK_DEV_CHARS sbc 0xb1 ["bdc"] */
/* VPD_MAN_ASS_SN ssc */
static void
-decode_b1_vpd(uint8_t * buff, int len, int do_hex)
+decode_b1_vpd(uint8_t * buff, int len, struct opts_t * op, sgj_opaque_p jop)
{
int pdt;
+ sgj_state * jsp = &op->json_st;
- if (do_hex) {
- hex2stdout(buff, len, (1 == do_hex) ? 0 : -1);
+ if (op->do_hex) {
+ hex2stdout(buff, len, no_ascii_4hex(op));
return;
}
pdt = PDT_MASK & buff[0];
switch (pdt) {
- case PDT_DISK: case PDT_WO: case PDT_OPTICAL: case PDT_ZBC:
- /* now done by decode_block_dev_ch_vpd() in sg_vpd_common.c */
- break;
- case PDT_TAPE: case PDT_MCHANGER: case PDT_ADC:
- printf(" Manufacturer-assigned serial number: %.*s\n",
- len - 4, buff + 4);
- break;
- default:
- printf(" Unable to decode pdt=0x%x, in hex:\n", pdt);
- hex2stdout(buff, len, 0);
- break;
+ case PDT_DISK: case PDT_WO: case PDT_OPTICAL: case PDT_ZBC:
+ /* now done by decode_block_dev_ch_vpd() in sg_vpd_common.c */
+ break;
+ case PDT_TAPE: case PDT_MCHANGER: case PDT_ADC:
+ sgj_pr_hr(jsp, " Manufacturer-assigned serial number: %.*s\n",
+ len - 4, buff + 4);
+ sgj_js_nv_s_len(jsp, jop, "manufacturer_assigned_serial_number",
+ (const char *)buff + 4, len - 4);
+ break;
+ default:
+ pr2serr(" Unable to decode pdt=0x%x, in hex:\n", pdt);
+ hex2stderr(buff, len, 0);
+ break;
}
}
-/* VPD_REFERRALS sbc */
+/* VPD_REFERRALS sbc 0xb3 ["ref"] */
+/* VPD_AUTOMATION_DEV_SN ssc 0xb3 ["adsn"] */
static void
-decode_b3_vpd(uint8_t * buff, int len, int do_hex)
+decode_b3_vpd(uint8_t * buff, int len, struct opts_t * op, sgj_opaque_p jop)
{
int pdt;
+ sgj_state * jsp = &op->json_st;
- if (do_hex) {
- hex2stdout(buff, len, (1 == do_hex) ? 0 : -1);
+ if (op->do_hex) {
+ hex2stdout(buff, len, no_ascii_4hex(op));
return;
}
- pdt = PDT_MASK & buff[0];
+ pdt = buff[0] & PDT_MASK;
switch (pdt) {
- case PDT_DISK: case PDT_WO: case PDT_OPTICAL: case PDT_ZBC:
- /* now done in decode)referrals_vpd() in sg_vpd_common.c */
- break;
- default:
- printf(" Unable to decode pdt=0x%x, in hex:\n", pdt);
- hex2stdout(buff, len, 0);
- break;
+ case PDT_DISK: case PDT_WO: case PDT_OPTICAL: case PDT_ZBC:
+ /* now done in decode_referrals_vpd() in sg_vpd_common.c */
+ break;
+ case PDT_TAPE: case PDT_MCHANGER:
+ sgj_pr_hr(jsp, " Automation device serial number: %.*s\n",
+ len - 4, buff + 4);
+ sgj_js_nv_s_len(jsp, jop, "automation_device_serial_number",
+ (const char *)buff + 4, len - 4);
+ break;
+ default:
+ pr2serr(" Unable to decode pdt=0x%x, in hex:\n", pdt);
+ hex2stderr(buff, len, 0);
+ break;
}
}
@@ -2084,7 +2128,7 @@ static const char * failover_mode_arr[] =
};
static void
-decode_upr_vpd_c0_emc(uint8_t * buff, int len, int do_hex)
+decode_upr_vpd_c0_emc(uint8_t * buff, int len, struct opts_t * op)
{
int k, ip_mgmt, vpp80, lun_z;
@@ -2092,8 +2136,8 @@ decode_upr_vpd_c0_emc(uint8_t * buff, int len, int do_hex)
pr2serr("EMC upr VPD page [0xc0]: length too short=%d\n", len);
return;
}
- if (do_hex) {
- hex2stdout(buff, len, (1 == do_hex) ? 1 : -1);
+ if (op->do_hex) {
+ hex2stdout(buff, len, no_ascii_4hex(op));
return;
}
if (buff[9] != 0x00) {
@@ -2162,14 +2206,14 @@ decode_upr_vpd_c0_emc(uint8_t * buff, int len, int do_hex)
}
static void
-decode_rdac_vpd_c2(uint8_t * buff, int len, int do_hex)
+decode_rdac_vpd_c2(uint8_t * buff, int len, struct opts_t * op)
{
if (len < 3) {
pr2serr("Software Version VPD page length too short=%d\n", len);
return;
}
- if (do_hex) {
- hex2stdout(buff, len, (1 == do_hex) ? 1 : -1);
+ if (op->do_hex) {
+ hex2stdout(buff, len, no_ascii_4hex(op));
return;
}
if (buff[4] != 's' && buff[5] != 'w' && buff[6] != 'r') {
@@ -2260,14 +2304,14 @@ decode_rdac_vpd_c9_rtpg_data(uint8_t aas, uint8_t vendor)
}
static void
-decode_rdac_vpd_c9(uint8_t * buff, int len, int do_hex)
+decode_rdac_vpd_c9(uint8_t * buff, int len, struct opts_t * op)
{
if (len < 3) {
pr2serr("Volume Access Control VPD page length too short=%d\n", len);
return;
}
- if (do_hex) {
- hex2stdout(buff, len, (1 == do_hex) ? 1 : -1);
+ if (op->do_hex) {
+ hex2stdout(buff, len, no_ascii_4hex(op));
return;
}
if (buff[4] != 'v' && buff[5] != 'a' && buff[6] != 'c') {
@@ -2398,7 +2442,7 @@ std_inq_decode(struct opts_t * op, sgj_opaque_p jop, int off)
return;
} else if (op->do_hex) {
/* with -H, print with address, -HH without */
- hex2stdout(rp, op->maxlen, ((1 == op->do_hex) ? 0 : -1));
+ hex2stdout(rp, op->maxlen, no_ascii_4hex(op));
return;
}
pqual = (rp[0] & 0xe0) >> 5;
@@ -2802,7 +2846,7 @@ cmddt_process(int sg_fd, const struct opts_t * op)
len = rsp_buff[5] + 6;
reserved_cmddt = rsp_buff[4];
if (op->do_hex)
- hex2stdout(rsp_buff, len, (1 == op->do_hex) ? 0 : -1);
+ hex2stdout(rsp_buff, len, no_ascii_4hex(op));
else if (op->do_raw)
dStrRaw((const char *)rsp_buff, len);
else {
@@ -2872,14 +2916,23 @@ cmddt_process(int sg_fd, const struct opts_t * op)
static int
vpd_mainly_hex(int sg_fd, struct opts_t * op, sgj_opaque_p jap, int off)
{
- int res, len;
+ bool as_json;
+ bool json_o_hr;
+ int res, len, n;
char b[128];
+ sgj_state * jsp = &op->json_st;
const char * cp;
uint8_t * rp;
+ as_json = jsp->pr_as_json;
+ json_o_hr = as_json && jsp->pr_out_hr;
rp = rsp_buff + off;
- if ((! op->do_raw) && (op->do_hex < 2))
- printf("VPD INQUIRY, page code=0x%.2x:\n", op->vpd_pn);
+ if ((! op->do_raw) && (op->do_hex < 3)) {
+ if (op->do_hex)
+ printf("VPD INQUIRY, page code=0x%.2x:\n", op->vpd_pn);
+ else
+ sgj_pr_hr(jsp, "VPD INQUIRY, page code=0x%.2x:\n", op->vpd_pn);
+ }
if (sg_fd < 0) {
len = sg_get_unaligned_be16(rp + 2) + 4;
res = 0;
@@ -2892,15 +2945,32 @@ vpd_mainly_hex(int sg_fd, struct opts_t * op, sgj_opaque_p jap, int off)
if (op->do_raw)
dStrRaw((const char *)rp, len);
else {
+ int pdt = pdt = rp[0] & PDT_MASK;
+
if (0 == op->vpd_pn)
decode_supported_vpd_4inq(rp, len, op, jap);
else {
if (op->verbose) {
- cp = sg_get_pdt_str(rp[0] & PDT_MASK, sizeof(b), b);
- printf(" [PQual=%d Peripheral device type: %s]\n",
- (rp[0] & 0xe0) >> 5, cp);
+ cp = sg_get_pdt_str(pdt, sizeof(b), b);
+ if (op->do_hex)
+ printf(" [PQual=%d Peripheral device type: %s]\n",
+ (rp[0] & 0xe0) >> 5, cp);
+ else
+ sgj_pr_hr(jsp, " [PQual=%d Peripheral device "
+ "type: %s]\n", (rp[0] & 0xe0) >> 5, cp);
}
- hex2stdout(rp, len, ((1 == op->do_hex) ? 0 : -1));
+ if (json_o_hr && (0 == op->do_hex) && (len > 0) &&
+ (len < UINT16_MAX)) {
+ char * p;
+
+ n = len * 4;
+ p = malloc(n);
+ if (p) {
+ n = hex2str(rp, len, NULL, 1, n - 1, p);
+ sgj_js_str_out(jsp, p, n);
+ }
+ } else
+ hex2stdout(rp, len, no_ascii_4hex(op));
}
}
} else {
@@ -2959,7 +3029,7 @@ vpd_decode(int sg_fd, struct opts_t * op, sgj_opaque_p jop, int off)
switch (pn) {
case VPD_SUPPORTED_VPDS: /* 0x0 ["sv"] */
np = "Supported VPD pages VPD page";
- if (!op->do_raw && (op->do_hex < 2))
+ if (!op->do_raw && (op->do_hex < 3))
sgj_pr_hr(jsp, "VPD INQUIRY: %s\n", np);
res = vpd_fetch_page(sg_fd, rp, pn, op->maxlen, qt, vb, &len);
if (res)
@@ -2967,7 +3037,7 @@ vpd_decode(int sg_fd, struct opts_t * op, sgj_opaque_p jop, int off)
if (op->do_raw)
dStrRaw((const char *)rp, len);
else if (op->do_hex)
- hex2stdout(rp, len, (1 == op->do_hex) ? 0 : -1);
+ hex2stdout(rp, len, no_ascii_4hex(op));
else {
if (as_json) {
jo2p = sg_vpd_js_hdr(jsp, jop, np, rp);
@@ -2979,7 +3049,7 @@ vpd_decode(int sg_fd, struct opts_t * op, sgj_opaque_p jop, int off)
break;
case VPD_UNIT_SERIAL_NUM: /* 0x80 ["sn"] */
np = "Unit serial number VPD page";
- if (! op->do_raw && ! op->do_export && (op->do_hex < 2))
+ if (! op->do_raw && ! op->do_export && (op->do_hex < 3))
sgj_pr_hr(jsp, "VPD INQUIRY: %s\n", np);
res = vpd_fetch_page(sg_fd, rp, pn, op->maxlen, qt, vb, &len);
if (res)
@@ -2987,7 +3057,7 @@ vpd_decode(int sg_fd, struct opts_t * op, sgj_opaque_p jop, int off)
if (op->do_raw)
dStrRaw((const char *)rp, len);
else if (op->do_hex)
- hex2stdout(rp, len, (1 == op->do_hex) ? 0 : -1);
+ hex2stdout(rp, len, no_ascii_4hex(op));
else {
char obuff[DEF_ALLOC_LEN];
int k, m;
@@ -3048,7 +3118,7 @@ vpd_decode(int sg_fd, struct opts_t * op, sgj_opaque_p jop, int off)
break;
case VPD_SOFTW_INF_ID: /* 0x84 ["sii"] */
np = "Software interface identification VPD page";
- if (! op->do_raw && (op->do_hex < 2))
+ if (! op->do_raw && (op->do_hex < 3))
sgj_pr_hr(jsp, "VPD INQUIRY: %s\n", np);
res = vpd_fetch_page(sg_fd, rp, pn, op->maxlen, qt, vb, &len);
if (res)
@@ -3066,7 +3136,7 @@ vpd_decode(int sg_fd, struct opts_t * op, sgj_opaque_p jop, int off)
break;
case VPD_MAN_NET_ADDR: /* 0x85 ["mna"] */
np = "Management network addresses page";
- if (!op->do_raw && (op->do_hex < 2))
+ if (!op->do_raw && (op->do_hex < 3))
sgj_pr_hr(jsp, "VPD INQUIRY: %s\n", np);
res = vpd_fetch_page(sg_fd, rp, pn, op->maxlen, qt, vb, &len);
if (res)
@@ -3087,7 +3157,7 @@ vpd_decode(int sg_fd, struct opts_t * op, sgj_opaque_p jop, int off)
break;
case VPD_EXT_INQ: /* 0x86 ["ei"] */
np = "Extended INQUIRY data";
- if (!op->do_raw && (op->do_hex < 2))
+ if (!op->do_raw && (op->do_hex < 3))
sgj_pr_hr(jsp, "VPD INQUIRY: %s page\n", np);
res = vpd_fetch_page(sg_fd, rp, pn, op->maxlen, qt, vb, &len);
if (res)
@@ -3095,14 +3165,30 @@ vpd_decode(int sg_fd, struct opts_t * op, sgj_opaque_p jop, int off)
if (op->do_raw)
dStrRaw((const char *)rp, len);
else {
+ bool protect = false;
+
+ op->protect_not_sure = false;
+ if ((sg_fd >= 0) && (! op->do_force)) {
+ struct sg_simple_inquiry_resp sir;
+
+ res = sg_simple_inquiry(sg_fd, &sir, false, vb);
+ if (res) {
+ if (op->verbose)
+ pr2serr("%s: sg_simple_inquiry() failed, res=%d\n",
+ __func__, res);
+ op->protect_not_sure = true;
+ } else
+ protect = !!(sir.byte_5 & 0x1); /* SPC-3 and later */
+ } else
+ op->protect_not_sure = true;
if (as_json)
jo2p = sg_vpd_js_hdr(jsp, jop, np, rp);
- decode_x_inq_vpd(rp, len, false /* protect */, op, jo2p);
+ decode_x_inq_vpd(rp, len, protect, op, jo2p);
}
break;
case VPD_MODE_PG_POLICY: /* 0x87 ["mpp"] */
np = "Mode page policy";
- if (!op->do_raw && (op->do_hex < 2))
+ if (!op->do_raw && (op->do_hex < 3))
sgj_pr_hr(jsp, "VPD INQUIRY: %s\n", np);
res = vpd_fetch_page(sg_fd, rp, pn, op->maxlen, qt, vb, &len);
if (res)
@@ -3120,7 +3206,7 @@ vpd_decode(int sg_fd, struct opts_t * op, sgj_opaque_p jop, int off)
break;
case VPD_SCSI_PORTS: /* 0x88 ["sp"] */
np = "SCSI Ports VPD page";
- if (!op->do_raw && (op->do_hex < 2))
+ if (!op->do_raw && (op->do_hex < 3))
sgj_pr_hr(jsp, "VPD INQUIRY: %s\n", np);
res = vpd_fetch_page(sg_fd, rp, pn, op->maxlen, qt, vb, &len);
if (res)
@@ -3138,7 +3224,7 @@ vpd_decode(int sg_fd, struct opts_t * op, sgj_opaque_p jop, int off)
break;
case VPD_ATA_INFO: /* 0x89 ["ai"] */
np = "ATA information VPD page";
- if (!op->do_raw && (op->do_hex < 2))
+ if (!op->do_raw && (op->do_hex < 3))
sgj_pr_hr(jsp, "VPD INQUIRY: %s\n", np);
res = vpd_fetch_page(sg_fd, rp, pn, op->maxlen, qt, vb, &len);
if (res)
@@ -3159,7 +3245,7 @@ vpd_decode(int sg_fd, struct opts_t * op, sgj_opaque_p jop, int off)
break;
case VPD_POWER_CONDITION: /* 0x8a ["pc"] */
np = "Power condition VPD page";
- if (!op->do_raw && (op->do_hex < 2))
+ if (!op->do_raw && (op->do_hex < 3))
sgj_pr_hr(jsp, "VPD INQUIRY: %s\n", np);
res = vpd_fetch_page(sg_fd, rp, pn, op->maxlen, qt, vb, &len);
if (res)
@@ -3172,9 +3258,9 @@ vpd_decode(int sg_fd, struct opts_t * op, sgj_opaque_p jop, int off)
decode_power_condition(rp, len, op, jo2p);
}
break;
- case VPD_POWER_CONSUMPTION: /* 0x8d ["psm"] */
- np = "Power consumption VPD page";
- if (!op->do_raw && (op->do_hex < 2))
+ case VPD_DEVICE_CONSTITUENTS: /* 0x8b ["dc"] */
+ np = "Device constituents page VPD page";
+ if (!op->do_raw && (op->do_hex < 3))
sgj_pr_hr(jsp, "VPD INQUIRY: %s\n", np);
res = vpd_fetch_page(sg_fd, rp, pn, op->maxlen, qt, vb, &len);
if (res)
@@ -3185,14 +3271,32 @@ vpd_decode(int sg_fd, struct opts_t * op, sgj_opaque_p jop, int off)
if (as_json) {
jo2p = sg_vpd_js_hdr(jsp, jop, np, rp);
jap = sgj_named_subarray_r(jsp, jo2p,
- "power_consumption_descriptor_list");
+ "constituent_descriptor_list");
}
- decode_power_consumption(rp, len, op, jap);
+ decode_dev_constit_vpd(rp, len, op, jap, recurse_vpd_decode);
}
break;
- case VPD_DEVICE_CONSTITUENTS: /* 0x8b ["dc"] */
- np = "Device constituents page VPD page";
- if (!op->do_raw && (op->do_hex < 2))
+ case VPD_CFA_PROFILE_INFO: /* 0x8c ["cfa"] */
+ np = "CFA profile information VPD page";
+ if (!op->do_raw && (op->do_hex < 3))
+ sgj_pr_hr(jsp, "%s:\n", np);
+ res = vpd_fetch_page(sg_fd, rp, pn, op->maxlen, qt, vb, &len);
+ if (0 == res) {
+ if (op->do_raw)
+ dStrRaw((const char *)rp, len);
+ else {
+ if (as_json) {
+ jo2p = sg_vpd_js_hdr(jsp, jop, np, rp);
+ jap = sgj_named_subarray_r(jsp, jo2p,
+ "cfa_profile_descriptor_list");
+ }
+ decode_cga_profile_vpd(rp, len, op, jap);
+ }
+ }
+ break;
+ case VPD_POWER_CONSUMPTION: /* 0x8d ["psm"] */
+ np = "Power consumption VPD page";
+ if (!op->do_raw && (op->do_hex < 3))
sgj_pr_hr(jsp, "VPD INQUIRY: %s\n", np);
res = vpd_fetch_page(sg_fd, rp, pn, op->maxlen, qt, vb, &len);
if (res)
@@ -3203,14 +3307,14 @@ vpd_decode(int sg_fd, struct opts_t * op, sgj_opaque_p jop, int off)
if (as_json) {
jo2p = sg_vpd_js_hdr(jsp, jop, np, rp);
jap = sgj_named_subarray_r(jsp, jo2p,
- "constituent_descriptor_list");
+ "power_consumption_descriptor_list");
}
- decode_dev_constit_vpd(rp, len, op, jap, recurse_vpd_decode);
+ decode_power_consumption(rp, len, op, jap);
}
break;
case VPD_3PARTY_COPY: /* 0x8f ["tpc"] */
np = "Third party copy VPD page";
- if (!op->do_raw && (op->do_hex < 2))
+ if (!op->do_raw && (op->do_hex < 3))
sgj_pr_hr(jsp, "VPD INQUIRY: %s\n", np);
res = vpd_fetch_page(sg_fd, rp, pn, op->maxlen, qt, vb, &len);
if (res)
@@ -3228,7 +3332,7 @@ vpd_decode(int sg_fd, struct opts_t * op, sgj_opaque_p jop, int off)
break;
case VPD_PROTO_LU: /* 0x90 ["pslu"] */
np = "Protocol specific logical unit information VPD page";
- if (!op->do_raw && (op->do_hex < 2))
+ if (!op->do_raw && (op->do_hex < 3))
sgj_pr_hr(jsp, "VPD INQUIRY: %s\n", np);
res = vpd_fetch_page(sg_fd, rp, pn, op->maxlen, qt, vb, &len);
if (res)
@@ -3246,7 +3350,7 @@ vpd_decode(int sg_fd, struct opts_t * op, sgj_opaque_p jop, int off)
break;
case VPD_PROTO_PORT: /* 0x91 ["pspo"] */
np = "Protocol specific port information VPD page";
- if (!op->do_raw && (op->do_hex < 2))
+ if (!op->do_raw && (op->do_hex < 3))
sgj_pr_hr(jsp, "VPD INQUIRY: %s\n", np);
res = vpd_fetch_page(sg_fd, rp, pn, op->maxlen, qt, vb, &len);
if (res)
@@ -3264,7 +3368,7 @@ vpd_decode(int sg_fd, struct opts_t * op, sgj_opaque_p jop, int off)
break;
case VPD_SCSI_FEATURE_SETS: /* 0x92 ["sfs"] */
np = "SCSI Feature sets VPD page";
- if (!op->do_raw && (op->do_hex < 2))
+ if (!op->do_raw && (op->do_hex < 3))
sgj_pr_hr(jsp, "VPD INQUIRY: %s\n", np);
res = vpd_fetch_page(sg_fd, rp, pn, op->maxlen, qt, vb, &len);
if (res)
@@ -3314,7 +3418,7 @@ vpd_decode(int sg_fd, struct opts_t * op, sgj_opaque_p jop, int off)
np = NULL;
break;
}
- if (op->do_hex < 2) {
+ if (op->do_hex < 3) {
if (NULL == np)
sgj_pr_hr(jsp, "VPD page=0x%x, pdt=0x%x:\n", pn, pdt);
else
@@ -3364,7 +3468,7 @@ vpd_decode(int sg_fd, struct opts_t * op, sgj_opaque_p jop, int off)
printf("VPD INQUIRY: page=0x%x, pdt=0x%x\n", 0xb1, pdt);
break;
}
- if (op->do_hex < 2) {
+ if (op->do_hex < 3) {
if (NULL == np)
sgj_pr_hr(jsp, "VPD page=0x%x, pdt=0x%x:\n", pn, pdt);
else
@@ -3375,7 +3479,7 @@ vpd_decode(int sg_fd, struct opts_t * op, sgj_opaque_p jop, int off)
if (bdc)
decode_block_dev_ch_vpd(rp, len, op, jo2p);
else
- decode_b1_vpd(rp, len, op->do_hex);
+ decode_b1_vpd(rp, len, op, jo2p);
} else if (! op->do_raw)
pr2serr("VPD INQUIRY: page=0xb1\n");
break;
@@ -3383,6 +3487,7 @@ vpd_decode(int sg_fd, struct opts_t * op, sgj_opaque_p jop, int off)
res = vpd_fetch_page(sg_fd, rp, pn, op->maxlen, qt, vb, &len);
if (0 == res) {
bool lbpv = false;
+ bool tas = false;
if (op->do_raw) {
dStrRaw((const char *)rp, len);
@@ -3398,12 +3503,13 @@ vpd_decode(int sg_fd, struct opts_t * op, sgj_opaque_p jop, int off)
case PDT_TAPE: case PDT_MCHANGER:
np = "TapeAlert supported flags VPD page";
ep = "(SSC)";
+ tas = true;
break;
default:
np = NULL;
break;
}
- if (op->do_hex < 2) {
+ if (op->do_hex < 3) {
if (NULL == np)
sgj_pr_hr(jsp, "VPD page=0x%x, pdt=0x%x:\n", pn, pdt);
else
@@ -3413,18 +3519,13 @@ vpd_decode(int sg_fd, struct opts_t * op, sgj_opaque_p jop, int off)
jo2p = sg_vpd_js_hdr(jsp, jop, np, rp);
if (lbpv)
return decode_block_lb_prov_vpd(rp, len, op, jo2p);
+ else if (tas)
+ decode_tapealert_supported_vpd(rp, len, op, jo2p);
else
return vpd_mainly_hex(sg_fd, op, NULL, off);
} else if (! op->do_raw)
pr2serr("VPD INQUIRY: page=0xb2\n");
break;
-#if 0
-xxxxx
- if (!op->do_raw && (op->do_hex < 2))
- pr2serr(" Only hex output supported. The sg_vpd utility decodes "
- "the B2h page.\n");
- return vpd_mainly_hex(sg_fd, op, NULL, off);
-#endif
case 0xb3:
res = vpd_fetch_page(sg_fd, rp, pn, op->maxlen, qt, vb, &len);
if (0 == res) {
@@ -3445,7 +3546,7 @@ xxxxx
np = NULL;
break;
}
- if (op->do_hex < 2) {
+ if (op->do_hex < 3) {
if (NULL == np)
sgj_pr_hr(jsp, "VPD page=0x%x, pdt=0x%x:\n", pn, pdt);
else
@@ -3456,7 +3557,7 @@ xxxxx
if (ref)
decode_referrals_vpd(rp, len, op, jo2p);
else
- decode_b3_vpd(rp, len, op->do_hex);
+ decode_b3_vpd(rp, len, op, jo2p);
return 0;
} else if (! op->do_raw)
pr2serr("VPD INQUIRY: page=0xb3\n");
@@ -3465,6 +3566,7 @@ xxxxx
res = vpd_fetch_page(sg_fd, rp, pn, op->maxlen, qt, vb, &len);
if (0 == res) {
bool sbl = false;
+ bool dtde = false;
if (op->do_raw) {
dStrRaw((const char *)rp, len);
@@ -3477,24 +3579,34 @@ xxxxx
ep = "(SBC)";
sbl = true;
break;
+ case PDT_TAPE: case PDT_MCHANGER:
+ np = "Device transfer data element VPD page";
+ ep = "(SSC)";
+ dtde = true;
+ break;
default:
np = NULL;
break;
}
- if (op->do_hex < 2) {
+ if (op->do_hex < 3) {
if (NULL == np)
sgj_pr_hr(jsp, "VPD page=0x%x, pdt=0x%x:\n", pn, pdt);
else
sgj_pr_hr(jsp, "VPD INQUIRY: %s %s\n", np, ep);
}
- if (as_json) {
+ if (as_json)
jo2p = sg_vpd_js_hdr(jsp, jop, np, rp);
- jap = sgj_named_subarray_r(jsp, jo2p, "logical_block_"
+ if (sbl) {
+ if (as_json)
+ jap = sgj_named_subarray_r(jsp, jo2p, "logical_block_"
"length_and_protection_types_descriptor_list");
- }
- if (sbl)
decode_sup_block_lens_vpd(rp, len, op, jap);
- else
+ } else if (dtde) {
+ if (! jsp->pr_as_json)
+ hex2stdout(rp + 4, len - 4, 1);
+ sgj_js_nv_hex_bytes(jsp, jop, "device_transfer_data_element",
+ rp + 4, len - 4);
+ } else
return vpd_mainly_hex(sg_fd, op, NULL, off);
return 0;
} else if (! op->do_raw)
@@ -3504,6 +3616,7 @@ xxxxx
res = vpd_fetch_page(sg_fd, rp, pn, op->maxlen, qt, vb, &len);
if (0 == res) {
bool bdce = false;
+ bool lbp = false;
if (op->do_raw) {
dStrRaw((const char *)rp, len);
@@ -3516,11 +3629,16 @@ xxxxx
ep = "(SBC)";
bdce = true;
break;
+ case PDT_TAPE: case PDT_MCHANGER:
+ np = "Logical block protection VPD page";
+ ep = "(SSC)";
+ lbp = true;
+ break;
default:
np = NULL;
break;
}
- if (op->do_hex < 2) {
+ if (op->do_hex < 3) {
if (NULL == np)
sgj_pr_hr(jsp, "VPD page=0x%x, pdt=0x%x:\n", pn, pdt);
else
@@ -3530,7 +3648,12 @@ xxxxx
jo2p = sg_vpd_js_hdr(jsp, jop, np, rp);
if (bdce)
decode_block_dev_char_ext_vpd(rp, len, op, jo2p);
- else
+ else if (lbp) { /* VPD_LB_PROTECTION 0xb5 ["lbpro"] (SSC) */
+ if (as_json)
+ jap = sgj_named_subarray_r(jsp, jo2p,
+ "logical_block_protection_method_descriptor_list");
+ decode_lb_protection_vpd(rp, len, op, jap);
+ } else
return vpd_mainly_hex(sg_fd, op, NULL, off);
return 0;
} else if (! op->do_raw)
@@ -3556,7 +3679,7 @@ xxxxx
np = NULL;
break;
}
- if (op->do_hex < 2) {
+ if (op->do_hex < 3) {
if (NULL == np)
sgj_pr_hr(jsp, "VPD page=0x%x, pdt=0x%x:\n", pn, pdt);
else
@@ -3592,7 +3715,7 @@ xxxxx
np = NULL;
break;
}
- if (op->do_hex < 2) {
+ if (op->do_hex < 3) {
if (NULL == np)
sgj_pr_hr(jsp, "VPD page=0x%x, pdt=0x%x:\n", pn, pdt);
else
@@ -3628,7 +3751,7 @@ xxxxx
np = NULL;
break;
}
- if (op->do_hex < 2) {
+ if (op->do_hex < 3) {
if (NULL == np)
sgj_pr_hr(jsp, "VPD page=0x%x, pdt=0x%x:\n", pn, pdt);
else
@@ -3667,7 +3790,7 @@ xxxxx
np = NULL;
break;
}
- if (op->do_hex < 2) {
+ if (op->do_hex < 3) {
if (NULL == np)
sgj_pr_hr(jsp, "VPD page=0x%x, pdt=0x%x:\n", pn, pdt);
else
@@ -3686,9 +3809,9 @@ xxxxx
} else if (! op->do_raw)
pr2serr("VPD INQUIRY: page=0xb8\n");
break;
-// yyyyyyyy
+ /* Vendor specific VPD pages (>= 0xc0) */
case VPD_UPR_EMC: /* 0xc0 */
- if (!op->do_raw && (op->do_hex < 2))
+ if (!op->do_raw && (op->do_hex < 3))
printf("VPD INQUIRY: Unit Path Report Page (EMC)\n");
res = vpd_fetch_page(sg_fd, rp, pn, -1, qt, vb, &len);
if (res)
@@ -3696,10 +3819,10 @@ xxxxx
if (op->do_raw)
dStrRaw((const char *)rp, len);
else
- decode_upr_vpd_c0_emc(rp, len, op->do_hex);
+ decode_upr_vpd_c0_emc(rp, len, op);
break;
case VPD_RDAC_VERS: /* 0xc2 */
- if (!op->do_raw && (op->do_hex < 2))
+ if (!op->do_raw && (op->do_hex < 3))
printf("VPD INQUIRY: Software Version (RDAC)\n");
res = vpd_fetch_page(sg_fd, rp, pn, -1, qt, vb, &len);
if (res)
@@ -3707,10 +3830,10 @@ xxxxx
if (op->do_raw)
dStrRaw((const char *)rp, len);
else
- decode_rdac_vpd_c2(rp, len, op->do_hex);
+ decode_rdac_vpd_c2(rp, len, op);
break;
case VPD_RDAC_VAC: /* 0xc9 */
- if (!op->do_raw && (op->do_hex < 2))
+ if (!op->do_raw && (op->do_hex < 3))
printf("VPD INQUIRY: Volume Access Control (RDAC)\n");
res = vpd_fetch_page(sg_fd, rp, pn, -1, qt, vb, &len);
if (res)
@@ -3718,7 +3841,47 @@ xxxxx
if (op->do_raw)
dStrRaw((const char *)rp, len);
else
- decode_rdac_vpd_c9(rp, len, op->do_hex);
+ decode_rdac_vpd_c9(rp, len, op);
+ break;
+ case SG_NVME_VPD_NICR: /* 0xde */
+ np = "NVMe Identify Controller Response VPD page";
+ /* NVMe: Identify Controller data structure (CNS 01h) */
+ ep = "(sg3_utils)";
+ res = vpd_fetch_page(sg_fd, rp, pn, op->maxlen, qt, vb, &len);
+ if (res) {
+ sgj_pr_hr(jsp, "VPD INQUIRY: %s %s\n", np, ep);
+ break;
+ }
+ if (op->do_raw) {
+ dStrRaw((const char *)rp, len);
+ break;
+ }
+ pdt = rp[0] & PDT_MASK;
+ if (op->do_hex < 3) {
+ if (NULL == np)
+ sgj_pr_hr(jsp, "VPD page=0x%x, pdt=0x%x:\n", pn, pdt);
+ else
+ sgj_pr_hr(jsp, "VPD INQUIRY: %s %s\n", np, ep);
+ }
+ if (len < 16) {
+ pr2serr("%s expected to be > 15 bytes long (got: %d)\n", ep, len);
+ break;
+ } else {
+ int n = len - 16;
+
+ if (n > 4096) {
+ pr2serr("NVMe Identify response expected to be <= 4096 "
+ "bytes (got: %d)\n", n);
+ break;
+ }
+ if (op->do_hex)
+ hex2stdout(rp, len, no_ascii_4hex(op));
+ else if (as_json) {
+ jo2p = sg_vpd_js_hdr(jsp, jop, np, rp);
+ sgj_js_nv_hex_bytes(jsp, jo2p, "response_bytes", rp + 16, n);
+ } else
+ hex2stdout(rp + 16, n, 1);
+ }
break;
default:
bad = true;
@@ -3726,7 +3889,7 @@ xxxxx
}
if (bad) {
if ((pn > 0) && (pn < 0x80)) {
- if (!op->do_raw && (op->do_hex < 2))
+ if (!op->do_raw && (op->do_hex < 3))
printf("VPD INQUIRY: ASCII information page, FRU code=0x%x\n",
pn);
res = vpd_fetch_page(sg_fd, rp, pn, op->maxlen, qt, vb, &len);
@@ -3734,12 +3897,11 @@ xxxxx
if (op->do_raw)
dStrRaw((const char *)rp, len);
else
- decode_ascii_inf(rp, len, op->do_hex);
+ decode_ascii_inf(rp, len, op);
}
} else {
- if (op->do_hex < 2)
- pr2serr(" Only hex output supported. The sg_vpd and sdparm "
- "utilities decode more VPD pages.\n");
+ if (op->do_hex < 3)
+ pr2serr(" Only hex output supported.\n");
return vpd_mainly_hex(sg_fd, op, NULL, off);
}
}
@@ -4212,7 +4374,8 @@ main(int argc, char * argv[])
enumerate_vpds();
return SG_LIB_SYNTAX_ERROR;
}
- if ((1 != op->do_hex) && (0 == op->do_raw))
+ // if ((1 != op->do_hex) && (0 == op->do_raw))
+ if (0 == op->do_raw)
op->do_decode = true;
op->vpd_pn = vnp->value;
subvalue = vnp->subvalue;
diff --git a/src/sg_logs.c b/src/sg_logs.c
index 32bfc721..6f5edd48 100644
--- a/src/sg_logs.c
+++ b/src/sg_logs.c
@@ -37,7 +37,7 @@
#include "sg_unaligned.h"
#include "sg_pr2serr.h"
-static const char * version_str = "1.99 20220729"; /* spc6r06 + sbc5r01 */
+static const char * version_str = "2.00 20220816"; /* spc6r06 + sbc5r03 */
#define MX_ALLOC_LEN (0xfffc)
#define MX_INLEN_ALLOC_LEN (0x800000)
@@ -6711,70 +6711,6 @@ skip:
return true;
}
-static const char * tape_alert_strs[] = {
- "<parameter code 0, unknown>", /* 0x0 */
- "Read warning",
- "Write warning",
- "Hard error",
- "Media",
- "Read failure",
- "Write failure",
- "Media life",
- "Not data grade", /* 0x8 */
- "Write protect",
- "No removal",
- "Cleaning media",
- "Unsupported format",
- "Recoverable mechanical cartridge failure",
- "Unrecoverable mechanical cartridge failure",
- "Memory chip in cartridge failure",
- "Forced eject", /* 0x10 */
- "Read only format",
- "Tape directory corrupted on load",
- "Nearing media life",
- "Cleaning required",
- "Cleaning requested",
- "Expired cleaning media",
- "Invalid cleaning tape",
- "Retension requested", /* 0x18 */
- "Dual port interface error",
- "Cooling fan failing",
- "Power supply failure",
- "Power consumption",
- "Drive maintenance",
- "Hardware A",
- "Hardware B",
- "Interface", /* 0x20 */
- "Eject media",
- "Microcode update fail",
- "Drive humidity",
- "Drive temperature",
- "Drive voltage",
- "Predictive failure",
- "Diagnostics required",
- "Obsolete (28h)", /* 0x28 */
- "Obsolete (29h)",
- "Obsolete (2Ah)",
- "Obsolete (2Bh)",
- "Obsolete (2Ch)",
- "Obsolete (2Dh)",
- "Obsolete (2Eh)",
- "Reserved (2Fh)",
- "Reserved (30h)", /* 0x30 */
- "Reserved (31h)",
- "Lost statistics",
- "Tape directory invalid at unload",
- "Tape system area write failure",
- "Tape system area read failure",
- "No start of data",
- "Loading failure",
- "Unrecoverable unload failure", /* 0x38 */
- "Automation interface failure",
- "Firmware failure",
- "WORM medium - integrity check failed",
- "WORM medium - overwrite attempted",
-};
-
/* TAPE_ALERT_LPAGE [0x2e] <ta> */
static bool
show_tape_alert_ssc_page(const uint8_t * resp, int len,
@@ -6807,8 +6743,11 @@ show_tape_alert_ssc_page(const uint8_t * resp, int len,
if (op->verbose && (0 == op->do_brief) && flag)
printf(" >>>> ");
if ((0 == op->do_brief) || op->verbose || flag) {
- if (pc < (int)SG_ARRAY_SIZE(tape_alert_strs))
- printf(" %s: %d\n", tape_alert_strs[pc], flag);
+ if (NULL == sg_lib_tapealert_strs[0])
+ printf(" No string available for code 0x%x, flag: %d\n",
+ pc, flag);
+ else if (pc <= 0x40)
+ printf(" %s: %d\n", sg_lib_tapealert_strs[pc], flag);
else
printf(" Reserved parameter code 0x%x, flag: %d\n", pc,
flag);
diff --git a/src/sg_ses.c b/src/sg_ses.c
index e6e1270b..cc1ce78d 100644
--- a/src/sg_ses.c
+++ b/src/sg_ses.c
@@ -38,7 +38,7 @@
* commands tailored for SES (enclosure) devices.
*/
-static const char * version_str = "2.57 20220309"; /* ses4r04 */
+static const char * version_str = "2.58 20220813"; /* ses4r04 */
#define MX_ALLOC_LEN ((64 * 1024) - 4) /* max allowable for big enclosures */
#define MX_ELEM_HDR 1024
@@ -1084,6 +1084,8 @@ parse_index(struct opts_t *op)
}
element_type_by_code.elem_type_code = n;
mallcp = (char *)malloc(8); /* willfully forget about freeing this */
+ if (NULL == mallcp)
+ return sg_convert_errno(ENOMEM);
mallcp[0] = '_';
snprintf(mallcp + 1, 6, "%d", n);
element_type_by_code.abbrev = mallcp;
@@ -5686,12 +5688,13 @@ main(int argc, char * argv[])
if (SET_OPT == cgs_clp->cgs_sel)
tavp->val = DEF_SET_VAL;
}
- if (!strcmp(cgs_clp->cgs_str, "sas_addr") && op->dev_slot_num < 0) {
- pr2serr("--get=sas_addr requires --dev-slot-num. For expander "
- "SAS address, use exp_sas_addr instead.\n");
+ if (!strcmp(cgs_clp->cgs_str, "sas_addr") &&
+ op->dev_slot_num < 0) {
+ pr2serr("--get=sas_addr requires --dev-slot-num. For "
+ "expander SAS address, use exp_sas_addr instead.\n");
ret = SG_LIB_SYNTAX_ERROR;
goto err_out;
- }
+ }
tavp->cgs_sel = cgs_clp->cgs_sel;
}
/* keep this descending for loop directly after ascending for loop */
diff --git a/src/sg_unmap.c b/src/sg_unmap.c
index c24c676a..2bfb12d6 100644
--- a/src/sg_unmap.c
+++ b/src/sg_unmap.c
@@ -36,7 +36,7 @@
* logical blocks. Note that DATA MAY BE LOST.
*/
-static const char * version_str = "1.18 20220608";
+static const char * version_str = "1.19 20220813";
#define DEF_TIMEOUT_SECS 60
@@ -253,7 +253,7 @@ build_joint_arr(const char * file_name, uint64_t * lba_arr, uint32_t * num_arr,
int64_t ll;
char line[1024];
char * lcp;
- FILE * fp;
+ FILE * fp = NULL;
have_stdin = ((1 == strlen(file_name)) && ('-' == file_name[0]));
if (have_stdin)
@@ -336,12 +336,12 @@ build_joint_arr(const char * file_name, uint64_t * lba_arr, uint32_t * num_arr,
goto bad_exit;
}
*arr_len = off >> 1;
- if (fp && (stdin != fp))
+ if (fp && (! have_stdin))
fclose(fp);
return 0;
bad_exit:
- if (fp && (stdin != fp))
+ if (fp && (! have_stdin))
fclose(fp);
return 1;
}
diff --git a/src/sg_vpd.c b/src/sg_vpd.c
index 0cb6f7ed..9aae8a72 100644
--- a/src/sg_vpd.c
+++ b/src/sg_vpd.c
@@ -42,7 +42,7 @@
*/
-static const char * version_str = "1.80 20220811"; /* spc6r06 + sbc5r03 */
+static const char * version_str = "1.81 20220818"; /* spc6r06 + sbc5r03 */
#define MY_NAME "sg_vpd"
@@ -110,17 +110,17 @@ static struct option long_options[] = {
/* arranged in alphabetical order by acronym */
static struct svpd_values_name_t standard_vpd_pg[] = {
+ {VPD_AUTOMATION_DEV_SN, 0, 1, "adsn", "Automation device serial "
+ "number (SSC)"},
{VPD_ATA_INFO, 0, -1, "ai", "ATA information (SAT)"},
{VPD_ASCII_OP_DEF, 0, -1, "aod",
"ASCII implemented operating definition (obsolete)"},
- {VPD_AUTOMATION_DEV_SN, 0, 1, "adsn", "Automation device serial "
- "number (SSC)"},
- {VPD_BLOCK_LIMITS, 0, 0, "bl", "Block limits (SBC)"},
- {VPD_BLOCK_LIMITS_EXT, 0, 0, "ble", "Block limits extension (SBC)"},
{VPD_BLOCK_DEV_CHARS, 0, 0, "bdc", "Block device characteristics "
"(SBC)"},
{VPD_BLOCK_DEV_C_EXTENS, 0, 0, "bdce", "Block device characteristics "
"extension (SBC)"},
+ {VPD_BLOCK_LIMITS, 0, 0, "bl", "Block limits (SBC)"},
+ {VPD_BLOCK_LIMITS_EXT, 0, 0, "ble", "Block limits extension (SBC)"},
{VPD_CFA_PROFILE_INFO, 0, 0, "cfa", "CFA profile information"},
{VPD_CON_POS_RANGE, 0, 0, "cpr", "Concurrent positioning ranges"},
{VPD_DEVICE_CONSTITUENTS, 0, -1, "dc", "Device constituents"},
@@ -147,7 +147,7 @@ static struct svpd_values_name_t standard_vpd_pg[] = {
{VPD_MAN_NET_ADDR, 0, -1, "mna", "Management network addresses"},
{VPD_MODE_PG_POLICY, 0, -1, "mpp", "Mode page policy"},
{VPD_OSD_INFO, 0, 0x11, "oi", "OSD information"},
- {VPD_POWER_CONDITION, 0, -1, "pc", "Power condition"},
+ {VPD_POWER_CONDITION, 0, -1, "pc", "Power condition"},/* "po" in sg_inq */
{VPD_POWER_CONSUMPTION, 0, -1, "psm", "Power consumption"},
{VPD_PROTO_LU, 0, -1, "pslu", "Protocol-specific logical unit "
"information"},
@@ -444,6 +444,17 @@ device_id_vpd_variants(uint8_t * buff, int len, int subvalue,
}
}
+static int
+no_ascii_4hex(const struct opts_t * op)
+{
+ if (op->do_hex < 2)
+ return 1;
+ else if (2 == op->do_hex)
+ return 0;
+ else
+ return -1;
+}
+
static void /* VPD_SUPPORTED_VPDS ["sv"] */
decode_supported_vpd_4vpd(uint8_t * buff, int len, struct opts_t * op,
sgj_opaque_p jap)
@@ -459,7 +470,7 @@ decode_supported_vpd_4vpd(uint8_t * buff, int len, struct opts_t * op,
static const char * svps = "Supported VPD pages";
if ((1 == op->do_hex) || (op->do_hex > 2)) {
- hex2stdout(buff, len, (1 == op->do_hex) ? 0 : -1);
+ hex2stdout(buff, len, no_ascii_4hex(op));
return;
}
pdt = PDT_MASK & buff[0];
@@ -525,7 +536,7 @@ decode_scsi_ports_vpd_4vpd(uint8_t * buff, int len, struct opts_t * op,
uint8_t * bp;
if ((1 == op->do_hex) || (op->do_hex > 2)) {
- hex2stdout(buff, len, (1 == op->do_hex) ? 1 : -1);
+ hex2stdout(buff, len, no_ascii_4hex(op));
return;
}
if (len < 4) {
@@ -876,7 +887,7 @@ decode_b0_vpd(uint8_t * buff, int len, struct opts_t * op, sgj_opaque_p jop)
sgj_state * jsp = &op->json_st;
if (op->do_hex) {
- hex2stdout(buff, len, (1 == op->do_hex) ? 0 : -1);
+ hex2stdout(buff, len, no_ascii_4hex(op));
return;
}
switch (pdt) {
@@ -904,18 +915,24 @@ decode_b0_vpd(uint8_t * buff, int len, struct opts_t * op, sgj_opaque_p jop)
/* VPD_SECURITY_TOKEN osd */
/* VPD_ES_DEV_CHARS ses-4 */
static void
-decode_b1_vpd(uint8_t * buff, int len, int do_hex, int pdt)
+decode_b1_vpd(uint8_t * buff, int len, struct opts_t * op, sgj_opaque_p jop)
{
- if (do_hex) {
- hex2stdout(buff, len, (1 == do_hex) ? 0 : -1);
+ int pdt;
+ sgj_state * jsp = &op->json_st;
+
+ pdt = buff[0] & PDT_MASK;
+ if (op->do_hex) {
+ hex2stdout(buff, len, no_ascii_4hex(op));
return;
}
switch (pdt) {
case PDT_DISK: case PDT_WO: case PDT_OPTICAL: case PDT_ZBC:
/* now done by decode_block_dev_ch_vpd() in sg_vpd_common.c */
case PDT_TAPE: case PDT_MCHANGER: case PDT_ADC:
- printf(" Manufacturer-assigned serial number: %.*s\n",
- len - 4, buff + 4);
+ sgj_pr_hr(jsp, " Manufacturer-assigned serial number: %.*s\n",
+ len - 4, buff + 4);
+ sgj_js_nv_s_len(jsp, jop, "manufacturer_assigned_serial_number",
+ (const char *)buff + 4, len - 4);
break;
default:
pr2serr(" Unable to decode pdt=0x%x, in hex:\n", pdt);
@@ -924,77 +941,21 @@ decode_b1_vpd(uint8_t * buff, int len, int do_hex, int pdt)
}
}
-/* VPD_LB_PROTECTION 0xb5 (SSC) [added in ssc5r02a] */
-static void
-decode_lb_protection_vpd(uint8_t * buff, int len, int do_hex)
-{
- int k, bump;
- uint8_t * bp;
-
- if ((1 == do_hex) || (do_hex > 2)) {
- hex2stdout(buff, len, (1 == do_hex) ? 0 : -1);
- return;
- }
- if (len < 8) {
- pr2serr("Logical block protection VPD page length too short=%d\n",
- len);
- return;
- }
- len -= 8;
- bp = buff + 8;
- for (k = 0; k < len; k += bump, bp += bump) {
- bump = 1 + bp[0];
- printf(" method: %d, info_len: %d, LBP_W_C=%d, LBP_R_C=%d, "
- "RBDP_C=%d\n", bp[1], 0x3f & bp[2], !!(0x80 & bp[3]),
- !!(0x40 & bp[3]), !!(0x20 & bp[3]));
- if ((k + bump) > len) {
- pr2serr("Logical block protection VPD page, short "
- "descriptor length=%d, left=%d\n", bump, (len - k));
- return;
- }
- }
-}
-
-/* VPD_TA_SUPPORTED 0xb2 */
-static int
-decode_tapealert_supported_vpd(uint8_t * b, int len)
-{
- int k, mod, div;
-
- if (len < 12) {
- pr2serr("TapeAlert supported flags length too short=%d\n", len);
- return SG_LIB_CAT_MALFORMED;
- }
- for (k = 1; k < 0x41; ++k) {
- mod = ((k - 1) % 8);
- div = (k - 1) / 8;
- if (0 == mod) {
- if (div > 0)
- printf("\n");
- printf(" Flag%02Xh: %d", k, !! (b[4 + div] & 0x80));
- } else
- printf(" %02Xh: %d", k, !! (b[4 + div] & (1 << (7 - mod))));
- }
- printf("\n");
- return 0;
-}
-
/* VPD_LB_PROVISIONING sbc */
/* VPD_TA_SUPPORTED ssc */
static void
decode_b2_vpd(uint8_t * buff, int len, int pdt, struct opts_t * op)
{
if (op->do_hex) {
- hex2stdout(buff, len, (1 == op->do_hex) ? 0 : -1);
+ hex2stdout(buff, len, no_ascii_4hex(op));
return;
}
switch (pdt) {
case PDT_DISK: case PDT_WO: case PDT_OPTICAL: case PDT_ZBC:
/* decode_block_lb_prov_vpd() is now in sg_vpd_common.c */
- // decode_block_lb_prov_vpd(buff, len, op);
break;
case PDT_TAPE: case PDT_MCHANGER:
- decode_tapealert_supported_vpd(buff, len);
+ /* decode_tapealert_supported_vpd() is now in sg_vpd_common.c */
break;
default:
pr2serr(" Unable to decode pdt=0x%x, in hex:\n", pdt);
@@ -1006,29 +967,29 @@ decode_b2_vpd(uint8_t * buff, int len, int pdt, struct opts_t * op)
/* VPD_REFERRALS sbc 0xb3 ["ref"] */
/* VPD_AUTOMATION_DEV_SN ssc 0xb3 ["adsn"] */
static void
-decode_b3_vpd(uint8_t * b, int len, int pdt, struct opts_t * op)
+decode_b3_vpd(uint8_t * buff, int len, struct opts_t * op, sgj_opaque_p jop)
{
- char obuff[DEF_ALLOC_LEN];
+ int pdt;
+ sgj_state * jsp = &op->json_st;
if (op->do_hex) {
- hex2stdout(b, len, (1 == op->do_hex) ? 0 : -1);
+ hex2stdout(buff, len, no_ascii_4hex(op));
return;
}
+ pdt = buff[0] & PDT_MASK;
switch (pdt) {
case PDT_DISK: case PDT_WO: case PDT_OPTICAL: case PDT_ZBC:
/* now done in decode_referrals_vpd() in sg_vpd_common.c */
break;
case PDT_TAPE: case PDT_MCHANGER:
- memset(obuff, 0, sizeof(obuff));
- len -= 4;
- if (len >= (int)sizeof(obuff))
- len = sizeof(obuff) - 1;
- memcpy(obuff, b + 4, len);
- printf(" Automation device serial number: %s\n", obuff);
+ sgj_pr_hr(jsp, " Automation device serial number: %.*s\n",
+ len - 4, buff + 4);
+ sgj_js_nv_s_len(jsp, jop, "automation_device_serial_number",
+ (const char *)buff + 4, len - 4);
break;
default:
pr2serr(" Unable to decode pdt=0x%x, in hex:\n", pdt);
- hex2stderr(b, len, 0);
+ hex2stderr(buff, len, 0);
break;
}
}
@@ -1036,12 +997,13 @@ decode_b3_vpd(uint8_t * b, int len, int pdt, struct opts_t * op)
/* VPD_SUP_BLOCK_LENS sbc ["sbl"] */
/* VPD_DTDE_ADDRESS ssc */
static void
-decode_b4_vpd(uint8_t * b, int len, int do_hex, int pdt)
+decode_b4_vpd(uint8_t * buff, int len, struct opts_t * op, sgj_opaque_p jop)
{
- int k;
+ int pdt = buff[0] & PDT_MASK;
+ sgj_state * jsp = &op->json_st;
- if (do_hex) {
- hex2stdout(b, len, (1 == do_hex) ? 0 : -1);
+ if (op->do_hex) {
+ hex2stdout(buff, len, no_ascii_4hex(op));
return;
}
switch (pdt) {
@@ -1049,19 +1011,21 @@ decode_b4_vpd(uint8_t * b, int len, int do_hex, int pdt)
/* now done by decode_sup_block_lens_vpd() in sg_vpd_common.c */
break;
case PDT_TAPE: case PDT_MCHANGER:
- printf(" Data transfer device element address: 0x");
- for (k = 4; k < len; ++k)
- printf("%02x", (unsigned int)b[k]);
- printf("\n");
+ sgj_pr_hr(jsp, " Device transfer data element:\n");
+ if (! jsp->pr_as_json)
+ hex2stdout(buff + 4, len - 4, 1);
+ sgj_js_nv_hex_bytes(jsp, jop, "device_transfer_data_element",
+ buff + 4, len - 4);
break;
default:
pr2serr(" Unable to decode pdt=0x%x, in hex:\n", pdt);
- hex2stderr(b, len, 0);
+ hex2stderr(buff, len, 0);
break;
}
}
/* VPD_BLOCK_DEV_C_EXTENS sbc */
+/* VPD_LB_PROTECTION 0xb5 ["lbpro"] ssc */
static void
decode_b5_vpd(uint8_t * b, int len, int do_hex, int pdt)
{
@@ -1074,7 +1038,7 @@ decode_b5_vpd(uint8_t * b, int len, int do_hex, int pdt)
/* now done by decode_block_dev_char_ext_vpd() in sg_vpd_common.c */
break;
case PDT_TAPE: case PDT_MCHANGER:
- decode_lb_protection_vpd(b, len, do_hex);
+ /* now done by decode_lb_protection_vpd() in sg_vpd_common.c */
break;
default:
pr2serr(" Unable to decode pdt=0x%x, in hex:\n", pdt);
@@ -1087,20 +1051,36 @@ decode_b5_vpd(uint8_t * b, int len, int do_hex, int pdt)
static int
svpd_unable_to_decode(int sg_fd, struct opts_t * op, int subvalue, int off)
{
- int len, res;
+ bool as_json, json_o_hr, hex0;
+ int res, len, n;
+ sgj_state * jsp = &op->json_st;
uint8_t * rp;
+ as_json = jsp->pr_as_json;
+ json_o_hr = as_json && jsp->pr_out_hr;
+ hex0 = (0 == op->do_hex);
rp = rsp_buff + off;
- if ((! op->do_hex) && (! op->do_raw) && (0 == op->examine))
- printf("Only hex output supported\n");
- if ((!op->do_raw) && (op->do_hex < 2) && (0 == op->examine)) {
- if (subvalue)
- printf("VPD page code=0x%.2x, subvalue=0x%.2x:\n", op->vpd_pn,
- subvalue);
- else if (op->vpd_pn >= 0)
- printf("VPD page code=0x%.2x:\n", op->vpd_pn);
- else
- printf("VPD page code=%d:\n", op->vpd_pn);
+ if (hex0 && (! op->do_raw) && (! op->examine_given))
+ sgj_pr_hr(jsp, "Only hex output supported\n");
+ if ((!op->do_raw) && (op->do_hex < 2) && (! op->examine_given)) {
+ if (subvalue) {
+ if (hex0)
+ sgj_pr_hr(jsp, "VPD page code=0x%.2x, subvalue=0x%.2x:\n",
+ op->vpd_pn, subvalue);
+ else
+ printf("VPD page code=0x%.2x, subvalue=0x%.2x:\n", op->vpd_pn,
+ subvalue);
+ } else if (op->vpd_pn >= 0) {
+ if (hex0)
+ sgj_pr_hr(jsp, "VPD page code=0x%.2x:\n", op->vpd_pn);
+ else
+ printf("VPD page code=0x%.2x:\n", op->vpd_pn);
+ } else {
+ if (hex0)
+ sgj_pr_hr(jsp, "VPD page code=%d:\n", op->vpd_pn);
+ else
+ printf("VPD page code=%d:\n", op->vpd_pn);
+ }
}
res = vpd_fetch_page(sg_fd, rp, op->vpd_pn, op->maxlen, op->do_quiet,
@@ -1109,6 +1089,18 @@ svpd_unable_to_decode(int sg_fd, struct opts_t * op, int subvalue, int off)
if (op->do_raw)
dStrRaw(rp, len);
else {
+ if (json_o_hr && hex0 && (len > 0) && (len < UINT16_MAX)) {
+ char * p;
+
+ n = len * 4;
+ p = malloc(n);
+ if (p) {
+ n = hex2str(rp, len, NULL, 1, n - 1, p);
+ sgj_js_str_out(jsp, p, n);
+ }
+ } else
+ hex2stdout(rp, len, no_ascii_4hex(op));
+#if 0
if (op->do_hex > 1)
hex2stdout(rp, len, -1);
else if (VPD_ASCII_OP_DEF == op->vpd_pn)
@@ -1117,8 +1109,9 @@ svpd_unable_to_decode(int sg_fd, struct opts_t * op, int subvalue, int off)
hex2stdout(rp, len, (op->do_long ? 0 : 1));
else
hex2stdout(rp, len, 0);
+#endif
}
- } else if ((! op->do_quiet) && (0 == op->examine)) {
+ } else if ((! op->do_quiet) && (! op->examine_given)) {
if (op->vpd_pn >= 0)
pr2serr("fetching VPD page code=0x%.2x: failed\n", op->vpd_pn);
else
@@ -1133,7 +1126,7 @@ recurse_vpd_decode(struct opts_t * op, sgj_opaque_p jop, int off)
int res = svpd_decode_t10(-1, op, jop, 0, off, NULL);
if (SG_LIB_CAT_OTHER == res) {
- res = svpd_decode_vendor(-1, op, off);
+ res = svpd_decode_vendor(-1, op, jop, off);
if (SG_LIB_CAT_OTHER == res)
svpd_unable_to_decode(-1, op, 0, off);
}
@@ -1149,6 +1142,7 @@ svpd_decode_t10(int sg_fd, struct opts_t * op, sgj_opaque_p jop,
bool allow_name, allow_if_found, long_notquiet, qt;
bool vpd_supported = false;
bool inhex_active = (-1 == sg_fd);
+ bool exam_not_given = ! op->examine_given;
int len, pdt, pqual, num, k, resid, alloc_len, pn, vb;
int res = 0;
sgj_state * jsp = &op->json_st;
@@ -1157,7 +1151,7 @@ svpd_decode_t10(int sg_fd, struct opts_t * op, sgj_opaque_p jop,
sgj_opaque_p jo2p = NULL;
const char * np;
const char * ep;
- const char * pre = (prefix ? prefix : "");;
+ const char * pre = (prefix ? prefix : "");
const char * pdt_str;
bool as_json = jsp->pr_as_json;
bool not_json = ! as_json;
@@ -1168,18 +1162,18 @@ svpd_decode_t10(int sg_fd, struct opts_t * op, sgj_opaque_p jop,
qt = op->do_quiet;
long_notquiet = op->do_long && (! op->do_quiet);
if (op->do_raw || (op->do_quiet && (! op->do_long) && (! op->do_all)) ||
- (op->do_hex >= 3) || (op->examine > 0))
+ (op->do_hex >= 3) || op->examine_given)
allow_name = false;
else
allow_name = true;
- allow_if_found = (op->examine > 0) && (! op->do_quiet);
+ allow_if_found = op->examine_given && (! op->do_quiet);
rp = rsp_buff + off;
pn = op->vpd_pn;
if ((off > 0) && (VPD_NOPE_WANT_STD_INQ != op->vpd_pn))
pn = rp[1];
else
pn = op->vpd_pn;
- if (!inhex_active && !op->do_force && 0 == op->examine &&
+ if (!inhex_active && !op->do_force && exam_not_given &&
pn != VPD_NOPE_WANT_STD_INQ &&
pn != VPD_SUPPORTED_VPDS) {
res = vpd_fetch_page(sg_fd, rp, VPD_SUPPORTED_VPDS, op->maxlen, qt,
@@ -1251,7 +1245,7 @@ svpd_decode_t10(int sg_fd, struct opts_t * op, sgj_opaque_p jop,
if (op->do_raw)
dStrRaw(rp, len);
else if (op->do_hex)
- hex2stdout(rp, len, (1 == op->do_hex) ? 0 : -1);
+ hex2stdout(rp, len, no_ascii_4hex(op));
else {
if (vb || long_notquiet)
sgj_pr_hr(jsp, " [PQual=%d Peripheral device type: "
@@ -1280,7 +1274,7 @@ svpd_decode_t10(int sg_fd, struct opts_t * op, sgj_opaque_p jop,
if (op->do_raw)
dStrRaw(rp, len);
else if (op->do_hex)
- hex2stdout(rp, len, (1 == op->do_hex) ? 0 : -1);
+ hex2stdout(rp, len, no_ascii_4hex(op));
else {
if (vb || long_notquiet)
sgj_pr_hr(jsp, " [PQual=%d Peripheral device type: "
@@ -1307,7 +1301,7 @@ svpd_decode_t10(int sg_fd, struct opts_t * op, sgj_opaque_p jop,
if (op->do_raw)
dStrRaw(rp, len);
else if (op->do_hex)
- hex2stdout(rp, len, (1 == op->do_hex) ? 0 : -1);
+ hex2stdout(rp, len, no_ascii_4hex(op));
else {
if (vb || long_notquiet)
sgj_pr_hr(jsp, " [PQual=%d Peripheral device type: "
@@ -1379,17 +1373,23 @@ svpd_decode_t10(int sg_fd, struct opts_t * op, sgj_opaque_p jop,
dStrRaw(rp, len);
else {
bool protect = false;
- struct sg_simple_inquiry_resp sir;
- if ((sg_fd >= 0) && long_notquiet) {
+ op->protect_not_sure = false;
+ if (op->std_inq_a_valid)
+ protect = !! (0x1 & op->std_inq_a[5]);
+ else if ((sg_fd >= 0) && (! op->do_force)) {
+ struct sg_simple_inquiry_resp sir;
+
res = sg_simple_inquiry(sg_fd, &sir, false, vb);
if (res) {
if (op->verbose)
pr2serr("%s: sg_simple_inquiry() failed, "
"res=%d\n", __func__, res);
+ op->protect_not_sure = true;
} else
protect = !!(sir.byte_5 & 0x1); /* SPC-3 and later */
- }
+ } else
+ op->protect_not_sure = true;
if (vb || long_notquiet)
sgj_pr_hr(jsp," [PQual=%d Peripheral device type: "
"%s]\n", pqual, pdt_str);
@@ -1523,6 +1523,30 @@ svpd_decode_t10(int sg_fd, struct opts_t * op, sgj_opaque_p jop,
return 0;
}
break;
+ case VPD_CFA_PROFILE_INFO: /* 0x8c ["cfa"] */
+ np = "CFA profile information VPD page";
+ if (allow_name)
+ sgj_pr_hr(jsp, "%s%s:\n", pre, np);
+ res = vpd_fetch_page(sg_fd, rp, pn, op->maxlen, qt, vb, &len);
+ if (0 == res) {
+ if (! allow_name && allow_if_found)
+ sgj_pr_hr(jsp, "%s%s\n", pre, np);
+ if (op->do_raw)
+ dStrRaw(rp, len);
+ else {
+ if (vb || long_notquiet)
+ sgj_pr_hr(jsp, " [PQual=%d Peripheral device type: "
+ "%s]\n", pqual, pdt_str);
+ if (as_json) {
+ jo2p = sg_vpd_js_hdr(jsp, jop, np, rp);
+ jap = sgj_named_subarray_r(jsp, jo2p,
+ "cfa_profile_descriptor_list");
+ }
+ decode_cga_profile_vpd(rp, len, op, jap);
+ }
+ return 0;
+ }
+ break;
case VPD_POWER_CONSUMPTION: /* 0x8d ["psm"] */
np = "Power consumption VPD page";
if (allow_name)
@@ -1614,7 +1638,7 @@ svpd_decode_t10(int sg_fd, struct opts_t * op, sgj_opaque_p jop,
jap = sgj_named_subarray_r(jsp, jo2p,
"port_information_descriptor_list");
}
- decode_proto_port_vpd(rp, len, op, jsp);
+ decode_proto_port_vpd(rp, len, op, jap);
}
return 0;
}
@@ -1694,7 +1718,7 @@ svpd_decode_t10(int sg_fd, struct opts_t * op, sgj_opaque_p jop,
}
return 0;
} else if ((! op->do_raw) && (! op->do_quiet) && (op->do_hex < 3) &&
- (0 == op->examine))
+ exam_not_given)
printf("%sVPD page=0xb0\n", pre);
break;
case 0xb1: /* depends on pdt */
@@ -1741,17 +1765,18 @@ svpd_decode_t10(int sg_fd, struct opts_t * op, sgj_opaque_p jop,
if (bdc)
decode_block_dev_ch_vpd(rp, len, op, jo2p);
else
- decode_b1_vpd(rp, len, op->do_hex, pdt);
+ decode_b1_vpd(rp, len, op, jo2p);
}
return 0;
} else if ((! op->do_raw) && (! op->do_quiet) && (op->do_hex < 3) &&
- (0 == op->examine))
+ exam_not_given)
printf("%sVPD page=0xb1\n", pre);
break;
case 0xb2: /* VPD page depends on pdt */
res = vpd_fetch_page(sg_fd, rp, pn, op->maxlen, qt, vb, &len);
if (0 == res) {
bool lbpv = false;
+ bool tas = false;
switch (pdt) {
case PDT_DISK: case PDT_WO: case PDT_OPTICAL: case PDT_ZBC:
@@ -1762,6 +1787,7 @@ svpd_decode_t10(int sg_fd, struct opts_t * op, sgj_opaque_p jop,
case PDT_TAPE: case PDT_MCHANGER:
np = "TapeAlert supported flags VPD page";
ep = "(SSC)";
+ tas = true;
break;
default:
np = NULL;
@@ -1781,12 +1807,14 @@ svpd_decode_t10(int sg_fd, struct opts_t * op, sgj_opaque_p jop,
jo2p = sg_vpd_js_hdr(jsp, jop, np, rp);
if (lbpv)
decode_block_lb_prov_vpd(rp, len, op, jo2p);
+ else if (tas)
+ decode_tapealert_supported_vpd(rp, len, op, jo2p);
else
decode_b2_vpd(rp, len, pdt, op);
}
return 0;
} else if ((! op->do_raw) && (! op->do_quiet) && (op->do_hex < 3) &&
- (0 == op->examine))
+ exam_not_given)
printf("%sVPD page=0xb2\n", pre);
break;
case 0xb3: /* VPD page depends on pdt */
@@ -1824,11 +1852,11 @@ svpd_decode_t10(int sg_fd, struct opts_t * op, sgj_opaque_p jop,
if (ref)
decode_referrals_vpd(rp, len, op, jo2p);
else
- decode_b3_vpd(rp, len, pdt, op);
+ decode_b3_vpd(rp, len, op, jo2p);
}
return 0;
} else if ((! op->do_raw) && (! op->do_quiet) && (op->do_hex < 3) &&
- (0 == op->examine))
+ exam_not_given)
printf("%sVPD page=0xb3\n", pre);
break;
case 0xb4: /* VPD page depends on pdt */
@@ -1861,25 +1889,26 @@ svpd_decode_t10(int sg_fd, struct opts_t * op, sgj_opaque_p jop,
if (vb || long_notquiet)
sgj_pr_hr(jsp, " [PQual=%d Peripheral device type: "
"%s]\n", pqual, pdt_str);
- if (as_json) {
+ if (as_json)
jo2p = sg_vpd_js_hdr(jsp, jop, np, rp);
- jap = sgj_named_subarray_r(jsp, jo2p, "logical_block_"
+ if (sbl) {
+ if (as_json)
+ jap = sgj_named_subarray_r(jsp, jo2p, "logical_block_"
"length_and_protection_types_descriptor_list");
- }
- if (sbl)
decode_sup_block_lens_vpd(rp, len, op, jap);
- else
- decode_b4_vpd(rp, len, op->do_hex, pdt);
+ } else
+ decode_b4_vpd(rp, len, op, jo2p);
}
return 0;
} else if ((! op->do_raw) && (! op->do_quiet) && (op->do_hex < 3) &&
- (0 == op->examine))
+ exam_not_given)
printf("%sVPD page=0xb4\n", pre);
break;
case 0xb5: /* VPD page depends on pdt */
res = vpd_fetch_page(sg_fd, rp, pn, op->maxlen, qt, vb, &len);
if (0 == res) {
bool bdce = false;
+ bool lbp = false;
pdt = rp[0] & PDT_MASK;
switch (pdt) {
@@ -1891,6 +1920,7 @@ svpd_decode_t10(int sg_fd, struct opts_t * op, sgj_opaque_p jop,
case PDT_TAPE: case PDT_MCHANGER:
np = "Logical block protection VPD page";
ep = "(SSC)";
+ lbp = true;
break;
default:
np = NULL;
@@ -1910,12 +1940,17 @@ svpd_decode_t10(int sg_fd, struct opts_t * op, sgj_opaque_p jop,
jo2p = sg_vpd_js_hdr(jsp, jop, np, rp);
if (bdce)
decode_block_dev_char_ext_vpd(rp, len, op, jo2p);
- else
+ else if (lbp) {
+ if (as_json)
+ jap = sgj_named_subarray_r(jsp, jo2p,
+ "logical_block_protection_method_descriptor_list");
+ decode_lb_protection_vpd(rp, len, op, jap);
+ } else
decode_b5_vpd(rp, len, op->do_hex, pdt);
}
return 0;
} else if ((! op->do_raw) && (! op->do_quiet) && (op->do_hex < 3) &&
- (0 == op->examine))
+ exam_not_given)
printf("%sVPD page=0xb5\n", pre);
break;
case VPD_ZBC_DEV_CHARS: /* 0xb6 for both pdt=0 and pdt=0x14 */
@@ -1953,7 +1988,7 @@ svpd_decode_t10(int sg_fd, struct opts_t * op, sgj_opaque_p jop,
}
return 0;
} else if ((! op->do_raw) && (! op->do_quiet) && (op->do_hex < 3) &&
- (0 == op->examine))
+ exam_not_given)
printf("%sVPD page=0xb6\n", pre);
break;
case 0xb7:
@@ -1991,7 +2026,7 @@ svpd_decode_t10(int sg_fd, struct opts_t * op, sgj_opaque_p jop,
}
return 0;
} else if ((! op->do_raw) && (! op->do_quiet) && (op->do_hex < 3) &&
- (0 == op->examine))
+ exam_not_given)
printf("%sVPD page=0xb7\n", pre);
break;
case 0xb8: /* VPD_FORMAT_PRESETS */
@@ -2032,7 +2067,7 @@ svpd_decode_t10(int sg_fd, struct opts_t * op, sgj_opaque_p jop,
}
return 0;
} else if ((! op->do_raw) && (! op->do_quiet) && (op->do_hex < 3) &&
- (0 == op->examine))
+ exam_not_given)
printf("%sVPD page=0xb8\n", pre);
break;
case 0xb9: /* VPD_CON_POS_RANGE */
@@ -2073,7 +2108,7 @@ svpd_decode_t10(int sg_fd, struct opts_t * op, sgj_opaque_p jop,
}
return 0;
} else if ((! op->do_raw) && (! op->do_quiet) && (op->do_hex < 3) &&
- (0 == op->examine))
+ exam_not_given)
printf("%sVPD page=0xb8\n", pre);
break;
default:
@@ -2129,7 +2164,7 @@ svpd_decode_all(int sg_fd, struct opts_t * op, sgj_opaque_p jop)
res = svpd_decode_t10(sg_fd, op, jop, 0, 0, NULL);
if (SG_LIB_CAT_OTHER == res) {
- res = svpd_decode_vendor(sg_fd, op, 0);
+ res = svpd_decode_vendor(sg_fd, op, jop, 0);
if (SG_LIB_CAT_OTHER == res)
res = svpd_unable_to_decode(sg_fd, op, 0, 0);
}
@@ -2185,7 +2220,7 @@ svpd_decode_all(int sg_fd, struct opts_t * op, sgj_opaque_p jop)
res = svpd_decode_t10(-1, op, jop, 0, off, NULL);
if (SG_LIB_CAT_OTHER == res) {
- res = svpd_decode_vendor(-1, op, off);
+ res = svpd_decode_vendor(-1, op, jop, off);
if (SG_LIB_CAT_OTHER == res)
res = svpd_unable_to_decode(-1, op, 0, off);
}
@@ -2199,14 +2234,29 @@ svpd_examine_all(int sg_fd, struct opts_t * op, sgj_opaque_p jop)
{
bool first = true;
bool got_one = false;
- int k, res;
- int max_pn = 255;
+ int k, res, start;
+ int max_pn;
int any_err = 0;
char b[80];
- if (op->vpd_pn > 0)
- max_pn = op->vpd_pn;
- for (k = op->examine > 1 ? 0 : 0x80; k <= max_pn; ++k) {
+ max_pn = (op->page_given ? op->vpd_pn : 0xff);
+ switch (op->examine) {
+ case 1:
+ start = 0x80;
+ break;
+ case 2:
+ start = 0x0;
+ break;
+ default:
+ start = 0xc0;
+ break;
+ }
+ if (start > max_pn) { /* swap them around */
+ k = start;
+ start = max_pn;
+ max_pn = k;
+ }
+ for (k = start; k <= max_pn; ++k) {
op->vpd_pn = k;
if (first)
first = false;
@@ -2220,7 +2270,7 @@ svpd_examine_all(int sg_fd, struct opts_t * op, sgj_opaque_p jop)
b[0] = '\0';
res = svpd_decode_t10(sg_fd, op, jop, 0, 0, b);
if (SG_LIB_CAT_OTHER == res) {
- res = svpd_decode_vendor(sg_fd, op, 0);
+ res = svpd_decode_vendor(sg_fd, op, jop, 0);
if (SG_LIB_CAT_OTHER == res)
res = svpd_unable_to_decode(sg_fd, op, 0, 0);
}
@@ -2279,6 +2329,7 @@ main(int argc, char * argv[])
break;
case 'E':
++op->examine;
+ op->examine_given = true;
break;
case 'f':
op->do_force = true;
@@ -2646,7 +2697,7 @@ main(int argc, char * argv[])
else {
res = svpd_decode_t10(-1, op, jop, subvalue, 0, NULL);
if (SG_LIB_CAT_OTHER == res) {
- res = svpd_decode_vendor(-1, op, 0);
+ res = svpd_decode_vendor(-1, op, jop, 0);
if (SG_LIB_CAT_OTHER == res)
res = svpd_unable_to_decode(-1, op, subvalue, 0);
}
@@ -2679,7 +2730,7 @@ main(int argc, char * argv[])
goto err_out;
}
- if (op->examine > 0) {
+ if (op->examine_given) {
ret = svpd_examine_all(sg_fd, op, jop);
} else if (op->do_all)
ret = svpd_decode_all(sg_fd, op, jop);
@@ -2688,7 +2739,7 @@ main(int argc, char * argv[])
res = svpd_decode_t10(sg_fd, op, jop, subvalue, 0, NULL);
if (SG_LIB_CAT_OTHER == res) {
- res = svpd_decode_vendor(sg_fd, op, 0);
+ res = svpd_decode_vendor(sg_fd, op, jop, 0);
if (SG_LIB_CAT_OTHER == res)
res = svpd_unable_to_decode(sg_fd, op, subvalue, 0);
}
diff --git a/src/sg_vpd_common.c b/src/sg_vpd_common.c
index 98e798fb..14b1bd2d 100644
--- a/src/sg_vpd_common.c
+++ b/src/sg_vpd_common.c
@@ -28,6 +28,7 @@
#endif
#include "sg_lib.h"
+#include "sg_lib_data.h"
#include "sg_cmds_basic.h"
#include "sg_unaligned.h"
#include "sg_pr2serr.h"
@@ -47,9 +48,13 @@ static const char * const y_s = "yes";
static const char * const n_s = "no";
static const char * const nl_s = "no limit";
static const char * const nlr_s = "no limit reported";
-static const char * const nr_s = "not reported";
+/* Earlier gcc compilers (e.g. 6.4) don't accept this first form when it is
+ * used in another array of strings initialization (e.g. bdc_zoned_strs) */
+// static const char * const nr_s = "not reported";
+static char nr_s[] = "not reported";
static const char * const ns_s = "not supported";
-static const char * const rsv_s = "Reserved";
+// static const char * const rsv_s = "Reserved";
+static char rsv_s[] = "Reserved";
static const char * const vs_s = "Vendor specific";
static const char * const null_s = "";
static const char * const mn_s = "meaning";
@@ -310,13 +315,13 @@ static const char * network_service_type_arr[] =
/* VPD_MAN_NET_ADDR 0x85 ["mna"] */
void
-decode_net_man_vpd(uint8_t * buff, int len, struct opts_t * op,
+decode_net_man_vpd(const uint8_t * buff, int len, struct opts_t * op,
sgj_opaque_p jap)
{
int k, bump, na_len, assoc, nst;
sgj_state * jsp = &op->json_st;
sgj_opaque_p jo2p;
- uint8_t * bp;
+ const uint8_t * bp;
const char * assoc_str;
const char * nst_str;
@@ -366,7 +371,7 @@ decode_net_man_vpd(uint8_t * buff, int len, struct opts_t * op,
/* VPD_EXT_INQ Extended Inquiry VPD ["ei"] */
void
-decode_x_inq_vpd(uint8_t * b, int len, bool protect, struct opts_t * op,
+decode_x_inq_vpd(const uint8_t * b, int len, bool protect, struct opts_t * op,
sgj_opaque_p jop)
{
bool do_long_nq = op->do_long && (! op->do_quiet);
@@ -431,6 +436,10 @@ decode_x_inq_vpd(uint8_t * b, int len, bool protect, struct opts_t * op,
cp = "protection types 1, 2 and 3 supported";
break;
}
+ } else if (op->protect_not_sure) {
+ cp = "Unsure because unable to read PROTECT bit in standard "
+ "INQUIRY response";
+ d[0] = '\0';
} else {
cp = "none";
d[0] = '\0';
@@ -620,7 +629,7 @@ decode_x_inq_vpd(uint8_t * b, int len, bool protect, struct opts_t * op,
/* VPD_SOFTW_INF_ID 0x84 */
void
-decode_softw_inf_id(uint8_t * buff, int len, struct opts_t * op,
+decode_softw_inf_id(const uint8_t * buff, int len, struct opts_t * op,
sgj_opaque_p jap)
{
sgj_state * jsp = &op->json_st;
@@ -654,13 +663,13 @@ static const char * mode_page_policy_arr[] =
/* VPD_MODE_PG_POLICY 0x87 ["mpp"] */
void
-decode_mode_policy_vpd(uint8_t * buff, int len, struct opts_t * op,
+decode_mode_policy_vpd(const uint8_t * buff, int len, struct opts_t * op,
sgj_opaque_p jap)
{
int k, n, bump, ppc, pspc;
sgj_state * jsp = &op->json_st;
sgj_opaque_p jo2p;
- uint8_t * bp;
+ const uint8_t * bp;
char b[128];
static const int blen = sizeof(b);
@@ -712,7 +721,7 @@ decode_mode_policy_vpd(uint8_t * buff, int len, struct opts_t * op,
/* VPD_POWER_CONDITION 0x8a ["pc"] */
void
-decode_power_condition(uint8_t * buff, int len, struct opts_t * op,
+decode_power_condition(const uint8_t * buff, int len, struct opts_t * op,
sgj_opaque_p jop)
{
sgj_state * jsp = &op->json_st;
@@ -884,13 +893,13 @@ decode_ata_info_vpd(const uint8_t * buff, int len, struct opts_t * op,
/* VPD_SCSI_FEATURE_SETS 0x92 ["sfs"] */
void
-decode_feature_sets_vpd(uint8_t * buff, int len, struct opts_t * op,
+decode_feature_sets_vpd(const uint8_t * buff, int len, struct opts_t * op,
sgj_opaque_p jap)
{
int k, bump;
uint16_t sf_code;
bool found;
- uint8_t * bp;
+ const uint8_t * bp;
sgj_opaque_p jo2p;
sgj_state * jsp = &op->json_st;
char b[256];
@@ -1061,6 +1070,38 @@ decode_dev_constit_vpd(const uint8_t * buff, int len, struct opts_t * op,
} /* end Constituent descriptor loop */
}
+/* VPD_CFA_PROFILE_INFO 0x8c ["cfa"] */
+void
+decode_cga_profile_vpd(const uint8_t * buff, int len, struct opts_t * op,
+ sgj_opaque_p jap)
+{
+ int k;
+ uint32_t u;
+ sgj_state * jsp = &op->json_st;
+ const uint8_t * bp;
+ sgj_opaque_p jo2p;
+
+ if (op->do_hex) {
+ hex2stdout(buff, len, (1 == op->do_hex) ? 0 : -1);
+ return;
+ }
+ if (len < 4) {
+ pr2serr("VPD page length too short=%d\n", len);
+ return;
+ }
+ len -= 4;
+ bp = buff + 4;
+ for (k = 0; k < len; k += 4, bp += 4) {
+ jo2p = sgj_new_unattached_object_r(jsp);
+ sgj_haj_vi(jsp, jo2p, 0, "CGA profile supported",
+ SGJ_SEP_COLON_1_SPACE, bp[0], true);
+ u = sg_get_unaligned_be16(bp + 2);
+ sgj_haj_vi_nex(jsp, jo2p, 2, "Sequential write data size",
+ SGJ_SEP_COLON_1_SPACE, u, true, "unit: LB");
+ sgj_js_nv_o(jsp, jap, NULL /* name */, jo2p);
+ }
+}
+
/* Assume index is less than 16 */
static const char * sg_ansi_version_arr[16] =
{
@@ -1205,14 +1246,14 @@ static const char * power_unit_arr[] =
/* VPD_POWER_CONSUMPTION 0x8d ["psm"] */
void
-decode_power_consumption(uint8_t * buff, int len, struct opts_t * op,
+decode_power_consumption(const uint8_t * buff, int len, struct opts_t * op,
sgj_opaque_p jap)
{
int k, bump, pcmp_id, pcmp_unit;
unsigned int pcmp_val;
sgj_state * jsp = &op->json_st;
sgj_opaque_p jo2p;
- uint8_t * bp;
+ const uint8_t * bp;
char b[128];
static const int blen = sizeof(b);
static const char * pcmp = "power_consumption";
@@ -1590,7 +1631,7 @@ static const char * prov_type_arr[8] = {
/* VPD_LB_PROVISIONING 0xb2 ["lbpv"] */
int
-decode_block_lb_prov_vpd(uint8_t * buff, int len, struct opts_t * op,
+decode_block_lb_prov_vpd(const uint8_t * buff, int len, struct opts_t * op,
sgj_opaque_p jop)
{
unsigned int u, dp, pt, t_exp;
@@ -1678,7 +1719,7 @@ decode_block_lb_prov_vpd(uint8_t * buff, int len, struct opts_t * op,
/* VPD_REFERRALS 0xb3 ["ref"] */
void
-decode_referrals_vpd(uint8_t * buff, int len, struct opts_t * op,
+decode_referrals_vpd(const uint8_t * buff, int len, struct opts_t * op,
sgj_opaque_p jop)
{
uint32_t u;
@@ -1703,12 +1744,12 @@ decode_referrals_vpd(uint8_t * buff, int len, struct opts_t * op,
/* VPD_SUP_BLOCK_LENS 0xb4 ["sbl"] (added sbc4r01) */
void
-decode_sup_block_lens_vpd(uint8_t * buff, int len, struct opts_t * op,
+decode_sup_block_lens_vpd(const uint8_t * buff, int len, struct opts_t * op,
sgj_opaque_p jap)
{
int k;
unsigned int u;
- uint8_t * bp;
+ const uint8_t * bp;
sgj_state * jsp = &op->json_st;
sgj_opaque_p jo2p = NULL;
@@ -1750,8 +1791,8 @@ decode_sup_block_lens_vpd(uint8_t * buff, int len, struct opts_t * op,
/* VPD_BLOCK_DEV_C_EXTENS 0xb5 ["bdce"] (added sbc4r02) */
void
-decode_block_dev_char_ext_vpd(uint8_t * buff, int len, struct opts_t * op,
- sgj_opaque_p jop)
+decode_block_dev_char_ext_vpd(const uint8_t * buff, int len,
+ struct opts_t * op, sgj_opaque_p jop)
{
bool b_active = false;
bool combined = false;
@@ -1838,8 +1879,8 @@ decode_block_dev_char_ext_vpd(uint8_t * buff, int len, struct opts_t * op,
/* VPD_ZBC_DEV_CHARS 0xb6 ["zdbch"] sbc or zbc [zbc2r04] */
void
-decode_zbdch_vpd(uint8_t * buff, int len, struct opts_t * op,
- sgj_opaque_p jop)
+decode_zbdch_vpd(const uint8_t * buff, int len, struct opts_t * op,
+ sgj_opaque_p jop)
{
uint32_t u, pdt;
sgj_state * jsp = &op->json_st;
@@ -1923,7 +1964,7 @@ decode_zbdch_vpd(uint8_t * buff, int len, struct opts_t * op,
/* VPD_BLOCK_LIMITS_EXT 0xb7 ["ble"] SBC */
void
-decode_block_limits_ext_vpd(uint8_t * buff, int len, struct opts_t * op,
+decode_block_limits_ext_vpd(const uint8_t * buff, int len, struct opts_t * op,
sgj_opaque_p jop)
{
uint32_t u;
@@ -2000,7 +2041,7 @@ get_zone_align_method(uint8_t val, char * b, int blen)
/* VPD_FORMAT_PRESETS 0xb8 ["fp"] (added sbc4r18) */
void
-decode_format_presets_vpd(uint8_t * buff, int len, struct opts_t * op,
+decode_format_presets_vpd(const uint8_t * buff, int len, struct opts_t * op,
sgj_opaque_p jap)
{
uint8_t sch_type;
@@ -2008,7 +2049,7 @@ decode_format_presets_vpd(uint8_t * buff, int len, struct opts_t * op,
uint32_t u;
uint64_t ul;
sgj_state * jsp = &op->json_st;
- uint8_t * bp;
+ const uint8_t * bp;
sgj_opaque_p jo2p, jo3p;
const char * cp;
char b[128];
@@ -2149,13 +2190,13 @@ decode_format_presets_vpd(uint8_t * buff, int len, struct opts_t * op,
/* VPD_CON_POS_RANGE 0xb9 (added sbc5r01) */
void
-decode_con_pos_range_vpd(uint8_t * buff, int len, struct opts_t * op,
+decode_con_pos_range_vpd(const uint8_t * buff, int len, struct opts_t * op,
sgj_opaque_p jap)
{
int k;
uint32_t u;
sgj_state * jsp = &op->json_st;
- uint8_t * bp;
+ const uint8_t * bp;
sgj_opaque_p jo2p;
if (op->do_hex) {
@@ -2426,8 +2467,8 @@ get_tpc_desc_type_s(uint32_t desc_type)
/* VPD_3PARTY_COPY 3PC, third party copy 0x8f ["tpc"] */
void
-decode_3party_copy_vpd(uint8_t * buff, int len, struct opts_t * op,
- sgj_opaque_p jap)
+decode_3party_copy_vpd(const uint8_t * buff, int len,
+ struct opts_t * op, sgj_opaque_p jap)
{
int j, k, m, bump, desc_type, desc_len, sa_len, pdt;
uint32_t u, v;
@@ -2726,11 +2767,11 @@ skip:
/* VPD_PROTO_LU 0x90 ["pslu"] */
void
-decode_proto_lu_vpd(uint8_t * buff, int len, struct opts_t * op,
+decode_proto_lu_vpd(const uint8_t * buff, int len, struct opts_t * op,
sgj_opaque_p jap)
{
int k, bump, rel_port, desc_len, proto;
- uint8_t * bp;
+ const uint8_t * bp;
sgj_state * jsp = &op->json_st;
sgj_opaque_p jo2p = NULL;
char b[128];
@@ -2764,10 +2805,10 @@ decode_proto_lu_vpd(uint8_t * buff, int len, struct opts_t * op,
return;
}
if (0 == desc_len)
- goto again;;
+ goto again;
if (2 == op->do_hex) {
hex2stdout(bp + 8, desc_len, 1);
- goto again;;
+ goto again;
}
switch (proto) {
case TPROTO_SAS:
@@ -2786,13 +2827,13 @@ again:
/* VPD_PROTO_PORT 0x91 ["pspo"] */
void
-decode_proto_port_vpd(uint8_t * buff, int len, struct opts_t * op,
+decode_proto_port_vpd(const uint8_t * buff, int len, struct opts_t * op,
sgj_opaque_p jap)
{
bool pds, ssp_pers;
int k, j, bump, rel_port, desc_len, proto, phy;
- uint8_t * bp;
- uint8_t * pidp;
+ const uint8_t * bp;
+ const uint8_t * pidp;
sgj_state * jsp = &op->json_st;
sgj_opaque_p jo2p = NULL;
sgj_opaque_p ja2p = NULL;
@@ -2862,3 +2903,91 @@ again:
sgj_js_nv_o(jsp, jap, NULL /* name */, jo2p);
}
}
+
+/* VPD_LB_PROTECTION 0xb5 (SSC) [added in ssc5r02a] */
+void
+decode_lb_protection_vpd(const uint8_t * buff, int len, struct opts_t * op,
+ sgj_opaque_p jap)
+{
+ int k, bump;
+ const uint8_t * bp;
+ sgj_state * jsp = &op->json_st;
+ sgj_opaque_p jo2p = NULL;
+
+ if ((1 == op->do_hex) || (op->do_hex > 2)) {
+ hex2stdout(buff, len, (1 == op->do_hex) ? 0 : -1);
+ return;
+ }
+ if (len < 8) {
+ pr2serr("VPD page length too short=%d\n", len);
+ return;
+ }
+ len -= 8;
+ bp = buff + 8;
+ for (k = 0; k < len; k += bump, bp += bump) {
+ jo2p = sgj_new_unattached_object_r(jsp);
+ bump = 1 + bp[0];
+ sgj_pr_hr(jsp, " method: %d, info_len: %d, LBP_W_C=%d, LBP_R_C=%d, "
+ "RBDP_C=%d\n", bp[1], 0x3f & bp[2], !!(0x80 & bp[3]),
+ !!(0x40 & bp[3]), !!(0x20 & bp[3]));
+ sgj_js_nv_ihex(jsp, jo2p, "logical_block_protection_method", bp[1]);
+ sgj_js_nv_ihex_nex(jsp, jo2p,
+ "logical_block_protection_information_length",
+ 0x3f & bp[2], true, "unit: byte");
+ sgj_js_nv_ihex_nex(jsp, jo2p, "lbp_w_c", !!(0x80 & bp[3]), false,
+ "Logical Blocks Protected during Write supported");
+ sgj_js_nv_ihex_nex(jsp, jo2p, "lbp_r_c", !!(0x40 & bp[3]), false,
+ "Logical Blocks Protected during Read supported");
+ sgj_js_nv_ihex_nex(jsp, jo2p, "rbdp_c", !!(0x20 & bp[3]), false,
+ "Recover Buffered Data Protected supported");
+ if ((k + bump) > len) {
+ pr2serr("Logical block protection VPD page, short "
+ "descriptor length=%d, left=%d\n", bump, (len - k));
+ sgj_js_nv_o(jsp, jap, NULL /* name */, jo2p);
+ return;
+ }
+ sgj_js_nv_o(jsp, jap, NULL /* name */, jo2p);
+ }
+}
+
+/* VPD_TA_SUPPORTED 0xb2 ["tas"] */
+void
+decode_tapealert_supported_vpd(const uint8_t * buff, int len,
+ struct opts_t * op, sgj_opaque_p jop)
+{
+ bool have_ta_strs = !! sg_lib_tapealert_strs[0];
+ int k, mod, div, n;
+ unsigned int supp;
+ sgj_state * jsp = &op->json_st;
+ char b[144];
+ char d[64];
+ static const int blen = sizeof(b);
+
+ if (len < 12) {
+ pr2serr("VPD page length too short=%d\n", len);
+ return;
+ }
+ b[0] ='\0';
+ for (k = 1, n = 0; k < 0x41; ++k) {
+ mod = ((k - 1) % 8);
+ div = (k - 1) / 8;
+ supp = !! (buff[4 + div] & (1 << (7 - mod)));
+ if (jsp->pr_as_json) {
+ snprintf(d, sizeof(d), "flag%02xh", k);
+ if (have_ta_strs)
+ sgj_js_nv_ihex_nex(jsp, jop, d, supp, false,
+ sg_lib_tapealert_strs[k]);
+ else
+ sgj_js_nv_i(jsp, jop, d, supp);
+ }
+ if (0 == mod) {
+ if (div > 0) {
+ sgj_pr_hr(jsp, "%s\n", b);
+ n = 0;
+ }
+ n += sg_scnpr(b + n, blen - n, " Flag%02Xh: %d", k, supp);
+ } else
+ n += sg_scnpr(b + n, blen - n, " %02Xh: %d", k, supp);
+ }
+ sgj_pr_hr(jsp, "%s\n", b);
+}
diff --git a/src/sg_vpd_common.h b/src/sg_vpd_common.h
index 722da1fd..50cdb48a 100644
--- a/src/sg_vpd_common.h
+++ b/src/sg_vpd_common.h
@@ -136,8 +136,10 @@ struct opts_t {
bool do_force; /* sg_inq + sg_vpd */
bool do_only; /* sg_inq: --only after stdinq: don't fetch VPD page 0x80 */
bool do_quiet; /* sg_vpd */
+ bool examine_given; /* sg_vpd */
bool page_given; /* sg_inq + sg_vpd */
bool possible_nvme; /* sg_inq */
+ bool protect_not_sure; /* sg_vpd */
bool verbose_given; /* sg_inq + sg_vpd */
bool version_given; /* sg_inq + sg_vpd */
bool do_vpd; /* sg_inq */
@@ -189,62 +191,71 @@ typedef int (*recurse_vpd_decodep)(struct opts_t *, sgj_opaque_p jop, int off);
sgj_opaque_p sg_vpd_js_hdr(sgj_state * jsp, sgj_opaque_p jop,
const char * name, const uint8_t * vpd_hdrp);
-void decode_net_man_vpd(uint8_t * buff, int len, struct opts_t * op,
+void decode_net_man_vpd(const uint8_t * buff, int len, struct opts_t * op,
sgj_opaque_p jap);
-void decode_x_inq_vpd(uint8_t * b, int len, bool protect, struct opts_t * op,
- sgj_opaque_p jop);
-void decode_softw_inf_id(uint8_t * buff, int len, struct opts_t * op,
+void decode_x_inq_vpd(const uint8_t * b, int len, bool protect,
+ struct opts_t * op, sgj_opaque_p jop);
+void decode_softw_inf_id(const uint8_t * buff, int len, struct opts_t * op,
sgj_opaque_p jap);
-void decode_mode_policy_vpd(uint8_t * buff, int len, struct opts_t * op,
+void decode_mode_policy_vpd(const uint8_t * buff, int len, struct opts_t * op,
sgj_opaque_p jap);
-void decode_power_condition(uint8_t * buff, int len, struct opts_t * op,
+void decode_cga_profile_vpd(const uint8_t * buff, int len, struct opts_t * op,
+ sgj_opaque_p jap);
+void decode_power_condition(const uint8_t * buff, int len, struct opts_t * op,
sgj_opaque_p jop);
int filter_json_dev_ids(uint8_t * buff, int len, int m_assoc,
struct opts_t * op, sgj_opaque_p jap);
void decode_ata_info_vpd(const uint8_t * buff, int len, struct opts_t * op,
sgj_opaque_p jop);
-void decode_feature_sets_vpd(uint8_t * buff, int len, struct opts_t * op,
+void decode_feature_sets_vpd(const uint8_t * buff, int len, struct opts_t * op,
sgj_opaque_p jap);
void decode_dev_constit_vpd(const uint8_t * buff, int len,
struct opts_t * op, sgj_opaque_p jap,
recurse_vpd_decodep fp);
sgj_opaque_p std_inq_decode_js(const uint8_t * b, int len,
struct opts_t * op, sgj_opaque_p jop);
-void decode_power_consumption(uint8_t * buff, int len,
+void decode_power_consumption(const uint8_t * buff, int len,
struct opts_t * op, sgj_opaque_p jap);
void decode_block_limits_vpd(const uint8_t * buff, int len,
struct opts_t * op, sgj_opaque_p jop);
void decode_block_dev_ch_vpd(const uint8_t * buff, int len,
struct opts_t * op, sgj_opaque_p jop);
-int decode_block_lb_prov_vpd(uint8_t * buff, int len,
+int decode_block_lb_prov_vpd(const uint8_t * buff, int len,
struct opts_t * op, sgj_opaque_p jop);
-void decode_referrals_vpd(uint8_t * buff, int len, struct opts_t * op,
+void decode_referrals_vpd(const uint8_t * buff, int len, struct opts_t * op,
sgj_opaque_p jop);
-void decode_sup_block_lens_vpd(uint8_t * buff, int len, struct opts_t * op,
- sgj_opaque_p jap);
-void decode_block_dev_char_ext_vpd(uint8_t * buff, int len,
+void decode_sup_block_lens_vpd(const uint8_t * buff, int len,
+ struct opts_t * op, sgj_opaque_p jap);
+void decode_block_dev_char_ext_vpd(const uint8_t * buff, int len,
struct opts_t * op, sgj_opaque_p jop);
-void decode_zbdch_vpd(uint8_t * buff, int len, struct opts_t * op,
+void decode_zbdch_vpd(const uint8_t * buff, int len, struct opts_t * op,
sgj_opaque_p jop);
-void decode_block_limits_ext_vpd(uint8_t * buff, int len, struct opts_t * op,
- sgj_opaque_p jop);
-void decode_format_presets_vpd(uint8_t * buff, int len, struct opts_t * op,
- sgj_opaque_p jap);
-void decode_con_pos_range_vpd(uint8_t * buff, int len, struct opts_t * op,
- sgj_opaque_p jap);
-void decode_3party_copy_vpd(uint8_t * buff, int len, struct opts_t * op,
+void decode_block_limits_ext_vpd(const uint8_t * buff, int len,
+ struct opts_t * op, sgj_opaque_p jop);
+void decode_format_presets_vpd(const uint8_t * buff, int len,
+ struct opts_t * op, sgj_opaque_p jap);
+void decode_con_pos_range_vpd(const uint8_t * buff, int len,
+ struct opts_t * op, sgj_opaque_p jap);
+void decode_3party_copy_vpd(const uint8_t * buff, int len, struct opts_t * op,
sgj_opaque_p jap);
void
-decode_proto_lu_vpd(uint8_t * buff, int len, struct opts_t * op,
+decode_proto_lu_vpd(const uint8_t * buff, int len, struct opts_t * op,
sgj_opaque_p jap);
void
-decode_proto_port_vpd(uint8_t * buff, int len, struct opts_t * op,
+decode_proto_port_vpd(const uint8_t * buff, int len, struct opts_t * op,
sgj_opaque_p jap);
+void
+decode_lb_protection_vpd(const uint8_t * buff, int len, struct opts_t * op,
+ sgj_opaque_p jap);
+void
+decode_tapealert_supported_vpd(const uint8_t * buff, int len,
+ struct opts_t * op, sgj_opaque_p jop);
const char * pqual_str(int pqual);
void svpd_enumerate_vendor(int vend_prod_num);
int svpd_count_vendor_vpds(int vpd_pn, int vend_prod_num);
-int svpd_decode_vendor(int sg_fd, struct opts_t * op, int off);
+int svpd_decode_vendor(int sg_fd, struct opts_t * op, sgj_opaque_p jop,
+ int off);
const struct svpd_values_name_t * svpd_find_vendor_by_acron(const char * ap);
int svpd_find_vp_num_by_acron(const char * vp_ap);
const struct svpd_values_name_t * svpd_find_vendor_by_num(int page_num,
diff --git a/src/sg_vpd_vendor.c b/src/sg_vpd_vendor.c
index 23df1442..5cfc7ee3 100644
--- a/src/sg_vpd_vendor.c
+++ b/src/sg_vpd_vendor.c
@@ -92,10 +92,6 @@
#define VPD_V_HIT_PG_D1 0xd1
#define VPD_V_HIT_PG_D2 0xd2
-#ifndef SG_NVME_VPD_NICR
-#define SG_NVME_VPD_NICR 0xde /* NVME Identify Controller Response */
-#endif
-
#define DEF_ALLOC_LEN 252
#define MX_ALLOC_LEN (0xc000 + 0x80)
@@ -115,6 +111,17 @@ dup_sanity_chk(int sz_opts_t, int sz_values_name_t)
sz_values_name_t);
}
+static int
+no_ascii_4hex(const struct opts_t * op)
+{
+ if (op->do_hex < 2)
+ return 1;
+ else if (2 == op->do_hex)
+ return 0;
+ else
+ return -1;
+}
+
static bool
is_like_pdt(int actual_pdt, const struct svpd_values_name_t * vnp)
{
@@ -1227,15 +1234,20 @@ decode_vpd_d2_hit(uint8_t * b, int blen)
/* Returns 0 if successful, see sg_ll_inquiry() plus SG_LIB_CAT_OTHER for
unsupported page */
int
-svpd_decode_vendor(int sg_fd, struct opts_t * op, int off)
+svpd_decode_vendor(int sg_fd, struct opts_t * op, sgj_opaque_p jop, int off)
{
- int len, res;
- char name[64];
- const struct svpd_values_name_t * vnp;
+ bool hex0 = (0 == op->do_hex);
+ int len, pdt, plen, pn;
int alloc_len = op->maxlen;
+ int res = 0;
+ const struct svpd_values_name_t * vnp;
+ sgj_state * jsp = &op->json_st;
+ sgj_opaque_p jo2p;
uint8_t * rp;
+ char name[80];
- switch (op->vpd_pn) {
+ pn = op->vpd_pn;
+ switch (pn) { /* VPD codes that we support vendor pages for */
case 0x3:
case 0xc0:
case 0xc1:
@@ -1249,6 +1261,7 @@ svpd_decode_vendor(int sg_fd, struct opts_t * op, int off)
case 0xd0:
case 0xd1:
case 0xd2:
+ case 0xde:
break;
default: /* not known so return prior to fetching page */
return SG_LIB_CAT_OTHER;
@@ -1258,135 +1271,195 @@ svpd_decode_vendor(int sg_fd, struct opts_t * op, int off)
if (0 == alloc_len)
alloc_len = DEF_ALLOC_LEN;
}
- res = vpd_fetch_page(sg_fd, rp, op->vpd_pn, alloc_len, op->do_quiet,
- op->verbose, &len);
- if (0 == res) {
- vnp = svpd_get_v_detail(op->vpd_pn, op->vend_prod_num, 0xf & rp[0]);
- if (vnp && vnp->name)
- snprintf(name, sizeof(name), "%s", vnp->name);
- else
- snprintf(name, sizeof(name) - 1, "Vendor VPD page=0x%x",
- op->vpd_pn);
- if ((! op->do_raw) && (! op->do_quiet) && (op->do_hex < 2))
- printf("%s VPD Page:\n", name);
- if (op->do_raw)
- dStrRaw(rp, len);
- else if (op->do_hex)
- hex2stdout(rp, len, ((1 == op->do_hex) ? 0 : -1));
- else {
- switch(op->vpd_pn) {
- case 0x3:
- if (VPD_VP_WDC_HITACHI == op->vend_prod_num)
- decode_vpd_3_hit(rp, len);
- else
- hex2stdout(rp, len, 0);
- break;
- case 0xc0:
- if (VPD_VP_SEAGATE == op->vend_prod_num)
- decode_firm_vpd_c0_sea(rp, len);
- else if (VPD_VP_EMC == op->vend_prod_num)
- decode_upr_vpd_c0_emc(rp, len);
- else if (VPD_VP_HP3PAR == op->vend_prod_num)
- decode_vpd_c0_hp3par(rp, len);
- else if (VPD_VP_RDAC == op->vend_prod_num)
- decode_rdac_vpd_c0(rp, len);
- else if (VPD_VP_DDS == op->vend_prod_num)
- decode_dds_vpd_c0(rp, len);
- else if (VPD_VP_IBM_LTO == op->vend_prod_num)
- decode_ibm_lto_dcrl(rp, len);
- else if (VPD_VP_HP_LTO == op->vend_prod_num)
- decode_hp_lto_vpd_cx(rp, len, op->vpd_pn);
- else
- hex2stdout(rp, len, 0);
- break;
- case 0xc1:
- if (VPD_VP_SEAGATE == op->vend_prod_num)
- decode_date_code_vpd_c1_sea(rp, len);
- else if (VPD_VP_RDAC == op->vend_prod_num)
- decode_rdac_vpd_c1(rp, len);
- else if (VPD_VP_IBM_LTO == op->vend_prod_num)
- decode_ibm_lto_dsn(rp, len);
- else if (VPD_VP_HP_LTO == op->vend_prod_num)
- decode_hp_lto_vpd_cx(rp, len, op->vpd_pn);
- else
- hex2stdout(rp, len, 0);
- break;
- case 0xc2:
- if (VPD_VP_RDAC == op->vend_prod_num)
- decode_rdac_vpd_c2(rp, len);
- else if (VPD_VP_HP_LTO == op->vend_prod_num)
- decode_hp_lto_vpd_cx(rp, len, op->vpd_pn);
- else
- hex2stdout(rp, len, 0);
- break;
- case 0xc3:
- if (VPD_VP_SEAGATE == op->vend_prod_num)
- decode_dev_beh_vpd_c3_sea(rp, len);
- else if (VPD_VP_RDAC == op->vend_prod_num)
- decode_rdac_vpd_c3(rp, len);
- else if (VPD_VP_HP_LTO == op->vend_prod_num)
- decode_hp_lto_vpd_cx(rp, len, op->vpd_pn);
- else
- hex2stdout(rp, len, 0);
- break;
- case 0xc4:
- if (VPD_VP_RDAC == op->vend_prod_num)
- decode_rdac_vpd_c4(rp, len);
- else if (VPD_VP_HP_LTO == op->vend_prod_num)
- decode_hp_lto_vpd_cx(rp, len, op->vpd_pn);
- else
- hex2stdout(rp, len, 0);
- break;
- case 0xc5:
- if (VPD_VP_HP_LTO == op->vend_prod_num)
- decode_hp_lto_vpd_cx(rp, len, op->vpd_pn);
- else
- hex2stdout(rp, len, 0);
- break;
- case 0xc8:
- if (VPD_VP_RDAC == op->vend_prod_num)
- decode_rdac_vpd_c8(rp, len);
- else
- hex2stdout(rp, len, 0);
- break;
- case 0xc9:
- if (VPD_VP_RDAC == op->vend_prod_num)
- decode_rdac_vpd_c9(rp, len);
- else
- hex2stdout(rp, len, 0);
- break;
- case 0xca:
- if (VPD_VP_RDAC == op->vend_prod_num)
- decode_rdac_vpd_ca(rp, len);
- else
- hex2stdout(rp, len, 0);
- break;
- case 0xd0:
- if (VPD_VP_RDAC == op->vend_prod_num)
- decode_rdac_vpd_d0(rp, len);
- else
- hex2stdout(rp, len, 0);
- break;
- case 0xd1:
- if (VPD_VP_WDC_HITACHI == op->vend_prod_num)
- decode_vpd_d1_hit(rp, len);
- else
- hex2stdout(rp, len, 0);
- break;
- case 0xd2:
- if (VPD_VP_WDC_HITACHI == op->vend_prod_num)
- decode_vpd_d2_hit(rp, len);
- else
- hex2stdout(rp, len, 0);
+ res = vpd_fetch_page(sg_fd, rp, pn, alloc_len, op->do_quiet, op->verbose,
+ &len);
+ if (res) {
+ pr2serr("Vendor VPD page=0x%x failed to fetch\n", pn);
+ return res;
+ }
+ pdt = rp[0] & PDT_MASK;
+ vnp = svpd_get_v_detail(pn, op->vend_prod_num, pdt);
+ if (vnp && vnp->name)
+ snprintf(name, sizeof(name), "%s", vnp->name);
+ else
+ snprintf(name, sizeof(name) - 1, "Vendor VPD page=0x%x", pn);
+ if ((! op->do_raw) && (! op->do_quiet) && (op->do_hex < 3))
+ sgj_pr_hr(jsp, "%s VPD Page:\n", name);
+ if (op->do_raw)
+ dStrRaw(rp, len);
+ else {
+ switch(pn) {
+ case 0x3:
+ if (hex0 && (VPD_VP_WDC_HITACHI == op->vend_prod_num))
+ decode_vpd_3_hit(rp, len);
+ else
+ res = SG_LIB_CAT_OTHER;
+ break;
+ case 0xc0:
+ if (! hex0)
+ hex2stdout(rp, len, no_ascii_4hex(op));
+ else if (VPD_VP_SEAGATE == op->vend_prod_num)
+ decode_firm_vpd_c0_sea(rp, len);
+ else if (VPD_VP_EMC == op->vend_prod_num)
+ decode_upr_vpd_c0_emc(rp, len);
+ else if (VPD_VP_HP3PAR == op->vend_prod_num)
+ decode_vpd_c0_hp3par(rp, len);
+ else if (VPD_VP_RDAC == op->vend_prod_num)
+ decode_rdac_vpd_c0(rp, len);
+ else if (VPD_VP_DDS == op->vend_prod_num)
+ decode_dds_vpd_c0(rp, len);
+ else if (VPD_VP_IBM_LTO == op->vend_prod_num)
+ decode_ibm_lto_dcrl(rp, len);
+ else if (VPD_VP_HP_LTO == op->vend_prod_num)
+ decode_hp_lto_vpd_cx(rp, len, pn);
+ else
+ res = SG_LIB_CAT_OTHER;
+ break;
+ case 0xc1:
+ if (! hex0)
+ hex2stdout(rp, len, no_ascii_4hex(op));
+ else if (VPD_VP_SEAGATE == op->vend_prod_num)
+ decode_date_code_vpd_c1_sea(rp, len);
+ else if (VPD_VP_RDAC == op->vend_prod_num)
+ decode_rdac_vpd_c1(rp, len);
+ else if (VPD_VP_IBM_LTO == op->vend_prod_num)
+ decode_ibm_lto_dsn(rp, len);
+ else if (VPD_VP_HP_LTO == op->vend_prod_num)
+ decode_hp_lto_vpd_cx(rp, len, pn);
+ else
+ res = SG_LIB_CAT_OTHER;
+ break;
+ case 0xc2:
+ if (! hex0)
+ hex2stdout(rp, len, no_ascii_4hex(op));
+ else if (VPD_VP_RDAC == op->vend_prod_num)
+ decode_rdac_vpd_c2(rp, len);
+ else if (VPD_VP_HP_LTO == op->vend_prod_num)
+ decode_hp_lto_vpd_cx(rp, len, pn);
+ else
+ res = SG_LIB_CAT_OTHER;
+ break;
+ case 0xc3:
+ if (! hex0)
+ hex2stdout(rp, len, no_ascii_4hex(op));
+ else if (VPD_VP_SEAGATE == op->vend_prod_num)
+ decode_dev_beh_vpd_c3_sea(rp, len);
+ else if (VPD_VP_RDAC == op->vend_prod_num)
+ decode_rdac_vpd_c3(rp, len);
+ else if (VPD_VP_HP_LTO == op->vend_prod_num)
+ decode_hp_lto_vpd_cx(rp, len, pn);
+ else
+ res = SG_LIB_CAT_OTHER;
+ break;
+ case 0xc4:
+ if (! hex0)
+ hex2stdout(rp, len, no_ascii_4hex(op));
+ else if (VPD_VP_RDAC == op->vend_prod_num)
+ decode_rdac_vpd_c4(rp, len);
+ else if (VPD_VP_HP_LTO == op->vend_prod_num)
+ decode_hp_lto_vpd_cx(rp, len, pn);
+ else
+ res = SG_LIB_CAT_OTHER;
+ break;
+ case 0xc5:
+ if (! hex0)
+ hex2stdout(rp, len, no_ascii_4hex(op));
+ else if (VPD_VP_HP_LTO == op->vend_prod_num)
+ decode_hp_lto_vpd_cx(rp, len, pn);
+ else
+ res = SG_LIB_CAT_OTHER;
+ break;
+ case 0xc8:
+ if (! hex0)
+ hex2stdout(rp, len, no_ascii_4hex(op));
+ else if (VPD_VP_RDAC == op->vend_prod_num)
+ decode_rdac_vpd_c8(rp, len);
+ else
+ res = SG_LIB_CAT_OTHER;
+ break;
+ case 0xc9:
+ if (! hex0)
+ hex2stdout(rp, len, no_ascii_4hex(op));
+ else if (VPD_VP_RDAC == op->vend_prod_num)
+ decode_rdac_vpd_c9(rp, len);
+ else
+ res = SG_LIB_CAT_OTHER;
+ break;
+ case 0xca:
+ if (! hex0)
+ hex2stdout(rp, len, no_ascii_4hex(op));
+ else if (VPD_VP_RDAC == op->vend_prod_num)
+ decode_rdac_vpd_ca(rp, len);
+ else
+ res = SG_LIB_CAT_OTHER;
+ break;
+ case 0xd0:
+ if (! hex0)
+ hex2stdout(rp, len, no_ascii_4hex(op));
+ else if (VPD_VP_RDAC == op->vend_prod_num)
+ decode_rdac_vpd_d0(rp, len);
+ else
+ res = SG_LIB_CAT_OTHER;
+ break;
+ case 0xd1:
+ if (! hex0)
+ hex2stdout(rp, len, no_ascii_4hex(op));
+ else if (VPD_VP_WDC_HITACHI == op->vend_prod_num)
+ decode_vpd_d1_hit(rp, len);
+ else
+ res = SG_LIB_CAT_OTHER;
+ break;
+ case 0xd2:
+ if (! hex0)
+ hex2stdout(rp, len, no_ascii_4hex(op));
+ else if (VPD_VP_WDC_HITACHI == op->vend_prod_num)
+ decode_vpd_d2_hit(rp, len);
+ else
+ res = SG_LIB_CAT_OTHER;
+ break;
+ case SG_NVME_VPD_NICR: /* 0xde */
+ if (VPD_VP_SG != op->vend_prod_num) {
+ res = SG_LIB_CAT_OTHER;
+ break;
+ }
+ /* NVMe: Identify Controller data structure (CNS 01h) */
+ plen = sg_get_unaligned_be16(rp + 2) + 4;
+ if (plen > len) { /* fetch the whole page */
+ res = vpd_fetch_page(sg_fd, rp, pn, plen,
+ op->do_quiet, op->verbose, &len);
+ if (res) {
+ pr2serr("Vendor VPD page=0x%x failed to fetch\n", pn);
+ return res;
+ }
+ }
+ if (len < 16) {
+ pr2serr("%s expected to be > 15 bytes long (got: %d)\n",
+ name, len);
+ break;
+ } else {
+ int n = len - 16;
+
+ if (n > 4096) {
+ pr2serr("NVMe Identify response expected to be "
+ "<= 4096 bytes (got: %d)\n", n);
break;
- default:
- pr2serr("%s: logic error, should know can't decode "
- "pn=0x%x\n", __func__, op->vpd_pn);
- return SG_LIB_CAT_OTHER;
+ }
+ if (op->do_hex)
+ hex2stdout(rp, len, no_ascii_4hex(op));
+ else if (jsp->pr_as_json) {
+ jo2p = sg_vpd_js_hdr(jsp, jop, name, rp);
+ sgj_js_nv_hex_bytes(jsp, jo2p, "response_bytes",
+ rp + 16, n);
+ } else
+ hex2stdout(rp + 16, n, 1);
}
- return 0;
+ break;
+ default:
+ res = SG_LIB_CAT_OTHER;
}
- } else
- pr2serr("Vendor VPD page=0x%x failed to fetch\n", op->vpd_pn);
+ }
+ if (res && op->verbose)
+ pr2serr("%s: can't decode pn=0x%x, vend_prod_num=%d\n", __func__,
+ pn, op->vend_prod_num);
return res;
}