summaryrefslogtreecommitdiffstats
path: root/commands
diff options
context:
space:
mode:
authorNishanth Menon <x0nishan@ti.com>2008-08-19 16:51:45 -0500
committerSascha Hauer <s.hauer@pengutronix.de>2008-08-20 09:17:32 +0200
commit580cd4ff283fd9aa36ea077c6cf136153f3ea044 (patch)
tree9a5541df0bd5a18cc65cfcc4c65b5619ec65e3b5 /commands
parent1e49fadf8ada076514afdebe89ddc0a22c4239d9 (diff)
downloadbarebox-580cd4ff283fd9aa36ea077c6cf136153f3ea044.tar.gz
barebox-580cd4ff283fd9aa36ea077c6cf136153f3ea044.tar.xz
loadb: Add buffered write
Default loadb behavior works on packet sized chunks of kermit data to be put on target file This would not work good on block devices such as NAND. solution will be to buffer data up to standard 4096 chunks before giving to device. Signed-off-by: Nishanth Menon <x0nishan@ti.com>
Diffstat (limited to 'commands')
-rw-r--r--commands/loadb.c55
1 files changed, 49 insertions, 6 deletions
diff --git a/commands/loadb.c b/commands/loadb.c
index 6f05cb42e0..1a3c30f7f6 100644
--- a/commands/loadb.c
+++ b/commands/loadb.c
@@ -63,6 +63,11 @@
static int ofd; /* output file descriptor */
+/* Size of my buffer to write to o/p file */
+#define MAX_WRITE_BUFFER 4096 /* Write size to o/p file */
+static char *write_buffer; /* buffer for finalized data to write */
+static int write_idx; /* index to the current location in buffer */
+
static char his_eol; /* character he needs at end of packet */
static int his_pad_count; /* number of pad chars he needs */
static char his_pad_char; /* pad chars he needs */
@@ -164,14 +169,31 @@ static int os_data_alloc(int length)
static int os_data_save(void)
{
int ret = 0;
+ int copy_size;
/* if there was an old data, flush it */
if (os_old_buffer) {
- flush_cache((ulong) os_old_buffer, os_old_count);
- ret = write(ofd, os_old_buffer, os_old_count);
- if (ret < 0)
- return ret;
- os_data_total += os_old_count;
- free(os_old_buffer);
+ char *ori_buf = os_old_buffer;
+ do {
+ if (write_idx == MAX_WRITE_BUFFER) {
+ ret = write(ofd, write_buffer,
+ MAX_WRITE_BUFFER);
+ if (ret < 0) {
+ fprintf(stderr,
+ "write to device failed\n");
+ return ret;
+ }
+ write_idx = 0;
+ }
+ copy_size = min(os_old_count, (MAX_WRITE_BUFFER -
+ write_idx));
+ memcpy(write_buffer + write_idx, os_old_buffer,
+ copy_size);
+ write_idx += copy_size;
+ os_data_total += copy_size;
+ os_old_count -= copy_size;
+ os_old_buffer += copy_size;
+ } while (os_old_count); /* if remaining bytes */
+ free(ori_buf);
}
os_old_count = os_data_count;
os_old_buffer = os_data_addr - os_data_count;
@@ -533,6 +555,14 @@ static ulong load_serial_bin(void)
int size, i;
char buf[32];
+ /* Try to allocate the buffer we shall write to files */
+ write_buffer = malloc(MAX_WRITE_BUFFER);
+ if (write_buffer == NULL) {
+ fprintf(stderr, "could not allocate file i/o buffer\n");
+ return -ENOMEM;
+ }
+
+ /* Lets get the image from host */
size = k_recv();
/*
@@ -545,10 +575,23 @@ static ulong load_serial_bin(void)
(void)getc();
udelay(1000);
}
+
+ /* Flush out the remaining data if any */
+ if (write_idx > 0) {
+ i = write(ofd, write_buffer, write_idx);
+ if (i < 0) {
+ fprintf(stderr, "write to device failed\n");
+ size = i;
+ goto err_quit;
+ }
+ write_idx = 0;
+ }
printf("## Total Size = 0x%08x = %d Bytes\n", size, size);
sprintf(buf, "%X", size);
setenv("filesize", buf);
+err_quit:
+ free(write_buffer);
return size;
}