From 456a3fc952d34a3e8781ca100851e6253c537109 Mon Sep 17 00:00:00 2001 From: Amaury Pouly Date: Thu, 5 Jan 2017 16:21:55 +0100 Subject: [PATCH] imxtools: various fixes for Windows Don't use colors since the terminal doesn't support it. Also packing is broken on MinGW so use #pragma pack when compiling for windows, this is also supported by MSCV. Change-Id: I635649d52ed5f2e0af46cb9ca2ec325955b2ddb2 --- utils/imxtools/scsitools/misc.c | 5 ++++ utils/imxtools/scsitools/stmp_scsi.c | 8 ++++++ utils/imxtools/scsitools/stmp_scsi.h | 41 +++++++++++++++++++--------- utils/nwztools/scsitools/misc.c | 5 ++++ utils/scsi/rbscsi.c | 22 ++++++++++++++- utils/scsi/rbscsi.h | 15 +++++++++- 6 files changed, 81 insertions(+), 15 deletions(-) diff --git a/utils/imxtools/scsitools/misc.c b/utils/imxtools/scsitools/misc.c index 108235e7fd..36eae198e5 100644 --- a/utils/imxtools/scsitools/misc.c +++ b/utils/imxtools/scsitools/misc.c @@ -32,7 +32,12 @@ char GREEN[] = { 0x1b, 0x5b, 0x31, 0x3b, '3', '2', 0x6d, '\0' }; char YELLOW[] = { 0x1b, 0x5b, 0x31, 0x3b, '3', '3', 0x6d, '\0' }; char BLUE[] = { 0x1b, 0x5b, 0x31, 0x3b, '3', '4', 0x6d, '\0' }; +#if defined(_WIN32) || defined(__WIN32__) +/* disable colors on Windows */ +static bool g_color_enable = false; +#else static bool g_color_enable = true; +#endif void *xmalloc(size_t s) { diff --git a/utils/imxtools/scsitools/stmp_scsi.c b/utils/imxtools/scsitools/stmp_scsi.c index e1d0dc4c77..8daeb8a532 100644 --- a/utils/imxtools/scsitools/stmp_scsi.c +++ b/utils/imxtools/scsitools/stmp_scsi.c @@ -245,14 +245,22 @@ int stmp_get_logical_media_table(stmp_device_t dev, struct stmp_logical_media_ta int len = sizeof(header); int ret = stmp_scsi_get_logical_table(dev, 0, &header, &len); if(ret || len != sizeof(header)) + { + stmp_debugf(dev, "Device returned the wrong size for logical media header: " + "%d bytes but expected %d\n", len, sizeof(header)); return -1; + } header.count = stmp_fix_endian16be(header.count); int sz = sizeof(header) + header.count * sizeof(struct scsi_stmp_logical_table_entry_t); len = sz; *table = malloc(sz); ret = stmp_scsi_get_logical_table(dev, header.count, &(*table)->header, &len); if(ret || len != sz) + { + stmp_debugf(dev, "Device returned the wrong size for logical media table: " + "%d bytes but expected %d (%d entries)\n", len, sz, header.count); return -1; + } (*table)->header.count = stmp_fix_endian16be((*table)->header.count); for(unsigned i = 0; i < (*table)->header.count; i++) (*table)->entry[i].size = stmp_fix_endian64be((*table)->entry[i].size); diff --git a/utils/imxtools/scsitools/stmp_scsi.h b/utils/imxtools/scsitools/stmp_scsi.h index 56068b5d4c..e85122041f 100644 --- a/utils/imxtools/scsitools/stmp_scsi.h +++ b/utils/imxtools/scsitools/stmp_scsi.h @@ -25,6 +25,17 @@ #include #include "rbscsi.h" +#if defined(_WIN32) || defined(__WIN32__) +/* Mingw has a curious behaviour: it packs only the last field, see + * https://gcc.gnu.org/bugzilla/show_bug.cgi?id=52991 */ +#pragma pack(push) +#pragma pack(1) +#define RB_POP_PACK +#define RB_PACKED +#else +#define RB_PACKED __attribute__((packed)) +#endif + /** * Low-Level SCSI stuff */ @@ -57,17 +68,17 @@ struct scsi_stmp_protocol_version_t { uint8_t major; uint8_t minor; -} __attribute__((packed)); +} RB_PACKED; struct scsi_stmp_rom_rev_id_t { uint16_t rev; /* big-endian */ -} __attribute__((packed)); +} RB_PACKED; struct scsi_stmp_chip_major_rev_id_t { uint16_t rev; /* big-endian */ -} __attribute__((packed)); +} RB_PACKED; struct scsi_stmp_logical_table_entry_t { @@ -75,7 +86,7 @@ struct scsi_stmp_logical_table_entry_t uint8_t type; uint8_t tag; uint64_t size; /* big-endian */ -} __attribute__((packed)); +} RB_PACKED; #define SCSI_STMP_DRIVE_TYPE_USER 0 #define SCSI_STMP_DRIVE_TYPE_SYSTEM 1 @@ -87,7 +98,7 @@ struct scsi_stmp_logical_table_entry_t struct scsi_stmp_logical_table_header_t { uint16_t count; /* big-endian */ -} __attribute__((packed)); +} RB_PACKED; #define SCSI_STMP_MEDIA_INFO_NR_DRIVES 0 /** Number of drives (obsolete) */ #define SCSI_STMP_MEDIA_INFO_SIZE 1 /** Total size (bytes) */ @@ -127,12 +138,12 @@ struct scsi_stmp_logical_table_header_t struct scsi_stmp_logical_media_info_type_t { uint8_t type; -} __attribute__((packed)); +} RB_PACKED; struct scsi_stmp_logical_media_info_manufacturer_t { uint32_t type; /* big-endian */ -} __attribute__((packed)); +} RB_PACKED; #define SCSI_STMP_DRIVE_INFO_SECTOR_SIZE 0 /** Sector Size (bytes) */ #define SCSI_STMP_DRIVE_INFO_ERASE_SIZE 1 /** Erase Size (bytes) */ @@ -170,29 +181,29 @@ struct scsi_stmp_logical_media_info_manufacturer_t struct scsi_stmp_logical_drive_info_sector_t { uint32_t size; /* big-endian */ -} __attribute__((packed)); +} RB_PACKED; struct scsi_stmp_logical_drive_info_count_t { uint64_t count; /* big-endian */ -} __attribute__((packed)); +} RB_PACKED; struct scsi_stmp_logical_drive_info_size_t { uint64_t size; /* big-endian */ -} __attribute__((packed)); +} RB_PACKED; struct scsi_stmp_logical_drive_info_type_t { uint8_t type; -} __attribute__((packed)); +} RB_PACKED; struct scsi_stmp_logical_drive_info_version_t { uint16_t major; uint16_t minor; uint16_t revision; -} __attribute__((packed)); +} RB_PACKED; struct stmp_device_t; typedef struct stmp_device_t *stmp_device_t; @@ -253,7 +264,11 @@ struct stmp_logical_media_table_t { struct scsi_stmp_logical_table_header_t header; struct scsi_stmp_logical_table_entry_t entry[]; -}__attribute__((packed)) table; +}RB_PACKED table; + +#ifdef RB_POP_PACK +#pragma pack(pop) +#endif struct stmp_logical_media_info_t { diff --git a/utils/nwztools/scsitools/misc.c b/utils/nwztools/scsitools/misc.c index 108235e7fd..36eae198e5 100644 --- a/utils/nwztools/scsitools/misc.c +++ b/utils/nwztools/scsitools/misc.c @@ -32,7 +32,12 @@ char GREEN[] = { 0x1b, 0x5b, 0x31, 0x3b, '3', '2', 0x6d, '\0' }; char YELLOW[] = { 0x1b, 0x5b, 0x31, 0x3b, '3', '3', 0x6d, '\0' }; char BLUE[] = { 0x1b, 0x5b, 0x31, 0x3b, '3', '4', 0x6d, '\0' }; +#if defined(_WIN32) || defined(__WIN32__) +/* disable colors on Windows */ +static bool g_color_enable = false; +#else static bool g_color_enable = true; +#endif void *xmalloc(size_t s) { diff --git a/utils/scsi/rbscsi.c b/utils/scsi/rbscsi.c index aa62ba0118..8a263f29e6 100644 --- a/utils/scsi/rbscsi.c +++ b/utils/scsi/rbscsi.c @@ -151,13 +151,33 @@ void rb_scsi_close(rb_scsi_device_t dev) /* Windpws */ #elif defined(RB_SCSI_WINDOWS) +/* return either path or something allocated with malloc() */ +static const char *map_to_physical_drive(const char *path, unsigned flags, void *user, + rb_scsi_printf_t printf) +{ + /* don't do anything if path starts with '\' */ + if(path[0] == '\\') + return path; + /* Convert to UNC path (C: -> \\.\C:) otherwise it won't work) */ + char *unc_path = malloc(strlen(path) + 5); + sprintf(unc_path, "\\\\.\\%s", path); + if(flags & RB_SCSI_DEBUG) + printf(user, "rb_scsi: map to UNC path: %s\n", unc_path); + return unc_path; +} + rb_scsi_device_t rb_scsi_open(const char *path, unsigned flags, void *user, rb_scsi_printf_t printf) { if(printf == NULL) printf = misc_std_printf; - HANDLE h = CreateFileA(path, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, + /* magic to auto-detect physical drive */ + const char *open_path = map_to_physical_drive(path, flags, user, printf); + HANDLE h = CreateFileA(open_path, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_FLAG_WRITE_THROUGH | FILE_FLAG_NO_BUFFERING, NULL); + /* free path if it was allocated */ + if(open_path != path) + free((char *)open_path); if(h == INVALID_HANDLE_VALUE) { if(flags & RB_SCSI_DEBUG) diff --git a/utils/scsi/rbscsi.h b/utils/scsi/rbscsi.h index 2b56aabad2..c7345a6cdf 100644 --- a/utils/scsi/rbscsi.h +++ b/utils/scsi/rbscsi.h @@ -66,7 +66,20 @@ struct rb_scsi_raw_cmd_t }; /* open a device, returns a handle or NULL on error - * the caller can optionally provide an error printing function */ + * the caller can optionally provide an error printing function + * + * Linux: + * Path must be the block device, typically /dev/sdX and the program + * must have the permission to open it in read/write mode. + * + * Windows: + * If the path starts with '\', it will be use as-is. This allows to use + * paths such as \\.\PhysicalDriveX or \\.\ScsiX + * Alternatively, the code will try to map a logical drive (such as 'C:') to + * the correspoding physical drive. + * In any case, on recent windows, the program needs to be started with + * Administrator privileges. + */ rb_scsi_device_t rb_scsi_open(const char *path, unsigned flags, void *user, rb_scsi_printf_t printf); /* performs a raw transfer, returns !=0 on error */