scripts: imx-usb-loader: fully read images into memory
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@pengutronix.de>
This commit is contained in:
parent
2ae40562ae
commit
eee4a26680
|
@ -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);
|
||||
int ret, mismatch = 0;
|
||||
void *readbuf;
|
||||
unsigned offset = 0, now;
|
||||
|
||||
while (size) {
|
||||
unsigned char mem_buf[64];
|
||||
unsigned char *p = file_buf;
|
||||
int cnt = addr & 0x3f;
|
||||
int request = get_min(size, sizeof(file_buf));
|
||||
readbuf = malloc(len);
|
||||
if (!readbuf)
|
||||
return -ENOMEM;
|
||||
|
||||
if (cnt) {
|
||||
cnt = 64 - cnt;
|
||||
if (request > cnt)
|
||||
request = cnt;
|
||||
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;
|
||||
}
|
||||
|
||||
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));
|
||||
|
||||
ret = read_memory(h, p_id, addr, mem_buf, request);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
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;
|
||||
}
|
||||
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]);
|
||||
}
|
||||
|
||||
p = buf;
|
||||
cnt = len;
|
||||
|
||||
while (1) {
|
||||
int retry;
|
||||
int now = get_min(cnt, p_id->mach_id->max_transfer);
|
||||
|
||||
if (cnt > (int)(fsize - transfer_size))
|
||||
cnt = (fsize - transfer_size);
|
||||
|
||||
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,21 +1076,24 @@ static int do_irom_download(struct libusb_device_handle *h, struct usb_id *p_id,
|
|||
return -5;
|
||||
}
|
||||
|
||||
buf = malloc(BUF_SIZE);
|
||||
fsize = get_file_size(xfile);
|
||||
if (fsize < 0x20) {
|
||||
printf("error, file: %s is too small\n", curr->filename);
|
||||
ret = -2;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
buf = malloc(fsize);
|
||||
if (!buf) {
|
||||
printf("error, out of memory\n");
|
||||
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);
|
||||
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;
|
||||
|
@ -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;
|
||||
}
|
||||
image = buf + skip;
|
||||
|
||||
fseek(xfile, skip, SEEK_SET);
|
||||
cnt -= skip;
|
||||
fsize -= skip;
|
||||
skip = 0;
|
||||
cnt = fread(buf, 1 , BUF_SIZE, xfile);
|
||||
}
|
||||
|
||||
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);
|
||||
|
|
Loading…
Reference in New Issue