summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Makefile4
-rw-r--r--src/cold-flash.c2
-rw-r--r--src/fiasco.c60
-rw-r--r--src/image.c7
-rw-r--r--src/local.c36
-rw-r--r--src/main.c93
-rw-r--r--src/nolo.c52
-rw-r--r--src/printf-utils.c2
-rw-r--r--src/usb-device.c30
9 files changed, 208 insertions, 78 deletions
diff --git a/src/Makefile b/src/Makefile
index d1df391..b436ee6 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -31,10 +31,10 @@ $(BIN).1: $(BIN) $(MANGEN) $(DEPENDS) ../doc/examples
mv $@.tmp $@
libusb-sniff-32.so: libusb-sniff.c $(DEPENDS)
- $(CC) $(CFLAGS) $(LDFLAGS) -fPIC -ldl -shared -m32 -o $@ $<
+ $(CC) $(CFLAGS) $(LDFLAGS) -fPIC $< -ldl -shared -m32 -o $@
libusb-sniff-64.so: libusb-sniff.c $(DEPENDS)
- $(CC) $(CFLAGS) $(LDFLAGS) -fPIC -ldl -shared -m64 -o $@ $<
+ $(CC) $(CFLAGS) $(LDFLAGS) -fPIC $< -ldl -shared -m64 -o $@
%.o: %.c $(DEPENDS)
$(CROSS_CC) $(CFLAGS) $(CPPFLAGS) -c -o $@ $<
diff --git a/src/cold-flash.c b/src/cold-flash.c
index 6441187..8874b32 100644
--- a/src/cold-flash.c
+++ b/src/cold-flash.c
@@ -130,7 +130,7 @@ struct xloader_msg {
uint32_t size; /* 4 bytes - size of file */
uint32_t crc1; /* 4 bytes - crc32 of file */
uint32_t crc2; /* 4 bytes - crc32 of first 12 bytes of message */
-};
+} __attribute__((__packed__));
#define XLOADER_MSG_TYPE_PING 0x6301326E
#define XLOADER_MSG_TYPE_SEND 0x6302326E
diff --git a/src/fiasco.c b/src/fiasco.c
index 721785e..a2cd55a 100644
--- a/src/fiasco.c
+++ b/src/fiasco.c
@@ -192,9 +192,12 @@ struct fiasco * fiasco_alloc_from_file(const char * file) {
if ( ! hwrevs[0] )
strcpy(hwrevs, hwrev);
else {
- /* TODO: check if hwrevs has enough size */
- strcat(hwrevs, ",");
- strcat(hwrevs, hwrev);
+ size_t len1 = strlen(hwrevs);
+ size_t len2 = strlen(hwrev);
+ if ( len1 + len2 + 2 < sizeof(hwrevs) ) {
+ hwrevs[len1] = ',';
+ memcpy(hwrevs+len1+1, hwrev, len2+1);
+ }
}
VERBOSE(" hw revision: %s\n", hwrev);
pbuf += strlen(hwrev) + 1;
@@ -410,6 +413,7 @@ int fiasco_write_to_file(struct fiasco * fiasco, const char * file) {
WRITE_OR_FAIL(file, fd, "2", 1); /* 2 - device & hwrevs */
WRITE_OR_FAIL(file, fd, &device_hwrevs_bufs[i][0], 1);
WRITE_OR_FAIL(file, fd, device_hwrevs_bufs[i]+1, ((uint8_t *)(device_hwrevs_bufs[i]))[0]);
+ /* FIXME: memory leak: device_hwrevs_bufs */
}
free(device_hwrevs_bufs);
@@ -449,9 +453,9 @@ int fiasco_write_to_file(struct fiasco * fiasco, const char * file) {
int fiasco_unpack(struct fiasco * fiasco, const char * dir) {
- int fd = -1;
- char * name = NULL;
- char * layout_name = NULL;
+ int fd;
+ char * name;
+ char * layout_name;
struct image * image;
struct image_list * image_list;
uint32_t size;
@@ -480,6 +484,10 @@ int fiasco_unpack(struct fiasco * fiasco, const char * dir) {
while ( image_list ) {
+ fd = -1;
+ name = NULL;
+ layout_name = NULL;
+
image = image_list->image;
name = image_name_alloc_from_values(image);
@@ -492,9 +500,11 @@ int fiasco_unpack(struct fiasco * fiasco, const char * dir) {
if ( image->layout ) {
- layout_name = calloc(1, strlen(name) + strlen(".layout") + 1);
- if ( ! layout_name )
+ layout_name = calloc(1, strlen(name) + sizeof(".layout")-1 + 1);
+ if ( ! layout_name ) {
+ free(name);
ALLOC_ERROR_RETURN(-1);
+ }
sprintf(layout_name, "%s.layout", name);
@@ -508,21 +518,32 @@ int fiasco_unpack(struct fiasco * fiasco, const char * dir) {
fd = open(name, O_RDWR|O_CREAT|O_TRUNC, 0644);
if ( fd < 0 ) {
ERROR_INFO("Cannot create output file %s", name);
+ free(name);
+ free(layout_name);
return -1;
}
}
- free(name);
-
image_seek(image, 0);
while ( 1 ) {
size = image_read(image, buf, sizeof(buf));
if ( size == 0 )
break;
- WRITE_OR_FAIL(name, fd, buf, size);
+ if ( ! simulate ) {
+ if ( write(fd, buf, size) != (ssize_t)size ) {
+ ERROR_INFO_STR(name, "Cannot write %d bytes", size);
+ close(fd);
+ free(name);
+ free(layout_name);
+ return -1;
+ }
+ }
}
- close(fd);
+ free(name);
+
+ if ( ! simulate )
+ close(fd);
if ( image->layout ) {
@@ -530,15 +551,24 @@ int fiasco_unpack(struct fiasco * fiasco, const char * dir) {
fd = open(layout_name, O_RDWR|O_CREAT|O_TRUNC, 0644);
if ( fd < 0 ) {
ERROR_INFO("Cannot create layout file %s", layout_name);
+ free(layout_name);
+ return -1;
+ }
+
+ size = strlen(image->layout);
+
+ if ( write(fd, image->layout, size) != (ssize_t)size ) {
+ ERROR_INFO_STR(layout_name, "Cannot write %d bytes", size);
+ close(fd);
+ free(layout_name);
return -1;
}
}
free(layout_name);
- WRITE_OR_FAIL(layout_name, fd, image->layout, (int)strlen(image->layout));
-
- close(fd);
+ if ( ! simulate )
+ close(fd);
}
diff --git a/src/image.c b/src/image.c
index 44655fb..48d80d8 100644
--- a/src/image.c
+++ b/src/image.c
@@ -88,14 +88,13 @@ static void image_missing_values_from_name(struct image * image, const char * na
if ( image->devices && image->devices->device && ! image->devices->hwrevs )
image->devices->hwrevs = hwrevs_alloc_from_string(hwrevs);
- else
- free(hwrevs);
if ( ! image->version )
image->version = version;
else
free(version);
+ free(hwrevs);
free(str);
}
@@ -135,8 +134,10 @@ char * image_name_alloc_from_values(struct image * image) {
length += 1 + strlen(image->version);
name = calloc(1, length);
- if ( ! name )
+ if ( ! name ) {
+ free(hwrevs);
ALLOC_ERROR_RETURN(NULL);
+ }
strcpy(name, type);
ptr = name + strlen(name);
diff --git a/src/local.c b/src/local.c
index e90011b..c7f3ad1 100644
--- a/src/local.c
+++ b/src/local.c
@@ -127,9 +127,9 @@ int local_init(void) {
while ( fgets(buf, sizeof(buf), file) ) {
- if ( strncmp(buf, "Hardware", strlen("Hardware")) == 0 ) {
+ if ( strncmp(buf, "Hardware", sizeof("Hardware")-1) == 0 ) {
- ptr = buf + strlen("Hardware");
+ ptr = buf + sizeof("Hardware")-1;
while ( ptr < buf + sizeof(buf) && *ptr > 0 && *ptr <= 32 )
++ptr;
@@ -316,21 +316,23 @@ int local_dump_image(enum image_type image, const char * file) {
while ( ( dirent = readdir(dir) ) ) {
- snprintf(buf, sizeof(buf), "/sys/class/mmc_host/%s/slot_name", dirent->d_name);
+ if ( snprintf(buf, sizeof(buf), "/sys/class/mmc_host/%s/slot_name", dirent->d_name) <= 0 )
+ continue;
fd = open(buf, O_RDONLY);
if ( fd < 0 )
continue;
- buf[0] = 0;
- if ( read(fd, buf, sizeof(buf)) < 0 )
+ memset(buf, 0, sizeof(buf));
+ if ( read(fd, buf, sizeof(buf)-1) < 0 )
buf[0] = 0;
close(fd);
- if ( strncmp(buf, "internal", strlen("internal")) != 0 )
+ if ( strncmp(buf, "internal", sizeof("internal")-1) != 0 )
continue;
- snprintf(buf, sizeof(buf), "/sys/class/mmc_host/%s/%s:0001/", dirent->d_name, dirent->d_name);
+ if ( snprintf(buf, sizeof(buf), "/sys/class/mmc_host/%s/%s:0001/", dirent->d_name, dirent->d_name) <= 0 )
+ continue;
dir2 = opendir(buf);
if ( ! dir2 )
@@ -338,10 +340,11 @@ int local_dump_image(enum image_type image, const char * file) {
while ( ( dirent2 = readdir(dir2) ) ) {
- if ( strncmp(dirent2->d_name, "block:mmcblk", strlen("block:mmcblk")) != 0 )
+ if ( strncmp(dirent2->d_name, "block:mmcblk", sizeof("block:mmcblk")-1) != 0 )
continue;
- snprintf(buf, sizeof(buf), "/sys/class/mmc_host/%s/%s:0001/%s/dev", dirent->d_name, dirent->d_name, dirent2->d_name);
+ if ( snprintf(buf, sizeof(buf), "/sys/class/mmc_host/%s/%s:0001/%s/dev", dirent->d_name, dirent->d_name, dirent2->d_name) <= 0 )
+ continue;
f = fopen(buf, "r");
if ( ! f )
@@ -385,7 +388,8 @@ int local_dump_image(enum image_type image, const char * file) {
while ( ( dirent = readdir(dir) ) ) {
- snprintf(buf, sizeof(buf), "/dev/%s", dirent->d_name);
+ if ( snprintf(buf, sizeof(buf), "/dev/%s", dirent->d_name) <= 0 )
+ continue;
if ( stat(buf, &st) != 0 )
continue;
@@ -410,7 +414,7 @@ int local_dump_image(enum image_type image, const char * file) {
VERBOSE("Detected internal mmc device: '%s'\n", blk);
- strncat(blk, "p1", sizeof(blk));
+ strncat(blk, "p1", sizeof(blk)-strlen(blk)-1);
printf("Using MyDocs mmc device: '%s'\n", blk);
@@ -457,6 +461,10 @@ int local_dump_image(enum image_type image, const char * file) {
if ( addr[nlen-1] != 0xFF )
break;
+ for ( ; nlen > 0; --nlen )
+ if ( addr[nlen-1] != 0x00 )
+ break;
+
if ( image == IMAGE_MMC )
align = 8;
else
@@ -532,7 +540,7 @@ int local_set_usb_host_mode(int enable) {
int local_get_rd_mode(void) {
- if ( strncmp(rd_mode, "master", strlen("master")) == 0 )
+ if ( strncmp(rd_mode, "master", sizeof("master")-1) == 0 )
return 1;
else
return 0;
@@ -551,8 +559,8 @@ int local_get_rd_flags(char * flags, size_t size) {
const char * ptr;
- if ( strncmp(rd_mode, "master", strlen("master")) == 0 )
- ptr = rd_mode + strlen("master");
+ if ( strncmp(rd_mode, "master", sizeof("master")-1) == 0 )
+ ptr = rd_mode + sizeof("master")-1;
else
ptr = rd_mode;
diff --git a/src/main.c b/src/main.c
index fdd2b4b..0552593 100644
--- a/src/main.c
+++ b/src/main.c
@@ -53,8 +53,8 @@ static void show_usage(void) {
" -f flash all specified images\n"
" -c cold flash 2nd and secondary images\n"
" -x [/dev/mtd] check for bad blocks on mtd device (default: all)\n"
- " -E file dump all device images to one fiasco image, see -t\n"
- " -e [dir] dump all device images to directory, see -t (default: current)\n"
+ " -E file dump all device images to one fiasco image\n"
+ " -e [dir] dump all device images (or one -t) to directory (default: current)\n"
"\n"
"Device configuration:\n"
@@ -84,7 +84,7 @@ static void show_usage(void) {
"\n"
"Image filters:\n"
- " -t types filter images by type\n"
+ " -t type filter images by type\n"
" -d dev filter images by device\n"
" -w hw filter images by HW revision\n"
"\n"
@@ -210,7 +210,7 @@ static void parse_image_arg(char * arg, struct image_list ** image_first) {
exit(1);
}
lseek(fd, 0, SEEK_SET);
- layout = malloc(len);
+ layout = malloc(len+1);
if ( ! layout ) {
ALLOC_ERROR();
exit(1);
@@ -219,6 +219,8 @@ static void parse_image_arg(char * arg, struct image_list ** image_first) {
ERROR_INFO("Cannot read %lu bytes from layout file %s", len, layout_file);
exit(1);
}
+ layout[len] = 0;
+ close(fd);
}
image = image_alloc_from_file(file, type, device, hwrevs, version, layout);
@@ -661,6 +663,9 @@ int main(int argc, char **argv) {
goto clean;
}
filter_images_by_type(type, &image_first);
+ /* make sure that fiasco_in has valid images */
+ if ( fiasco_in )
+ fiasco_in->first = image_first;
}
/* filter images by device */
@@ -672,11 +677,18 @@ int main(int argc, char **argv) {
goto clean;
}
filter_images_by_device(device, &image_first);
+ /* make sure that fiasco_in has valid images */
+ if ( fiasco_in )
+ fiasco_in->first = image_first;
}
/* filter images by hwrev */
- if ( filter_hwrev )
+ if ( filter_hwrev ) {
filter_images_by_hwrev(atoi(filter_hwrev_arg), &image_first);
+ /* make sure that fiasco_in has valid images */
+ if ( fiasco_in )
+ fiasco_in->first = image_first;
+ }
/* reorder images for flashing (first x-loader, second secondary) */
/* set 2nd and secondary images for cold-flashing */
@@ -740,11 +752,29 @@ int main(int argc, char **argv) {
image_ptr = next;
}
+ /* make sure that fiasco_in has valid images */
+ if ( fiasco_in )
+ fiasco_in->first = image_first;
+
}
- /* make sure that fiasco_in has valid images*/
- if ( fiasco_in )
- fiasco_in->first = image_first;
+ /* remove 2nd image when doing normal flash */
+ if ( dev_flash ) {
+ image_ptr = image_first;
+ while ( image_ptr ) {
+ struct image_list * next = image_ptr->next;
+ if ( image_ptr->image->type == IMAGE_2ND ) {
+ if ( image_ptr == image_first )
+ image_first = next;
+ image_list_del(image_ptr);
+ }
+ image_ptr = next;
+ }
+
+ /* make sure that fiasco_in has valid images */
+ if ( fiasco_in )
+ fiasco_in->first = image_first;
+ }
/* identify images */
if ( image_ident ) {
@@ -782,8 +812,9 @@ int main(int argc, char **argv) {
WARNING("Removing unknown image (specified by %s %s)", image_ptr->image->orig_filename ? "file" : "fiasco", image_ptr->image->orig_filename ? image_ptr->image->orig_filename : "image");
if ( image_ptr == image_first )
image_first = next;
- image_list_unlink(image_ptr);
- free(image_ptr);
+ if ( fiasco_in && image_ptr == fiasco_in->first )
+ fiasco_in->first = fiasco_in->first->next;
+ image_list_del(image_ptr);
}
image_ptr = next;
}
@@ -983,6 +1014,8 @@ int main(int argc, char **argv) {
filter_images_by_device(dev->detected_device, &image_first);
if ( detected_hwrev )
filter_images_by_hwrev(dev->detected_hwrev, &image_first);
+ if ( fiasco_in && ( detected_device || detected_hwrev ) )
+ fiasco_in->first = image_first;
/* set kernel and initfs images for loading */
if ( dev_load ) {
@@ -1047,8 +1080,7 @@ int main(int argc, char **argv) {
if ( fiasco_in && image_kernel == fiasco_in->first )
fiasco_in->first = fiasco_in->first->next;
- image_list_unlink(image_kernel);
- free(image_kernel);
+ image_list_del(image_kernel);
image_kernel = NULL;
}
@@ -1059,11 +1091,10 @@ int main(int argc, char **argv) {
if ( image_initfs == image_first )
image_first = image_first->next;
- if ( fiasco_in && image_kernel == fiasco_in->first )
+ if ( fiasco_in && image_initfs == fiasco_in->first )
fiasco_in->first = fiasco_in->first->next;
- image_list_unlink(image_initfs);
- free(image_initfs);
+ image_list_del(image_initfs);
image_initfs = NULL;
}
}
@@ -1079,11 +1110,10 @@ int main(int argc, char **argv) {
if ( image_ptr == image_first )
image_first = image_first->next;
- if ( fiasco_in && image_kernel == fiasco_in->first )
+ if ( fiasco_in && image_ptr == fiasco_in->first )
fiasco_in->first = fiasco_in->first->next;
- image_list_unlink(image_ptr);
- free(image_ptr);
+ image_list_del(image_ptr);
image_ptr = next;
}
}
@@ -1175,9 +1205,21 @@ int main(int argc, char **argv) {
buf[0] = 0;
}
- for ( i = 0; i < IMAGE_COUNT; ++i )
- if ( image_tmp_name(i) )
- dev_dump_image(dev, i, image_tmp_name(i));
+ if ( filter_type ) {
+ enum image_type type = image_type_from_string(filter_type_arg);
+ if ( ! type || ! image_tmp_name(type) ) {
+ ERROR("Specified unknown image type for filtering: %s", filter_type_arg);
+ ret = 1;
+ goto clean;
+ }
+ ret = dev_dump_image(dev, type, image_tmp_name(type));
+ if ( ret != 0 )
+ goto clean;
+ } else {
+ for ( i = 0; i < IMAGE_COUNT; ++i )
+ if ( image_tmp_name(i) )
+ dev_dump_image(dev, i, image_tmp_name(i));
+ }
if ( buf[0] )
if ( chdir(buf) < 0 )
@@ -1196,7 +1238,8 @@ int main(int argc, char **argv) {
if ( ! image_tmp_name(i) )
continue;
- sprintf(buf, "%hd", dev->detected_hwrev);
+ buf[0] = 0;
+ snprintf(buf, sizeof(buf), "%hd", dev->detected_hwrev);
switch ( i ) {
case IMAGE_2ND:
@@ -1298,14 +1341,16 @@ int main(int argc, char **argv) {
break;
}
- sprintf(buf, "%s-%s:%hd_%s", image_type_to_string(i), device_to_string(dev->detected_device), dev->detected_hwrev, ptr);
+ buf[0] = 0;
+ snprintf(buf, sizeof(buf), "%s-%s:%hd_%s", image_type_to_string(i), device_to_string(dev->detected_device), dev->detected_hwrev, ptr);
printf("Renaming %s image file to %s...\n", image_type_to_string(i), buf);
if ( rename(image_tmp_name(i), buf) < 0 ) {
ERROR_INFO("Renaming failed");
- sprintf(buf, "%s-%s_%s", image_type_to_string(i), device_to_string(dev->detected_device), ptr);
+ buf[0] = 0;
+ snprintf(buf, sizeof(buf), "%s-%s_%s", image_type_to_string(i), device_to_string(dev->detected_device), ptr);
printf("Trying to rename %s image file to %s...\n", image_type_to_string(i), buf);
if ( rename(image_tmp_name(i), buf) < 0 )
diff --git a/src/nolo.c b/src/nolo.c
index 238336d..e437ef7 100644
--- a/src/nolo.c
+++ b/src/nolo.c
@@ -84,12 +84,14 @@ static void nolo_error_log(struct usb_device_info * dev, int only_clear) {
char buf[2048];
size_t i, count;
+ int ret;
for ( count = 0; count < 20; ++count ) {
memset(buf, 0, sizeof(buf));
- if ( usb_control_msg(dev->udev, NOLO_QUERY, NOLO_ERROR_LOG, 0, 0, buf, sizeof(buf), 2000) <= 0 )
+ ret = usb_control_msg(dev->udev, NOLO_QUERY, NOLO_ERROR_LOG, 0, 0, buf, sizeof(buf), 2000);
+ if ( ret < 0 )
break;
if ( ! only_clear ) {
@@ -103,6 +105,9 @@ static void nolo_error_log(struct usb_device_info * dev, int only_clear) {
}
+ if ( (size_t)ret < sizeof(buf) )
+ break;
+
}
}
@@ -176,14 +181,14 @@ static int nolo_get_version_string(struct usb_device_info * dev, const char * st
if ( strlen(str) > 500 )
return -1;
- sprintf(buf, "version:%s", str);
+ if ( sprintf(buf, "version:%s", str) <= 0 )
+ return -1;
ret = nolo_get_string(dev, buf, out, size);
-
- nolo_error_log(dev, 1);
-
- if ( ret < 0 )
+ if ( ret < 0 ) {
+ nolo_error_log(dev, 1);
return ret;
+ }
if ( ! out[0] )
return -1;
@@ -311,7 +316,7 @@ static int nolo_send_image(struct usb_device_info * dev, struct image * image, i
if ( bufs ) {
memset(buf, 0, sizeof(buf));
- snprintf(buf, 8, "%d", dev->hwrev);
+ snprintf(buf, 8+1, "%d", dev->hwrev);
for ( i = 0; bufs[i]; ++i ) {
len = ((uint8_t*)bufs[i])[0];
@@ -418,8 +423,8 @@ int nolo_flash_image(struct usb_device_info * dev, struct image * image) {
unsigned long long int part;
unsigned long long int total;
unsigned long long int last_total;
- char status[20];
char buf[128];
+ char * ptr;
if ( image->type == IMAGE_ROOTFS )
flash = 1;
@@ -463,7 +468,7 @@ int nolo_flash_image(struct usb_device_info * dev, struct image * image) {
if ( nolo_get_string(dev, "cmt:status", buf, sizeof(buf)) < 0 )
NOLO_ERROR_RETURN("cmt:status failed", -1);
- if ( strncmp(buf, "idle", strlen("idle")) == 0 )
+ if ( strncmp(buf, "idle", sizeof("idle")-1) == 0 )
state = 4;
else
printf("Erasing CMT...\n");
@@ -475,7 +480,7 @@ int nolo_flash_image(struct usb_device_info * dev, struct image * image) {
NOLO_ERROR_RETURN("cmt:status failed", -1);
}
- if ( strncmp(buf, "finished", strlen("finished")) == 0 ) {
+ if ( strncmp(buf, "finished", sizeof("finished")-1) == 0 ) {
if ( state <= 0 ) {
printf_progressbar(last_total, last_total);
@@ -490,18 +495,29 @@ int nolo_flash_image(struct usb_device_info * dev, struct image * image) {
state = 4;
+ } else if ( strncmp(buf, "error", sizeof("error")-1) == 0 ) {
+
+ PRINTF_ERROR_RETURN("cmt:status error", -1);
+
} else {
- if ( sscanf(buf, "%s:%llu/%llu", status, &part, &total) != 3 )
+ ptr = strchr(buf, ':');
+ if ( ! ptr )
+ PRINTF_ERROR_RETURN("cmt:status unknown", -1);
+
+ *ptr = 0;
+ ptr++;
+
+ if ( sscanf(ptr, "%llu/%llu", &part, &total) != 2 )
PRINTF_ERROR_RETURN("cmt:status unknown", -1);
- if ( strcmp(status, "program") == 0 && state <= 0 ) {
+ if ( strcmp(buf, "program") == 0 && state <= 0 ) {
printf_progressbar(last_total, last_total);
printf("Done\n");
state = 1;
}
- if ( strcmp(status, "program") == 0 && state <= 1 ) {
+ if ( strcmp(buf, "program") == 0 && state <= 1 ) {
printf("Programming CMT...\n");
state = 2;
}
@@ -509,12 +525,12 @@ int nolo_flash_image(struct usb_device_info * dev, struct image * image) {
printf_progressbar(part, total);
last_total = total;
- if ( strcmp(status, "erase") == 0 && state <= 0 && part == total ) {
+ if ( strcmp(buf, "erase") == 0 && state <= 0 && part == total ) {
printf("Done\n");
state = 1;
}
- if ( strcmp(status, "program") == 0 && state <= 2 && part == total ) {
+ if ( strcmp(buf, "program") == 0 && state <= 2 && part == total ) {
printf("Done\n");
state = 3;
}
@@ -536,9 +552,9 @@ int nolo_boot_device(struct usb_device_info * dev, const char * cmdline) {
int size = 0;
int mode = NOLO_BOOT_MODE_NORMAL;
- if ( cmdline && strncmp(cmdline, "update", strlen("update")) == 0 && cmdline[strlen("update")] <= 32 ) {
+ if ( cmdline && strncmp(cmdline, "update", sizeof("update")-1) == 0 && cmdline[sizeof("update")-1] <= 32 ) {
mode = NOLO_BOOT_MODE_UPDATE;
- cmdline += strlen("update");
+ cmdline += sizeof("update")-1;
if ( *cmdline ) ++cmdline;
while ( *cmdline && *cmdline <= 32 )
++cmdline;
@@ -763,7 +779,7 @@ int nolo_set_hwrev(struct usb_device_info * dev, int16_t hwrev) {
char buf[9];
memset(buf, 0, sizeof(buf));
- snprintf(buf, 8, "%d", hwrev);
+ snprintf(buf, sizeof(buf), "%d", hwrev);
printf("Setting HW revision to: %s\n", buf);
return nolo_set_string(dev, "hw_rev", buf);
diff --git a/src/printf-utils.c b/src/printf-utils.c
index 939cf54..3520d0b 100644
--- a/src/printf-utils.c
+++ b/src/printf-utils.c
@@ -39,7 +39,7 @@ void printf_progressbar(unsigned long long part, unsigned long long total) {
int tmp, cols = 80;
/* percentage calculation */
- pc = (int)(part*100/total);
+ pc = total==0?100:(int)(part*100/total);
(pc<0)?pc=0:(pc>100)?pc=100:0;
PRINTF_BACK();
diff --git a/src/usb-device.c b/src/usb-device.c
index 039e82e..bf1241e 100644
--- a/src/usb-device.c
+++ b/src/usb-device.c
@@ -27,6 +27,10 @@
#include <usb.h>
+#ifdef LIBUSB_HAS_DETACH_KERNEL_DRIVER_NP
+#include <sys/ioctl.h>
+#endif
+
#include "global.h"
#include "device.h"
#include "usb-device.h"
@@ -73,6 +77,25 @@ static void usb_flash_device_info_print(const struct usb_flash_device * dev) {
}
+static void usb_reattach_kernel_driver(usb_dev_handle * udev, int interface) {
+
+#ifdef LIBUSB_HAS_DETACH_KERNEL_DRIVER_NP
+ struct {
+ int ifno;
+ int ioctl_code;
+ void * data;
+ } command = {
+ .ifno = interface,
+ .ioctl_code = _IO('U', 23),
+ .data = NULL,
+ };
+
+ usb_release_interface(udev, interface);
+ ioctl(*((int *)udev), _IOWR('U', 18, command), &command);
+#endif
+
+}
+
static void usb_descriptor_info_print(usb_dev_handle * udev, struct usb_device * dev, char * product, size_t size) {
char buf[1024];
@@ -145,6 +168,7 @@ static struct usb_device_info * usb_device_is_valid(struct usb_device * dev) {
if ( usb_claim_interface(udev, usb_devices[i].interface) < 0 ) {
PRINTF_ERROR("usb_claim_interface failed");
fprintf(stderr, "\n");
+ usb_reattach_kernel_driver(udev, usb_devices[i].interface);
usb_close(udev);
return NULL;
}
@@ -154,6 +178,7 @@ static struct usb_device_info * usb_device_is_valid(struct usb_device * dev) {
if ( usb_set_altinterface(udev, usb_devices[i].alternate) < 0 ) {
PRINTF_ERROR("usb_claim_interface failed");
fprintf(stderr, "\n");
+ usb_reattach_kernel_driver(udev, usb_devices[i].interface);
usb_close(udev);
return NULL;
}
@@ -164,6 +189,7 @@ static struct usb_device_info * usb_device_is_valid(struct usb_device * dev) {
if ( usb_set_configuration(udev, usb_devices[i].configuration) < 0 ) {
PRINTF_ERROR("usb_set_configuration failed");
fprintf(stderr, "\n");
+ usb_reattach_kernel_driver(udev, usb_devices[i].interface);
usb_close(udev);
return NULL;
}
@@ -172,6 +198,7 @@ static struct usb_device_info * usb_device_is_valid(struct usb_device * dev) {
ret = calloc(1, sizeof(struct usb_device_info));
if ( ! ret ) {
ALLOC_ERROR();
+ usb_reattach_kernel_driver(udev, usb_devices[i].interface);
usb_close(udev);
return NULL;
}
@@ -197,7 +224,9 @@ static struct usb_device_info * usb_device_is_valid(struct usb_device * dev) {
if ( ! *device ) {
ERROR("Device mishmash");
fprintf(stderr, "\n");
+ usb_reattach_kernel_driver(udev, usb_devices[i].interface);
usb_close(udev);
+ free(ret);
return NULL;
}
}
@@ -308,6 +337,7 @@ struct usb_device_info * usb_open_and_wait_for_device(void) {
void usb_close_device(struct usb_device_info * dev) {
+ usb_reattach_kernel_driver(dev->udev, dev->flash_device->interface);
usb_close(dev->udev);
free(dev);