diff options
Diffstat (limited to 'utils/imxtools/scsitools/stmp_scsi.c')
-rw-r--r-- | utils/imxtools/scsitools/stmp_scsi.c | 616 |
1 files changed, 616 insertions, 0 deletions
diff --git a/utils/imxtools/scsitools/stmp_scsi.c b/utils/imxtools/scsitools/stmp_scsi.c new file mode 100644 index 0000000000..dcda91e295 --- /dev/null +++ b/utils/imxtools/scsitools/stmp_scsi.c | |||
@@ -0,0 +1,616 @@ | |||
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 <stdlib.h> | ||
22 | #include <string.h> | ||
23 | #include <stdarg.h> | ||
24 | #include <stdio.h> | ||
25 | #define _BSD_SOURCE | ||
26 | #include <endian.h> | ||
27 | #include "stmp_scsi.h" | ||
28 | |||
29 | #define MIN(a, b) ((a) < (b) ? (a) : (b)) | ||
30 | |||
31 | static int g_endian = -1; | ||
32 | |||
33 | struct stmp_device_t | ||
34 | { | ||
35 | rb_scsi_device_t dev; | ||
36 | unsigned flags; | ||
37 | void *user; | ||
38 | stmp_printf_t printf; | ||
39 | }; | ||
40 | |||
41 | static inline int little_endian(void) | ||
42 | { | ||
43 | if(g_endian == -1) | ||
44 | { | ||
45 | int i = 1; | ||
46 | g_endian = (int)*((unsigned char *)&i) == 1; | ||
47 | } | ||
48 | return g_endian; | ||
49 | } | ||
50 | |||
51 | uint16_t stmp_fix_endian16be(uint16_t w) | ||
52 | { | ||
53 | return little_endian() ? w << 8 | w >> 8 : w; | ||
54 | } | ||
55 | |||
56 | uint32_t stmp_fix_endian32be(uint32_t w) | ||
57 | { | ||
58 | return !little_endian() ? w : | ||
59 | (uint32_t)stmp_fix_endian16be(w) << 16 | stmp_fix_endian16be(w >> 16); | ||
60 | } | ||
61 | |||
62 | uint64_t stmp_fix_endian64be(uint64_t w) | ||
63 | { | ||
64 | return !little_endian() ? w : | ||
65 | (uint64_t)stmp_fix_endian32be(w) << 32 | stmp_fix_endian32be(w >> 32); | ||
66 | } | ||
67 | |||
68 | static void misc_std_printf(void *user, const char *fmt, ...) | ||
69 | { | ||
70 | (void) user; | ||
71 | va_list args; | ||
72 | va_start(args, fmt); | ||
73 | vprintf(fmt, args); | ||
74 | va_end(args); | ||
75 | } | ||
76 | |||
77 | #define stmp_printf(dev, ...) \ | ||
78 | dev->printf(dev->user, __VA_ARGS__) | ||
79 | |||
80 | #define stmp_debugf(dev, ...) \ | ||
81 | do{ if(dev->flags & STMP_DEBUG) stmp_printf(dev, __VA_ARGS__); }while(0) | ||
82 | |||
83 | stmp_device_t stmp_open(rb_scsi_device_t rdev, unsigned flags, void *user, stmp_printf_t printf) | ||
84 | { | ||
85 | if(printf == NULL) | ||
86 | printf = misc_std_printf; | ||
87 | stmp_device_t sdev = malloc(sizeof(struct stmp_device_t)); | ||
88 | memset(sdev, 0, sizeof(struct stmp_device_t)); | ||
89 | sdev->dev = rdev; | ||
90 | sdev->flags = flags; | ||
91 | sdev->user = user; | ||
92 | sdev->printf = printf; | ||
93 | return sdev; | ||
94 | } | ||
95 | |||
96 | void stmp_close(stmp_device_t dev) | ||
97 | { | ||
98 | free(dev); | ||
99 | } | ||
100 | |||
101 | /* returns <0 on error and status otherwise */ | ||
102 | int stmp_scsi(stmp_device_t dev, uint8_t *cdb, int cdb_size, unsigned flags, | ||
103 | void *sense, int *sense_size, void *buffer, int *buf_size) | ||
104 | { | ||
105 | struct rb_scsi_raw_cmd_t cmd; | ||
106 | memset(&cmd, 0, sizeof(cmd)); | ||
107 | cmd.dir = RB_SCSI_NONE; | ||
108 | if(flags & STMP_READ) | ||
109 | cmd.dir = RB_SCSI_READ; | ||
110 | if(flags & STMP_WRITE) | ||
111 | cmd.dir = RB_SCSI_WRITE; | ||
112 | cmd.cdb = cdb; | ||
113 | cmd.cdb_len = cdb_size; | ||
114 | cmd.sense = sense; | ||
115 | cmd.sense_len = *sense_size; | ||
116 | cmd.buf = buffer; | ||
117 | cmd.buf_len = *buf_size; | ||
118 | cmd.tmo = 1; | ||
119 | int ret = rb_scsi_raw_xfer(dev->dev, &cmd); | ||
120 | *sense_size = cmd.sense_len; | ||
121 | *buf_size = cmd.buf_len; | ||
122 | return ret == RB_SCSI_OK || ret == RB_SCSI_SENSE ? cmd.status : -ret; | ||
123 | } | ||
124 | |||
125 | int stmp_sense_analysis(stmp_device_t dev, int status, uint8_t *sense, int sense_size) | ||
126 | { | ||
127 | if(status != 0 && (dev->flags & STMP_DEBUG)) | ||
128 | { | ||
129 | stmp_printf(dev, "Status: %d\n", status); | ||
130 | stmp_printf(dev, "Sense:"); | ||
131 | for(int i = 0; i < sense_size; i++) | ||
132 | stmp_printf(dev, " %02x", sense[i]); | ||
133 | stmp_printf(dev, "\n"); | ||
134 | } | ||
135 | return status; | ||
136 | } | ||
137 | |||
138 | static int stmp_scsi_read_cmd(stmp_device_t dev, uint8_t cmd, uint8_t subcmd, | ||
139 | uint8_t subsubcmd, void *buf, int *len) | ||
140 | { | ||
141 | uint8_t cdb[16]; | ||
142 | memset(cdb, 0, sizeof(cdb)); | ||
143 | cdb[0] = SCSI_STMP_READ; | ||
144 | cdb[1] = cmd; | ||
145 | cdb[2] = subcmd; | ||
146 | cdb[3] = subsubcmd; | ||
147 | |||
148 | uint8_t sense[32]; | ||
149 | int sense_size = sizeof(sense); | ||
150 | |||
151 | int ret = stmp_scsi(dev, cdb, sizeof(cdb), STMP_READ, sense, &sense_size, buf, len); | ||
152 | if(ret < 0) | ||
153 | return ret; | ||
154 | ret = stmp_sense_analysis(dev, ret, sense, sense_size); | ||
155 | if(ret) | ||
156 | return ret; | ||
157 | return 0; | ||
158 | } | ||
159 | |||
160 | int stmp_scsi_inquiry(stmp_device_t dev, uint8_t *dev_type, char vendor[9], char product[17]) | ||
161 | { | ||
162 | unsigned char buffer[36]; | ||
163 | uint8_t cdb[10]; | ||
164 | memset(cdb, 0, sizeof(cdb)); | ||
165 | cdb[0] = 0x12; | ||
166 | cdb[4] = sizeof(buffer); | ||
167 | |||
168 | uint8_t sense[32]; | ||
169 | int sense_size = sizeof(sense); | ||
170 | |||
171 | int buf_sz = sizeof(buffer); | ||
172 | int ret = stmp_scsi(dev, cdb, sizeof(cdb), STMP_READ, sense, &sense_size, buffer, &buf_sz); | ||
173 | if(ret < 0) | ||
174 | return ret; | ||
175 | ret = stmp_sense_analysis(dev, ret, sense, sense_size); | ||
176 | if(ret) | ||
177 | return ret; | ||
178 | if(buf_sz != sizeof(buffer)) | ||
179 | return -1; | ||
180 | *dev_type = buffer[0]; | ||
181 | memcpy(vendor, buffer + 8, 8); | ||
182 | vendor[8] = 0; | ||
183 | memcpy(product, buffer + 16, 16); | ||
184 | product[16] = 0; | ||
185 | return 0; | ||
186 | } | ||
187 | |||
188 | int stmp_scsi_get_protocol_version(stmp_device_t dev, void *buf, int *len) | ||
189 | { | ||
190 | return stmp_scsi_read_cmd(dev, SCSI_STMP_CMD_GET_PROTOCOL_VERSION, 0, 0, buf, len); | ||
191 | } | ||
192 | |||
193 | int stmp_get_protocol_version(stmp_device_t dev, struct scsi_stmp_protocol_version_t *ver) | ||
194 | { | ||
195 | int len = sizeof(*ver); | ||
196 | int ret = stmp_scsi_get_protocol_version(dev, ver, &len); | ||
197 | if(ret || len != sizeof(*ver)) | ||
198 | return -1; | ||
199 | return 0; | ||
200 | } | ||
201 | |||
202 | int stmp_scsi_get_chip_major_rev_id(stmp_device_t dev, void *buf, int *len) | ||
203 | { | ||
204 | return stmp_scsi_read_cmd(dev, SCSI_STMP_CMD_GET_CHIP_MAJOR_REV_ID, 0, 0, buf, len); | ||
205 | } | ||
206 | |||
207 | int stmp_get_chip_major_rev_id(stmp_device_t dev, uint16_t *ver) | ||
208 | { | ||
209 | int len = sizeof(*ver); | ||
210 | int ret = stmp_scsi_get_chip_major_rev_id(dev, ver, &len); | ||
211 | if(ret || len != sizeof(*ver)) | ||
212 | return -1; | ||
213 | *ver = stmp_fix_endian16be(*ver); | ||
214 | return 0; | ||
215 | } | ||
216 | |||
217 | int stmp_scsi_get_rom_rev_id(stmp_device_t dev, void *buf, int *len) | ||
218 | { | ||
219 | return stmp_scsi_read_cmd(dev, SCSI_STMP_CMD_GET_ROM_REV_ID, 0, 0, buf, len); | ||
220 | } | ||
221 | |||
222 | int stmp_get_rom_rev_id(stmp_device_t dev, uint16_t *ver) | ||
223 | { | ||
224 | int len = sizeof(*ver); | ||
225 | int ret = stmp_scsi_get_rom_rev_id(dev, ver, &len); | ||
226 | if(ret || len != sizeof(*ver)) | ||
227 | return -1; | ||
228 | *ver = stmp_fix_endian16be(*ver); | ||
229 | return 0; | ||
230 | } | ||
231 | |||
232 | int stmp_scsi_get_logical_media_info(stmp_device_t dev, uint8_t info, void *data, int *len) | ||
233 | { | ||
234 | return stmp_scsi_read_cmd(dev, SCSI_STMP_CMD_GET_LOGICAL_MEDIA_INFO, info, 0, data, len); | ||
235 | } | ||
236 | |||
237 | int stmp_scsi_get_logical_table(stmp_device_t dev, int entry_count, void *buf, int *len) | ||
238 | { | ||
239 | return stmp_scsi_read_cmd(dev, SCSI_STMP_CMD_GET_LOGICAL_TABLE, entry_count, 0, buf, len); | ||
240 | } | ||
241 | |||
242 | int stmp_get_logical_media_table(stmp_device_t dev, struct stmp_logical_media_table_t **table) | ||
243 | { | ||
244 | struct scsi_stmp_logical_table_header_t header; | ||
245 | int len = sizeof(header); | ||
246 | int ret = stmp_scsi_get_logical_table(dev, 0, &header, &len); | ||
247 | if(ret || len != sizeof(header)) | ||
248 | return -1; | ||
249 | header.count = stmp_fix_endian16be(header.count); | ||
250 | int sz = sizeof(header) + header.count * sizeof(struct scsi_stmp_logical_table_entry_t); | ||
251 | len = sz; | ||
252 | *table = malloc(sz); | ||
253 | ret = stmp_scsi_get_logical_table(dev, header.count, &(*table)->header, &len); | ||
254 | if(ret || len != sz) | ||
255 | return -1; | ||
256 | (*table)->header.count = stmp_fix_endian16be((*table)->header.count); | ||
257 | for(unsigned i = 0; i < (*table)->header.count; i++) | ||
258 | (*table)->entry[i].size = stmp_fix_endian64be((*table)->entry[i].size); | ||
259 | return 0; | ||
260 | } | ||
261 | |||
262 | int stmp_scsi_get_logical_drive_info(stmp_device_t dev, uint8_t drive, uint8_t info, void *data, int *len) | ||
263 | { | ||
264 | return stmp_scsi_read_cmd(dev, SCSI_STMP_CMD_GET_LOGICAL_DRIVE_INFO, drive, info, data, len); | ||
265 | } | ||
266 | |||
267 | int stmp_scsi_get_device_info(stmp_device_t dev, uint8_t info, void *data, int *len) | ||
268 | { | ||
269 | return stmp_scsi_read_cmd(dev, SCSI_STMP_CMD_GET_DEVICE_INFO, info, 0, data, len); | ||
270 | } | ||
271 | |||
272 | int stmp_scsi_get_serial_number(stmp_device_t dev, uint8_t info, void *data, int *len) | ||
273 | { | ||
274 | return stmp_scsi_read_cmd(dev, SCSI_STMP_CMD_GET_CHIP_SERIAL_NUMBER, info, 0, data, len); | ||
275 | } | ||
276 | |||
277 | int stmp_scsi_read_logical_drive_sectors(stmp_device_t dev, uint8_t drive, uint64_t address, | ||
278 | uint32_t count, void *buffer, int *buffer_size) | ||
279 | { | ||
280 | uint8_t cdb[16]; | ||
281 | memset(cdb, 0, sizeof(cdb)); | ||
282 | cdb[0] = SCSI_STMP_READ; | ||
283 | cdb[1] = SCSI_STMP_CMD_READ_LOGICAL_DRIVE_SECTOR; | ||
284 | cdb[2] = drive; | ||
285 | address = stmp_fix_endian64be(address); | ||
286 | memcpy(&cdb[3], &address, sizeof(address)); | ||
287 | count = stmp_fix_endian32be(count); | ||
288 | memcpy(&cdb[11], &count, sizeof(count)); | ||
289 | |||
290 | uint8_t sense[32]; | ||
291 | int sense_size = sizeof(sense); | ||
292 | |||
293 | int ret = stmp_scsi(dev, cdb, sizeof(cdb), STMP_READ, sense, &sense_size, buffer, buffer_size); | ||
294 | if(ret < 0) | ||
295 | return ret; | ||
296 | return stmp_sense_analysis(dev, ret, sense, sense_size); | ||
297 | } | ||
298 | |||
299 | int stmp_scsi_write_logical_drive_sectors(stmp_device_t dev, uint8_t drive, uint64_t address, | ||
300 | uint32_t count, void *buffer, int *buffer_size) | ||
301 | { | ||
302 | uint8_t cdb[16]; | ||
303 | memset(cdb, 0, sizeof(cdb)); | ||
304 | cdb[0] = SCSI_STMP_WRITE; | ||
305 | cdb[1] = SCSI_STMP_CMD_WRITE_LOGICAL_DRIVE_SECTOR; | ||
306 | cdb[2] = drive; | ||
307 | address = stmp_fix_endian64be(address); | ||
308 | memcpy(&cdb[3], &address, sizeof(address)); | ||
309 | count = stmp_fix_endian32be(count); | ||
310 | memcpy(&cdb[11], &count, sizeof(count)); | ||
311 | |||
312 | uint8_t sense[32]; | ||
313 | int sense_size = sizeof(sense); | ||
314 | |||
315 | int ret = stmp_scsi(dev, cdb, sizeof(cdb), STMP_WRITE, sense, &sense_size, buffer, buffer_size); | ||
316 | if(ret < 0) | ||
317 | return ret; | ||
318 | return stmp_sense_analysis(dev, ret, sense, sense_size); | ||
319 | } | ||
320 | |||
321 | int stmp_read_logical_drive_sectors(stmp_device_t dev, uint8_t drive, uint64_t address, | ||
322 | uint32_t count, void *buffer, int buffer_size) | ||
323 | { | ||
324 | int len = buffer_size; | ||
325 | int ret = stmp_scsi_read_logical_drive_sectors(dev, drive, address, count, buffer, &len); | ||
326 | if(ret || len != buffer_size) | ||
327 | return -1; | ||
328 | return 0; | ||
329 | } | ||
330 | |||
331 | int stmp_write_logical_drive_sectors(stmp_device_t dev, uint8_t drive, uint64_t address, | ||
332 | uint32_t count, void *buffer, int buffer_size) | ||
333 | { | ||
334 | int len = buffer_size; | ||
335 | int ret = stmp_scsi_write_logical_drive_sectors(dev, drive, address, count, buffer, &len); | ||
336 | if(ret || len != buffer_size) | ||
337 | return -1; | ||
338 | return 0; | ||
339 | } | ||
340 | |||
341 | #define check_len(l) if(len != l) return -1; | ||
342 | #define fixn(n, p) *(uint##n##_t *)(p) = stmp_fix_endian##n##be(*(uint##n##_t *)(p)) | ||
343 | #define fix16(p) fixn(16, p) | ||
344 | #define fix32(p) fixn(32, p) | ||
345 | #define fix64(p) fixn(64, p) | ||
346 | |||
347 | int stmp_fix_logical_media_info(uint8_t info, void *data, int len) | ||
348 | { | ||
349 | switch(info) | ||
350 | { | ||
351 | case SCSI_STMP_MEDIA_INFO_NR_DRIVES: | ||
352 | check_len(2); | ||
353 | fix16(data); | ||
354 | return 0; | ||
355 | case SCSI_STMP_MEDIA_INFO_TYPE: | ||
356 | case SCSI_STMP_MEDIA_INFO_SERIAL_NUMBER_SIZE: | ||
357 | case SCSI_STMP_MEDIA_INFO_VENDOR: | ||
358 | case SCSI_STMP_MEDIA_INFO_ALLOC_UNIT_SIZE: | ||
359 | case SCSI_STMP_MEDIA_INFO_PAGE_SIZE: | ||
360 | case SCSI_STMP_MEDIA_INFO_NR_DEVICES: | ||
361 | check_len(4); | ||
362 | fix32(data); | ||
363 | return 0; | ||
364 | case SCSI_STMP_MEDIA_INFO_SIZE: | ||
365 | case SCSI_STMP_MEDIA_INFO_NAND_ID: | ||
366 | check_len(8); | ||
367 | fix64(data); | ||
368 | return 0; | ||
369 | case SCSI_STMP_MEDIA_INFO_IS_INITIALISED: | ||
370 | case SCSI_STMP_MEDIA_INFO_STATE: | ||
371 | case SCSI_STMP_MEDIA_INFO_IS_WRITE_PROTECTED: | ||
372 | case SCSI_STMP_MEDIA_INFO_IS_SYSTEM_MEDIA: | ||
373 | case SCSI_STMP_MEDIA_INFO_IS_MEDIA_PRESENT: | ||
374 | check_len(1); | ||
375 | return 0; | ||
376 | case SCSI_STMP_MEDIA_INFO_SERIAL_NUMBER: | ||
377 | return 0; | ||
378 | default: | ||
379 | return -1; | ||
380 | } | ||
381 | } | ||
382 | |||
383 | static void stmp_fix_version(struct scsi_stmp_logical_drive_info_version_t *w) | ||
384 | { | ||
385 | w->major = stmp_fix_endian16be(w->major); | ||
386 | w->minor = stmp_fix_endian16be(w->minor); | ||
387 | w->revision = stmp_fix_endian16be(w->revision); | ||
388 | } | ||
389 | |||
390 | int stmp_fix_logical_drive_info(uint8_t info, void *data, int len) | ||
391 | { | ||
392 | switch(info) | ||
393 | { | ||
394 | case SCSI_STMP_DRIVE_INFO_SERIAL_NUMBER_SIZE: | ||
395 | check_len(2); | ||
396 | fix16(data); | ||
397 | return 0; | ||
398 | case SCSI_STMP_DRIVE_INFO_SECTOR_SIZE: | ||
399 | case SCSI_STMP_DRIVE_INFO_ERASE_SIZE: | ||
400 | case SCSI_STMP_DRIVE_INFO_SIZE_MEGA: | ||
401 | case SCSI_STMP_DRIVE_INFO_TYPE: | ||
402 | case SCSI_STMP_DRIVE_INFO_SECTOR_ALLOCATION: | ||
403 | check_len(4); | ||
404 | fix32(data); | ||
405 | return 0; | ||
406 | case SCSI_STMP_DRIVE_INFO_SIZE: | ||
407 | case SCSI_STMP_DRIVE_INFO_SECTOR_COUNT: | ||
408 | check_len(8); | ||
409 | fix64(data); | ||
410 | return 0; | ||
411 | case SCSI_STMP_DRIVE_INFO_TAG: | ||
412 | case SCSI_STMP_DRIVE_INFO_IS_WRITE_PROTETED: | ||
413 | case SCSI_STMP_DRIVE_INFO_MEDIA_PRESENT: | ||
414 | case SCSI_STMP_DRIVE_INFO_MEDIA_CHANGE: | ||
415 | check_len(1); | ||
416 | return 0; | ||
417 | case SCSI_STMP_DRIVE_INFO_COMPONENT_VERSION: | ||
418 | case SCSI_STMP_DRIVE_INFO_PROJECT_VERSION: | ||
419 | check_len(6) | ||
420 | stmp_fix_version(data); | ||
421 | return 0; | ||
422 | case SCSI_STMP_DRIVE_INFO_SERIAL_NUMBER: | ||
423 | return 0; | ||
424 | default: | ||
425 | return -1; | ||
426 | } | ||
427 | } | ||
428 | |||
429 | int stmp_fix_device_info(uint8_t info, void *data, int len) | ||
430 | { | ||
431 | switch(info) | ||
432 | { | ||
433 | case 0: case 1: | ||
434 | check_len(4); | ||
435 | fix32(data); | ||
436 | return 0; | ||
437 | default: | ||
438 | return -1; | ||
439 | } | ||
440 | } | ||
441 | #undef fix64 | ||
442 | #undef fix32 | ||
443 | #undef fix16 | ||
444 | #undef fixn | ||
445 | #undef checl_len | ||
446 | |||
447 | const char *stmp_get_logical_media_type_string(uint32_t type) | ||
448 | { | ||
449 | switch(type) | ||
450 | { | ||
451 | case SCSI_STMP_MEDIA_TYPE_NAND: return "NAND"; | ||
452 | case SCSI_STMP_MEDIA_TYPE_SDMMC: return "SD/MMC"; | ||
453 | case SCSI_STMP_MEDIA_TYPE_HDD: return "HDD"; | ||
454 | case SCSI_STMP_MEDIA_TYPE_RAM: return "RAM"; | ||
455 | case SCSI_STMP_MEDIA_TYPE_iNAND: return "iNAND"; | ||
456 | default: return "?"; | ||
457 | } | ||
458 | } | ||
459 | |||
460 | const char *stmp_get_logical_media_vendor_string(uint32_t type) | ||
461 | { | ||
462 | switch(type) | ||
463 | { | ||
464 | case SCSI_STMP_MEDIA_VENDOR_SAMSUNG: return "Samsung"; | ||
465 | case SCSI_STMP_MEDIA_VENDOR_STMICRO: return "ST Micro"; | ||
466 | case SCSI_STMP_MEDIA_VENDOR_HYNIX: return "Hynix"; | ||
467 | case SCSI_STMP_MEDIA_VENDOR_MICRON: return "Micron"; | ||
468 | case SCSI_STMP_MEDIA_VENDOR_TOSHIBA: return "Toshiba"; | ||
469 | case SCSI_STMP_MEDIA_VENDOR_RENESAS: return "Renesas"; | ||
470 | case SCSI_STMP_MEDIA_VENDOR_INTEL: return "Intel"; | ||
471 | case SCSI_STMP_MEDIA_VENDOR_SANDISK: return "Sandisk"; | ||
472 | default: return "?"; | ||
473 | } | ||
474 | } | ||
475 | |||
476 | const char *stmp_get_logical_drive_type_string(uint32_t type) | ||
477 | { | ||
478 | switch(type) | ||
479 | { | ||
480 | case SCSI_STMP_DRIVE_TYPE_DATA: return "Data"; | ||
481 | case SCSI_STMP_DRIVE_TYPE_SYSTEM: return "System"; | ||
482 | case SCSI_STMP_DRIVE_TYPE_HIDDEN: return "Hidden"; | ||
483 | case SCSI_STMP_DRIVE_TYPE_UNKNOWN: return "Unknown"; | ||
484 | default: return "?"; | ||
485 | } | ||
486 | } | ||
487 | |||
488 | const char *stmp_get_logical_drive_tag_string(uint32_t type) | ||
489 | { | ||
490 | switch(type) | ||
491 | { | ||
492 | case SCSI_STMP_DRIVE_TAG_STMPSYS_S: return "System"; | ||
493 | case SCSI_STMP_DRIVE_TAG_HOSTLINK_S: return "Hostlink"; | ||
494 | case SCSI_STMP_DRIVE_TAG_RESOURCE_BIN: return "Resource"; | ||
495 | case SCSI_STMP_DRIVE_TAG_EXTRA_S: return "Extra"; | ||
496 | case SCSI_STMP_DRIVE_TAG_RESOURCE1_BIN: return "Resource1"; | ||
497 | case SCSI_STMP_DRIVE_TAG_OTGHOST_S: return "OTG"; | ||
498 | case SCSI_STMP_DRIVE_TAG_HOSTRSC_BIN: return "Host Resource"; | ||
499 | case SCSI_STMP_DRIVE_TAG_DATA: return "Data"; | ||
500 | case SCSI_STMP_DRIVE_TAG_HIDDEN: return "Hidden"; | ||
501 | case SCSI_STMP_DRIVE_TAG_BOOTMANAGER_S: return "Boot"; | ||
502 | case SCSI_STMP_DRIVE_TAG_UPDATER_S: return "Updater"; | ||
503 | default: return "?"; | ||
504 | } | ||
505 | } | ||
506 | |||
507 | const char *stmp_get_logical_media_state_string(uint8_t state) | ||
508 | { | ||
509 | switch(state) | ||
510 | { | ||
511 | case SCSI_STMP_MEDIA_STATE_UNKNOWN: return "Unknown"; | ||
512 | case SCSI_STMP_MEDIA_STATE_ERASED: return "Erased"; | ||
513 | case SCSI_STMP_MEDIA_STATE_ALLOCATED: return "Allocated"; | ||
514 | default: return "?"; | ||
515 | } | ||
516 | } | ||
517 | |||
518 | int stmp_get_device_serial(stmp_device_t dev, uint8_t **buffer, int *len) | ||
519 | { | ||
520 | *len = 2; | ||
521 | uint16_t len16; | ||
522 | int ret = stmp_scsi_get_serial_number(dev, 0, &len16, len); | ||
523 | if(!ret && *len == 2) | ||
524 | { | ||
525 | len16 = stmp_fix_endian16be(len16); | ||
526 | *len = len16; | ||
527 | *buffer = malloc(*len); | ||
528 | ret = stmp_scsi_get_serial_number(dev, 1, *buffer, len); | ||
529 | } | ||
530 | else | ||
531 | ret = -1; | ||
532 | return ret; | ||
533 | } | ||
534 | |||
535 | #define ARRAYLEN(x) (int)(sizeof(x)/sizeof((x)[0])) | ||
536 | |||
537 | int stmp_get_logical_media_info(stmp_device_t dev, struct stmp_logical_media_info_t *info) | ||
538 | { | ||
539 | memset(info, 0, sizeof(struct stmp_logical_media_info_t)); | ||
540 | int len, ret; | ||
541 | #define entry(name, def) \ | ||
542 | len = sizeof(info->name); \ | ||
543 | ret = stmp_scsi_get_logical_media_info(dev, SCSI_STMP_MEDIA_INFO_##def, &info->name, &len); \ | ||
544 | if(!ret) \ | ||
545 | ret = stmp_fix_logical_media_info(SCSI_STMP_MEDIA_INFO_##def, &info->name, len); \ | ||
546 | if(!ret) \ | ||
547 | info->has.name = true; | ||
548 | |||
549 | entry(nr_drives, NR_DRIVES); | ||
550 | entry(size, SIZE); | ||
551 | entry(alloc_size, ALLOC_UNIT_SIZE); | ||
552 | entry(initialised, IS_INITIALISED); | ||
553 | entry(state, STATE); | ||
554 | entry(write_protected, IS_WRITE_PROTECTED); | ||
555 | entry(type, TYPE); | ||
556 | entry(serial_len, SERIAL_NUMBER_SIZE); | ||
557 | entry(system, IS_SYSTEM_MEDIA); | ||
558 | entry(present, IS_MEDIA_PRESENT); | ||
559 | entry(page_size, PAGE_SIZE); | ||
560 | entry(vendor, VENDOR); | ||
561 | entry(nand_id, NAND_ID); | ||
562 | entry(nr_devices, NR_DEVICES); | ||
563 | #undef entry | ||
564 | if(info->has.serial_len) | ||
565 | { | ||
566 | info->serial = malloc(info->serial_len); | ||
567 | int len = info->serial_len; | ||
568 | ret = stmp_scsi_get_logical_media_info(dev, SCSI_STMP_MEDIA_INFO_SERIAL_NUMBER, | ||
569 | info->serial, &len); | ||
570 | if(ret || len != (int)info->serial_len) | ||
571 | free(info->serial); | ||
572 | else | ||
573 | info->has.serial = true; | ||
574 | } | ||
575 | return 0; | ||
576 | } | ||
577 | |||
578 | int stmp_get_logical_drive_info(stmp_device_t dev, uint8_t drive, struct stmp_logical_drive_info_t *info) | ||
579 | { | ||
580 | memset(info, 0, sizeof(struct stmp_logical_drive_info_t)); | ||
581 | int len, ret; | ||
582 | #define entry(name, def) \ | ||
583 | len = sizeof(info->name); \ | ||
584 | ret = stmp_scsi_get_logical_drive_info(dev, drive, SCSI_STMP_DRIVE_INFO_##def, &info->name, &len); \ | ||
585 | if(!ret) \ | ||
586 | ret = stmp_fix_logical_drive_info(SCSI_STMP_DRIVE_INFO_##def, &info->name, len); \ | ||
587 | if(!ret) \ | ||
588 | info->has.name = true; | ||
589 | |||
590 | entry(sector_size, SECTOR_SIZE); | ||
591 | entry(erase_size, ERASE_SIZE); | ||
592 | entry(size, SIZE); | ||
593 | entry(sector_count, SECTOR_COUNT); | ||
594 | entry(type, TYPE); | ||
595 | entry(tag, TAG); | ||
596 | entry(component_version, COMPONENT_VERSION); | ||
597 | entry(project_version, PROJECT_VERSION); | ||
598 | entry(write_protected, IS_WRITE_PROTECTED); | ||
599 | entry(serial_len, SERIAL_NUMBER_SIZE); | ||
600 | entry(present, MEDIA_PRESENT); | ||
601 | entry(change, MEDIA_CHANGE); | ||
602 | entry(sector_alloc, SECTOR_ALLOCATION); | ||
603 | #undef entry | ||
604 | if(info->has.serial_len) | ||
605 | { | ||
606 | info->serial = malloc(info->serial_len); | ||
607 | int len = info->serial_len; | ||
608 | ret = stmp_scsi_get_logical_media_info(dev, SCSI_STMP_DRIVE_INFO_SERIAL_NUMBER, | ||
609 | info->serial, &len); | ||
610 | if(ret || len != (int)info->serial_len) | ||
611 | free(info->serial); | ||
612 | else | ||
613 | info->has.serial = true; | ||
614 | } | ||
615 | return 0; | ||
616 | } | ||