Index: layout.c |
diff --git a/layout.c b/layout.c |
index c917274a1aeb1fdb4fa98efe56cfb0f7c486ea31..31c99f73b521ac37efd715ab76f8bb6009ace04e 100644 |
--- a/layout.c |
+++ b/layout.c |
@@ -39,6 +39,7 @@ typedef struct { |
unsigned int end; |
unsigned int included; |
char name[256]; |
+ char file[256]; /* file[0]=='\0' means not specified. */ |
} romlayout_t; |
static romlayout_t rom_entries[MAX_ROMLAYOUT]; |
@@ -178,6 +179,7 @@ int read_romlayout(char *name) |
rom_entries[romimages].start = strtol(tstr1, (char **)NULL, 16); |
rom_entries[romimages].end = strtol(tstr2, (char **)NULL, 16); |
rom_entries[romimages].included = 0; |
+ strcpy(rom_entries[romimages].file, ""); |
romimages++; |
} |
@@ -196,15 +198,24 @@ int read_romlayout(char *name) |
int find_romentry(char *name) |
{ |
int i; |
+ char *file = NULL; |
if (!romimages) |
return -1; |
- msg_gdbg("Looking for \"%s\"... ", name); |
+ /* -i <image>[:<file>] */ |
+ if (strtok(name, ":")) { |
+ file = strtok(NULL, ""); |
+ } |
+ msg_gdbg("Looking for \"%s\" (file=\"%s\")... ", |
+ name, file ? file : "<not specified>"); |
for (i = 0; i < romimages; i++) { |
if (!strcmp(rom_entries[i].name, name)) { |
rom_entries[i].included = 1; |
+ snprintf(rom_entries[i].file, |
+ sizeof(rom_entries[i].file), |
+ "%s", file ? file : ""); |
msg_gdbg("found.\n"); |
return i; |
} |
@@ -239,6 +250,32 @@ int find_next_included_romentry(unsigned int start) |
return best_entry; |
} |
+static int read_content_from_file(int entry, uint8_t *newcontents) { |
+ char *file; |
+ FILE *fp; |
+ int len; |
+ |
+ /* If file name is specified for this partition, read file |
+ * content to overwrite. */ |
+ file = rom_entries[entry].file; |
+ len = rom_entries[entry].end - rom_entries[entry].start + 1; |
+ if (file[0]) { |
+ int numbytes; |
+ if ((fp = fopen(file, "rb")) == NULL) { |
+ perror(file); |
+ return -1; |
+ } |
+ numbytes = fread(newcontents + rom_entries[entry].start, |
+ 1, len, fp); |
+ fclose(fp); |
+ if (numbytes == -1) { |
+ perror(file); |
+ return -1; |
+ } |
+ } |
+ return 0; |
+} |
+ |
int handle_romentries(struct flashchip *flash, uint8_t *oldcontents, uint8_t *newcontents) |
{ |
unsigned int start = 0; |
@@ -254,6 +291,7 @@ int handle_romentries(struct flashchip *flash, uint8_t *oldcontents, uint8_t *ne |
* The union of all included romentries is used from the new image. |
*/ |
while (start < size) { |
+ |
entry = find_next_included_romentry(start); |
/* No more romentries for remaining region? */ |
if (entry < 0) { |
@@ -261,9 +299,14 @@ int handle_romentries(struct flashchip *flash, uint8_t *oldcontents, uint8_t *ne |
size - start); |
break; |
} |
+ |
+ /* For non-included region, copy from old content. */ |
if (rom_entries[entry].start > start) |
memcpy(newcontents + start, oldcontents + start, |
rom_entries[entry].start - start); |
+ /* For included region, copy from file if specified. */ |
+ if (read_content_from_file(entry, newcontents) < 0) return -1; |
+ |
/* Skip to location after current romentry. */ |
start = rom_entries[entry].end + 1; |
/* Catch overflow. */ |
@@ -273,3 +316,72 @@ int handle_romentries(struct flashchip *flash, uint8_t *oldcontents, uint8_t *ne |
return 0; |
} |
+ |
+static int write_content_to_file(int entry, uint8_t *buf) { |
+ char *file; |
+ FILE *fp; |
+ int len = rom_entries[entry].end - rom_entries[entry].start + 1; |
+ |
+ file = rom_entries[entry].file; |
+ if (file[0]) { /* save to file if name is specified. */ |
+ int numbytes; |
+ if ((fp = fopen(file, "wb")) == NULL) { |
+ perror(file); |
+ return -1; |
+ } |
+ numbytes = fwrite(buf + rom_entries[entry].start, 1, len, fp); |
+ fclose(fp); |
+ if (numbytes != len) { |
+ perror(file); |
+ return -1; |
+ } |
+ } |
+ return 0; |
+} |
+ |
+int handle_partial_read( |
+ struct flashchip *flash, |
+ uint8_t *buf, |
+ int (*read) (struct flashchip *flash, uint8_t *buf, int start, int len)) { |
+ |
+ unsigned int start = 0; |
+ int entry; |
+ unsigned int size = flash->total_size * 1024; |
+ int count = 0; |
+ |
+ /* If no layout file was specified or the layout file was empty, assume |
+ * that the user wants to flash the complete new image. |
+ */ |
+ if (!romimages) |
+ return 0; |
+ /* Walk through the table and write content to file for those included |
+ * partition. */ |
+ while (start < size) { |
+ int len; |
+ |
+ entry = find_next_included_romentry(start); |
+ /* No more romentries for remaining region? */ |
+ if (entry < 0) { |
+ break; |
+ } |
+ ++count; |
+ |
+ /* read content from flash. */ |
+ len = rom_entries[entry].end - rom_entries[entry].start + 1; |
+ if (read(flash, buf + rom_entries[entry].start, |
+ rom_entries[entry].start, len)) { |
+ perror("flash partial read failed."); |
+ return -1; |
+ } |
+ /* If file is specified, write this partition to file. */ |
+ if (write_content_to_file(entry, buf) < 0) return -1; |
+ |
+ /* Skip to location after current romentry. */ |
+ start = rom_entries[entry].end + 1; |
+ /* Catch overflow. */ |
+ if (!start) |
+ break; |
+ } |
+ |
+ return count; |
+} |