summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAmaury Pouly <amaury.pouly@gmail.com>2017-01-04 00:26:52 +0100
committerAmaury Pouly <amaury.pouly@gmail.com>2017-01-07 15:52:33 +0100
commit7fafbe1fc13bec744d1fcc70ba431fa77472680a (patch)
tree51e41b48e59f5f5e49dc3c051241eff09bac22d0
parent0fd869423ab3456288fcd323cff3206f37363153 (diff)
downloadrockbox-7fafbe1fc13bec744d1fcc70ba431fa77472680a.tar.gz
rockbox-7fafbe1fc13bec744d1fcc70ba431fa77472680a.zip
imxtools/scsitools: rework stmp scsi API
Sanitize the whole library by hiding most of the horrible details of the implementation. This means that all logical/drive/table attributes are exported in structures that are internally filled by higher-level API functions. This makes the code much more readable and prepares for a split between scsitool and the stmp scsi library. Change-Id: Id85d450b25cf99cd7c0896c6fc35bcd00babe9e1
-rw-r--r--utils/imxtools/scsitools/scsitool.c810
-rw-r--r--utils/imxtools/scsitools/stmp_scsi.h169
2 files changed, 604 insertions, 375 deletions
diff --git a/utils/imxtools/scsitools/scsitool.c b/utils/imxtools/scsitools/scsitool.c
index 86956d0910..a1f1b7a2ba 100644
--- a/utils/imxtools/scsitools/scsitool.c
+++ b/utils/imxtools/scsitools/scsitool.c
@@ -47,19 +47,32 @@ struct stmp_device_t
47 stmp_printf_t printf; 47 stmp_printf_t printf;
48}; 48};
49 49
50static uint16_t fix_endian16be(uint16_t w) 50static inline int little_endian(void)
51{ 51{
52 return w << 8 | w >> 8; 52 static int g_endian = -1;
53 if(g_endian == -1)
54 {
55 int i = 1;
56 g_endian = (int)*((unsigned char *)&i) == 1;
57 }
58 return g_endian;
59}
60
61uint16_t stmp_fix_endian16be(uint16_t w)
62{
63 return little_endian() ? w << 8 | w >> 8 : w;
53} 64}
54 65
55static uint32_t fix_endian32be(uint32_t w) 66uint32_t stmp_fix_endian32be(uint32_t w)
56{ 67{
57 return __builtin_bswap32(w); 68 return !little_endian() ? w :
69 (uint32_t)stmp_fix_endian16be(w) << 16 | stmp_fix_endian16be(w >> 16);
58} 70}
59 71
60static uint64_t fix_endian64be(uint64_t w) 72uint64_t stmp_fix_endian64be(uint64_t w)
61{ 73{
62 return __builtin_bswap64(w); 74 return !little_endian() ? w :
75 (uint64_t)stmp_fix_endian32be(w) << 32 | stmp_fix_endian32be(w >> 32);
63} 76}
64 77
65static void print_hex(void *_buffer, int buffer_size) 78static void print_hex(void *_buffer, int buffer_size)
@@ -84,6 +97,8 @@ static void print_hex(void *_buffer, int buffer_size)
84 } 97 }
85 printf("\n"); 98 printf("\n");
86 } 99 }
100 if(buffer_size == 0)
101 printf("\n");
87} 102}
88 103
89static void misc_std_printf(void *user, const char *fmt, ...) 104static void misc_std_printf(void *user, const char *fmt, ...)
@@ -231,7 +246,7 @@ int stmp_get_chip_major_rev_id(stmp_device_t dev, uint16_t *ver)
231 int ret = stmp_scsi_get_chip_major_rev_id(dev, ver, &len); 246 int ret = stmp_scsi_get_chip_major_rev_id(dev, ver, &len);
232 if(ret || len != sizeof(*ver)) 247 if(ret || len != sizeof(*ver))
233 return -1; 248 return -1;
234 *ver = fix_endian16be(*ver); 249 *ver = stmp_fix_endian16be(*ver);
235 return 0; 250 return 0;
236} 251}
237 252
@@ -246,7 +261,7 @@ int stmp_get_rom_rev_id(stmp_device_t dev, uint16_t *ver)
246 int ret = stmp_scsi_get_rom_rev_id(dev, ver, &len); 261 int ret = stmp_scsi_get_rom_rev_id(dev, ver, &len);
247 if(ret || len != sizeof(*ver)) 262 if(ret || len != sizeof(*ver))
248 return -1; 263 return -1;
249 *ver = fix_endian16be(*ver); 264 *ver = stmp_fix_endian16be(*ver);
250 return 0; 265 return 0;
251} 266}
252 267
@@ -260,19 +275,23 @@ int stmp_scsi_get_logical_table(stmp_device_t dev, int entry_count, void *buf, i
260 return stmp_scsi_read_cmd(dev, SCSI_STMP_CMD_GET_LOGICAL_TABLE, entry_count, 0, buf, len); 275 return stmp_scsi_read_cmd(dev, SCSI_STMP_CMD_GET_LOGICAL_TABLE, entry_count, 0, buf, len);
261} 276}
262 277
263int stmp_get_logical_table(stmp_device_t dev, struct scsi_stmp_logical_table_t *table, int entry_count) 278int stmp_get_logical_media_table(stmp_device_t dev, struct stmp_logical_media_table_t **table)
264{ 279{
265 int buf_sz = sizeof(struct scsi_stmp_logical_table_t) + 280 struct scsi_stmp_logical_table_header_t header;
266 entry_count * sizeof(struct scsi_stmp_logical_table_entry_t); 281 int len = sizeof(header);
267 int ret = stmp_scsi_get_logical_table(dev, entry_count, table, &buf_sz); 282 int ret = stmp_scsi_get_logical_table(dev, 0, &header, &len);
268 if(ret != 0) 283 if(ret || len != sizeof(header))
269 return ret; 284 return -1;
270 if((buf_sz - sizeof(struct scsi_stmp_logical_table_t)) % sizeof(struct scsi_stmp_logical_table_entry_t)) 285 header.count = stmp_fix_endian16be(header.count);
286 int sz = sizeof(header) + header.count * sizeof(struct scsi_stmp_logical_table_entry_t);
287 len = sz;
288 *table = malloc(sz);
289 ret = stmp_scsi_get_logical_table(dev, header.count, &(*table)->header, &len);
290 if(ret || len != sz)
271 return -1; 291 return -1;
272 table->count = fix_endian16be(table->count); 292 (*table)->header.count = stmp_fix_endian16be((*table)->header.count);
273 struct scsi_stmp_logical_table_entry_t *entry = (void *)(table + 1); 293 for(unsigned i = 0; i < (*table)->header.count; i++)
274 for(int i = 0; i < entry_count; i++) 294 (*table)->entry[i].size = stmp_fix_endian64be((*table)->entry[i].size);
275 entry[i].size = fix_endian64be(entry[i].size);
276 return 0; 295 return 0;
277} 296}
278 297
@@ -299,9 +318,9 @@ int stmp_scsi_read_logical_drive_sectors(stmp_device_t dev, uint8_t drive, uint6
299 cdb[0] = SCSI_STMP_READ; 318 cdb[0] = SCSI_STMP_READ;
300 cdb[1] = SCSI_STMP_CMD_READ_LOGICAL_DRIVE_SECTOR; 319 cdb[1] = SCSI_STMP_CMD_READ_LOGICAL_DRIVE_SECTOR;
301 cdb[2] = drive; 320 cdb[2] = drive;
302 address = fix_endian64be(address); 321 address = stmp_fix_endian64be(address);
303 memcpy(&cdb[3], &address, sizeof(address)); 322 memcpy(&cdb[3], &address, sizeof(address));
304 count = fix_endian32be(count); 323 count = stmp_fix_endian32be(count);
305 memcpy(&cdb[11], &count, sizeof(count)); 324 memcpy(&cdb[11], &count, sizeof(count));
306 325
307 uint8_t sense[32]; 326 uint8_t sense[32];
@@ -321,9 +340,9 @@ int stmp_scsi_write_logical_drive_sectors(stmp_device_t dev, uint8_t drive, uint
321 cdb[0] = SCSI_STMP_WRITE; 340 cdb[0] = SCSI_STMP_WRITE;
322 cdb[1] = SCSI_STMP_CMD_WRITE_LOGICAL_DRIVE_SECTOR; 341 cdb[1] = SCSI_STMP_CMD_WRITE_LOGICAL_DRIVE_SECTOR;
323 cdb[2] = drive; 342 cdb[2] = drive;
324 address = fix_endian64be(address); 343 address = stmp_fix_endian64be(address);
325 memcpy(&cdb[3], &address, sizeof(address)); 344 memcpy(&cdb[3], &address, sizeof(address));
326 count = fix_endian32be(count); 345 count = stmp_fix_endian32be(count);
327 memcpy(&cdb[11], &count, sizeof(count)); 346 memcpy(&cdb[11], &count, sizeof(count));
328 347
329 uint8_t sense[32]; 348 uint8_t sense[32];
@@ -335,7 +354,133 @@ int stmp_scsi_write_logical_drive_sectors(stmp_device_t dev, uint8_t drive, uint
335 return stmp_sense_analysis(dev, ret, sense, sense_size); 354 return stmp_sense_analysis(dev, ret, sense, sense_size);
336} 355}
337 356
338static const char *stmp_get_logical_media_type_string(uint32_t type) 357int stmp_read_logical_drive_sectors(stmp_device_t dev, uint8_t drive, uint64_t address,
358 uint32_t count, void *buffer, int buffer_size)
359{
360 int len = buffer_size;
361 int ret = stmp_scsi_read_logical_drive_sectors(dev, drive, address, count, buffer, &len);
362 if(ret || len != buffer_size)
363 return -1;
364 return 0;
365}
366
367int stmp_write_logical_drive_sectors(stmp_device_t dev, uint8_t drive, uint64_t address,
368 uint32_t count, void *buffer, int buffer_size)
369{
370 int len = buffer_size;
371 int ret = stmp_scsi_write_logical_drive_sectors(dev, drive, address, count, buffer, &len);
372 if(ret || len != buffer_size)
373 return -1;
374 return 0;
375}
376
377#define check_len(l) if(len != l) return -1;
378#define fixn(n, p) *(uint##n##_t *)(p) = stmp_fix_endian##n##be(*(uint##n##_t *)(p))
379#define fix16(p) fixn(16, p)
380#define fix32(p) fixn(32, p)
381#define fix64(p) fixn(64, p)
382
383int stmp_fix_logical_media_info(uint8_t info, void *data, int len)
384{
385 switch(info)
386 {
387 case SCSI_STMP_MEDIA_INFO_NR_DRIVES:
388 check_len(2);
389 fix16(data);
390 return 0;
391 case SCSI_STMP_MEDIA_INFO_TYPE:
392 case SCSI_STMP_MEDIA_INFO_SERIAL_NUMBER_SIZE:
393 case SCSI_STMP_MEDIA_INFO_VENDOR:
394 case SCSI_STMP_MEDIA_INFO_ALLOC_UNIT_SIZE:
395 case SCSI_STMP_MEDIA_INFO_PAGE_SIZE:
396 case SCSI_STMP_MEDIA_INFO_NR_DEVICES:
397 check_len(4);
398 fix32(data);
399 return 0;
400 case SCSI_STMP_MEDIA_INFO_SIZE:
401 case SCSI_STMP_MEDIA_INFO_NAND_ID:
402 check_len(8);
403 fix64(data);
404 return 0;
405 case SCSI_STMP_MEDIA_INFO_IS_INITIALISED:
406 case SCSI_STMP_MEDIA_INFO_STATE:
407 case SCSI_STMP_MEDIA_INFO_IS_WRITE_PROTECTED:
408 case SCSI_STMP_MEDIA_INFO_IS_SYSTEM_MEDIA:
409 case SCSI_STMP_MEDIA_INFO_IS_MEDIA_PRESENT:
410 check_len(1);
411 return 0;
412 case SCSI_STMP_MEDIA_INFO_SERIAL_NUMBER:
413 return 0;
414 default:
415 return -1;
416 }
417}
418
419static void stmp_fix_version(struct scsi_stmp_logical_drive_info_version_t *w)
420{
421 w->major = stmp_fix_endian16be(w->major);
422 w->minor = stmp_fix_endian16be(w->minor);
423 w->revision = stmp_fix_endian16be(w->revision);
424}
425
426int stmp_fix_logical_drive_info(uint8_t info, void *data, int len)
427{
428 switch(info)
429 {
430 case SCSI_STMP_DRIVE_INFO_SERIAL_NUMBER_SIZE:
431 check_len(2);
432 fix16(data);
433 return 0;
434 case SCSI_STMP_DRIVE_INFO_SECTOR_SIZE:
435 case SCSI_STMP_DRIVE_INFO_ERASE_SIZE:
436 case SCSI_STMP_DRIVE_INFO_SIZE_MEGA:
437 case SCSI_STMP_DRIVE_INFO_TYPE:
438 case SCSI_STMP_DRIVE_INFO_SECTOR_ALLOCATION:
439 check_len(4);
440 fix32(data);
441 return 0;
442 case SCSI_STMP_DRIVE_INFO_SIZE:
443 case SCSI_STMP_DRIVE_INFO_SECTOR_COUNT:
444 check_len(8);
445 fix64(data);
446 return 0;
447 case SCSI_STMP_DRIVE_INFO_TAG:
448 case SCSI_STMP_DRIVE_INFO_IS_WRITE_PROTETED:
449 case SCSI_STMP_DRIVE_INFO_MEDIA_PRESENT:
450 case SCSI_STMP_DRIVE_INFO_MEDIA_CHANGE:
451 check_len(1);
452 return 0;
453 case SCSI_STMP_DRIVE_INFO_COMPONENT_VERSION:
454 case SCSI_STMP_DRIVE_INFO_PROJECT_VERSION:
455 check_len(6)
456 stmp_fix_version(data);
457 return 0;
458 case SCSI_STMP_DRIVE_INFO_SERIAL_NUMBER:
459 return 0;
460 default:
461 return -1;
462 }
463}
464
465int stmp_fix_device_info(uint8_t info, void *data, int len)
466{
467 switch(info)
468 {
469 case 0: case 1:
470 check_len(4);
471 fix32(data);
472 return 0;
473 default:
474 return -1;
475 }
476}
477#undef fix64
478#undef fix32
479#undef fix16
480#undef fixn
481#undef checl_len
482
483const char *stmp_get_logical_media_type_string(uint32_t type)
339{ 484{
340 switch(type) 485 switch(type)
341 { 486 {
@@ -406,6 +551,106 @@ const char *stmp_get_logical_media_state_string(uint8_t state)
406 } 551 }
407} 552}
408 553
554int stmp_get_device_serial(stmp_device_t dev, uint8_t **buffer, int *len)
555{
556 *len = 2;
557 uint16_t len16;
558 int ret = stmp_scsi_get_serial_number(dev, 0, &len16, len);
559 if(!ret && *len == 2)
560 {
561 len16 = stmp_fix_endian16be(len16);
562 *len = len16;
563 *buffer = malloc(*len);
564 ret = stmp_scsi_get_serial_number(dev, 1, *buffer, len);
565 }
566 else
567 ret = -1;
568 return ret;
569}
570
571#define ARRAYLEN(x) (int)(sizeof(x)/sizeof((x)[0]))
572
573int stmp_get_logical_media_info(stmp_device_t dev, struct stmp_logical_media_info_t *info)
574{
575 memset(info, 0, sizeof(struct stmp_logical_media_info_t));
576 int len, ret;
577#define entry(name, def) \
578 len = sizeof(info->name); \
579 ret = stmp_scsi_get_logical_media_info(dev, SCSI_STMP_MEDIA_INFO_##def, &info->name, &len); \
580 if(!ret) \
581 ret = stmp_fix_logical_media_info(SCSI_STMP_MEDIA_INFO_##def, &info->name, len); \
582 if(!ret) \
583 info->has.name = true;
584
585 entry(nr_drives, NR_DRIVES);
586 entry(size, SIZE);
587 entry(alloc_size, ALLOC_UNIT_SIZE);
588 entry(initialised, IS_INITIALISED);
589 entry(state, STATE);
590 entry(write_protected, IS_WRITE_PROTECTED);
591 entry(type, TYPE);
592 entry(serial_len, SERIAL_NUMBER_SIZE);
593 entry(system, IS_SYSTEM_MEDIA);
594 entry(present, IS_MEDIA_PRESENT);
595 entry(page_size, PAGE_SIZE);
596 entry(vendor, VENDOR);
597 entry(nand_id, NAND_ID);
598 entry(nr_devices, NR_DEVICES);
599#undef entry
600 if(info->has.serial_len)
601 {
602 info->serial = malloc(info->serial_len);
603 int len = info->serial_len;
604 ret = stmp_scsi_get_logical_media_info(dev, SCSI_STMP_MEDIA_INFO_SERIAL_NUMBER,
605 info->serial, &len);
606 if(ret || len != (int)info->serial_len)
607 free(info->serial);
608 else
609 info->has.serial = true;
610 }
611 return 0;
612}
613
614int stmp_get_logical_drive_info(stmp_device_t dev, uint8_t drive, struct stmp_logical_drive_info_t *info)
615{
616 memset(info, 0, sizeof(struct stmp_logical_drive_info_t));
617 int len, ret;
618#define entry(name, def) \
619 len = sizeof(info->name); \
620 ret = stmp_scsi_get_logical_drive_info(dev, drive, SCSI_STMP_DRIVE_INFO_##def, &info->name, &len); \
621 if(!ret) \
622 ret = stmp_fix_logical_drive_info(SCSI_STMP_DRIVE_INFO_##def, &info->name, len); \
623 if(!ret) \
624 info->has.name = true;
625
626 entry(sector_size, SECTOR_SIZE);
627 entry(erase_size, ERASE_SIZE);
628 entry(size, SIZE);
629 entry(sector_count, SECTOR_COUNT);
630 entry(type, TYPE);
631 entry(tag, TAG);
632 entry(component_version, COMPONENT_VERSION);
633 entry(project_version, PROJECT_VERSION);
634 entry(write_protected, IS_WRITE_PROTECTED);
635 entry(serial_len, SERIAL_NUMBER_SIZE);
636 entry(present, MEDIA_PRESENT);
637 entry(change, MEDIA_CHANGE);
638 entry(sector_alloc, SECTOR_ALLOCATION);
639#undef entry
640 if(info->has.serial_len)
641 {
642 info->serial = malloc(info->serial_len);
643 int len = info->serial_len;
644 ret = stmp_scsi_get_logical_media_info(dev, SCSI_STMP_DRIVE_INFO_SERIAL_NUMBER,
645 info->serial, &len);
646 if(ret || len != (int)info->serial_len)
647 free(info->serial);
648 else
649 info->has.serial = true;
650 }
651 return 0;
652}
653
409static const char *get_size_suffix(unsigned long long size) 654static const char *get_size_suffix(unsigned long long size)
410{ 655{
411 int order = 0; 656 int order = 0;
@@ -426,6 +671,11 @@ static float get_size_natural(unsigned long long size)
426 return res; 671 return res;
427} 672}
428 673
674static void print_ver(struct scsi_stmp_logical_drive_info_version_t *ver)
675{
676 cprintf(YELLOW, "%x.%x.%x\n", ver->major, ver->minor, ver->revision);
677}
678
429static int do_info(void) 679static int do_info(void)
430{ 680{
431 cprintf(BLUE, "Information\n"); 681 cprintf(BLUE, "Information\n");
@@ -439,347 +689,181 @@ static int do_info(void)
439 cprintf_field(" Vendor: ", "%s\n", vendor); 689 cprintf_field(" Vendor: ", "%s\n", vendor);
440 cprintf_field(" Product: ", "%s\n", product); 690 cprintf_field(" Product: ", "%s\n", product);
441 } 691 }
692 else if(g_debug)
693 cprintf(GREY, "Cannot get inquiry data: %d\n", ret);
442 694
443 struct scsi_stmp_protocol_version_t ver; 695 struct scsi_stmp_protocol_version_t ver;
444 ret = stmp_get_protocol_version(g_dev_fd, &ver); 696 ret = stmp_get_protocol_version(g_dev_fd, &ver);
445 if(ret == 0) 697 if(ret == 0)
446 cprintf_field(" Protocol: ", "%x.%x\n", ver.major, ver.minor); 698 cprintf_field(" Protocol: ", "%x.%x\n", ver.major, ver.minor);
699 else if(g_debug)
700 cprintf(GREY, "Cannot get protocol version: %d\n", ret);
447 701
448 do 702 cprintf(BLUE, "Device\n");
449 {
450 union
451 {
452 uint8_t u8;
453 uint16_t u16;
454 uint32_t u32;
455 uint64_t u64;
456 uint8_t buf[1024];
457 }u;
458
459 cprintf(GREEN, " Device\n");
460 int len = 4;
461 ret = stmp_scsi_get_device_info(g_dev_fd, 0, &u.u32, &len);
462 if(!ret && len == 4)
463 {
464 u.u32 = fix_endian32be(u.u32);
465 cprintf_field(" Info 0: ", "%lu\n", (unsigned long)u.u32);
466 }
467
468 len = 4;
469 ret = stmp_scsi_get_device_info(g_dev_fd, 1, &u.u32, &len);
470 if(!ret && len == 4)
471 {
472 u.u32 = fix_endian32be(u.u32);
473 cprintf_field(" Info 1: ", "%lu\n", (unsigned long)u.u32);
474 }
475
476 len = 2;
477 ret = stmp_scsi_get_serial_number(g_dev_fd, 0, &u.u16, &len);
478 if(!ret && len == 2)
479 {
480 u.u16 = fix_endian16be(u.u16);
481 len = MIN(u.u16, sizeof(u.buf));
482 ret = stmp_scsi_get_serial_number(g_dev_fd, 1, u.buf, &len);
483 cprintf_field(" Serial Number:", " ");
484 print_hex(u.buf, len);
485 cprintf(OFF, "\n");
486 }
487
488 len = 2;
489 ret = stmp_scsi_get_logical_media_info(g_dev_fd, SCSI_STMP_MEDIA_INFO_NR_DRIVES, &u.u16, &len);
490 if(!ret && len == 2)
491 {
492 u.u16 = fix_endian16be(u.u16);
493 cprintf_field(" Number of Drives: ", "%d\n", u.u16);
494 }
495 703
496 len = 4; 704 uint8_t *serial;
497 ret = stmp_scsi_get_logical_media_info(g_dev_fd, SCSI_STMP_MEDIA_INFO_TYPE, &u.u32, &len); 705 int serial_len;
498 if(!ret && len == 4) 706 if(!stmp_get_device_serial(g_dev_fd, &serial, &serial_len))
499 { 707 {
500 u.u32 = fix_endian32be(u.u32); 708 cprintf_field(" Serial Number:", " ");
501 cprintf_field(" Media Type: ", "%#x", u.u32); 709 print_hex(serial, serial_len);
502 cprintf(RED, " (%s)\n", stmp_get_logical_media_type_string(u.u32)); 710 free(serial);
503 } 711 }
504
505 len = 1;
506 ret = stmp_scsi_get_logical_media_info(g_dev_fd, SCSI_STMP_MEDIA_INFO_IS_INITIALISED, &u.u8, &len);
507 if(!ret && len == 1)
508 cprintf_field(" Is Initialised: ", "%d\n", u.u8);
509
510 len = 1;
511 ret = stmp_scsi_get_logical_media_info(g_dev_fd, SCSI_STMP_MEDIA_INFO_STATE, &u.u8, &len);
512 if(!ret && len == 1)
513 cprintf_field(" State: ", "%s\n", stmp_get_logical_media_state_string(u.u8));
514 712
515 len = 1; 713 uint16_t chip_rev;
516 ret = stmp_scsi_get_logical_media_info(g_dev_fd, SCSI_STMP_MEDIA_INFO_IS_WRITE_PROTECTED, &u.u8, &len); 714 ret = stmp_get_chip_major_rev_id(g_dev_fd, &chip_rev);
517 if(!ret && len == 1) 715 if(ret)
518 cprintf_field(" Is Write Protected: ", "%#x\n", u.u8); 716 cprintf(GREY, "Cannot get chip major revision id: %d\n", ret);
717 else
718 cprintf_field(" Chip Major Rev ID: ", "%x\n", chip_rev);
519 719
520 len = 8; 720 uint16_t rom_rev;
521 ret = stmp_scsi_get_logical_media_info(g_dev_fd, SCSI_STMP_MEDIA_INFO_SIZE, &u.u64, &len); 721 ret = stmp_get_rom_rev_id(g_dev_fd, &rom_rev);
522 if(!ret && len == 8) 722 if(ret)
523 { 723 cprintf(GREY, "Cannot get rom revision id: %d\n", ret);
524 u.u64 = fix_endian64be(u.u64); 724 else
525 cprintf_field(" Media Size: ", "%llu B (%.3f %s)\n", (unsigned long long)u.u64, 725 cprintf_field(" ROM Rev ID: ", "%x\n", rom_rev);
526 get_size_natural(u.u64), get_size_suffix(u.u64));
527 }
528 726
529 int serial_number_size = 0; 727 cprintf(BLUE, "Logical Media\n");
530 len = 4; 728 struct stmp_logical_media_info_t info;
531 ret = stmp_scsi_get_logical_media_info(g_dev_fd, SCSI_STMP_MEDIA_INFO_SERIAL_NUMBER_SIZE, &u.u32, &len); 729 ret = stmp_get_logical_media_info(g_dev_fd, &info);
532 if(!ret && len == 4) 730 if(!ret)
731 {
732 if(info.has.nr_drives)
733 cprintf_field(" Number of drives:", " %u\n", info.nr_drives);
734 if(info.has.size)
533 { 735 {
534 u.u32 = fix_endian32be(u.u32); 736 cprintf_field(" Media size:", " %llu ", (unsigned long long)info.size);
535 cprintf_field(" Serial Number Size: ", "%d\n", u.u32); 737 cprintf(RED, "(%.3f %s)\n", get_size_natural(info.size), get_size_suffix(info.size));
536 serial_number_size = u.u32;
537 } 738 }
538 739 if(info.has.alloc_size)
539 len = serial_number_size;
540 ret = stmp_scsi_get_logical_media_info(g_dev_fd, SCSI_STMP_MEDIA_INFO_SERIAL_NUMBER, &u.buf, &len);
541 if(!ret && len != 0)
542 { 740 {
543 cprintf(GREEN, " Serial Number:"); 741 cprintf_field(" Allocation unit size:", " %lu ", (unsigned long)info.alloc_size);
544 print_hex(u.buf, len); 742 cprintf(RED, "(%.3f %s)\n", get_size_natural(info.alloc_size), get_size_suffix(info.alloc_size));
545 } 743 }
546 744 if(info.has.initialised)
547 len = 1; 745 cprintf_field(" Initialised:", " %u\n", info.initialised);
548 ret = stmp_scsi_get_logical_media_info(g_dev_fd, SCSI_STMP_MEDIA_INFO_IS_SYSTEM_MEDIA, &u.u8, &len); 746 if(info.has.state)
549 if(!ret && len == 1) 747 cprintf_field(" State:", " %u\n", info.state);
550 cprintf_field(" Is System Media: ", "%d\n", u.u8); 748 if(info.has.write_protected)
551 749 cprintf_field(" Write protected:", " %u\n", info.write_protected);
552 len = 1; 750 if(info.has.type)
553 ret = stmp_scsi_get_logical_media_info(g_dev_fd, SCSI_STMP_MEDIA_INFO_IS_MEDIA_PRESENT, &u.u8, &len);
554 if(!ret && len == 1)
555 cprintf_field(" Is Media Present: ", "%d\n", u.u8);
556
557 len = 4;
558 ret = stmp_scsi_get_logical_media_info(g_dev_fd, SCSI_STMP_MEDIA_INFO_VENDOR, &u.u32, &len);
559 if(!ret && len == 4)
560 { 751 {
561 u.u32 = fix_endian32be(u.u32); 752 cprintf_field(" Type:", " %u ", info.type);
562 cprintf_field(" Media Vendor: ", "%#x", u.u32); 753 cprintf(RED, "(%s)\n", stmp_get_logical_media_type_string(info.type));
563 cprintf(RED, " (%s)\n", stmp_get_logical_media_vendor_string(u.u32));
564 } 754 }
565 755 if(info.has.serial)
566 len = 8;
567 ret = stmp_scsi_get_logical_media_info(g_dev_fd, 13, &u.u64, &len);
568 if(!ret && len == 8)
569 { 756 {
570 u.u64 = fix_endian64be(u.u64); 757 cprintf_field(" Serial:", " ");
571 cprintf_field(" Logical Media Info (13): ", "%#llx\n", (unsigned long long)u.u64); 758 print_hex(info.serial, info.serial_len);
759 free(info.serial);
572 } 760 }
573 761 if(info.has.system)
574 len = 4; 762 cprintf_field(" System:", " %u\n", info.system);
575 ret = stmp_scsi_get_logical_media_info(g_dev_fd, 11, &u.u32, &len); 763 if(info.has.present)
576 if(!ret && len == 4) 764 cprintf_field(" Present:", " %u\n", info.present);
765 if(info.has.page_size)
577 { 766 {
578 u.u32 = fix_endian32be(u.u32); 767 cprintf_field(" Page size:", " %lu ", (unsigned long)info.page_size);
579 cprintf_field(" Logical Media Info (11): ", "%#x\n", u.u32); 768 cprintf(RED, "(%.3f %s)\n", get_size_natural(info.page_size), get_size_suffix(info.page_size));
580 } 769 }
581 770 if(info.has.vendor)
582 len = 4;
583 ret = stmp_scsi_get_logical_media_info(g_dev_fd, 14, &u.u32, &len);
584 if(!ret && len == 4)
585 { 771 {
586 u.u32 = fix_endian32be(u.u32); 772 cprintf_field(" Vendor:", " %u ", info.vendor);
587 cprintf_field(" Logical Media Info (14): ", "%#x\n", u.u32); 773 cprintf(RED, "(%s)\n", stmp_get_logical_media_vendor_string(info.vendor));
588 } 774 }
589 775 if(info.has.nand_id)
590 len = 4;
591 ret = stmp_scsi_get_logical_media_info(g_dev_fd, SCSI_STMP_MEDIA_INFO_ALLOC_UNIT_SIZE, &u.u32, &len);
592 if(!ret && len == 4)
593 { 776 {
594 u.u32 = fix_endian32be(u.u32); 777 cprintf_field(" Nand ID:", " ");
595 cprintf_field(" Allocation Unit Size: ", "%d B\n", u.u32); 778 print_hex(info.nand_id, sizeof(info.nand_id));
596 } 779 }
597 }while(0); 780 if(info.has.nr_devices)
598 781 cprintf_field(" Number of devices:", " %lu\n", (unsigned long)info.nr_devices);
599 uint16_t chip_rev; 782 }
600 ret = stmp_get_chip_major_rev_id(g_dev_fd, &chip_rev);
601 if(ret)
602 cprintf(GREY, "Cannot get chip major revision id: %d\n", ret);
603 else
604 cprintf_field(" Chip Major Rev ID: ", "%x\n", chip_rev);
605
606 uint16_t rom_rev;
607 ret = stmp_get_rom_rev_id(g_dev_fd, &rom_rev);
608 if(ret)
609 cprintf(GREY, "Cannot get rom revision id: %d\n", ret);
610 else 783 else
611 cprintf_field(" ROM Rev ID: ", "%x\n", rom_rev); 784 cprintf(GREY, "Cannot get media info: %d\n", ret);
612 785
613 struct 786 struct stmp_logical_media_table_t *table;
787 ret = stmp_get_logical_media_table(g_dev_fd, &table);
788 if(!ret)
614 { 789 {
615 struct scsi_stmp_logical_table_t header; 790 cprintf(BLUE, "Logical Media Table\n");
616 struct scsi_stmp_logical_table_entry_t entry[20]; 791 for(int i = 0; i < table->header.count; i++)
617 }__attribute__((packed)) table;
618
619 ret = stmp_get_logical_table(g_dev_fd, &table.header, sizeof(table.entry) / sizeof(table.entry[0]));
620 if(ret)
621 cprintf(GREY, "Cannot get logical table: %d\n", ret);
622 else
623 {
624 cprintf_field(" Logical Table: ", "%d entries\n", table.header.count);
625 for(int i = 0; i < table.header.count; i++)
626 { 792 {
627 cprintf(BLUE, " Drive "); 793 cprintf(RED, " Drive ");
628 cprintf_field("No: ", "%2x", table.entry[i].drive_no); 794 cprintf_field("No: ", "%2x", table->entry[i].drive_no);
629 cprintf_field(" Type: ", "%#x ", table.entry[i].type); 795 cprintf_field(" Type: ", "%#x ", table->entry[i].type);
630 cprintf(RED, "(%s)", stmp_get_logical_drive_type_string(table.entry[i].type)); 796 cprintf(RED, "(%s)", stmp_get_logical_drive_type_string(table->entry[i].type));
631 cprintf_field(" Tag: ", "%#x ", table.entry[i].tag); 797 cprintf_field(" Tag: ", "%#x ", table->entry[i].tag);
632 cprintf(RED, "(%s)", stmp_get_logical_drive_tag_string(table.entry[i].tag)); 798 cprintf(RED, "(%s)", stmp_get_logical_drive_tag_string(table->entry[i].tag));
633 unsigned long long size = table.entry[i].size; 799 unsigned long long size = table->entry[i].size;
634 int order = 0; 800 cprintf_field(" Size: ", "%.3f %s", get_size_natural(size), get_size_suffix(size));
635 while(size >= 1024)
636 {
637 size /= 1024;
638 order++;
639 }
640 static const char *suffix[] = {"B", "KiB", "MiB", "GiB", "TiB"};
641 cprintf_field(" Size: ", "%llu %s", size, suffix[order]);
642 cprintf(OFF, "\n"); 801 cprintf(OFF, "\n");
643 } 802 }
644 803
645 for(int i = 0; i < table.header.count; i++) 804 for(int i = 0; i < table->header.count; i++)
646 { 805 {
647 union 806 uint8_t drive = table->entry[i].drive_no;
648 { 807 cprintf(BLUE, "Drive ");
649 uint8_t u8; 808 cprintf(YELLOW, "%02x\n", drive);
650 uint16_t u16; 809 struct stmp_logical_drive_info_t info;
651 uint32_t u32; 810 ret = stmp_get_logical_drive_info(g_dev_fd, drive, &info);
652 uint64_t u64; 811 if(ret)
653 uint8_t buf[52]; 812 continue;
654 }u; 813 if(info.has.sector_size)
655 uint8_t drive = table.entry[i].drive_no;
656 cprintf_field(" Drive ", "%02x\n", drive);
657
658 int len = 4;
659 ret = stmp_scsi_get_logical_drive_info(g_dev_fd, drive, SCSI_STMP_DRIVE_INFO_SECTOR_SIZE, &u.u32, &len);
660 if(!ret && len == 4)
661 {
662 u.u32 = fix_endian32be(u.u32);
663 cprintf_field(" Sector Size: ", "%lu B (%.3f %s)\n", (unsigned long)u.u32,
664 get_size_natural(u.u32), get_size_suffix(u.u32));
665 }
666
667 len = 4;
668 ret = stmp_scsi_get_logical_drive_info(g_dev_fd, drive, SCSI_STMP_DRIVe_INFO_ERASE_SIZE, &u.u32, &len);
669 if(!ret && len == 4)
670 {
671 u.u32 = fix_endian32be(u.u32);
672 cprintf_field(" Erase Size: ", "%lu B (%.3f %s)\n", (unsigned long)u.u32,
673 get_size_natural(u.u32), get_size_suffix(u.u32));
674 }
675
676 len = 8;
677 ret = stmp_scsi_get_logical_drive_info(g_dev_fd, drive, SCSI_STMP_DRIVE_INFO_SIZE, &u.u64, &len);
678 if(!ret && len == 8)
679 {
680 u.u64 = fix_endian64be(u.u64);
681 cprintf_field(" Total Size: ", "%llu B (%.3f %s)\n",
682 (unsigned long long)u.u64, get_size_natural(u.u32),
683 get_size_suffix(u.u32));
684 }
685
686 len = 4;
687 ret = stmp_scsi_get_logical_drive_info(g_dev_fd, drive, SCSI_STMP_DRIVE_INFO_SIZE_MEGA, &u.u32, &len);
688 if(!ret && len == 4)
689 {
690 u.u32 = fix_endian32be(u.u32);
691 cprintf_field(" Total Size (MB): ", "%lu MB\n", (unsigned long)u.u32);
692 }
693
694 len = 8;
695 ret = stmp_scsi_get_logical_drive_info(g_dev_fd, drive, SCSI_STMP_DRIVE_INFO_SECTOR_COUNT, &u.u64, &len);
696 if(!ret && len == 8)
697 {
698 u.u64 = fix_endian64be(u.u64);
699 cprintf_field(" Sector Count: ", "%llu\n", (unsigned long long)u.u64);
700 }
701
702 len = 4;
703 ret = stmp_scsi_get_logical_drive_info(g_dev_fd, drive,SCSI_STMP_DRIVE_INFO_TYPE, &u.u32, &len);
704 if(!ret && len == 4)
705 {
706 u.u32 = fix_endian32be(u.u32);
707 cprintf_field(" Type: ", "%#x", u.u32);
708 cprintf(RED, " (%s)\n", stmp_get_logical_drive_type_string(u.u32));
709 }
710
711 len = 1;
712 ret = stmp_scsi_get_logical_drive_info(g_dev_fd, drive, SCSI_STMP_DRIVE_INFO_TAG, &u.u8, &len);
713 if(!ret && len == 1)
714 {
715 cprintf_field(" Tag: ", "%#x", u.u8);
716 cprintf(RED, " (%s)\n", stmp_get_logical_drive_tag_string(u.u8));
717 }
718
719 len = 52;
720 ret = stmp_scsi_get_logical_drive_info(g_dev_fd, drive, SCSI_STMP_DRIVE_INFO_COMPONENT_VERSION, &u.buf, &len);
721 if(!ret && len != 0)
722 { 814 {
723 cprintf(GREEN, " Component Version:"); 815 cprintf_field(" Sector size:", " %llu ", (unsigned long long)info.sector_size);
724 print_hex(u.buf, len); 816 cprintf(RED, "(%.3f %s)\n", get_size_natural(info.sector_size), get_size_suffix(info.sector_size));
725 } 817 }
726 818 if(info.has.erase_size)
727 len = 52;
728 ret = stmp_scsi_get_logical_drive_info(g_dev_fd, drive, SCSI_STMP_DRIVE_INFO_PROJECT_VERSION, &u.buf, &len);
729 if(!ret && len != 0)
730 { 819 {
731 cprintf(GREEN, " Project Version:"); 820 cprintf_field(" Erase size:", " %llu ", (unsigned long long)info.erase_size);
732 print_hex(u.buf, len); 821 cprintf(RED, "(%.3f %s)\n", get_size_natural(info.erase_size), get_size_suffix(info.erase_size));
733 } 822 }
734 823 if(info.has.size)
735 len = 1;
736 ret = stmp_scsi_get_logical_drive_info(g_dev_fd, drive, SCSI_STMP_DRIVE_INFO_IS_WRITE_PROTETED, &u.u8, &len);
737 if(!ret && len == 1)
738 { 824 {
739 cprintf_field(" Is Writed Protected: ", "%d\n", u.u8); 825 cprintf_field(" Drive size:", " %llu ", (unsigned long long)info.size);
826 cprintf(RED, "(%.3f %s)\n", get_size_natural(info.size), get_size_suffix(info.size));
740 } 827 }
741 828 if(info.has.sector_count)
742 len = 2; 829 cprintf_field(" Sector count:", " %lu\n", (unsigned long)info.sector_count);
743 int serial_number_size = 0; 830 if(info.has.type)
744 ret = stmp_scsi_get_logical_drive_info(g_dev_fd, drive, SCSI_STMP_DRIVE_INFO_SERIAL_NUMBER_SIZE, &u.u16, &len);
745 if(!ret && len == 2)
746 { 831 {
747 u.u16 = fix_endian16be(u.u16); 832 cprintf_field(" Type:", " %u ", info.type);
748 cprintf_field(" Serial Number Size: ", "%d\n", u.u16); 833 cprintf(RED, "(%s)\n", stmp_get_logical_drive_type_string(info.type));
749 serial_number_size = u.u16;
750 } 834 }
751 835 if(info.has.tag)
752 len = serial_number_size;
753 ret = stmp_scsi_get_logical_drive_info(g_dev_fd, drive, SCSI_STMP_DRIVE_INFO_SERIAL_NUMBER, &u.buf, &len);
754 if(!ret && len != 0)
755 { 836 {
756 cprintf(GREEN, " Serial Number:"); 837 cprintf_field(" Tag:", " %u ", info.tag);
757 print_hex(u.buf, len); 838 cprintf(RED, "(%s)\n", stmp_get_logical_drive_tag_string(info.tag));
758 } 839 }
759 840 if(info.has.component_version)
760 len = 1;
761 ret = stmp_scsi_get_logical_drive_info(g_dev_fd, drive, SCSI_STMP_DRIVE_INFO_MEDIA_PRESENT, &u.u8, &len);
762 if(!ret && len == 1)
763 { 841 {
764 cprintf_field(" Is Media Present: ", "%d\n", u.u8); 842 cprintf_field(" Component version:", " ");
843 print_ver(&info.component_version);
765 } 844 }
766 845 if(info.has.project_version)
767 len = 1;
768 ret = stmp_scsi_get_logical_drive_info(g_dev_fd, drive, SCSI_STMP_DRIVE_INFO_MEDIA_CHANGE, &u.u8, &len);
769 if(!ret && len == 1)
770 { 846 {
771 cprintf_field(" Media Change: ", "%d\n", u.u8); 847 cprintf_field(" Project version:", " ");
848 print_ver(&info.project_version);
772 } 849 }
773 850 if(info.has.write_protected)
774 len = 4; 851 cprintf_field(" Write protected:", " %u\n", info.write_protected);
775 ret = stmp_scsi_get_logical_drive_info(g_dev_fd, drive, SCSI_STMP_DRIVE_INFO_SECTOR_ALLOCATION, &u.u32, &len); 852 if(info.has.serial)
776 if(!ret && len == 4)
777 { 853 {
778 u.u32 = fix_endian32be(u.u32); 854 cprintf_field(" Serial:", " ");
779 cprintf_field(" Sector Allocation: ", "%lu\n", (unsigned long)u.u32); 855 print_hex(info.serial, info.serial_len);
856 free(info.serial);
780 } 857 }
858 if(info.has.change)
859 cprintf_field(" Change:", " %u\n", info.change);
860 if(info.has.present)
861 cprintf_field(" Present:", " %u\n", info.present);
781 } 862 }
863 free(table);
782 } 864 }
865 else
866 cprintf(GREY, "Cannot get logical table: %d\n", ret);
783 867
784 return 0; 868 return 0;
785} 869}
@@ -789,32 +873,27 @@ void do_extract(const char *file)
789 FILE *f = NULL; 873 FILE *f = NULL;
790 cprintf(BLUE, "Extracting firmware...\n"); 874 cprintf(BLUE, "Extracting firmware...\n");
791 875
792 struct 876 struct stmp_logical_media_table_t *table = NULL;
793 { 877 int ret = stmp_get_logical_media_table(g_dev_fd, &table);
794 struct scsi_stmp_logical_table_t header;
795 struct scsi_stmp_logical_table_entry_t entry[20];
796 }__attribute__((packed)) table;
797
798 int ret = stmp_get_logical_table(g_dev_fd, &table.header, sizeof(table.entry) / sizeof(table.entry[0]));
799 if(ret) 878 if(ret)
800 { 879 {
801 cprintf(GREY, "Cannot get logical table: %d\n", ret); 880 cprintf(GREY, "Cannot get logical table: %d\n", ret);
802 goto Lend; 881 goto Lend;
803 } 882 }
804 int entry = 0; 883 int entry = 0;
805 while(entry < table.header.count) 884 while(entry < table->header.count)
806 if(table.entry[entry].type == SCSI_STMP_DRIVE_TYPE_SYSTEM && 885 if(table->entry[entry].type == SCSI_STMP_DRIVE_TYPE_SYSTEM &&
807 table.entry[entry].tag == SCSI_STMP_DRIVE_TAG_SYSTEM_BOOT) 886 table->entry[entry].tag == SCSI_STMP_DRIVE_TAG_SYSTEM_BOOT)
808 break; 887 break;
809 else 888 else
810 entry++; 889 entry++;
811 if(entry == table.header.count) 890 if(entry == table->header.count)
812 { 891 {
813 cprintf(GREY, "Cannot find firmware partition\n"); 892 cprintf(GREY, "Cannot find firmware partition\n");
814 goto Lend; 893 goto Lend;
815 } 894 }
816 uint8_t drive_no = table.entry[entry].drive_no; 895 uint8_t drive_no = table->entry[entry].drive_no;
817 uint64_t drive_sz = table.entry[entry].size; 896 uint64_t drive_sz = table->entry[entry].size;
818 if(g_debug) 897 if(g_debug)
819 { 898 {
820 cprintf(RED, "* "); 899 cprintf(RED, "* ");
@@ -822,27 +901,25 @@ void do_extract(const char *file)
822 cprintf(RED, "* "); 901 cprintf(RED, "* ");
823 cprintf_field("Size: ", "%#llx\n", (unsigned long long)drive_sz); 902 cprintf_field("Size: ", "%#llx\n", (unsigned long long)drive_sz);
824 } 903 }
825 int len = 4; 904 struct stmp_logical_drive_info_t info;
826 uint32_t sector_size; 905 ret = stmp_get_logical_drive_info(g_dev_fd, drive_no, &info);
827 ret = stmp_scsi_get_logical_drive_info(g_dev_fd, drive_no, SCSI_STMP_DRIVE_INFO_SECTOR_SIZE, &sector_size, &len); 906 if(ret || !info.has.sector_size)
828 if(ret || len != 4)
829 { 907 {
830 cprintf(GREY, "Cannot get sector size\n"); 908 cprintf(GREY, "Cannot get sector size\n");
831 goto Lend; 909 goto Lend;
832 } 910 }
833 sector_size = fix_endian32be(sector_size); 911 unsigned sector_size = info.sector_size;
834 if(g_debug) 912 if(g_debug)
835 { 913 {
836 cprintf(RED, "* "); 914 cprintf(RED, "* ");
837 cprintf_field("Sector size: ", "%lu\n", (unsigned long)sector_size); 915 cprintf_field("Sector size: ", "%lu\n", (unsigned long)sector_size);
838 } 916 }
839 uint8_t *sector = malloc(sector_size); 917 uint8_t *sector = malloc(sector_size);
840 len = sector_size; 918 ret = stmp_read_logical_drive_sectors(g_dev_fd, drive_no, 0, 1, sector, sector_size);
841 ret = stmp_scsi_read_logical_drive_sectors(g_dev_fd, drive_no, 0, 1, sector, &len); 919 if(ret)
842 if(ret || len != (int)sector_size)
843 { 920 {
844 cprintf(GREY, "Cannot read first sector\n"); 921 cprintf(GREY, "Cannot read first sector: %d\n", ret);
845 return; 922 goto Lend;
846 } 923 }
847 uint32_t fw_size = *(uint32_t *)(sector + 0x1c) * 16; 924 uint32_t fw_size = *(uint32_t *)(sector + 0x1c) * 16;
848 if(g_debug) 925 if(g_debug)
@@ -860,10 +937,10 @@ void do_extract(const char *file)
860 937
861 for(int sec = 0; sec * sector_size < fw_size; sec++) 938 for(int sec = 0; sec * sector_size < fw_size; sec++)
862 { 939 {
863 ret = stmp_scsi_read_logical_drive_sectors(g_dev_fd, drive_no, sec, 1, sector, &len); 940 ret = stmp_read_logical_drive_sectors(g_dev_fd, drive_no, sec, 1, sector, sector_size);
864 if(ret || len != (int)sector_size) 941 if(ret)
865 { 942 {
866 cprintf(GREY, "Cannot read sector %d\n", sec); 943 cprintf(GREY, "Cannot read sector %d: %d\n", sec, ret);
867 goto Lend; 944 goto Lend;
868 } 945 }
869 if(fwrite(sector, sector_size, 1, f) != 1) 946 if(fwrite(sector, sector_size, 1, f) != 1)
@@ -874,6 +951,7 @@ void do_extract(const char *file)
874 } 951 }
875 cprintf(BLUE, "Done\n"); 952 cprintf(BLUE, "Done\n");
876Lend: 953Lend:
954 free(table);
877 if(f) 955 if(f)
878 fclose(f); 956 fclose(f);
879} 957}
@@ -890,33 +968,27 @@ void do_write(const char *file, int want_a_brick)
890 FILE *f = NULL; 968 FILE *f = NULL;
891 cprintf(BLUE, "Writing firmware...\n"); 969 cprintf(BLUE, "Writing firmware...\n");
892 970
893 struct 971 struct stmp_logical_media_table_t *table = NULL;
894 { 972 int ret = stmp_get_logical_media_table(g_dev_fd, &table);
895 struct scsi_stmp_logical_table_t header;
896 struct scsi_stmp_logical_table_entry_t entry[20];
897 }__attribute__((packed)) table;
898
899 int len = sizeof(table);
900 int ret = stmp_scsi_get_logical_table(g_dev_fd, sizeof(table.entry) / sizeof(table.entry[0]), &table.header, &len);
901 if(ret) 973 if(ret)
902 { 974 {
903 cprintf(GREY, "Cannot get logical table: %d\n", ret); 975 cprintf(GREY, "Cannot get logical table: %d\n", ret);
904 goto Lend; 976 goto Lend;
905 } 977 }
906 int entry = 0; 978 int entry = 0;
907 while(entry < table.header.count) 979 while(entry < table->header.count)
908 if(table.entry[entry].type == SCSI_STMP_DRIVE_TYPE_SYSTEM && 980 if(table->entry[entry].type == SCSI_STMP_DRIVE_TYPE_SYSTEM &&
909 table.entry[entry].tag == SCSI_STMP_DRIVE_TAG_SYSTEM_BOOT) 981 table->entry[entry].tag == SCSI_STMP_DRIVE_TAG_SYSTEM_BOOT)
910 break; 982 break;
911 else 983 else
912 entry++; 984 entry++;
913 if(entry == table.header.count) 985 if(entry == table->header.count)
914 { 986 {
915 cprintf(GREY, "Cannot find firmware partition\n"); 987 cprintf(GREY, "Cannot find firmware partition\n");
916 goto Lend; 988 goto Lend;
917 } 989 }
918 uint8_t drive_no = table.entry[entry].drive_no; 990 uint8_t drive_no = table->entry[entry].drive_no;
919 uint64_t drive_sz = table.entry[entry].size; 991 uint64_t drive_sz = table->entry[entry].size;
920 if(g_debug) 992 if(g_debug)
921 { 993 {
922 cprintf(RED, "* "); 994 cprintf(RED, "* ");
@@ -924,28 +996,21 @@ void do_write(const char *file, int want_a_brick)
924 cprintf(RED, "* "); 996 cprintf(RED, "* ");
925 cprintf_field("Size: ", "%#llx\n", (unsigned long long)drive_sz); 997 cprintf_field("Size: ", "%#llx\n", (unsigned long long)drive_sz);
926 } 998 }
927 len = 4; 999 struct stmp_logical_drive_info_t info;
928 uint32_t sector_size; 1000 ret = stmp_get_logical_drive_info(g_dev_fd, drive_no, &info);
929 ret = stmp_scsi_get_logical_drive_info(g_dev_fd, drive_no, SCSI_STMP_DRIVE_INFO_SECTOR_SIZE, &sector_size, &len); 1001 if(ret || !info.has.sector_size)
930 if(ret || len != 4)
931 { 1002 {
932 cprintf(GREY, "Cannot get sector size\n"); 1003 cprintf(GREY, "Cannot get sector size\n");
933 goto Lend; 1004 goto Lend;
934 } 1005 }
935 sector_size = fix_endian32be(sector_size); 1006 unsigned sector_size = info.sector_size;
936 if(g_debug)
937 {
938 cprintf(RED, "* ");
939 cprintf_field("Sector size: ", "%lu\n", (unsigned long)sector_size);
940 }
941 uint8_t *sector = malloc(sector_size); 1007 uint8_t *sector = malloc(sector_size);
942 1008
943 /* sanity check by reading first sector */ 1009 /* sanity check by reading first sector */
944 len = sector_size; 1010 ret = stmp_read_logical_drive_sectors(g_dev_fd, drive_no, 0, 1, sector, sector_size);
945 ret = stmp_scsi_read_logical_drive_sectors(g_dev_fd, drive_no, 0, 1, sector, &len); 1011 if(ret)
946 if(ret || len != (int)sector_size)
947 { 1012 {
948 cprintf(GREY, "Cannot read first sector\n"); 1013 cprintf(GREY, "Cannot read first sector: %d\n", ret);
949 return; 1014 return;
950 } 1015 }
951 uint32_t sig = *(uint32_t *)(sector + 0x14); 1016 uint32_t sig = *(uint32_t *)(sector + 0x14);
@@ -998,11 +1063,10 @@ void do_write(const char *file, int want_a_brick)
998 * partial sectors */ 1063 * partial sectors */
999 if(xfer_len < (int)sector_size) 1064 if(xfer_len < (int)sector_size)
1000 memset(sector + xfer_len, 0, sector_size - xfer_len); 1065 memset(sector + xfer_len, 0, sector_size - xfer_len);
1001 len = sector_size; 1066 ret = stmp_write_logical_drive_sectors(g_dev_fd, drive_no, sec, 1, sector, sector_size);
1002 ret = stmp_scsi_write_logical_drive_sectors(g_dev_fd, drive_no, sec, 1, sector, &len); 1067 if(ret)
1003 if(ret || len != (int)sector_size)
1004 { 1068 {
1005 cprintf(GREY, "Cannot write sector %d\n", sec); 1069 cprintf(GREY, "Cannot write sector %d: %d\n", sec, ret);
1006 goto Lend; 1070 goto Lend;
1007 } 1071 }
1008 } 1072 }
diff --git a/utils/imxtools/scsitools/stmp_scsi.h b/utils/imxtools/scsitools/stmp_scsi.h
index 1a035cc649..68d77daeec 100644
--- a/utils/imxtools/scsitools/stmp_scsi.h
+++ b/utils/imxtools/scsitools/stmp_scsi.h
@@ -84,7 +84,7 @@ struct scsi_stmp_logical_table_entry_t
84#define SCSI_STMP_DRIVE_TAG_USER_STORAGE 0xa 84#define SCSI_STMP_DRIVE_TAG_USER_STORAGE 0xa
85#define SCSI_STMP_DRIVE_TAG_SYSTEM_BOOT 0x50 85#define SCSI_STMP_DRIVE_TAG_SYSTEM_BOOT 0x50
86 86
87struct scsi_stmp_logical_table_t 87struct scsi_stmp_logical_table_header_t
88{ 88{
89 uint16_t count; /* big-endian */ 89 uint16_t count; /* big-endian */
90} __attribute__((packed)); 90} __attribute__((packed));
@@ -135,7 +135,7 @@ struct scsi_stmp_logical_media_info_manufacturer_t
135} __attribute__((packed)); 135} __attribute__((packed));
136 136
137#define SCSI_STMP_DRIVE_INFO_SECTOR_SIZE 0 /** Sector Size (bytes) */ 137#define SCSI_STMP_DRIVE_INFO_SECTOR_SIZE 0 /** Sector Size (bytes) */
138#define SCSI_STMP_DRIVe_INFO_ERASE_SIZE 1 /** Erase Size (bytes) */ 138#define SCSI_STMP_DRIVE_INFO_ERASE_SIZE 1 /** Erase Size (bytes) */
139#define SCSI_STMP_DRIVE_INFO_SIZE 2 /** Total Size (bytes) */ 139#define SCSI_STMP_DRIVE_INFO_SIZE 2 /** Total Size (bytes) */
140#define SCSI_STMP_DRIVE_INFO_SIZE_MEGA 3 /** Total Size (mega-bytes) */ 140#define SCSI_STMP_DRIVE_INFO_SIZE_MEGA 3 /** Total Size (mega-bytes) */
141#define SCSI_STMP_DRIVE_INFO_SECTOR_COUNT 4 /** Sector Count */ 141#define SCSI_STMP_DRIVE_INFO_SECTOR_COUNT 4 /** Sector Count */
@@ -187,6 +187,14 @@ struct scsi_stmp_logical_drive_info_type_t
187 uint8_t type; 187 uint8_t type;
188} __attribute__((packed)); 188} __attribute__((packed));
189 189
190struct scsi_stmp_logical_drive_info_version_t
191{
192 uint16_t major;
193 uint16_t minor;
194 uint16_t revision;
195} __attribute__((packed));
196
197struct stmp_device_t;
190typedef struct stmp_device_t *stmp_device_t; 198typedef struct stmp_device_t *stmp_device_t;
191 199
192typedef void (*stmp_printf_t)(void *user, const char *fmt, ...); 200typedef void (*stmp_printf_t)(void *user, const char *fmt, ...);
@@ -197,4 +205,161 @@ typedef void (*stmp_printf_t)(void *user, const char *fmt, ...);
197#define STMP_READ (1 << 1) 205#define STMP_READ (1 << 1)
198#define STMP_WRITE (1 << 2) 206#define STMP_WRITE (1 << 2)
199 207
208uint16_t stmp_fix_endian16be(uint16_t w);
209uint32_t stmp_fix_endian32be(uint32_t w);
210uint64_t stmp_fix_endian64be(uint64_t w);
211/* returns NULL on error */
212stmp_device_t stmp_open(rb_scsi_device_t dev, unsigned flags, void *user, stmp_printf_t printf);
213void stmp_close(stmp_device_t dev);
214/* returns <0 on error and status otherwise */
215int stmp_scsi(stmp_device_t dev, uint8_t *cdb, int cdb_size, unsigned flags,
216 void *sense, int *sense_size, void *buffer, int *buf_size);
217/* returns != 0 on error */
218int stmp_sense_analysis(stmp_device_t dev, int status, uint8_t *sense, int sense_size);
219void stmp_printf(rb_scsi_device_t dev, const char *fmt, ...);
220void stmp_debugf(rb_scsi_device_t dev, const char *fmt, ...);
221
222/**
223 * Mid-level API
224 */
225
226/* returns !=0 on error */
227int stmp_scsi_inquiry(stmp_device_t dev, uint8_t *dev_type, char vendor[9], char product[17]);
228
229int stmp_scsi_get_protocol_version(stmp_device_t dev, void *buf, int *len);
230int stmp_scsi_get_chip_major_rev_id(stmp_device_t dev, void *buf, int *len);
231int stmp_scsi_get_rom_rev_id(stmp_device_t dev, void *buf, int *len);
232int stmp_scsi_read_logical_drive_sectors(stmp_device_t dev, uint8_t drive, uint64_t address,
233 uint32_t count, void *buffer, int *buffer_size);
234int stmp_scsi_write_logical_drive_sectors(stmp_device_t dev, uint8_t drive, uint64_t address,
235 uint32_t count, void *buffer, int *buffer_size);
236/* the following functions *DO NOT* fix the endianness of the structures */
237int stmp_scsi_get_logical_table(stmp_device_t dev, int entry_count, void *buf, int *len);
238int stmp_scsi_get_serial_number(stmp_device_t dev, uint8_t info, void *data, int *len);
239int stmp_scsi_get_logical_media_info(stmp_device_t dev, uint8_t info, void *data, int *len);
240int stmp_scsi_get_logical_drive_info(stmp_device_t dev, uint8_t drive, uint8_t info, void *data, int *len);
241int stmp_scsi_get_device_info(stmp_device_t dev, uint8_t info, void *data, int *len);
242/* these helper functions fix the endianness for the previous calls, or returns != 0
243 * if they don't know about this info or the size doesn't match */
244int stmp_fix_logical_media_info(uint8_t info, void *data, int len);
245int stmp_fix_logical_drive_info(uint8_t info, void *data, int len);
246int stmp_fix_device_info(uint8_t info, void *data, int len);
247
248/**
249 * High-Level API
250 */
251
252struct stmp_logical_media_table_t
253{
254 struct scsi_stmp_logical_table_header_t header;
255 struct scsi_stmp_logical_table_entry_t entry[];
256}__attribute__((packed)) table;
257
258struct stmp_logical_media_info_t
259{
260 struct
261 {
262 bool nr_drives;
263 bool size;
264 bool alloc_size;
265 bool initialised;
266 bool state;
267 bool write_protected;
268 bool type;
269 bool serial_len;
270 bool serial;
271 bool system;
272 bool present;
273 bool page_size;
274 bool vendor;
275 bool nand_id;
276 bool nr_devices;
277 }has;
278 uint16_t nr_drives;
279 uint64_t size;
280 uint32_t alloc_size;
281 uint8_t initialised;
282 uint8_t state;
283 uint8_t write_protected;
284 uint8_t type;
285 uint32_t serial_len;
286 uint8_t *serial; /* must be released with free() */
287 uint8_t system;
288 uint8_t present;
289 uint32_t page_size;
290 uint32_t vendor;
291 uint8_t nand_id[6];
292 uint32_t nr_devices;
293};
294
295#define SCSI_STMP_DRIVE_INFO_SECTOR_SIZE 0 /** Sector Size (bytes) */
296#define SCSI_STMP_DRIVE_INFO_ERASE_SIZE 1 /** Erase Size (bytes) */
297#define SCSI_STMP_DRIVE_INFO_SIZE 2 /** Total Size (bytes) */
298#define SCSI_STMP_DRIVE_INFO_SIZE_MEGA 3 /** Total Size (mega-bytes) */
299#define SCSI_STMP_DRIVE_INFO_SECTOR_COUNT 4 /** Sector Count */
300#define SCSI_STMP_DRIVE_INFO_TYPE 5 /** Drive Type */
301#define SCSI_STMP_DRIVE_INFO_TAG 6 /** Drive Tag */
302#define SCSI_STMP_DRIVE_INFO_COMPONENT_VERSION 7 /** Component Version */
303#define SCSI_STMP_DRIVE_INFO_PROJECT_VERSION 8 /** Project Version */
304#define SCSI_STMP_DRIVE_INFO_IS_WRITE_PROTECTED 9 /** Is Write Protected */
305#define SCSI_STMP_DRIVE_INFO_SERIAL_NUMBER_SIZE 10 /** Serial Number Size */
306#define SCSI_STMP_DRIVE_INFO_SERIAL_NUMBER 11 /** Serial Number */
307#define SCSI_STMP_DRIVE_INFO_MEDIA_PRESENT 12 /** Is Media Present */
308#define SCSI_STMP_DRIVE_INFO_MEDIA_CHANGE 13 /** Media Change */
309#define SCSI_STMP_DRIVE_INFO_SECTOR_ALLOCATION 14 /** Sector Allocation */
310
311struct stmp_logical_drive_info_t
312{
313 struct
314 {
315 bool sector_size;
316 bool erase_size;
317 bool size;
318 bool sector_count;
319 bool type;
320 bool tag;
321 bool component_version;
322 bool project_version;
323 bool write_protected;
324 bool serial_len;
325 bool serial;
326 bool present;
327 bool change;
328 bool sector_alloc;
329 }has;
330 uint32_t sector_size;
331 uint32_t erase_size;
332 uint64_t size;
333 uint64_t sector_count;
334 uint32_t type;
335 uint8_t tag;
336 struct scsi_stmp_logical_drive_info_version_t component_version;
337 struct scsi_stmp_logical_drive_info_version_t project_version;
338 uint8_t write_protected;
339 uint32_t serial_len;
340 uint8_t *serial;
341 uint8_t present;
342 uint8_t change;
343 uint32_t sector_alloc;
344};
345
346int stmp_get_protocol_version(stmp_device_t dev, struct scsi_stmp_protocol_version_t *ver);
347int stmp_get_chip_major_rev_id(stmp_device_t dev, uint16_t *ver);
348int stmp_get_rom_rev_id(stmp_device_t dev, uint16_t *ver);
349/* return 0 on success, buffers must be released with free() */
350int stmp_get_device_serial(stmp_device_t dev, uint8_t **buffer, int *len);
351int stmp_get_logical_media_info(stmp_device_t dev, struct stmp_logical_media_info_t *info);
352int stmp_get_logical_media_table(stmp_device_t dev, struct stmp_logical_media_table_t **table);
353int stmp_get_logical_drive_info(stmp_device_t dev, uint8_t drive, struct stmp_logical_drive_info_t *info);
354int stmp_read_logical_drive_sectors(stmp_device_t dev, uint8_t drive, uint64_t address,
355 uint32_t count, void *buffer, int buffer_size);
356int stmp_write_logical_drive_sectors(stmp_device_t dev, uint8_t drive, uint64_t address,
357 uint32_t count, void *buffer, int buffer_size);
358/* string helpers */
359const char *stmp_get_logical_media_type_string(uint32_t type);
360const char *stmp_get_logical_media_vendor_string(uint32_t type);
361const char *stmp_get_logical_drive_type_string(uint32_t type);
362const char *stmp_get_logical_drive_tag_string(uint32_t type);
363const char *stmp_get_logical_media_state_string(uint8_t state);
364
200#endif /* __STMP_SCSI__ */ 365#endif /* __STMP_SCSI__ */