| 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; | 
| +} | 
|  |