imx-usb-loader tries to safe memory by reading the image in chunks.
This is unnecessarily complicated. The images are small, so fully read
them into memory and store them in a single buffer. This makes handling
them a lot easier.

Signed-off-by: Sascha Hauer <[email protected]>
---
 scripts/imx/imx-usb-loader.c | 246 +++++++++++++------------------------------
 1 file changed, 75 insertions(+), 171 deletions(-)

diff --git a/scripts/imx/imx-usb-loader.c b/scripts/imx/imx-usb-loader.c
index 5a94cf1..d3de05f 100644
--- a/scripts/imx/imx-usb-loader.c
+++ b/scripts/imx/imx-usb-loader.c
@@ -750,81 +750,42 @@ static int write_dcd_table_old(struct 
libusb_device_handle *h, struct usb_id *p_
 }
 
 static int verify_memory(struct libusb_device_handle *h, struct usb_id *p_id,
-               FILE *xfile, unsigned offset, unsigned addr, unsigned size,
-               unsigned char *verify_buffer, unsigned verify_cnt)
+                        const void *buf, unsigned len, unsigned addr)
 {
-       int mismatch = 0;
-       unsigned char file_buf[1024];
-       fseek(xfile, offset + verify_cnt, SEEK_SET);
-
-       while (size) {
-               unsigned char mem_buf[64];
-               unsigned char *p = file_buf;
-               int cnt = addr & 0x3f;
-               int request = get_min(size, sizeof(file_buf));
-
-               if (cnt) {
-                       cnt = 64 - cnt;
-                       if (request > cnt)
-                               request = cnt;
-               }
-
-               if (verify_cnt) {
-                       p = verify_buffer;
-                       cnt = get_min(request, verify_cnt);
-                       verify_buffer += cnt;
-                       verify_cnt -= cnt;
-               } else {
-                       cnt = fread(p, 1, request, xfile);
-                       if (cnt <= 0) {
-                               printf("Unexpected end of file, request=0x%0x, 
size=0x%x, cnt=%i\n",
-                                               request, size, cnt);
-                               return -1;
-                       }
-               }
-
-               size -= cnt;
-
-               while (cnt) {
-                       int ret;
-
-                       request = get_min(cnt, sizeof(mem_buf));
+       int ret, mismatch = 0;
+       void *readbuf;
+       unsigned offset = 0, now;
 
-                       ret = read_memory(h, p_id, addr, mem_buf, request);
-                       if (ret < 0)
-                               return ret;
+       readbuf = malloc(len);
+       if (!readbuf)
+               return -ENOMEM;
 
-                       if (memcmp(p, mem_buf, request)) {
-                               unsigned char * m = mem_buf;
-                               if (!mismatch)
-                                       printf("!!!!mismatch\n");
-                               mismatch++;
-
-                               while (request) {
-                                       unsigned req = get_min(request, 32);
-                                       if (memcmp(p, m, req)) {
-                                               dump_long(p, req, offset);
-                                               dump_long(m, req, addr);
-                                               printf("\n");
-                                       }
-                                       p += req;
-                                       m+= req;
-                                       offset += req;
-                                       addr += req;
-                                       cnt -= req;
-                                       request -= req;
-                               }
-                               if (mismatch >= 5)
-                                       return -1;
-                       }
-                       p += request;
-                       offset += request;
-                       addr += request;
-                       cnt -= request;
+       ret = read_memory(h, p_id, addr, readbuf, len);
+       if (ret < 0)
+               goto err;
+
+       while (len) {
+               now = get_min(len, 32);
+
+               if (memcmp(buf + offset, readbuf + offset, now)) {
+                       printf("mismatch at offset 0x%08x. expected:\n", 
offset);
+                       dump_long(buf + offset, now, addr + offset);
+                       printf("read:\n");
+                       dump_long(readbuf + offset, now, addr + offset);
+                       ret = -EINVAL;
+                       mismatch++;
+                       if (mismatch > 4)
+                               goto err;
                }
+
+               len -= now;
+               offset += now;
        }
 
-       return mismatch ? -1 : 0;
+err:
+       free(readbuf);
+
+       return ret;
 }
 
 static int is_header(struct usb_id *p_id, unsigned char *p)
@@ -998,8 +959,7 @@ static int process_header(struct libusb_device_handle *h, 
struct usb_id *p_id,
 }
 
 static int load_file(struct libusb_device_handle *h, struct usb_id *p_id,
-               unsigned char *p, int cnt, unsigned char *buf, unsigned buf_cnt,
-               unsigned dladdr, unsigned fsize, unsigned char type, FILE* 
xfile)
+               void *buf, unsigned len, unsigned dladdr, unsigned char type)
 {
        static unsigned char dl_command[] = {
                0x04,
@@ -1013,18 +973,19 @@ static int load_file(struct libusb_device_handle *h, 
struct usb_id *p_id,
        int last_trans, err;
        int retry = 0;
        unsigned transfer_size = 0;
-       int max = p_id->mach_id->max_transfer;
        unsigned char tmp[64];
+       void *p;
+       int cnt;
 
        dl_command[2] = (unsigned char)(dladdr >> 24);
        dl_command[3] = (unsigned char)(dladdr >> 16);
        dl_command[4] = (unsigned char)(dladdr >> 8);
        dl_command[5] = (unsigned char)(dladdr);
 
-       dl_command[7] = (unsigned char)(fsize >> 24);
-       dl_command[8] = (unsigned char)(fsize >> 16);
-       dl_command[9] = (unsigned char)(fsize >> 8);
-       dl_command[10] = (unsigned char)(fsize);
+       dl_command[7] = (unsigned char)(len >> 24);
+       dl_command[8] = (unsigned char)(len >> 16);
+       dl_command[9] = (unsigned char)(len >> 8);
+       dl_command[10] = (unsigned char)(len);
        dl_command[15] =  type;
 
        for (;;) {
@@ -1048,61 +1009,23 @@ static int load_file(struct libusb_device_handle *h, 
struct usb_id *p_id,
                                        err, last_trans, tmp[0], tmp[1], 
tmp[2], tmp[3]);
        }
 
-       while (1) {
-               int retry;
+       p = buf;
+       cnt = len;
 
-               if (cnt > (int)(fsize - transfer_size))
-                       cnt = (fsize - transfer_size);
+       while (1) {
+               int now = get_min(cnt, p_id->mach_id->max_transfer);
 
-               if (cnt <= 0)
+               if (!now)
                        break;
 
-               retry = 0;
-
-               while (cnt) {
-                       err = transfer(h, 2, p, get_min(cnt, max), &last_trans, 
p_id);
-                       if (err) {
-                               printf("out err=%i, last_trans=%i cnt=0x%x 
max=0x%x transfer_size=0x%X retry=%i\n",
-                                               err, last_trans, cnt, max, 
transfer_size, retry);
-                               if (retry >= 10) {
-                                       printf("Giving up\n");
-                                       return err;
-                               }
-                               if (max >= 16)
-                                       max >>= 1;
-                               else
-                                       max <<= 1;
-                               usleep(10000);
-                               retry++;
-                               continue;
-                       }
-                       max = p_id->mach_id->max_transfer;
-                       retry = 0;
-                       if (cnt < last_trans) {
-                               printf("error: last_trans=0x%x, attempted 
only=0%x\n", last_trans, cnt);
-                               cnt = last_trans;
-                       }
-                       if (!last_trans) {
-                               printf("Nothing last_trans, err=%i\n", err);
-                               break;
-                       }
-                       p += last_trans;
-                       cnt -= last_trans;
-                       transfer_size += last_trans;
+               err = transfer(h, 2, p, now, &now, p_id);
+               if (err) {
+                       printf("dl_command err=%i, last_trans=%i\n", err, 
last_trans);
+                       return err;
                }
 
-               if (!last_trans)
-                       break;
-
-               if (feof(xfile))
-                       break;
-
-               cnt = fsize - transfer_size;
-               if (cnt <= 0)
-                       break;
-
-               cnt = fread(buf, 1 , get_min(cnt, buf_cnt), xfile);
-               p = buf;
+               p += now;
+               cnt -= now;
        }
 
        if (p_id->mach_id->mode == MODE_HID) {
@@ -1134,10 +1057,9 @@ static int do_irom_download(struct libusb_device_handle 
*h, struct usb_id *p_id,
        int cnt;
        unsigned file_base;
        int last_trans, err;
-#define BUF_SIZE (1024*16)
        unsigned char *buf = NULL;
+       unsigned char *image;
        unsigned char *verify_buffer = NULL;
-       unsigned verify_cnt;
        unsigned char *p;
        unsigned char tmp[64];
        unsigned dladdr = 0;
@@ -1146,7 +1068,6 @@ static int do_irom_download(struct libusb_device_handle 
*h, struct usb_id *p_id,
        unsigned header_addr = 0;
 
        unsigned skip = 0;
-       unsigned transfer_size=0;
        int retry = 0;
 
        xfile = fopen(curr->filename, "rb" );
@@ -1155,23 +1076,26 @@ static int do_irom_download(struct libusb_device_handle 
*h, struct usb_id *p_id,
                return -5;
        }
 
-       buf = malloc(BUF_SIZE);
-       if (!buf) {
-               printf("error, out of memory\n");
+       fsize = get_file_size(xfile);
+       if (fsize < 0x20) {
+               printf("error, file: %s is too small\n", curr->filename);
                ret = -2;
                goto cleanup;
        }
 
-       fsize = get_file_size(xfile);
-
-       cnt = fread(buf, 1 , BUF_SIZE, xfile);
-
-       if (cnt < 0x20) {
-               printf("error, file: %s is too small\n", curr->filename);
+       buf = malloc(fsize);
+       if (!buf) {
+               printf("error, out of memory\n");
                ret = -2;
                goto cleanup;
        }
 
+       cnt = fread(buf, 1 , fsize, xfile);
+       if (cnt < fsize) {
+               printf("error, cannot read %s\n", curr->filename);
+               return -1;
+       }
+
        max_length = fsize;
 
        ret = process_header(h, p_id, curr, buf, cnt,
@@ -1215,22 +1139,9 @@ static int do_irom_download(struct libusb_device_handle 
*h, struct usb_id *p_id,
 
        skip = dladdr - file_base;
 
-       if (skip > cnt) {
-               if (skip > fsize) {
-                       printf("skip(0x%08x) > fsize(0x%08x) file_base=0x%08x, 
header_offset=0x%x\n",
-                                       skip, fsize, file_base, header_offset);
-                       ret = -4;
-                       goto cleanup;
-               }
-
-               fseek(xfile, skip, SEEK_SET);
-               cnt -= skip;
-               fsize -= skip;
-               skip = 0;
-               cnt = fread(buf, 1 , BUF_SIZE, xfile);
-       }
+       image = buf + skip;
 
-       p = &buf[skip];
+       p = image;
        cnt -= skip;
        fsize -= skip;
 
@@ -1238,13 +1149,7 @@ static int do_irom_download(struct libusb_device_handle 
*h, struct usb_id *p_id,
                fsize = max_length;
 
        if (verify) {
-               /*
-                * we need to save header for verification
-                * because some of the file is changed
-                * before download
-                */
-               verify_buffer = malloc(cnt);
-               verify_cnt = cnt;
+               verify_buffer = malloc(64);
 
                if (!verify_buffer) {
                        printf("error, out of memory\n");
@@ -1252,7 +1157,7 @@ static int do_irom_download(struct libusb_device_handle 
*h, struct usb_id *p_id,
                        goto cleanup;
                }
 
-               memcpy(verify_buffer, p, cnt);
+               memcpy(verify_buffer, p, 64);
 
                if ((type == FT_APP) && (p_id->mach_id->mode != MODE_HID)) {
                        type = FT_LOAD_ONLY;
@@ -1263,19 +1168,16 @@ static int do_irom_download(struct libusb_device_handle 
*h, struct usb_id *p_id,
        printf("loading binary file(%s) to %08x, skip=0x%x, fsize=%u 
type=%d...\n",
                        curr->filename, dladdr, skip, fsize, type);
 
-       ret = load_file(h, p_id, p, cnt, buf, BUF_SIZE,
-                       dladdr, fsize, type, xfile);
+       ret = load_file(h, p_id, image, fsize, dladdr, type);
        if (ret < 0)
                goto cleanup;
 
        printf("binary file successfully loaded\n");
 
-       transfer_size = ret;
-
        if (verify) {
                printf("verifying file...\n");
 
-               ret = verify_memory(h, p_id, xfile, skip, dladdr, fsize, 
verify_buffer, verify_cnt);
+               ret = verify_memory(h, p_id, image, fsize, dladdr);
                if (ret < 0) {
                        printf("verifying failed\n");
                        goto cleanup;
@@ -1284,11 +1186,13 @@ static int do_irom_download(struct libusb_device_handle 
*h, struct usb_id *p_id,
                printf("file successfully verified\n");
 
                if (verify == 2) {
-                       if (verify_cnt > 64)
-                               verify_cnt = 64;
-                       ret = load_file(h, p_id, verify_buffer, verify_cnt,
-                                       buf, BUF_SIZE, dladdr, verify_cnt,
-                                       FT_APP, xfile);
+                       /*
+                        * In bulk mode we do not have an explicit jump command,
+                        * so we load part of the image again with type FT_APP
+                        * this time.
+                        */
+                       ret = load_file(h, p_id, verify_buffer, 64,
+                                       dladdr, FT_APP);
                        if (ret < 0)
                                goto cleanup;
 
@@ -1327,7 +1231,7 @@ static int do_irom_download(struct libusb_device_handle 
*h, struct usb_id *p_id,
                                        err, last_trans, tmp[0], tmp[1], 
tmp[2], tmp[3]);
        }
 
-       ret = (fsize == transfer_size) ? 0 : -16;
+       ret = 0;
 cleanup:
        fclose(xfile);
        free(verify_buffer);
-- 
2.7.0.rc3


_______________________________________________
barebox mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/barebox

Reply via email to