summaryrefslogtreecommitdiff
path: root/utils
diff options
context:
space:
mode:
Diffstat (limited to 'utils')
-rw-r--r--utils/imxtools/scsitools/Makefile20
-rw-r--r--utils/imxtools/scsitools/misc.c53
-rw-r--r--utils/imxtools/scsitools/misc.h50
-rw-r--r--utils/imxtools/scsitools/scsitool.c310
-rw-r--r--utils/imxtools/scsitools/stmp_scsi.h42
5 files changed, 475 insertions, 0 deletions
diff --git a/utils/imxtools/scsitools/Makefile b/utils/imxtools/scsitools/Makefile
new file mode 100644
index 0000000000..ed4bc88d0b
--- /dev/null
+++ b/utils/imxtools/scsitools/Makefile
@@ -0,0 +1,20 @@
1DEFINES=
2CC=gcc
3LD=gcc
4CFLAGS=-g -std=c99 -W -Wall $(DEFINES)
5LDFLAGS=-lsgutils2
6BINS=scsitool
7
8all: $(BINS)
9
10%.o: %.c
11 $(CC) $(CFLAGS) -c -o $@ $<
12
13scsitool: scsitool.o misc.o
14 $(LD) -o $@ $^ $(LDFLAGS)
15
16clean:
17 rm -fr *.o
18
19veryclean:
20 rm -rf $(BINS)
diff --git a/utils/imxtools/scsitools/misc.c b/utils/imxtools/scsitools/misc.c
new file mode 100644
index 0000000000..108235e7fd
--- /dev/null
+++ b/utils/imxtools/scsitools/misc.c
@@ -0,0 +1,53 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2010 Amaury Pouly
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21#include <stdlib.h>
22#include <stdio.h>
23#include <time.h>
24#include <ctype.h>
25#include "misc.h"
26
27char OFF[] = { 0x1b, 0x5b, 0x31, 0x3b, '0', '0', 0x6d, '\0' };
28
29char GREY[] = { 0x1b, 0x5b, 0x31, 0x3b, '3', '0', 0x6d, '\0' };
30char RED[] = { 0x1b, 0x5b, 0x31, 0x3b, '3', '1', 0x6d, '\0' };
31char GREEN[] = { 0x1b, 0x5b, 0x31, 0x3b, '3', '2', 0x6d, '\0' };
32char YELLOW[] = { 0x1b, 0x5b, 0x31, 0x3b, '3', '3', 0x6d, '\0' };
33char BLUE[] = { 0x1b, 0x5b, 0x31, 0x3b, '3', '4', 0x6d, '\0' };
34
35static bool g_color_enable = true;
36
37void *xmalloc(size_t s)
38{
39 void * r = malloc(s);
40 if(!r) bugp("malloc");
41 return r;
42}
43
44void enable_color(bool enable)
45{
46 g_color_enable = enable;
47}
48
49void color(color_t c)
50{
51 if(g_color_enable)
52 printf("%s", (char *)c);
53}
diff --git a/utils/imxtools/scsitools/misc.h b/utils/imxtools/scsitools/misc.h
new file mode 100644
index 0000000000..035b0ef8c1
--- /dev/null
+++ b/utils/imxtools/scsitools/misc.h
@@ -0,0 +1,50 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2010 Amaury Pouly
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21#ifndef __MISC_H__
22#define __MISC_H__
23
24#include <stdbool.h>
25#include <stdio.h>
26
27#define _STR(a) #a
28#define STR(a) _STR(a)
29
30#define bug(...) do { fprintf(stderr,"["__FILE__":"STR(__LINE__)"]ERROR: "__VA_ARGS__); exit(1); } while(0)
31#define bugp(...) do { fprintf(stderr, __VA_ARGS__); perror(" "); exit(1); } while(0)
32
33#define ROUND_UP(val, round) ((((val) + (round) - 1) / (round)) * (round))
34
35typedef char color_t[];
36
37extern color_t OFF, GREY, RED, GREEN, YELLOW, BLUE;
38void *xmalloc(size_t s);
39void color(color_t c);
40void enable_color(bool enable);
41
42#ifndef MIN
43#define MIN(a,b) ((a) < (b) ? (a) : (b))
44#endif
45
46#define cprintf(col, ...) do {color(col); printf(__VA_ARGS__); }while(0)
47
48#define cprintf_field(str1, ...) do{ cprintf(GREEN, str1); cprintf(YELLOW, __VA_ARGS__); }while(0)
49
50#endif /* __MISC_H__ */
diff --git a/utils/imxtools/scsitools/scsitool.c b/utils/imxtools/scsitools/scsitool.c
new file mode 100644
index 0000000000..7fc68f8c37
--- /dev/null
+++ b/utils/imxtools/scsitools/scsitool.c
@@ -0,0 +1,310 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2012 Amaury Pouly
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21#include <stdio.h>
22#include <stdint.h>
23#include <stdbool.h>
24#include <stdlib.h>
25#include <stddef.h>
26#include <string.h>
27#include <getopt.h>
28#include <stdarg.h>
29#include <ctype.h>
30#include <sys/types.h>
31#include <sys/stat.h>
32#include <fcntl.h>
33#include <unistd.h>
34#include <scsi/scsi.h>
35#include <scsi/sg_lib.h>
36#include <scsi/sg_pt.h>
37#include "misc.h"
38#include "stmp_scsi.h"
39
40bool g_debug = false;
41bool g_force = false;
42int g_dev_fd = 0;
43
44#define let_the_force_flow(x) do { if(!g_force) return x; } while(0)
45#define continue_the_force(x) if(x) let_the_force_flow(x)
46
47#define check_field(v_exp, v_have, str_ok, str_bad) \
48 if((v_exp) != (v_have)) \
49 { cprintf(RED, str_bad); let_the_force_flow(__LINE__); } \
50 else { cprintf(RED, str_ok); }
51
52#define errorf(...) do { cprintf(GREY, __VA_ARGS__); return __LINE__; } while(0)
53
54#if 0
55void *buffer_alloc(int sz)
56{
57#ifdef SG_LIB_MINGW
58 unsigned psz = getpagesize();
59#else
60 unsigned psz = sysconf(_SC_PAGESIZE); /* was getpagesize() */
61#endif
62 void *buffer = malloc(sz + psz);
63 return (void *)(((ptrdiff_t)(buffer + psz - 1)) & ~(psz - 1));
64}
65#else
66void *buffer_alloc(int sz)
67{
68 return malloc(sz);
69}
70#endif
71
72static void print_hex(void *_buffer, int buffer_size)
73{
74 uint8_t *buffer = _buffer;
75 for(int i = 0; i < buffer_size; i += 16)
76 {
77 for(int j = 0; j < 16; j++)
78 {
79 if(i + j < buffer_size)
80 cprintf(YELLOW, " %02x", buffer[i + j]);
81 else
82 cprintf(YELLOW, " ");
83 }
84 printf(" ");
85 for(int j = 0; j < 16; j++)
86 {
87 if(i + j < buffer_size)
88 cprintf(RED, "%c", isprint(buffer[i + j]) ? buffer[i + j] : '.');
89 else
90 cprintf(RED, " ");
91 }
92 printf("\n");
93 }
94}
95
96/* Do read */
97#define DO_READ (1 << 1)
98/* Do write */
99#define DO_WRITE (1 << 2)
100
101/* returns <0 on error and status otherwise */
102int do_scsi(uint8_t *cdb, int cdb_size, unsigned flags, void *sense, int *sense_size, void *buffer, int *buf_size)
103{
104 char error[256];
105 struct sg_pt_base *obj = construct_scsi_pt_obj();
106 if(obj == NULL)
107 {
108 cprintf(GREY, "construct_scsi_pt_obj failed\n");
109 return 1;
110 }
111 set_scsi_pt_cdb(obj, cdb, cdb_size);
112 if(sense)
113 set_scsi_pt_sense(obj, sense, *sense_size);
114 if(flags & DO_READ)
115 set_scsi_pt_data_in(obj, buffer, *buf_size);
116 if(flags & DO_WRITE)
117 set_scsi_pt_data_out(obj, buffer, *buf_size);
118 int ret = do_scsi_pt(obj, g_dev_fd, 1, 0);
119 switch(get_scsi_pt_result_category(obj))
120 {
121 case SCSI_PT_RESULT_SENSE:
122 case SCSI_PT_RESULT_GOOD:
123 ret = get_scsi_pt_status_response(obj);
124 break;
125 case SCSI_PT_RESULT_STATUS:
126 cprintf(GREY, "Status error: %d (", get_scsi_pt_status_response(obj));
127 sg_print_scsi_status(get_scsi_pt_status_response(obj));
128 printf(")\n");
129 break;
130 case SCSI_PT_RESULT_TRANSPORT_ERR:
131 cprintf(GREY, "Transport error: %s\n", get_scsi_pt_transport_err_str(obj, 256, error));
132 ret = -2;
133 break;
134 case SCSI_PT_RESULT_OS_ERR:
135 cprintf(GREY, "OS error: %s\n", get_scsi_pt_os_err_str(obj, 256, error));
136 ret = -3;
137 break;
138 default:
139 cprintf(GREY, "Unknown error\n");
140 break;
141 }
142
143 if(sense)
144 *sense_size = get_scsi_pt_sense_len(obj);
145 if(flags & (DO_WRITE | DO_READ))
146 *buf_size -= get_scsi_pt_resid(obj);
147
148 destruct_scsi_pt_obj(obj);
149 return ret;
150}
151
152int do_sense_analysis(int status, uint8_t *sense, int sense_size)
153{
154 if(status != GOOD || g_debug)
155 {
156 cprintf_field("Status:", " "); fflush(stdout);
157 sg_print_scsi_status(status);
158 cprintf_field("\nSense:", " "); fflush(stdout);
159 sg_print_sense(NULL, sense, sense_size, 0);
160 }
161 if(status == GOOD)
162 return 0;
163 return status;
164}
165
166int stmp_inquiry(uint8_t *dev_type, char vendor[9], char product[17])
167{
168 unsigned char buffer[56];
169 uint8_t cdb[10];
170 memset(cdb, 0, sizeof(cdb));
171 cdb[0] = 0x12;
172 cdb[4] = sizeof(buffer);
173
174 uint8_t sense[32];
175 int sense_size = sizeof(sense);
176
177 int buf_sz = sizeof(buffer);
178 int ret = do_scsi(cdb, sizeof(cdb), DO_READ, sense, &sense_size, buffer, &buf_sz);
179 if(ret < 0)
180 return ret;
181 ret = do_sense_analysis(ret, sense, sense_size);
182 if(ret)
183 return ret;
184 if(buf_sz != sizeof(buffer))
185 return -1;
186 *dev_type = buffer[0];
187 memcpy(vendor, buffer + 8, 8);
188 vendor[8] = 0;
189 memcpy(product, buffer + 16, 16);
190 product[16] = 0;
191 return 0;
192}
193
194static int stmp_get_protocol_version(struct scsi_stmp_protocol_version_t *ver)
195{
196 uint8_t cdb[10];
197 memset(cdb, 0, sizeof(cdb));
198 cdb[0] = SCSI_STMP_READ;
199 cdb[1] = SCSI_STMP_CMD_GET_PROTOCOL_VERSION;
200
201 uint8_t sense[32];
202 int sense_size = sizeof(sense);
203
204 int buf_sz = sizeof(struct scsi_stmp_protocol_version_t);
205 int ret = do_scsi(cdb, sizeof(cdb), DO_READ, sense, &sense_size, ver, &buf_sz);
206 if(ret < 0)
207 return ret;
208 ret = do_sense_analysis(ret, sense, sense_size);
209 if(ret)
210 return ret;
211 if(buf_sz != sizeof(struct scsi_stmp_protocol_version_t))
212 return -1;
213 return 0;
214}
215
216static int do_work(void)
217{
218 cprintf(BLUE, "Information\n");
219
220 uint8_t dev_type;
221 char vendor[9];
222 char product[17];
223 int ret = stmp_inquiry(&dev_type, vendor, product);
224 if(ret)
225 errorf("Cannot get inquiry data: %d\n", ret);
226 cprintf_field(" Vendor: ", "%s\n", vendor);
227 cprintf_field(" Product: ", "%s\n", product);
228
229 struct scsi_stmp_protocol_version_t ver;
230 ret = stmp_get_protocol_version(&ver);
231 if(ret)
232 errorf("Cannot get protocol version: %d\n", ret);
233
234 cprintf_field(" Protocol: ", "%x.%x\n", ver.major, ver.minor);
235
236 return 0;
237}
238
239static void usage(void)
240{
241 printf("Usage: scsitool [options] <dev>\n");
242 printf("Options:\n");
243 printf(" -f/--force\tForce to continue on errors\n");
244 printf(" -?/--help\tDisplay this message\n");
245 printf(" -d/--debug\tDisplay debug messages\n");
246 printf(" -c/--no-color\tDisable color output\n");
247 exit(1);
248}
249
250int main(int argc, char **argv)
251{
252 while(1)
253 {
254 static struct option long_options[] =
255 {
256 {"help", no_argument, 0, '?'},
257 {"debug", no_argument, 0, 'd'},
258 {"no-color", no_argument, 0, 'c'},
259 {"force", no_argument, 0, 'f'},
260 {0, 0, 0, 0}
261 };
262
263 int c = getopt_long(argc, argv, "?dcf", long_options, NULL);
264 if(c == -1)
265 break;
266 switch(c)
267 {
268 case -1:
269 break;
270 case 'c':
271 enable_color(false);
272 break;
273 case 'd':
274 g_debug = true;
275 break;
276 case 'f':
277 g_force = true;
278 break;
279 case '?':
280 usage();
281 break;
282 default:
283 abort();
284 }
285 }
286
287 if(argc - optind != 1)
288 {
289 usage();
290 return 1;
291 }
292
293 int ret = 0;
294 g_dev_fd = scsi_pt_open_device(argv[optind], false, true);
295 if(g_dev_fd < 0)
296 {
297 cprintf(GREY, "Cannot open device: %m\n");
298 ret = 1;
299 goto Lend;
300 }
301
302 do_work();
303
304 scsi_pt_close_device(g_dev_fd);
305Lend:
306 color(OFF);
307
308 return ret;
309}
310
diff --git a/utils/imxtools/scsitools/stmp_scsi.h b/utils/imxtools/scsitools/stmp_scsi.h
new file mode 100644
index 0000000000..14f651f6dd
--- /dev/null
+++ b/utils/imxtools/scsitools/stmp_scsi.h
@@ -0,0 +1,42 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2012 Amaury Pouly
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21#ifndef __STMP_SCSI__
22#define __STMP_SCSI__
23
24#include <stdint.h>
25
26#define SCSI_STMP_READ 0xc0
27#define SCSI_STMP_WRITE 0xc1
28/** STMP: Command */
29#define SCSI_STMP_CMD_GET_PROTOCOL_VERSION 0
30#define SCSI_STMP_CMD_GET_LOGICAL_MEDIA_INFO 2
31#define SCSI_STMP_CMD_GET_LOGICAL_TABLE 5
32#define SCSI_STMP_CMD_GET_LOGICAL_DRIVE_INFO 0x12
33#define SCSI_STMP_CMD_GET_CHIP_MAJOR_REV_ID 0x30
34#define SCSI_STMP_CMD_GET_ROM_REV_ID 0x37
35
36struct scsi_stmp_protocol_version_t
37{
38 uint8_t major;
39 uint8_t minor;
40} __attribute__((packed));
41
42#endif /* __STMP_SCSI__ */