summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--utils/nwztools/scsitools/scsitool.c140
1 files changed, 138 insertions, 2 deletions
diff --git a/utils/nwztools/scsitools/scsitool.c b/utils/nwztools/scsitools/scsitool.c
index c85eb75f9a..7c18a46daa 100644
--- a/utils/nwztools/scsitools/scsitool.c
+++ b/utils/nwztools/scsitools/scsitool.c
@@ -989,6 +989,7 @@ static void usage(void)
989{ 989{
990 printf("Usage:\n"); 990 printf("Usage:\n");
991 printf(" scsitool [options] list_devices\n"); 991 printf(" scsitool [options] list_devices\n");
992 printf(" scsitool [options] decode_scsi <cdb>\n");
992 printf(" scsitool [options] <dev> <command> [arguments]\n"); 993 printf(" scsitool [options] <dev> <command> [arguments]\n");
993 printf("Options:\n"); 994 printf("Options:\n");
994 printf(" -o <prefix> Set output prefix\n"); 995 printf(" -o <prefix> Set output prefix\n");
@@ -1067,6 +1068,139 @@ static int list_devices(bool list_all)
1067 return 0; 1068 return 0;
1068} 1069}
1069 1070
1071inline uint8_t xdigit2val(char c)
1072{
1073 if('0' <= c && c <= '9')
1074 return c - '0';
1075 else if('a' <= c && c <= 'f')
1076 return c - 'a' + 10;
1077 else if('A' <= c && c <= 'F')
1078 return c - 'A' + 10;
1079 else
1080 return 255;
1081}
1082
1083static int decode_scsi_a3(uint8_t *cdb, int cdb_len)
1084{
1085 cprintf_field("Opcode: ", "A3\n");
1086 cprintf(RED, "Unimplemented\n");
1087 return 0;
1088}
1089
1090static int decode_scsi_a4(uint8_t *cdb, int cdb_len)
1091{
1092 cprintf_field("Opcode: ", "A3\n");
1093 cprintf(RED, "Unimplemented\n");
1094 return 0;
1095}
1096
1097static int decode_scsi_empr_dpcc(uint8_t *cdb, int cdb_len)
1098{
1099 cprintf_field("Opcode: ", "%X (EMPR DPCC)\n", cdb[0]);
1100 cprintf(RED, "Unimplemented\n");
1101 return 0;
1102}
1103
1104static int decode_scsi_dnk(uint8_t *cdb, int cdb_len)
1105{
1106 cprintf_field("Opcode: ", "%X (DNK)\n", cdb[0]);
1107 cprintf(RED, "Unimplemented\n");
1108 return 0;
1109}
1110
1111static int decode_scsi_dpcc(uint8_t *cdb, int cdb_len)
1112{
1113 cprintf_field("Opcode: ", "%X (DPCC)\n", cdb[0]);
1114 cprintf(RED, "Unimplemented\n");
1115 return 0;
1116}
1117
1118static int decode_scsi_fc(uint8_t *cdb, int cdb_len)
1119{
1120 cprintf_field("Opcode: ", "FC\n");
1121 if(cdb[3] == 'd' && cdb[4] == 'b' && cdb[5] == 'm' && cdb[6] == 'n')
1122 {
1123 uint8_t cmd = cdb[2];
1124 uint8_t flags = cdb[8];
1125 const char *cmd_name = "Unknown";
1126 if(cmd == 0x04)
1127 cmd_name = "Firmware Upgrade";
1128 if(cmd == 0x20)
1129 cmd_name = "Get Device Info";
1130
1131 cprintf(BLUE, "Device request:\n");
1132 cprintf_field(" Command: ", "%x (%s)\n", cmd, cmd_name);
1133 cprintf_field(" Flags(?): ", "%x (Unknown)\n", flags);
1134
1135 }
1136 return 0;
1137}
1138
1139static int decode_scsi(int argc, char **argv)
1140{
1141 /* we need to parse the arguments, we support either as one big hexdump:
1142 * fc002064626d6e0080000000
1143 * or as a sequence of hex bytes:
1144 * fc 00 20 64 62 6d 6e 00 80 00 00 00
1145 */
1146 if(argc == 0)
1147 {
1148 cprintf(GREY, "You need to specify the CDB to decode\n");
1149 return 1;
1150 }
1151#define MAX_CDB 16
1152 uint8_t cdb[MAX_CDB];
1153 int cdb_len;
1154 if(argc > MAX_CDB)
1155 {
1156 cprintf(GREY, "This does not look like a CDB (more than %d bytes)\n", MAX_CDB);
1157 return 1;
1158 }
1159 if(argc == 1)
1160 {
1161 /* allow the string to start with 0x */
1162 char *str = argv[0];
1163 if(str[0] == '0' && str[1] == 'x')
1164 str += 2;
1165 cdb_len = strlen(str);
1166 if(cdb_len % 2)
1167 {
1168 cprintf(GREY, "The CDB must contain an even number of hex digits!\n");
1169 return 1;
1170 }
1171 cdb_len /= 2;
1172 for(int i = 0; i < cdb_len; i++)
1173 {
1174 if(!isxdigit(str[2 * i]) || !isxdigit(str[2 * i + 1]))
1175 {
1176 cprintf(GREY, "The CDB must contain hex digits!\n");
1177 return 1;
1178 }
1179 cdb[i] = xdigit2val(str[2 * i]) << 4 | xdigit2val(str[2 * i + 1]);
1180 }
1181 }
1182 else
1183 {
1184 cprintf(GREY, "unimplemented\n");
1185 return 1;
1186 }
1187 cprintf(GREEN, "CDB: ");
1188 print_hex(cdb, cdb_len);
1189
1190 if(cdb[0] == CMD_A3) return decode_scsi_a3(cdb, cdb_len);
1191 if(cdb[0] == CMD_A4) return decode_scsi_a4(cdb, cdb_len);
1192 if(cdb[0] == CMD_EMPR_DPCC) return decode_scsi_empr_dpcc(cdb, cdb_len);
1193 if(cdb[0] == CMD_DNK) return decode_scsi_dnk(cdb, cdb_len);
1194 if(cdb[0] == CMD_DPCC) return decode_scsi_dpcc(cdb, cdb_len);
1195 if(cdb[0] == 0xfc) return decode_scsi_fc(cdb, cdb_len);
1196 else
1197 {
1198 cprintf(RED, "I cannot decode this SCSI command\n");
1199 }
1200
1201 return 0;
1202}
1203
1070int main(int argc, char **argv) 1204int main(int argc, char **argv)
1071{ 1205{
1072 bool list_all = false; 1206 bool list_all = false;
@@ -1130,9 +1264,11 @@ int main(int argc, char **argv)
1130 return 0; 1264 return 0;
1131 } 1265 }
1132 1266
1133 /* special list_devices command */ 1267 /* special list_devices/decode_scsi command */
1134 if(argc == optind + 1 && strcmp(argv[optind], "list_devices") == 0) 1268 if(argc >= optind + 1 && strcmp(argv[optind], "list_devices") == 0)
1135 return list_devices(list_all); 1269 return list_devices(list_all);
1270 if(argc >= optind + 1 && strcmp(argv[optind], "decode_scsi") == 0)
1271 return decode_scsi(argc - optind - 1, argv + optind + 1);
1136 1272
1137 if(argc - optind < 2) 1273 if(argc - optind < 2)
1138 { 1274 {