diff options
Diffstat (limited to 'utils/imxtools/scsitools/scsitool.c')
-rw-r--r-- | utils/imxtools/scsitools/scsitool.c | 810 |
1 files changed, 437 insertions, 373 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 | ||
50 | static uint16_t fix_endian16be(uint16_t w) | 50 | static 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 | |||
61 | uint16_t stmp_fix_endian16be(uint16_t w) | ||
62 | { | ||
63 | return little_endian() ? w << 8 | w >> 8 : w; | ||
53 | } | 64 | } |
54 | 65 | ||
55 | static uint32_t fix_endian32be(uint32_t w) | 66 | uint32_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 | ||
60 | static uint64_t fix_endian64be(uint64_t w) | 72 | uint64_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 | ||
65 | static void print_hex(void *_buffer, int buffer_size) | 78 | static 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 | ||
89 | static void misc_std_printf(void *user, const char *fmt, ...) | 104 | static 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 | ||
263 | int stmp_get_logical_table(stmp_device_t dev, struct scsi_stmp_logical_table_t *table, int entry_count) | 278 | int 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 | ||
338 | static const char *stmp_get_logical_media_type_string(uint32_t type) | 357 | int 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 | |||
367 | int 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 | |||
383 | int 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 | |||
419 | static 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 | |||
426 | int 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 | |||
465 | int 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 | |||
483 | const 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 | ||
554 | int 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 | |||
573 | int 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 | |||
614 | int 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 | |||
409 | static const char *get_size_suffix(unsigned long long size) | 654 | static 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 | ||
674 | static 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 | |||
429 | static int do_info(void) | 679 | static 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, §or_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"); |
876 | Lend: | 953 | Lend: |
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, §or_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 | } |