From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id F0FB3C433EF for ; Thu, 30 Sep 2021 16:20:19 +0000 (UTC) Received: from phobos.denx.de (phobos.denx.de [85.214.62.61]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id C3201613CE for ; Thu, 30 Sep 2021 16:20:18 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.4.1 mail.kernel.org C3201613CE Authentication-Results: mail.kernel.org; dmarc=fail (p=quarantine dis=none) header.from=fris.de Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=lists.denx.de Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 33CB880F5F; Thu, 30 Sep 2021 18:20:16 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=quarantine dis=none) header.from=fris.de Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (2048-bit key; unprotected) header.d=fris.de header.i=@fris.de header.b="ryppY34D"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 1D47E802C6; Thu, 30 Sep 2021 18:20:13 +0200 (CEST) Received: from mail.fris.de (mail.fris.de [IPv6:2a01:4f8:c2c:390b::1]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id E750C80185 for ; Thu, 30 Sep 2021 18:20:09 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=quarantine dis=none) header.from=fris.de Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=frieder@fris.de Received: from [127.0.0.1] (localhost [127.0.0.1]) by localhost (Mailerdaemon) with ESMTPSA id C57F4BFBEE; Thu, 30 Sep 2021 18:20:07 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=fris.de; s=dkim; t=1633018808; h=from:subject:date:message-id:to:cc:mime-version: content-transfer-encoding; bh=5HryYZqxnTvXWhAvyqIxDDM48H+vOWkR6CcmJq/Vyqk=; b=ryppY34DW+qnULGGo75NwvWiC+BzE8SarDEtotdmfmVRsIkGMDmDr403LDArTYH6F7ukCC 027Yb1fuQIu9oCHJwRKjdMvMRuAPX2Jr6/tBE5P10/RCyjREflYdi7QumHFUlyuTR9GyDX OQ2vkeVhYX4a5fsSHJh7dXBHui0zz/LyIo5KaPtqnoJ2tI+KaPUdBFGMzt47mRf/aXc9kT yxtf3vYQVL2gu7Ro39hUBPhz61U4QASmN68+aXVEgVs9zk1iJwtNCao+sUKNmvjW4XishU /l8dwnTJ3EV8p4fbGOha0+Akpm+oH8SoT5+owWmdvmCmDAaLF46IOeitAPC5/w== From: Frieder Schrempf To: u-boot@lists.denx.de Cc: Heiko Thiery , Michael Walle , Frieder Schrempf , Bin Meng , Jagan Teki , Pratyush Yadav , Sean Anderson , Simon Glass Subject: [PATCH] cmd: sf: Support unaligned flash updates with 'sf update' Date: Thu, 30 Sep 2021 18:19:25 +0200 Message-Id: <20210930161926.2748887-1-frieder@fris.de> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Last-TLS-Session-Version: TLSv1.3 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.34 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" X-Virus-Scanned: clamav-milter 0.103.2 at phobos.denx.de X-Virus-Status: Clean From: Frieder Schrempf 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 --- 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