sdparm_vpd.c (sdparm-1.11.tgz) | : | sdparm_vpd.c (sdparm-1.12.tgz) | ||
---|---|---|---|---|
/* | /* | |||
* Copyright (c) 2005-2020, Douglas Gilbert | * Copyright (c) 2005-2021, Douglas Gilbert | |||
* All rights reserved. | * All rights reserved. | |||
* | * | |||
* Redistribution and use in source and binary forms, with or without | * Redistribution and use in source and binary forms, with or without | |||
* modification, are permitted provided that the following conditions are met: | * modification, are permitted provided that the following conditions are met: | |||
* | * | |||
* 1. Redistributions of source code must retain the above copyright notice, | * 1. Redistributions of source code must retain the above copyright notice, | |||
* this list of conditions and the following disclaimer. | * this list of conditions and the following disclaimer. | |||
* 2. Redistributions in binary form must reproduce the above copyright | * 2. Redistributions in binary form must reproduce the above copyright | |||
* notice, this list of conditions and the following disclaimer in the | * notice, this list of conditions and the following disclaimer in the | |||
* documentation and/or other materials provided with the distribution. | * documentation and/or other materials provided with the distribution. | |||
skipping to change at line 1486 | skipping to change at line 1486 | |||
"Not specified", | "Not specified", | |||
"CFast", | "CFast", | |||
"CompactFlash", | "CompactFlash", | |||
"MemoryStick", | "MemoryStick", | |||
"MultiMediaCard", | "MultiMediaCard", | |||
"Secure Digital Card (SD)", | "Secure Digital Card (SD)", | |||
"XQD", | "XQD", | |||
"Universal Flash Storage Card (UFS)", | "Universal Flash Storage Card (UFS)", | |||
}; | }; | |||
static const char * zoned_strs[] = { | ||||
"", | ||||
" [host-aware]", | ||||
" [host-managed]", | ||||
"", | ||||
}; | ||||
/* VPD_BLOCK_DEV_CHARS 0xb1 */ | /* VPD_BLOCK_DEV_CHARS 0xb1 */ | |||
static int | static int | |||
decode_block_dev_chars_vpd(uint8_t * buff, int len) | decode_block_dev_chars_vpd(uint8_t * buff, int len) | |||
{ | { | |||
int zoned; | ||||
unsigned int u, k; | unsigned int u, k; | |||
if (len < 64) { | if (len < 64) { | |||
pr2serr("Block device characteristics VPD page length too short=%d\n", | pr2serr("Block device characteristics VPD page length too short=%d\n", | |||
len); | len); | |||
return SG_LIB_CAT_MALFORMED; | return SG_LIB_CAT_MALFORMED; | |||
} | } | |||
u = sg_get_unaligned_be16(buff + 4); | u = sg_get_unaligned_be16(buff + 4); | |||
if (0 == u) | if (0 == u) | |||
printf(" Medium rotation rate is not reported\n"); | printf(" Medium rotation rate is not reported\n"); | |||
skipping to change at line 1542 | skipping to change at line 1550 | |||
case 4: | case 4: | |||
printf(": 1.8 inch\n"); | printf(": 1.8 inch\n"); | |||
break; | break; | |||
case 5: | case 5: | |||
printf(": less then 1.8 inch\n"); | printf(": less then 1.8 inch\n"); | |||
break; | break; | |||
default: | default: | |||
printf(": reserved\n"); | printf(": reserved\n"); | |||
break; | break; | |||
} | } | |||
printf(" ZONED=%d\n", (buff[8] >> 4) & 0x3); /* sbc4r04 */ | zoned = (buff[8] >> 4) & 0x3; /* added sbc4r04 */ | |||
printf(" ZONED=%d%s\n", zoned, zoned_strs[zoned]); | ||||
printf(" BOCS=%d\n", !!(buff[8] & 0x4)); | printf(" BOCS=%d\n", !!(buff[8] & 0x4)); | |||
printf(" FUAB=%d\n", !!(buff[8] & 0x2)); | printf(" FUAB=%d\n", !!(buff[8] & 0x2)); | |||
printf(" VBULS=%d\n", !!(buff[8] & 0x1)); | printf(" VBULS=%d\n", !!(buff[8] & 0x1)); | |||
printf(" DEPOPULATION_TIME=%u (seconds)\n", | printf(" DEPOPULATION_TIME=%u (seconds)\n", | |||
sg_get_unaligned_be32(buff + 12)); /* added sbc4r14 */ | sg_get_unaligned_be32(buff + 12)); /* added sbc4r14 */ | |||
return 0; | return 0; | |||
} | } | |||
/* VPD_SA_DEV_CAP 0xb0 */ | /* VPD_SA_DEV_CAP 0xb0 */ | |||
static int | static int | |||
skipping to change at line 1816 | skipping to change at line 1825 | |||
!!(0x40 & bp[3]), !!(0x20 & bp[3])); | !!(0x40 & bp[3]), !!(0x20 & bp[3])); | |||
if ((k + bump) > len) { | if ((k + bump) > len) { | |||
pr2serr("Logical block protection VPD page, short descriptor " | pr2serr("Logical block protection VPD page, short descriptor " | |||
"length=%d, left=%d\n", bump, (len - k)); | "length=%d, left=%d\n", bump, (len - k)); | |||
return SG_LIB_CAT_MALFORMED; | return SG_LIB_CAT_MALFORMED; | |||
} | } | |||
} | } | |||
return 0; | return 0; | |||
} | } | |||
/* VPD_FORMAT_PRESETS 0xb8 (added sbc4r18) */ | ||||
static int | ||||
decode_format_presets_vpd(uint8_t * buff, int len) | ||||
{ | ||||
int k; | ||||
unsigned int sch_type; | ||||
uint8_t * bp; | ||||
len -= 4; | ||||
bp = buff + 4; | ||||
for (k = 0; k < len; k += 64, bp += 64) { | ||||
printf(" Preset identifier: 0x%x\n", sg_get_unaligned_be32(bp)); | ||||
sch_type = bp[4]; | ||||
printf(" schema type: %u\n", sch_type); | ||||
printf(" logical blocks per physical block exponent type: %u\n", | ||||
0xf & bp[7]); | ||||
printf(" logical block length: %u\n", | ||||
sg_get_unaligned_be32(bp + 8)); | ||||
printf(" designed last LBA: 0x%" PRIx64 "\n", | ||||
sg_get_unaligned_be64(bp + 16)); | ||||
printf(" FMPT_INFO: %u\n", (bp[38] >> 6) & 0x3); | ||||
printf(" protection field usage: %u\n", bp[38] & 0x7); | ||||
printf(" protection interval exponent: %u\n", bp[39] & 0xf); | ||||
if (2 == sch_type) | ||||
printf(" Defines zones for host aware device:\n"); | ||||
else if (3 == sch_type) | ||||
printf(" Defines zones for host managed device:\n"); | ||||
if ((2 == sch_type) || (3 == sch_type)) { | ||||
unsigned int u = bp[40 + 0]; | ||||
printf(" low LBA conventional zones percentage: " | ||||
"%u.%u %%\n", u / 10, u % 10); | ||||
u = bp[40 + 1]; | ||||
printf(" high LBA conventional zones percentage: " | ||||
"%u.%u %%\n", u / 10, u % 10); | ||||
printf(" logical blocks per zone: %u\n", | ||||
sg_get_unaligned_be32(bp + 40 + 12)); | ||||
} | ||||
} | ||||
return 0; | ||||
} | ||||
/* VPD_CON_POS_RANGE 0xb9 (added 20-089r2) */ | ||||
static int | ||||
decode_con_pos_range_vpd(uint8_t * buff, int len) | ||||
{ | ||||
int k; | ||||
uint64_t u; | ||||
uint8_t * bp; | ||||
if (len < 64) { | ||||
pr2serr("Concurrent position ranges VPD page length too short=%d\n", | ||||
len); | ||||
return SG_LIB_CAT_MALFORMED; | ||||
} | ||||
len -= 64; | ||||
bp = buff + 64; | ||||
for (k = 0; k < len; k += 32, bp += 32) { | ||||
printf(" LBA range number: %u\n", bp[0]); | ||||
printf(" number of storage elements: %u\n", bp[1]); | ||||
printf(" starting LBA: 0x%" PRIx64 "\n", | ||||
sg_get_unaligned_be64(bp + 8)); | ||||
u = sg_get_unaligned_be64(bp + 16); | ||||
printf(" number of LBAs: 0x%" PRIx64 " [%" PRIu64 "]\n", u, u); | ||||
} | ||||
return 0; | ||||
} | ||||
/* VPD_ZBC_DEV_CHARS sbc or zbc */ | /* VPD_ZBC_DEV_CHARS sbc or zbc */ | |||
static int | static int | |||
decode_zbdc_vpd(uint8_t * b, int len) | decode_zbdc_vpd(uint8_t * b, int len) | |||
{ | { | |||
uint32_t u; | uint32_t u; | |||
if (len < 64) { | if (len < 64) { | |||
pr2serr("Zoned block device characteristics VPD page length too " | pr2serr("Zoned block device characteristics VPD page length too " | |||
"short=%d\n", len); | "short=%d\n", len); | |||
return SG_LIB_CAT_MALFORMED; | return SG_LIB_CAT_MALFORMED; | |||
skipping to change at line 1963 | skipping to change at line 2040 | |||
else if (3 == pqual) | else if (3 == pqual) | |||
printf(" [PQ indicates LU not accessible via this port]\n"); | printf(" [PQ indicates LU not accessible via this port]\n"); | |||
else | else | |||
printf(" [reserved or vendor specific qualifier [%d]]\n", pqual); | printf(" [reserved or vendor specific qualifier [%d]]\n", pqual); | |||
len = b[4] + 5; | len = b[4] + 5; | |||
len = (len <= sz) ? len : sz; | len = (len <= sz) ? len : sz; | |||
if (op->do_hex) { | if (op->do_hex) { | |||
hex2stdout(b, len, 0); | hex2stdout(b, len, 0); | |||
return 0; | return 0; | |||
} | } | |||
printf(" PQual=%d Device_type=%d RMB=%d LU_CONG=%d version=0x%02x ", | printf(" PQual=%d PDT=%d RMB=%d LU_CONG=%d hot_pluggable=%d " | |||
pqual, b[0] & 0x1f, !!(b[1] & 0x80), !!(b[1] & 0x40), | "version=0x%02x ", pqual, b[0] & 0x1f, !!(b[1] & 0x80), | |||
(unsigned int)b[2]); | !!(b[1] & 0x40), (b[1] >> 4) & 0x3, (unsigned int)b[2]); | |||
printf(" [%s]\n", sg_ansi_version_arr[b[2] & 0xf]); | printf(" [%s]\n", sg_ansi_version_arr[b[2] & 0xf]); | |||
printf(" [AERC=%d] [TrmTsk=%d] NormACA=%d HiSUP=%d " | printf(" [AERC=%d] [TrmTsk=%d] NormACA=%d HiSUP=%d " | |||
" Resp_data_format=%d\n SCCS=%d ", | " Resp_data_format=%d\n SCCS=%d ", | |||
!!(b[3] & 0x80), !!(b[3] & 0x40), !!(b[3] & 0x20), | !!(b[3] & 0x80), !!(b[3] & 0x40), !!(b[3] & 0x20), | |||
!!(b[3] & 0x10), b[3] & 0x0f, !!(b[5] & 0x80)); | !!(b[3] & 0x10), b[3] & 0x0f, !!(b[5] & 0x80)); | |||
printf("ACC=%d TPGS=%d 3PC=%d Protect=%d ", | printf("ACC=%d TPGS=%d 3PC=%d Protect=%d ", | |||
!!(b[5] & 0x40), ((b[5] & 0x30) >> 4), !!(b[5] & 0x08), | !!(b[5] & 0x40), ((b[5] & 0x30) >> 4), !!(b[5] & 0x08), | |||
!!(b[5] & 0x01)); | !!(b[5] & 0x01)); | |||
printf(" [BQue=%d]\n EncServ=%d ", !!(b[6] & 0x80), !!(b[6] & 0x40)); | printf(" [BQue=%d]\n EncServ=%d ", !!(b[6] & 0x80), !!(b[6] & 0x40)); | |||
if (b[6] & 0x10) | if (b[6] & 0x10) | |||
skipping to change at line 2755 | skipping to change at line 2832 | |||
hex2stdout(b, len + 4, 0); | hex2stdout(b, len + 4, 0); | |||
if (ret) | if (ret) | |||
goto fini; | goto fini; | |||
break; | break; | |||
case 0xb7: /* VPD page depends on pdt */ | case 0xb7: /* VPD page depends on pdt */ | |||
if (b[1] != pn) | if (b[1] != pn) | |||
goto dumb_inq; | goto dumb_inq; | |||
len = sg_get_unaligned_be16(b + 2); | len = sg_get_unaligned_be16(b + 2); | |||
switch (pdt) { | switch (pdt) { | |||
case PDT_DISK: case PDT_WO: case PDT_OPTICAL: case PDT_ZBC: | case PDT_DISK: case PDT_WO: case PDT_OPTICAL: case PDT_ZBC: | |||
vpd_name = "Block limits extension"; | vpd_name = "Block limits extension (SBC)"; | |||
sbc = true; | sbc = true; | |||
break; | break; | |||
default: | default: | |||
vpd_name = "unexpected pdt for B7h"; | vpd_name = "unexpected pdt for B7h"; | |||
break; | break; | |||
} | } | |||
if (op->do_long) | if (op->do_long) | |||
printf("%s [0xb7] VPD page:\n", vpd_name); | printf("%s [0xb7] VPD page:\n", vpd_name); | |||
else | else | |||
printf("%s VPD page:\n", vpd_name); | printf("%s VPD page:\n", vpd_name); | |||
skipping to change at line 2778 | skipping to change at line 2855 | |||
goto fini; | goto fini; | |||
} | } | |||
ret = 0; | ret = 0; | |||
if (sbc) /* added in sbc4r07 */ | if (sbc) /* added in sbc4r07 */ | |||
ret = decode_block_limits_ext_vpd(b, len + 4); | ret = decode_block_limits_ext_vpd(b, len + 4); | |||
else | else | |||
hex2stdout(b, len + 4, 0); | hex2stdout(b, len + 4, 0); | |||
if (ret) | if (ret) | |||
goto fini; | goto fini; | |||
break; | break; | |||
case 0xb8: /* VPD page depends on pdt */ | ||||
if (b[1] != pn) | ||||
goto dumb_inq; | ||||
len = sg_get_unaligned_be16(b + 2); | ||||
switch (pdt) { | ||||
case PDT_DISK: case PDT_WO: case PDT_OPTICAL: case PDT_ZBC: | ||||
vpd_name = "Format presets (SBC)"; | ||||
sbc = true; | ||||
break; | ||||
default: | ||||
vpd_name = "unexpected pdt for B8h"; | ||||
break; | ||||
} | ||||
if (op->do_long) | ||||
printf("%s [0xb8] VPD page:\n", vpd_name); | ||||
else | ||||
printf("%s VPD page:\n", vpd_name); | ||||
if (op->do_hex) { | ||||
hex2stdout(b, len + 4, hex_format); | ||||
goto fini; | ||||
} | ||||
ret = 0; | ||||
if (sbc) /* added in sbc4r18 */ | ||||
ret = decode_format_presets_vpd(b, len + 4); | ||||
else | ||||
hex2stdout(b, len + 4, 0); | ||||
if (ret) | ||||
goto fini; | ||||
break; | ||||
case 0xb9: /* VPD page depends on pdt */ | ||||
if (b[1] != pn) | ||||
goto dumb_inq; | ||||
len = sg_get_unaligned_be16(b + 2); | ||||
switch (pdt) { | ||||
case PDT_DISK: case PDT_WO: case PDT_OPTICAL: case PDT_ZBC: | ||||
vpd_name = "Concurrent positioning ranges (SBC)"; | ||||
sbc = true; | ||||
break; | ||||
default: | ||||
vpd_name = "unexpected pdt for B9h"; | ||||
break; | ||||
} | ||||
if (op->do_long) | ||||
printf("%s [0xb9] VPD page:\n", vpd_name); | ||||
else | ||||
printf("%s VPD page:\n", vpd_name); | ||||
if (op->do_hex) { | ||||
hex2stdout(b, len + 4, hex_format); | ||||
goto fini; | ||||
} | ||||
ret = 0; | ||||
if (sbc) | ||||
ret = decode_con_pos_range_vpd(b, len + 4); | ||||
else | ||||
hex2stdout(b, len + 4, 0); | ||||
if (ret) | ||||
goto fini; | ||||
break; | ||||
default: | default: | |||
if (b[1] != pn) | if (b[1] != pn) | |||
goto dumb_inq; | goto dumb_inq; | |||
len = sg_get_unaligned_be16(b + 2) + 4; | len = sg_get_unaligned_be16(b + 2) + 4; | |||
vpp = sdp_get_vpd_detail(pn, -1, pdt); | vpp = sdp_get_vpd_detail(pn, -1, pdt); | |||
if (vpp) | if (vpp) | |||
snprintf(c, sizeof(c), "%s VPD page", vpp->name); | snprintf(c, sizeof(c), "%s VPD page", vpp->name); | |||
else | else | |||
snprintf(c, sizeof(c), "VPD page 0x%x", pn); | snprintf(c, sizeof(c), "VPD page 0x%x", pn); | |||
if (op->do_hex) | if (op->do_hex) | |||
End of changes. 8 change blocks. | ||||
6 lines changed or deleted | 141 lines changed or added |