[PATCH 07/23] scripts: imx-usb-loader: fully read images into memory

Sascha Hauer s.hauer at pengutronix.de
Fri Jan 29 02:43:47 PST 2016


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 <s.hauer at pengutronix.de>
---
 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 58fa12d..fa2ce47 100644
--- a/scripts/imx/imx-usb-loader.c
+++ b/scripts/imx/imx-usb-loader.c
@@ -747,81 +747,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)
@@ -995,8 +956,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,
@@ -1010,18 +970,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 (;;) {
@@ -1045,61 +1006,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) {
@@ -1131,10 +1054,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;
@@ -1143,7 +1065,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" );
@@ -1152,23 +1073,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,
@@ -1212,22 +1136,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;
 
@@ -1235,13 +1146,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");
@@ -1249,7 +1154,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;
@@ -1260,19 +1165,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;
@@ -1281,11 +1183,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;
 
@@ -1324,7 +1228,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




More information about the barebox mailing list