All of lore.kernel.org
 help / color / mirror / Atom feed
From: Frieder Schrempf <frieder@fris.de>
To: u-boot@lists.denx.de
Cc: Heiko Thiery <heiko.thiery@gmail.com>,
	Michael Walle <michael@walle.cc>,
	Frieder Schrempf <frieder.schrempf@kontron.de>,
	Bin Meng <bmeng.cn@gmail.com>,
	Jagan Teki <jagan@amarulasolutions.com>,
	Pratyush Yadav <p.yadav@ti.com>,
	Sean Anderson <seanga2@gmail.com>, Simon Glass <sjg@chromium.org>
Subject: [PATCH] cmd: sf: Support unaligned flash updates with 'sf update'
Date: Thu, 30 Sep 2021 18:19:25 +0200	[thread overview]
Message-ID: <20210930161926.2748887-1-frieder@fris.de> (raw)

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


             reply	other threads:[~2021-09-30 16:20 UTC|newest]

Thread overview: 9+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-09-30 16:19 Frieder Schrempf [this message]
2021-09-30 16:35 ` [PATCH] cmd: sf: Support unaligned flash updates with 'sf update' 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

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20210930161926.2748887-1-frieder@fris.de \
    --to=frieder@fris.de \
    --cc=bmeng.cn@gmail.com \
    --cc=frieder.schrempf@kontron.de \
    --cc=heiko.thiery@gmail.com \
    --cc=jagan@amarulasolutions.com \
    --cc=michael@walle.cc \
    --cc=p.yadav@ti.com \
    --cc=seanga2@gmail.com \
    --cc=sjg@chromium.org \
    --cc=u-boot@lists.denx.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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.