diff options
Diffstat (limited to 'layout.c')
-rw-r--r-- | layout.c | 31 |
1 files changed, 26 insertions, 5 deletions
@@ -257,7 +257,28 @@ int normalize_romentries(const struct flashctx *flash) return ret; } -int build_new_image(const struct flashctx *flash, uint8_t *oldcontents, uint8_t *newcontents) +static int copy_old_content(struct flashctx *flash, int oldcontents_valid, uint8_t *oldcontents, uint8_t *newcontents, unsigned int start, unsigned int size) +{ + if (!oldcontents_valid) { + /* oldcontents is a zero-filled buffer. By reading the current data into oldcontents here, we + * avoid a rewrite of identical regions even if an initial full chip read didn't happen. */ + msg_gdbg2("Read a chunk starting at 0x%06x (len=0x%06x).\n", start, size); + int ret = flash->chip->read(flash, oldcontents + start, start, size); + if (ret != 0) { + msg_gerr("Failed to read chunk 0x%06x-0x%06x.\n", start, start + size - 1); + return 1; + } + } + memcpy(newcontents + start, oldcontents + start, size); + return 0; +} + +/** + * Modify @newcontents so that it contains the data that should be on the chip eventually. In the case the user + * wants to update only parts of it, copy the chunks to be preserved from @oldcontents to @newcontents. If + * @oldcontents is not valid, we need to fetch the current data from the chip first. + */ +int build_new_image(struct flashctx *flash, bool oldcontents_valid, uint8_t *oldcontents, uint8_t *newcontents) { unsigned int start = 0; romentry_t *entry; @@ -276,14 +297,14 @@ int build_new_image(const struct flashctx *flash, uint8_t *oldcontents, uint8_t entry = get_next_included_romentry(start); /* No more romentries for remaining region? */ if (!entry) { - memcpy(newcontents + start, oldcontents + start, - size - start); + copy_old_content(flash, oldcontents_valid, oldcontents, newcontents, start, + size - start); break; } /* For non-included region, copy from old content. */ if (entry->start > start) - memcpy(newcontents + start, oldcontents + start, - entry->start - start); + copy_old_content(flash, oldcontents_valid, oldcontents, newcontents, start, + entry->start - start); /* Skip to location after current romentry. */ start = entry->end + 1; /* Catch overflow. */ |