All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] cmd: sf: Support unaligned flash updates with 'sf update'
@ 2021-09-30 16:19 Frieder Schrempf
  2021-09-30 16:35 ` Michael Walle
                   ` (2 more replies)
  0 siblings, 3 replies; 9+ messages in thread
From: Frieder Schrempf @ 2021-09-30 16:19 UTC (permalink / raw)
  To: u-boot
  Cc: Heiko Thiery, Michael Walle, Frieder Schrempf, Bin Meng,
	Jagan Teki, Pratyush Yadav, Sean Anderson, Simon Glass

From: Frieder Schrempf <frieder.schrempf@kontron.de>

Currently 'sf update' supports only offsets that are aligned to the
erase block size of the serial flash. Unaligned offsets result in
something like:

=> sf update ${kernel_addr_r} 0x400 ${filesize}
device 0 offset 0x400, size 0x11f758
SPI flash failed in erase step

In order to support unaligned updates, we simply read the first full
block and check only the requested part of the block for changes. If
necessary, the block is erased, the first (unchanged) part of the block
is written back together with the second part of the block (updated data).

Signed-off-by: Frieder Schrempf <frieder.schrempf@kontron.de>
---
 cmd/sf.c | 17 +++++++++++------
 1 file changed, 11 insertions(+), 6 deletions(-)

diff --git a/cmd/sf.c b/cmd/sf.c
index eac27ed2d7..c54b4b10bb 100644
--- a/cmd/sf.c
+++ b/cmd/sf.c
@@ -171,30 +171,32 @@ static int do_spi_flash_probe(int argc, char *const argv[])
 static const char *spi_flash_update_block(struct spi_flash *flash, u32 offset,
 		size_t len, const char *buf, char *cmp_buf, size_t *skipped)
 {
+	u32 offset_aligned = ALIGN_DOWN(offset, flash->sector_size);
+	u32 sector_offset = offset - offset_aligned;
 	char *ptr = (char *)buf;
 
 	debug("offset=%#x, sector_size=%#x, len=%#zx\n",
 	      offset, flash->sector_size, len);
 	/* Read the entire sector so to allow for rewriting */
-	if (spi_flash_read(flash, offset, flash->sector_size, cmp_buf))
+	if (spi_flash_read(flash, offset_aligned, flash->sector_size, cmp_buf))
 		return "read";
 	/* Compare only what is meaningful (len) */
-	if (memcmp(cmp_buf, buf, len) == 0) {
+	if (memcmp(cmp_buf + sector_offset, buf, len) == 0) {
 		debug("Skip region %x size %zx: no change\n",
 		      offset, len);
 		*skipped += len;
 		return NULL;
 	}
 	/* Erase the entire sector */
-	if (spi_flash_erase(flash, offset, flash->sector_size))
+	if (spi_flash_erase(flash, offset_aligned, flash->sector_size))
 		return "erase";
 	/* If it's a partial sector, copy the data into the temp-buffer */
 	if (len != flash->sector_size) {
-		memcpy(cmp_buf, buf, len);
+		memcpy(cmp_buf + sector_offset, buf, len);
 		ptr = cmp_buf;
 	}
 	/* Write one complete sector */
-	if (spi_flash_write(flash, offset, flash->sector_size, ptr))
+	if (spi_flash_write(flash, offset_aligned, flash->sector_size, ptr))
 		return "write";
 
 	return NULL;
@@ -230,7 +232,10 @@ static int spi_flash_update(struct spi_flash *flash, u32 offset,
 		ulong last_update = get_timer(0);
 
 		for (; buf < end && !err_oper; buf += todo, offset += todo) {
-			todo = min_t(size_t, end - buf, flash->sector_size);
+			if (offset % flash->sector_size)
+				todo = flash->sector_size - (offset % flash->sector_size);
+			else
+				todo = min_t(size_t, end - buf, flash->sector_size);
 			if (get_timer(last_update) > 100) {
 				printf("   \rUpdating, %zu%% %lu B/s",
 				       100 - (end - buf) / scale,
-- 
2.33.0


^ permalink raw reply related	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2021-10-04 11:22 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-09-30 16:19 [PATCH] cmd: sf: Support unaligned flash updates with 'sf update' Frieder Schrempf
2021-09-30 16:35 ` Michael Walle
2021-09-30 17:17   ` Frieder Schrempf
2021-09-30 21:08     ` Michael Walle
2021-10-04 10:31       ` Frieder Schrempf
2021-10-04 11:21         ` Michael Walle
2021-09-30 21:21 ` Michael Walle
2021-10-04 10:41   ` Frieder Schrempf
2021-10-01  5:03 ` Simon Glass

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.