aboutsummaryrefslogtreecommitdiff
path: root/src/sg_vpd.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/sg_vpd.c')
-rw-r--r--src/sg_vpd.c343
1 files changed, 197 insertions, 146 deletions
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);
}